use of org.metaborg.spoofax.core.dynamicclassloading.DynamicClassLoadingFacet in project spoofax by metaborg.
the class LanguageComponentFactory method createConfig.
@Override
public ComponentCreationConfig createConfig(IComponentCreationConfigRequest configRequest) throws MetaborgException {
final ComponentFactoryRequest request = (ComponentFactoryRequest) configRequest;
final FileObject location = request.location();
if (!request.valid()) {
throw new MetaborgException(request.toString());
}
final ILanguageComponentConfig componentConfig = request.config();
logger.debug("Creating language component for {}", location);
final LanguageIdentifier identifier = componentConfig.identifier();
final Collection<LanguageContributionIdentifier> langContribs = request.config().langContribs();
if (langContribs.isEmpty()) {
langContribs.add(new LanguageContributionIdentifier(identifier, componentConfig.name()));
}
final ComponentCreationConfig config = new ComponentCreationConfig(identifier, location, langContribs, componentConfig);
final SyntaxFacet syntaxFacet;
if (componentConfig.sdfEnabled()) {
syntaxFacet = request.syntaxFacet();
if (syntaxFacet != null) {
config.addFacet(syntaxFacet);
}
} else {
syntaxFacet = null;
}
final DynamicClassLoadingFacet dynamicClassLoadingFacet = request.dynamicClassLoadingFacet();
if (dynamicClassLoadingFacet != null) {
config.addFacet(dynamicClassLoadingFacet);
}
final StrategoRuntimeFacet strategoRuntimeFacet = request.strategoRuntimeFacet();
if (strategoRuntimeFacet != null) {
config.addFacet(strategoRuntimeFacet);
}
final IStrategoAppl esvTerm = request.esvTerm();
if (esvTerm != null) {
final String[] extensions = extensions(esvTerm);
if (extensions.length != 0) {
final Iterable<String> extensionsIterable = Iterables2.from(extensions);
final IdentificationFacet identificationFacet = new IdentificationFacet(new ResourceExtensionsIdentifier(extensionsIterable));
config.addFacet(identificationFacet);
final ResourceExtensionFacet resourceExtensionsFacet = new ResourceExtensionFacet(extensionsIterable);
config.addFacet(resourceExtensionsFacet);
}
if (ParseFacetFromESV.hasParser(esvTerm)) {
@Nullable final ParseFacet parseFacet = ParseFacetFromESV.create(esvTerm);
if (parseFacet != null) {
config.addFacet(parseFacet);
}
// If parser is set to 'none' in ESV, ParseFacetFromESV.create returns `null` and we create no
// ParserFacet, which is used to in language extension to select which language component contributes
// the parser, since multiple language components contributing a parser is not supported.
} else if (syntaxFacet != null) {
// Default to JSGLR when there is a syntax facet, but no parser was explicitly set in ESV.
config.addFacet(new ParseFacet("jsglr"));
}
final boolean hasContext = ContextFacetFromESV.hasContext(esvTerm);
final boolean hasAnalysis = AnalysisFacetFromESV.hasAnalysis(esvTerm);
final IContextFactory contextFactory;
final ISpoofaxAnalyzer analyzer;
final AnalysisFacet analysisFacet;
if (hasAnalysis) {
final String analysisType = AnalysisFacetFromESV.type(esvTerm);
assert analysisType != null : "Analyzer type cannot be null because hasAnalysis is true, no null check is needed.";
analyzer = analyzers.get(analysisType);
analysisFacet = AnalysisFacetFromESV.create(esvTerm);
final String contextType = hasContext ? ContextFacetFromESV.type(esvTerm) : null;
if (hasContext && contextType == null) {
contextFactory = null;
} else {
final String analysisContextType;
switch(analysisType) {
default:
case StrategoAnalyzer.name:
analysisContextType = contextType == null ? LegacyContextFactory.name : contextType;
break;
case TaskEngineAnalyzer.name:
analysisContextType = IndexTaskContextFactory.name;
break;
case SingleFileConstraintAnalyzer.name:
case MultiFileConstraintAnalyzer.name:
analysisContextType = ConstraintContextFactory.name;
break;
}
if (hasContext && !analysisType.equals(StrategoAnalyzer.name) && !analysisContextType.equals(contextType)) {
logger.warn("Ignoring explicit context type {}, because it is incompatible with analysis {}.", contextType, analysisType);
}
contextFactory = contextFactory(analysisContextType);
}
} else if (hasContext) {
final String type = ContextFacetFromESV.type(esvTerm);
contextFactory = contextFactory(type);
analyzer = null;
analysisFacet = null;
} else {
contextFactory = contextFactory(LegacyContextFactory.name);
analyzer = null;
analysisFacet = null;
}
if (contextFactory != null) {
final IContextStrategy contextStrategy = contextStrategy(ProjectContextStrategy.name);
config.addFacet(new ContextFacet(contextFactory, contextStrategy));
}
if (analyzer != null) {
config.addFacet(new AnalyzerFacet<>(analyzer));
}
if (analysisFacet != null) {
config.addFacet(analysisFacet);
}
final ActionFacet menusFacet = ActionFacetFromESV.create(esvTerm);
if (menusFacet != null) {
config.addFacet(menusFacet);
}
final StylerFacet stylerFacet = StylerFacetFromESV.create(esvTerm);
if (stylerFacet != null) {
config.addFacet(stylerFacet);
}
final IFacet resolverFacet = ResolverFacetFromESV.createResolver(esvTerm);
if (resolverFacet != null) {
config.addFacet(resolverFacet);
}
final IFacet hoverFacet = ResolverFacetFromESV.createHover(esvTerm);
if (hoverFacet != null) {
config.addFacet(hoverFacet);
}
final OutlineFacet outlineFacet = OutlineFacetFromESV.create(esvTerm);
if (outlineFacet != null) {
config.addFacet(outlineFacet);
}
final ShellFacet shellFacet = ShellFacetFromESV.create(esvTerm);
if (shellFacet != null) {
config.addFacet(shellFacet);
}
}
return config;
}
use of org.metaborg.spoofax.core.dynamicclassloading.DynamicClassLoadingFacet in project spoofax by metaborg.
the class SpoofaxLanguageTest method discoverLanguage.
/**
* The 'res://' filesystem redirects to resources inside the tests' JAR file or class file location, which are copied
* to the class file location from src/test/resources by Maven. The binary files of the Entity language are located
* in the resources to test language discovery.
*/
@Test
public void discoverLanguage() throws Exception {
final FileObject location = resourceService.resolve("res://languages");
final Iterable<ILanguageComponent> languages = languageDiscoveryService.discover(languageDiscoveryService.request(location));
assertEquals(1, Iterables.size(languages));
final ILanguageComponent component = Iterables.get(languages, 0);
final ILanguageImpl impl = Iterables.get(component.contributesTo(), 0);
final ILanguage language = impl.belongsTo();
assertEquals("Entity", language.name());
assertEquals(resourceService.resolve("res://languages/Entity"), component.location());
final IdentificationFacet identificationFacet = impl.facet(IdentificationFacet.class);
assertTrue(identificationFacet.identify(resourceService.resolve("ram:///Entity/test.ent")));
final SyntaxFacet syntaxFacet = impl.facet(SyntaxFacet.class);
assertEquals(resourceService.resolve("res://languages/Entity/target/metaborg/sdf.tbl"), syntaxFacet.parseTable);
assertIterableEquals(syntaxFacet.startSymbols, "Start");
final DynamicClassLoadingFacet dynamicClassLoadingFacet = impl.facet(DynamicClassLoadingFacet.class);
final StrategoRuntimeFacet strategoRuntimeFacet = impl.facet(StrategoRuntimeFacet.class);
assertIterableEquals(strategoRuntimeFacet.ctreeFiles, resourceService.resolve("res://languages/Entity/target/metaborg/stratego.ctree"));
assertIterableEquals(dynamicClassLoadingFacet.jarFiles, resourceService.resolve("res://languages/Entity/target/metaborg/stratego.jar"));
final AnalysisFacet analysisFacet = impl.facet(AnalysisFacet.class);
assertEquals("editor-analyze", analysisFacet.strategyName);
}
use of org.metaborg.spoofax.core.dynamicclassloading.DynamicClassLoadingFacet in project spoofax by metaborg.
the class LanguageSpecBuilder method generateSourcesBuilderInput.
private GenerateSourcesBuilder.Input generateSourcesBuilderInput(LanguageSpecBuildInput input) throws FileSystemException, MetaborgException {
final ISpoofaxLanguageSpec languageSpec = input.languageSpec();
final ISpoofaxLanguageSpecConfig config = languageSpec.config();
final FileObject baseLoc = input.languageSpec().location();
final SpoofaxLangSpecCommonPaths paths = new SpoofaxLangSpecCommonPaths(baseLoc);
final FileObject buildInfoLoc = paths.plutoBuildInfoDir();
final SpoofaxContext context = new SpoofaxContext(baseLoc, buildInfoLoc);
// Sort source dependencies to ensure deterministic input.
final ArrayList<LanguageIdentifier> sourceDeps = new ArrayList<>(config.sourceDeps());
Collections.sort(sourceDeps);
// SDF
final Boolean sdfEnabled = config.sdfEnabled();
final String sdfModule = config.sdfName();
final JSGLRVersion jsglrVersion = config.jsglrVersion();
final Boolean checkOverlap = config.checkOverlap();
final Boolean checkPriorities = config.checkPriorities();
final FileObject sdfFileCandidate;
final SdfVersion sdfVersion = config.sdfVersion();
final Sdf2tableVersion sdf2tableVersion = config.sdf2tableVersion();
switch(sdfVersion) {
case sdf2:
final Iterable<FileObject> sdfRoots = languagePathService.sourcePaths(input.project(), SpoofaxConstants.LANG_SDF_NAME);
sdfFileCandidate = paths.findSyntaxMainFile(sdfRoots, sdfModule);
break;
case sdf3:
sdfFileCandidate = paths.syntaxSrcGenMainFile(sdfModule);
break;
default:
throw new MetaborgException("Unknown SDF version: " + sdfVersion);
}
@Nullable final File sdfFile;
if (sdfFileCandidate != null && sdfFileCandidate.exists()) {
sdfFile = resourceService.localPath(sdfFileCandidate);
} else {
sdfFile = null;
}
@Nullable final File sdfExternalDef;
final String sdfExternalDefStr = config.sdfExternalDef();
if (sdfExternalDefStr != null) {
final FileObject sdfExternalDefLoc = resourceService.resolve(sdfExternalDefStr);
if (!sdfExternalDefLoc.exists()) {
throw new MetaborgException("External SDF definition at " + sdfExternalDefLoc + " does not exist");
}
sdfExternalDef = resourceService.localFile(sdfExternalDefLoc);
} else {
sdfExternalDef = null;
}
final Iterable<FileObject> sdfIncludePaths = languagePathService.sourceAndIncludePaths(languageSpec, SpoofaxConstants.LANG_SDF_NAME);
final FileObject packSdfIncludesReplicateDir = paths.replicateDir().resolveFile("pack-sdf-includes");
packSdfIncludesReplicateDir.delete(new AllFileSelector());
final List<File> packSdfIncludePaths = Lists.newArrayList();
for (FileObject path : sdfIncludePaths) {
if (!path.exists()) {
continue;
}
packSdfIncludePaths.add(resourceService.localFileUpdate(path, packSdfIncludesReplicateDir));
}
final Arguments packSdfArgs = config.sdfArgs();
// SDF completions
final String sdfCompletionModule = config.sdfName() + "-completion-insertions";
@Nullable final File sdfCompletionFile;
FileObject sdfCompletionFileCandidate = null;
if (!sdf2tableVersion.javaBased) {
sdfCompletionFileCandidate = paths.syntaxCompletionMainFile(sdfCompletionModule);
} else {
sdfCompletionFileCandidate = paths.syntaxCompletionMainFileNormalized(sdfCompletionModule);
}
if (sdfCompletionFileCandidate != null && sdfCompletionFileCandidate.exists()) {
sdfCompletionFile = resourceService.localPath(sdfCompletionFileCandidate);
} else {
sdfCompletionFile = null;
}
// Meta-SDF
final Iterable<FileObject> sdfRoots = languagePathService.sourcePaths(input.project(), SpoofaxConstants.LANG_SDF_NAME);
// final String sdfMetaModule = config.metaSdfName();
List<String> sdfMetaModules = config.sdfMetaFiles();
@Nullable final List<File> sdfMetaFiles = Lists.newArrayList();
for (String sdfMetaModule : sdfMetaModules) {
final FileObject sdfMetaFileCandidate;
if (config.sdf2tableVersion().javaBased)
sdfMetaFileCandidate = paths.syntaxSrcGenMainNormFile(sdfMetaModule);
else
sdfMetaFileCandidate = paths.findSyntaxMainFile(sdfRoots, sdfMetaModule);
if (sdfMetaFileCandidate != null && sdfMetaFileCandidate.exists())
sdfMetaFiles.add(resourceService.localPath(sdfMetaFileCandidate));
}
// Stratego
final Boolean strEnabled = config.strEnabled();
final String strModule = config.strategoName();
final ArrayList<Supplier<Stratego2LibInfo>> str2libraries = new ArrayList<>();
for (LanguageIdentifier sourceDep : sourceDeps) {
@Nullable final ILanguageImpl sourceDepImpl = languageService.getImpl(sourceDep);
if (sourceDepImpl == null) {
continue;
}
for (ILanguageComponent sourceDepImplComp : sourceDepImpl.components()) {
final String[] str2libProject = { null };
for (IExportConfig export : sourceDepImplComp.config().exports()) {
if (str2libProject[0] != null) {
break;
}
export.accept(new IExportVisitor() {
@Override
public void visit(LangDirExport resource) {
}
@Override
public void visit(LangFileExport resource) {
if (resource.language.equals("StrategoLang") && resource.file.endsWith("str2lib")) {
str2libProject[0] = resource.file;
}
}
@Override
public void visit(ResourceExport resource) {
}
});
}
if (str2libProject[0] != null) {
final String str2IncludeDir = "str2-includes/" + sourceDepImplComp.id().toFullFileString() + "-" + sourceDepImplComp.sequenceId();
final ResourcePath str2LibFile = new FSPath(resourceService.localFileUpdate(sourceDepImplComp.location().resolveFile(str2libProject[0]), paths.replicateDir().resolveFile(str2IncludeDir)));
@Nullable final DynamicClassLoadingFacet facet = sourceDepImplComp.facet(DynamicClassLoadingFacet.class);
if (facet == null) {
continue;
}
final ArrayList<ResourcePath> jarFiles = new ArrayList<>(facet.jarFiles.size());
for (FileObject file : facet.jarFiles) {
jarFiles.add(new FSPath(resourceService.localFileUpdate(file, paths.replicateDir().resolveFile(str2IncludeDir))));
}
str2libraries.add(new ValueSupplier<>(new Stratego2LibInfo(str2LibFile, jarFiles)));
}
}
}
final Iterable<FileObject> strRoots = languagePathService.sourcePaths(input.project(), SpoofaxConstants.LANG_STRATEGO_NAME);
final FileObject strFileCandidate = config.strVersion().findStrMainFile(paths, strRoots, strModule);
@Nullable final File strFile;
if (strEnabled) {
if (strFileCandidate != null && strFileCandidate.exists()) {
strFile = resourceService.localPath(strFileCandidate);
} else {
final String fileExtension = config.strVersion() == StrategoVersion.v1 ? "str" : "str2";
throw new MetaborgException("Cannot find Stratego main file '" + NameUtil.toJavaId(strModule.toLowerCase()) + "." + fileExtension + "'.");
}
} else {
strFile = null;
}
final String strStratPkg = paths.strJavaTransPkg(config.identifier().id);
final String strJavaStratPkg = paths.strJavaStratPkg(config.identifier().id);
final FileObject strJavaStratFileCandidate = paths.strMainJavaStratFile(config.identifier().id);
@Nullable final File strJavaStratFile;
if (strJavaStratFileCandidate.exists()) {
strJavaStratFile = resourceService.localPath(strJavaStratFileCandidate);
} else {
strJavaStratFile = null;
}
final StrategoFormat strFormat = config.strFormat();
@Nullable final File strExternalJar;
final String strExternalJarStr = config.strExternalJar();
if (strEnabled && strExternalJarStr != null) {
final FileObject strExternalJarLoc = resourceService.resolve(strExternalJarStr);
if (!strExternalJarLoc.exists()) {
throw new MetaborgException("External Stratego JAR at " + strExternalJarLoc + " does not exist");
}
strExternalJar = resourceService.localFile(strExternalJarLoc);
} else {
strExternalJar = null;
}
final String strExternalJarFlags = config.strExternalJarFlags();
final Iterable<FileObject> strIncludePaths = Iterables.concat(languagePathService.sourceAndIncludePaths(languageSpec, SpoofaxConstants.LANG_STRATEGO_NAME), languagePathService.sourceAndIncludePaths(languageSpec, SpoofaxConstants.LANG_STRATEGO2_NAME));
final FileObject strjIncludesReplicateDir = paths.replicateDir().resolveFile("strj-includes");
strjIncludesReplicateDir.delete(new AllFileSelector());
final List<File> strjIncludeDirs = Lists.newArrayList();
final List<File> strjIncludeFiles = Lists.newArrayList();
for (FileObject path : strIncludePaths) {
if (!path.exists()) {
continue;
}
if (path.isFolder()) {
strjIncludeDirs.add(resourceService.localFileUpdate(path, strjIncludesReplicateDir));
}
if (path.isFile()) {
strjIncludeFiles.add(resourceService.localFileUpdate(path, strjIncludesReplicateDir));
}
}
final Arguments strjArgs = config.strArgs();
return new GenerateSourcesBuilder.Input(context, config.identifier(), sourceDeps, sdfEnabled, sdfModule, sdfFile, jsglrVersion, sdfVersion, sdf2tableVersion, checkOverlap, checkPriorities, sdfExternalDef, packSdfIncludePaths, packSdfArgs, sdfCompletionModule, sdfCompletionFile, sdfMetaModules, sdfMetaFiles, strEnabled, strFile, strStratPkg, strJavaStratPkg, strJavaStratFile, strFormat, strExternalJar, strExternalJarFlags, strjIncludeDirs, strjIncludeFiles, str2libraries, strjArgs, languageSpec.config().strShadowJar(), languageSpec.config().strVersion());
}
use of org.metaborg.spoofax.core.dynamicclassloading.DynamicClassLoadingFacet in project spoofax by metaborg.
the class LanguageComponentFactory method request.
private IComponentCreationConfigRequest request(FileObject root) throws MetaborgException {
final Collection<String> errors = Lists.newLinkedList();
final Collection<Throwable> exceptions = Lists.newLinkedList();
final ConfigRequest<ILanguageComponentConfig> configRequest = componentConfigService.get(root);
if (!configRequest.valid()) {
for (IMessage message : configRequest.errors()) {
errors.add(message.message());
final Throwable exception = message.exception();
if (exception != null) {
exceptions.add(exception);
}
}
}
final ILanguageComponentConfig config = configRequest.config();
if (config == null) {
final String message = logger.format("Cannot retrieve language component configuration at {}", root);
errors.add(message);
return new ComponentFactoryRequest(root, errors, exceptions);
}
final IStrategoAppl esvTerm;
try {
final FileObject esvFile = root.resolveFile("target/metaborg/editor.esv.af");
if (!esvFile.exists()) {
esvTerm = null;
} else {
esvTerm = esvTerm(root, esvFile);
}
} catch (ParseError | IOException | MetaborgException e) {
exceptions.add(e);
return new ComponentFactoryRequest(root, errors, exceptions);
}
SyntaxFacet syntaxFacet = null;
DynamicClassLoadingFacet dynamicClassLoadingFacet = null;
StrategoRuntimeFacet strategoRuntimeFacet = null;
if (esvTerm != null) {
try {
syntaxFacet = SyntaxFacetFromESV.create(esvTerm, root);
if (syntaxFacet != null) {
Iterables.addAll(errors, syntaxFacet.available());
}
} catch (FileSystemException e) {
exceptions.add(e);
}
try {
dynamicClassLoadingFacet = DynamicClassLoadingFacetFromESV.create(esvTerm, root);
if (!dynamicClassLoadingFacet.jarFiles.isEmpty()) {
Iterables.addAll(errors, dynamicClassLoadingFacet.available(resourceService));
}
} catch (IOException e) {
exceptions.add(e);
}
try {
strategoRuntimeFacet = StrategoRuntimeFacetFromESV.create(esvTerm, root);
if (!strategoRuntimeFacet.ctreeFiles.isEmpty() || (dynamicClassLoadingFacet != null && !dynamicClassLoadingFacet.jarFiles.isEmpty())) {
Iterables.addAll(errors, strategoRuntimeFacet.available(resourceService));
}
} catch (IOException e) {
exceptions.add(e);
}
}
final ComponentFactoryRequest request;
if (errors.isEmpty() && exceptions.isEmpty()) {
request = new ComponentFactoryRequest(root, config, esvTerm, syntaxFacet, dynamicClassLoadingFacet, strategoRuntimeFacet);
} else {
request = new ComponentFactoryRequest(root, errors, exceptions);
}
return request;
}
use of org.metaborg.spoofax.core.dynamicclassloading.DynamicClassLoadingFacet in project spoofax by metaborg.
the class StrategoRuntimeService method loadFiles.
private void loadFiles(HybridInterpreter runtime, ILanguageComponent component) throws MetaborgException {
final StrategoRuntimeFacet strategoRuntimeFacet = component.facet(StrategoRuntimeFacet.class);
if (strategoRuntimeFacet == null) {
final String message = String.format("Cannot get Stratego runtime for %s, it does not have a Stratego facet", component);
logger.error(message);
throw new MetaborgException(message);
}
final DynamicClassLoadingFacet dynamicClassLoadingFacet = component.facet(DynamicClassLoadingFacet.class);
if (dynamicClassLoadingFacet == null) {
final String message = String.format("Cannot get Stratego runtime for %s, it does not have a DynamicClassLoading facet", component);
logger.error(message);
throw new MetaborgException(message);
}
// Order is important, load CTrees first.
final Iterable<FileObject> ctrees = strategoRuntimeFacet.ctreeFiles;
if (Iterables.size(ctrees) > 0) {
loadCtrees(runtime, ctrees);
}
final Iterable<FileObject> jars = dynamicClassLoadingFacet.jarFiles;
if (Iterables.size(jars) > 0) {
loadJars(runtime, jars);
}
}
Aggregations