GP-1 Hard-wired DefaultLanguageService into SleighLanguageProvider and

eliminated single-ldef usage.
This commit is contained in:
ghidra1 2022-12-12 11:47:24 -05:00
parent 1a99e2518d
commit 12cb9010c5
13 changed files with 77 additions and 136 deletions

View file

@ -810,7 +810,7 @@ public class AssemblyDualTextField {
AssemblyDualTextField input = new AssemblyDualTextField(); AssemblyDualTextField input = new AssemblyDualTextField();
SleighLanguageProvider provider = new SleighLanguageProvider(); SleighLanguageProvider provider = SleighLanguageProvider.getSleighLanguageProvider();
SleighLanguage lang = (SleighLanguage) provider.getLanguage(DEMO_LANG_ID); SleighLanguage lang = (SleighLanguage) provider.getLanguage(DEMO_LANG_ID);
curAddr = lang.getDefaultSpace().getAddress(0); curAddr = lang.getDefaultSpace().getAddress(0);

View file

@ -30,7 +30,6 @@ import ghidra.app.cmd.function.CreateFunctionCmd;
import ghidra.app.cmd.label.AddLabelCmd; import ghidra.app.cmd.label.AddLabelCmd;
import ghidra.app.cmd.label.CreateNamespacesCmd; import ghidra.app.cmd.label.CreateNamespacesCmd;
import ghidra.app.plugin.core.analysis.AutoAnalysisManager; import ghidra.app.plugin.core.analysis.AutoAnalysisManager;
import ghidra.app.plugin.processors.sleigh.SleighLanguageProvider;
import ghidra.app.util.NamespaceUtils; import ghidra.app.util.NamespaceUtils;
import ghidra.app.util.SymbolPath; import ghidra.app.util.SymbolPath;
import ghidra.framework.options.Options; import ghidra.framework.options.Options;
@ -47,6 +46,7 @@ import ghidra.program.model.mem.Memory;
import ghidra.program.model.mem.MemoryBlock; import ghidra.program.model.mem.MemoryBlock;
import ghidra.program.model.symbol.*; import ghidra.program.model.symbol.*;
import ghidra.program.model.util.*; import ghidra.program.model.util.*;
import ghidra.program.util.DefaultLanguageService;
import ghidra.program.util.GhidraProgramUtilities; import ghidra.program.util.GhidraProgramUtilities;
import ghidra.test.AbstractGhidraHeadedIntegrationTest; import ghidra.test.AbstractGhidraHeadedIntegrationTest;
import ghidra.util.*; import ghidra.util.*;
@ -83,7 +83,6 @@ public class ProgramBuilder {
protected static final String _TOY_LANGUAGE_PREFIX = "Toy:"; protected static final String _TOY_LANGUAGE_PREFIX = "Toy:";
private static final Map<String, Language> LANGUAGE_CACHE = new HashMap<>(); private static final Map<String, Language> LANGUAGE_CACHE = new HashMap<>();
private static SleighLanguageProvider languageProvider;
private ProgramDB program; private ProgramDB program;
@ -248,21 +247,11 @@ public class ProgramBuilder {
} }
} }
private static synchronized LanguageProvider getLanguageProvider() throws Exception { private static Language getLanguage(String languageId) throws LanguageNotFoundException {
if (languageProvider == null) {
languageProvider = new SleighLanguageProvider();
}
return languageProvider;
}
private Language getLanguage(String languageId) throws Exception {
Language language = LANGUAGE_CACHE.get(languageId); Language language = LANGUAGE_CACHE.get(languageId);
if (language == null) { if (language == null) {
LanguageID id = new LanguageID(languageId); language =
language = getLanguageProvider().getLanguage(id); DefaultLanguageService.getLanguageService().getLanguage(new LanguageID(languageId));
if (language == null) {
throw new LanguageNotFoundException(id);
}
LANGUAGE_CACHE.put(languageId, language); LANGUAGE_CACHE.put(languageId, language);
} }
return language; return language;
@ -1072,7 +1061,8 @@ public class ProgramBuilder {
tx(() -> { tx(() -> {
PropertyMapManager pm = program.getUsrPropertyManager(); PropertyMapManager pm = program.getUsrPropertyManager();
ObjectPropertyMap propertyMap = pm.getObjectPropertyMap(propertyName); ObjectPropertyMap<? extends Saveable> propertyMap =
pm.getObjectPropertyMap(propertyName);
if (propertyMap == null) { if (propertyMap == null) {
propertyMap = pm.createObjectPropertyMap(propertyName, value.getClass()); propertyMap = pm.createObjectPropertyMap(propertyName, value.getClass());
} }

View file

@ -1,6 +1,5 @@
AnnotationHandler AnnotationHandler
RelocationHandler RelocationHandler
LanguageProvider
LanguageTranslator LanguageTranslator
Constraint Constraint
DataType DataType

View file

@ -62,12 +62,26 @@ public class SleighLanguageProvider implements LanguageProvider {
public final static String LANGUAGE_DIR_NAME = "languages"; public final static String LANGUAGE_DIR_NAME = "languages";
public SleighLanguageProvider() throws Exception { private static SleighLanguageProvider instance; // sleigh language provider instance (singleton)
createLanguages();
public static synchronized SleighLanguageProvider getSleighLanguageProvider() {
if (instance == null) {
instance = new SleighLanguageProvider();
try {
instance.createLanguages();
}
catch (Exception e) {
Msg.error(SleighLanguageProvider.class,
"Sleigh language provider initiailization failed", e);
}
}
return instance;
} }
public SleighLanguageProvider(ResourceFile ldefsFile) throws Exception { /**
createLanguages(ldefsFile); * Construct sleigh language provider (singleton)
*/
private SleighLanguageProvider() {
} }
private void createLanguages() throws Exception { private void createLanguages() throws Exception {
@ -96,7 +110,11 @@ public class SleighLanguageProvider implements LanguageProvider {
@Override @Override
public Language getLanguage(LanguageID languageId) { public Language getLanguage(LanguageID languageId) {
return getNewSleigh(languageId); Language language = languages.get(languageId);
if (language == null) {
language = getNewSleigh(languageId);
}
return language;
} }
@Override @Override
@ -104,7 +122,7 @@ public class SleighLanguageProvider implements LanguageProvider {
return languages.get(languageId) != null; return languages.get(languageId) != null;
} }
private Language getNewSleigh(LanguageID languageId) { private SleighLanguage getNewSleigh(LanguageID languageId) {
SleighLanguageDescription description = descriptions.get(languageId); SleighLanguageDescription description = descriptions.get(languageId);
SleighLanguage lang = languages.get(languageId); SleighLanguage lang = languages.get(languageId);
if (lang == null) { if (lang == null) {

View file

@ -30,7 +30,8 @@ public interface LanguageProvider extends ExtensionPoint {
* Returns the language with the given name or null if no language has that name * Returns the language with the given name or null if no language has that name
* *
* @param languageId the name of the language to be retrieved * @param languageId the name of the language to be retrieved
* @return the {@link Language} with the given name * @return the {@link Language} with the given name or null if not found
* @throws RuntimeException if language instantiation error occurs
*/ */
Language getLanguage(LanguageID languageId); Language getLanguage(LanguageID languageId);

View file

@ -17,28 +17,22 @@ package ghidra.program.util;
import java.util.*; import java.util.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import generic.jar.ResourceFile;
import ghidra.app.plugin.processors.sleigh.SleighLanguageProvider; import ghidra.app.plugin.processors.sleigh.SleighLanguageProvider;
import ghidra.program.model.lang.*; import ghidra.program.model.lang.*;
import ghidra.util.classfinder.ClassSearcher;
import ghidra.util.task.TaskBuilder; import ghidra.util.task.TaskBuilder;
/** /**
* Default Language service used gather up all the languages that were found * Default Language service used gather up all the languages that were found
* during the class search (search was for language providers) * during the class search (search was for language providers)
*/ */
public class DefaultLanguageService implements LanguageService, ChangeListener { public class DefaultLanguageService implements LanguageService {
private static final Logger log = LogManager.getLogger(DefaultLanguageService.class); private static final Logger log = LogManager.getLogger(DefaultLanguageService.class);
private List<LanguageInfo> languageInfos = new ArrayList<>(); private List<LanguageInfo> languageInfos = new ArrayList<>();
private HashMap<LanguageID, LanguageInfo> languageMap = new HashMap<>(); private HashMap<LanguageID, LanguageInfo> languageMap = new HashMap<>();
private boolean searchCompleted = false;
private static DefaultLanguageService languageService; private static DefaultLanguageService languageService;
@ -50,58 +44,17 @@ public class DefaultLanguageService implements LanguageService, ChangeListener {
if (languageService == null) { if (languageService == null) {
languageService = new DefaultLanguageService(); languageService = new DefaultLanguageService();
} }
else if (!languageService.searchCompleted) {
languageService.searchForProviders();
}
return languageService;
}
/**
* Return the single instance of the DefaultLanguageService. If not already
* instantiated in the default mode, the factory will be lazy and limit
* it set of languages to those defined by the specified Sleigh language definition
* file (*.ldefs) or those provided by subsequent calls to this method.
* @param sleighLdefsFile sleigh language definition file
* @return language factory instance
* @throws Exception if an error occurs while parsing the specified definition file
*/
public static synchronized LanguageService getLanguageService(ResourceFile sleighLdefsFile)
throws Exception {
SleighLanguageProvider provider = new SleighLanguageProvider(sleighLdefsFile);
if (languageService == null) {
languageService = new DefaultLanguageService(provider);
}
languageService.addLanguages(provider);
return languageService; return languageService;
} }
private DefaultLanguageService() { private DefaultLanguageService() {
searchForProviders(); addLanguages(SleighLanguageProvider.getSleighLanguageProvider());
ClassSearcher.addChangeListener(this);
} }
private DefaultLanguageService(LanguageProvider provider) { private DefaultLanguageService(LanguageProvider provider) {
addLanguages(provider); addLanguages(provider);
} }
private void searchForProviders() {
List<LanguageProvider> languageProviders =
ClassSearcher.getInstances(LanguageProvider.class);
searchCompleted = true;
//@formatter:off
TaskBuilder.withRunnable(monitor -> {
processProviders(languageProviders); // load and cache
})
.setTitle("Language Search")
.setCanCancel(false)
.setHasProgress(false)
.launchModal()
;
//@formatter:on
}
@Override @Override
public Language getLanguage(LanguageID languageID) throws LanguageNotFoundException { public Language getLanguage(LanguageID languageID) throws LanguageNotFoundException {
LanguageInfo info = languageMap.get(languageID); LanguageInfo info = languageMap.get(languageID);
@ -338,12 +291,6 @@ public class DefaultLanguageService implements LanguageService, ChangeListener {
throw new LanguageNotFoundException(processor); throw new LanguageNotFoundException(processor);
} }
private void processProviders(List<LanguageProvider> providers) {
for (LanguageProvider provider : providers) {
addLanguages(provider);
}
}
private void addLanguages(LanguageProvider provider) { private void addLanguages(LanguageProvider provider) {
LanguageDescription[] lds = provider.getLanguageDescriptions(); LanguageDescription[] lds = provider.getLanguageDescriptions();
for (LanguageDescription description : lds) { for (LanguageDescription description : lds) {
@ -414,10 +361,4 @@ public class DefaultLanguageService implements LanguageService, ChangeListener {
} }
} }
@Override
public void stateChanged(ChangeEvent e) {
// NOTE: this is only intended to pickup new language providers
// which is not really supported with the introduction of Sleigh.
searchForProviders();
}
} }

View file

@ -15,7 +15,7 @@
*/ */
package ghidra.app.plugin.assembler.sleigh; package ghidra.app.plugin.assembler.sleigh;
import static org.junit.Assert.fail; import static org.junit.Assert.*;
import java.util.*; import java.util.*;
@ -29,13 +29,15 @@ import ghidra.app.plugin.assembler.sleigh.parse.*;
import ghidra.app.plugin.assembler.sleigh.sem.*; import ghidra.app.plugin.assembler.sleigh.sem.*;
import ghidra.app.plugin.assembler.sleigh.tree.AssemblyParseTreeNode; import ghidra.app.plugin.assembler.sleigh.tree.AssemblyParseTreeNode;
import ghidra.app.plugin.assembler.sleigh.util.DbgTimer; import ghidra.app.plugin.assembler.sleigh.util.DbgTimer;
import ghidra.app.plugin.processors.sleigh.*; import ghidra.app.plugin.processors.sleigh.SleighInstructionPrototype;
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.app.util.PseudoInstruction; import ghidra.app.util.PseudoInstruction;
import ghidra.generic.util.datastruct.TreeSetValuedTreeMap; import ghidra.generic.util.datastruct.TreeSetValuedTreeMap;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressOverflowException; import ghidra.program.model.address.AddressOverflowException;
import ghidra.program.model.lang.*; import ghidra.program.model.lang.*;
import ghidra.program.model.mem.*; import ghidra.program.model.mem.*;
import ghidra.program.util.DefaultLanguageService;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.NumericUtilities; import ghidra.util.NumericUtilities;
@ -70,8 +72,7 @@ public abstract class AbstractAssemblyTest extends AbstractGenericTest {
public void setUp() throws Exception { public void setUp() throws Exception {
LanguageID langID = getLanguageID(); LanguageID langID = getLanguageID();
if (!setupLangID.equals(langID.toString())) { if (!setupLangID.equals(langID.toString())) {
SleighLanguageProvider provider = new SleighLanguageProvider(); lang = getLanguage(langID);
lang = (SleighLanguage) provider.getLanguage(langID);
context = new AssemblyDefaultContext(lang); context = new AssemblyDefaultContext(lang);
setupLangID = langID.toString(); setupLangID = langID.toString();
} }
@ -83,6 +84,11 @@ public abstract class AbstractAssemblyTest extends AbstractGenericTest {
//dbg.resetOutputStream(oldOutput).close(); //dbg.resetOutputStream(oldOutput).close();
} }
private static SleighLanguage getLanguage(LanguageID langID) throws LanguageNotFoundException {
LanguageService languageService = DefaultLanguageService.getLanguageService();
return (SleighLanguage) languageService.getLanguage(langID);
}
/** /**
* Print a collection of parse trees to the debug printer * Print a collection of parse trees to the debug printer
* *

View file

@ -15,7 +15,7 @@
*/ */
package ghidra.app.plugin.assembler.sleigh; package ghidra.app.plugin.assembler.sleigh;
import static org.junit.Assert.fail; import static org.junit.Assert.*;
import java.util.*; import java.util.*;
@ -72,7 +72,7 @@ public abstract class AssemblyTestCase extends AbstractGenericTest {
public void setUp() throws Exception { public void setUp() throws Exception {
LanguageID langID = getLanguageID(); LanguageID langID = getLanguageID();
if (!setupLangID.equals(langID.toString())) { if (!setupLangID.equals(langID.toString())) {
SleighLanguageProvider provider = new SleighLanguageProvider(); SleighLanguageProvider provider = SleighLanguageProvider.getSleighLanguageProvider();
lang = (SleighLanguage) provider.getLanguage(langID); lang = (SleighLanguage) provider.getLanguage(langID);
context = new AssemblyDefaultContext(lang); context = new AssemblyDefaultContext(lang);
setupLangID = langID.toString(); setupLangID = langID.toString();

View file

@ -15,8 +15,7 @@
*/ */
package ghidra.app.plugin.assembler.sleigh; package ghidra.app.plugin.assembler.sleigh;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.*;
import static org.junit.Assert.assertNotEquals;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -25,14 +24,13 @@ import org.junit.*;
import generic.test.AbstractGenericTest; import generic.test.AbstractGenericTest;
import ghidra.app.plugin.assembler.*; import ghidra.app.plugin.assembler.*;
import ghidra.app.plugin.processors.sleigh.SleighLanguageProvider;
import ghidra.program.database.ProgramDB; import ghidra.program.database.ProgramDB;
import ghidra.program.database.util.ProgramTransaction; import ghidra.program.database.util.ProgramTransaction;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressOverflowException; import ghidra.program.model.address.AddressOverflowException;
import ghidra.program.model.lang.Language; import ghidra.program.model.lang.*;
import ghidra.program.model.lang.LanguageID;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.*;
import ghidra.program.util.DefaultLanguageService;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
@ -44,9 +42,8 @@ public class PublicAPITest extends AbstractGenericTest {
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
SleighLanguageProvider provider = new SleighLanguageProvider(); x86 = getLanguage("x86:LE:64:default");
x86 = provider.getLanguage(new LanguageID("x86:LE:64:default")); toy = getLanguage("Toy:BE:64:default");
toy = provider.getLanguage(new LanguageID("Toy:BE:64:default"));
} }
@After @After
@ -56,6 +53,11 @@ public class PublicAPITest extends AbstractGenericTest {
} }
} }
private static Language getLanguage(String languageName) throws LanguageNotFoundException {
LanguageService languageService = DefaultLanguageService.getLanguageService();
return languageService.getLanguage(new LanguageID(languageName));
}
@Test @Test
public void testADD0() throws AssemblySyntaxException, AssemblySemanticException { public void testADD0() throws AssemblySyntaxException, AssemblySemanticException {
// Mostly just test that it doesn't crash // Mostly just test that it doesn't crash

View file

@ -36,7 +36,8 @@ import ghidra.app.plugin.processors.sleigh.template.ConstructTpl;
import ghidra.app.plugin.processors.sleigh.template.HandleTpl; import ghidra.app.plugin.processors.sleigh.template.HandleTpl;
import ghidra.framework.Application; import ghidra.framework.Application;
import ghidra.framework.ApplicationConfiguration; import ghidra.framework.ApplicationConfiguration;
import ghidra.program.model.lang.LanguageID; import ghidra.program.model.lang.*;
import ghidra.program.util.DefaultLanguageService;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.xml.XmlPullParser; import ghidra.xml.XmlPullParser;
import ghidra.xml.XmlPullParserFactory; import ghidra.xml.XmlPullParserFactory;
@ -183,13 +184,18 @@ public class SolverTest {
assertEquals(e, res); assertEquals(e, res);
} }
private static Language getLanguage(String languageName) throws LanguageNotFoundException {
LanguageService languageService = DefaultLanguageService.getLanguageService();
return languageService.getLanguage(new LanguageID(languageName));
}
public static Constructor findConstructor(String langId, String subtableName, String patternStr) public static Constructor findConstructor(String langId, String subtableName, String patternStr)
throws Exception { throws Exception {
if (!Application.isInitialized()) { if (!Application.isInitialized()) {
Application.initializeApplication(new GhidraApplicationLayout(), Application.initializeApplication(new GhidraApplicationLayout(),
new ApplicationConfiguration()); new ApplicationConfiguration());
} }
SleighLanguageProvider provider = new SleighLanguageProvider(); SleighLanguageProvider provider = SleighLanguageProvider.getSleighLanguageProvider();
SleighLanguage lang = (SleighLanguage) provider.getLanguage(new LanguageID(langId)); SleighLanguage lang = (SleighLanguage) provider.getLanguage(new LanguageID(langId));
AtomicReference<Constructor> consref = new AtomicReference<>(); AtomicReference<Constructor> consref = new AtomicReference<>();
SleighLanguages.traverseConstructors(lang, new ConstructorEntryVisitor() { SleighLanguages.traverseConstructors(lang, new ConstructorEntryVisitor() {
@ -213,7 +219,7 @@ public class SolverTest {
Application.initializeApplication(new GhidraApplicationLayout(), Application.initializeApplication(new GhidraApplicationLayout(),
new ApplicationConfiguration()); new ApplicationConfiguration());
} }
SleighLanguageProvider provider = new SleighLanguageProvider(); SleighLanguageProvider provider = SleighLanguageProvider.getSleighLanguageProvider();
SleighLanguage lang = (SleighLanguage) provider.getLanguage(new LanguageID(langId)); SleighLanguage lang = (SleighLanguage) provider.getLanguage(new LanguageID(langId));
AtomicReference<Constructor> consref = new AtomicReference<>(); AtomicReference<Constructor> consref = new AtomicReference<>();
SleighLanguages.traverseConstructors(lang, new ConstructorEntryVisitor() { SleighLanguages.traverseConstructors(lang, new ConstructorEntryVisitor() {

View file

@ -24,9 +24,7 @@ import org.junit.*;
import db.*; import db.*;
import db.buffers.BufferFile; import db.buffers.BufferFile;
import generic.jar.ResourceFile;
import generic.test.AbstractGenericTest; import generic.test.AbstractGenericTest;
import ghidra.framework.Application;
import ghidra.framework.store.db.PrivateDatabase; import ghidra.framework.store.db.PrivateDatabase;
import ghidra.program.database.ProgramDB; import ghidra.program.database.ProgramDB;
import ghidra.program.model.lang.*; import ghidra.program.model.lang.*;
@ -292,14 +290,8 @@ public class FileBytesTest extends AbstractGenericTest {
program.release(this); program.release(this);
} }
private Language getLanguage(String languageName) throws Exception { private static Language getLanguage(String languageName) throws LanguageNotFoundException {
LanguageService languageService = DefaultLanguageService.getLanguageService();
ResourceFile ldefFile = Application.getModuleDataFile("Toy", "languages/toy.ldefs"); return languageService.getLanguage(new LanguageID(languageName));
if (ldefFile != null) {
LanguageService languageService = DefaultLanguageService.getLanguageService(ldefFile);
Language language = languageService.getLanguage(new LanguageID(languageName));
return language;
}
throw new LanguageNotFoundException("Unsupported test language: " + languageName);
} }
} }

View file

@ -25,9 +25,7 @@ import org.junit.*;
import db.DBConstants; import db.DBConstants;
import db.DBHandle; import db.DBHandle;
import generic.jar.ResourceFile;
import generic.test.AbstractGenericTest; import generic.test.AbstractGenericTest;
import ghidra.framework.Application;
import ghidra.program.database.ProgramDB; import ghidra.program.database.ProgramDB;
import ghidra.program.database.map.AddressMapDB; import ghidra.program.database.map.AddressMapDB;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
@ -1024,14 +1022,9 @@ public class MemBlockDBTest extends AbstractGenericTest {
return addressFactory.getDefaultAddressSpace().getAddress(offset); return addressFactory.getDefaultAddressSpace().getAddress(offset);
} }
private Language getLanguage(String languageName) throws Exception { private static Language getLanguage(String languageName) throws LanguageNotFoundException {
LanguageService languageService = DefaultLanguageService.getLanguageService();
return languageService.getLanguage(new LanguageID(languageName));
}
ResourceFile ldefFile = Application.getModuleDataFile("Toy", "languages/toy.ldefs");
if (ldefFile != null) {
LanguageService languageService = DefaultLanguageService.getLanguageService(ldefFile);
Language language = languageService.getLanguage(new LanguageID(languageName));
return language;
}
throw new LanguageNotFoundException("Unsupported test language: " + languageName);
}
} }

View file

@ -20,9 +20,7 @@ import static org.junit.Assert.*;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import generic.jar.ResourceFile;
import generic.test.AbstractGenericTest; import generic.test.AbstractGenericTest;
import ghidra.framework.Application;
import ghidra.program.database.ProgramDB; import ghidra.program.database.ProgramDB;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
import ghidra.program.model.lang.*; import ghidra.program.model.lang.*;
@ -39,14 +37,9 @@ public class VariableUtilitiesTest extends AbstractGenericTest {
program = new ProgramDB("Test", language, compilerSpec, this); program = new ProgramDB("Test", language, compilerSpec, this);
} }
private Language getLanguage(String languageName) throws Exception { private static Language getLanguage(String languageName) throws LanguageNotFoundException {
ResourceFile ldefFile = Application.getModuleDataFile("Toy", "languages/toy.ldefs"); LanguageService languageService = DefaultLanguageService.getLanguageService();
if (ldefFile != null) { return languageService.getLanguage(new LanguageID(languageName));
LanguageService languageService = DefaultLanguageService.getLanguageService(ldefFile);
Language language = languageService.getLanguage(new LanguageID(languageName));
return language;
}
throw new LanguageNotFoundException("Unsupported test language: " + languageName);
} }
@Test @Test