Search in sources :

Example 1 with FileConfig

use of org.lflang.FileConfig in project lingua-franca by lf-lang.

the class GeneratorBase method doGenerate.

/**
 * Generate code from the Lingua Franca model contained by the specified resource.
 *
 * This is the main entry point for code generation. This base class finds all
 * reactor class definitions, including any reactors defined in imported .lf files
 * (except any main reactors in those imported files), and adds them to the
 * {@link #GeneratorBase.reactors reactors} list. If errors occur during
 * generation, then a subsequent call to errorsOccurred() will return true.
 * @param resource The resource containing the source code.
 * @param context Context relating to invocation of the code generator.
 * In stand alone mode, this object is also used to relay CLI arguments.
 */
public void doGenerate(Resource resource, LFGeneratorContext context) {
    GeneratorUtils.setTargetConfig(context, GeneratorUtils.findTarget(fileConfig.resource), targetConfig, errorReporter);
    cleanIfNeeded(context);
    printInfo(context.getMode());
    // Markers mark problems in the Eclipse IDE when running in integrated mode.
    if (errorReporter instanceof EclipseErrorReporter) {
        ((EclipseErrorReporter) errorReporter).clearMarkers();
    }
    ASTUtils.setMainName(fileConfig.resource, fileConfig.name);
    createMainInstantiation();
    // Check if there are any conflicting main reactors elsewhere in the package.
    if (Objects.equal(context.getMode(), LFGeneratorContext.Mode.STANDALONE) && mainDef != null) {
        for (String conflict : new MainConflictChecker(fileConfig).conflicts) {
            errorReporter.reportError(this.mainDef.getReactorClass(), "Conflicting main reactor in " + conflict);
        }
    }
    // Configure the command factory
    commandFactory.setVerbose();
    if (Objects.equal(context.getMode(), LFGeneratorContext.Mode.STANDALONE) && context.getArgs().containsKey("quiet")) {
        commandFactory.setQuiet();
    }
    // This must be done before desugaring delays below.
    analyzeFederates(context);
    // Process target files. Copy each of them into the src-gen dir.
    // FIXME: Should we do this here? This doesn't make sense for federates the way it is
    // done here.
    copyUserFiles(this.targetConfig, this.fileConfig);
    // Collect reactors and create an instantiation graph.
    // These are needed to figure out which resources we need
    // to validate, which happens in setResources().
    setReactorsAndInstantiationGraph(context.getMode());
    GeneratorUtils.validate(context, fileConfig, instantiationGraph, errorReporter);
    List<Resource> allResources = GeneratorUtils.getResources(reactors);
    resources.addAll(// FIXME: This filter reproduces the behavior of the method it replaces. But why must it be so complicated? Why are we worried about weird corner cases like this?
    allResources.stream().filter(it -> !Objects.equal(it, fileConfig.resource) || mainDef != null && it == mainDef.getReactorClass().eResource()).map(it -> GeneratorUtils.getLFResource(it, fileConfig.getSrcGenBasePath(), context, errorReporter)).collect(Collectors.toList()));
    GeneratorUtils.accommodatePhysicalActionsIfPresent(allResources, getTarget().setsKeepAliveOptionAutomatically(), targetConfig, errorReporter);
    // FIXME: Should the GeneratorBase pull in `files` from imported
    // resources?
    // Reroute connections that have delays associated with them via
    // generated delay reactors.
    transformDelays();
    // Transform connections that reside in mutually exclusive modes and are otherwise conflicting
    // This should be done before creating the instantiation graph
    transformConflictingConnectionsInModalReactors();
    // Invoke these functions a second time because transformations
    // may have introduced new reactors!
    setReactorsAndInstantiationGraph(context.getMode());
    // Check for existence and support of modes
    hasModalReactors = IterableExtensions.exists(reactors, it -> !it.getModes().isEmpty());
    checkModalReactorSupport(false);
    enableSupportForSerializationIfApplicable(context.getCancelIndicator());
}
Also used : SupportedSerializers(org.lflang.federated.serialization.SupportedSerializers) Delay(org.lflang.lf.Delay) FedASTUtils(org.lflang.federated.FedASTUtils) Action(org.lflang.lf.Action) InferredType(org.lflang.InferredType) Matcher(java.util.regex.Matcher) Map(java.util.Map) Instantiation(org.lflang.lf.Instantiation) Objects(com.google.common.base.Objects) Path(java.nio.file.Path) Connection(org.lflang.lf.Connection) MainConflictChecker(org.lflang.MainConflictChecker) TargetConfig(org.lflang.TargetConfig) Collection(java.util.Collection) Set(java.util.Set) EObject(org.eclipse.emf.ecore.EObject) Collectors(java.util.stream.Collectors) Parameter(org.lflang.lf.Parameter) List(java.util.List) Value(org.lflang.lf.Value) CollectionLiterals(org.eclipse.xtext.xbase.lib.CollectionLiterals) Target(org.lflang.Target) Resource(org.eclipse.emf.ecore.resource.Resource) Pattern(java.util.regex.Pattern) Pair(org.eclipse.xtext.xbase.lib.Pair) FileConfig(org.lflang.FileConfig) ASTUtils(org.lflang.ASTUtils) FederateInstance(org.lflang.federated.FederateInstance) Iterables(com.google.common.collect.Iterables) LfFactory(org.lflang.lf.LfFactory) ErrorReporter(org.lflang.ErrorReporter) AbstractLFValidator(org.lflang.validation.AbstractLFValidator) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) LinkedHashMap(java.util.LinkedHashMap) CancelIndicator(org.eclipse.xtext.util.CancelIndicator) Reaction(org.lflang.lf.Reaction) TimeUnit(org.lflang.TimeUnit) TimeValue(org.lflang.TimeValue) LinkedHashSet(java.util.LinkedHashSet) IMarker(org.eclipse.core.resources.IMarker) InstantiationGraph(org.lflang.graph.InstantiationGraph) CoordinationType(org.lflang.TargetProperty.CoordinationType) Model(org.lflang.lf.Model) IOException(java.io.IOException) Time(org.lflang.lf.Time) File(java.io.File) IteratorExtensions(org.eclipse.xtext.xbase.lib.IteratorExtensions) IterableExtensions(org.eclipse.xtext.xbase.lib.IterableExtensions) Paths(java.nio.file.Paths) Reactor(org.lflang.lf.Reactor) VarRef(org.lflang.lf.VarRef) MainConflictChecker(org.lflang.MainConflictChecker) Resource(org.eclipse.emf.ecore.resource.Resource)

Example 2 with FileConfig

use of org.lflang.FileConfig in project lingua-franca by lf-lang.

the class LFGenerator method doGenerate.

@Override
public void doGenerate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context) {
    final LFGeneratorContext lfContext = LFGeneratorContext.lfGeneratorContextOf(context, resource);
    // The fastest way to generate code is to not generate any code.
    if (lfContext.getMode() == LFGeneratorContext.Mode.LSP_FAST)
        return;
    final Target target = Target.fromDecl(ASTUtils.targetDecl(resource));
    assert target != null;
    FileConfig fileConfig;
    try {
        fileConfig = Objects.requireNonNull(createFileConfig(target, resource, fsa, lfContext));
    } catch (IOException e) {
        throw new RuntimeIOException("Error during FileConfig instantiation", e);
    }
    final ErrorReporter errorReporter = lfContext.constructErrorReporter(fileConfig);
    final GeneratorBase generator = createGenerator(target, fileConfig, errorReporter);
    if (generator != null) {
        generator.doGenerate(resource, lfContext);
        generatorErrorsOccurred = generator.errorsOccurred();
    }
    if (errorReporter instanceof LanguageServerErrorReporter) {
        ((LanguageServerErrorReporter) errorReporter).publishDiagnostics();
    }
}
Also used : FileConfig(org.lflang.FileConfig) RuntimeIOException(org.eclipse.xtext.util.RuntimeIOException) Target(org.lflang.Target) ErrorReporter(org.lflang.ErrorReporter) IOException(java.io.IOException) RuntimeIOException(org.eclipse.xtext.util.RuntimeIOException)

Example 3 with FileConfig

use of org.lflang.FileConfig in project lingua-franca by lf-lang.

the class IntegratedBuilder method run.

/* ------------------------- PUBLIC METHODS -------------------------- */
/**
 * Generates code from the Lingua Franca file {@code f}.
 * @param uri The URI of a Lingua Franca file.
 * @param mustComplete Whether the build must be taken to completion.
 * @return The result of the build.
 */
public GeneratorResult run(URI uri, boolean mustComplete, ReportProgress reportProgress, CancelIndicator cancelIndicator) {
    // FIXME: A refactoring of the following line is needed. This refactor will affect FileConfig and
    // org.lflang.lfc.Main. The issue is that there is duplicated code.
    fileAccess.setOutputPath(FileConfig.findPackageRoot(Path.of(uri.path()), s -> {
    }).resolve(FileConfig.DEFAULT_SRC_GEN_DIR).toString());
    List<EObject> parseRoots = getResource(uri).getContents();
    if (parseRoots.isEmpty())
        return GeneratorResult.NOTHING;
    ErrorReporter errorReporter = new LanguageServerErrorReporter(parseRoots.get(0));
    reportProgress.apply("Validating...", START_PERCENT_PROGRESS);
    validate(uri, errorReporter);
    reportProgress.apply("Code validation complete.", VALIDATED_PERCENT_PROGRESS);
    if (cancelIndicator.isCanceled())
        return GeneratorResult.CANCELLED;
    if (errorReporter.getErrorsOccurred())
        return GeneratorResult.FAILED;
    reportProgress.apply("Generating code...", VALIDATED_PERCENT_PROGRESS);
    return doGenerate(uri, mustComplete, reportProgress, cancelIndicator);
}
Also used : Properties(java.util.Properties) URI(org.eclipse.emf.common.util.URI) Severity(org.eclipse.xtext.diagnostics.Severity) ErrorReporter(org.lflang.ErrorReporter) Inject(com.google.inject.Inject) GeneratorDelegate(org.eclipse.xtext.generator.GeneratorDelegate) IResourceValidator(org.eclipse.xtext.validation.IResourceValidator) EObject(org.eclipse.emf.ecore.EObject) ResourceSet(org.eclipse.emf.ecore.resource.ResourceSet) List(java.util.List) Provider(com.google.inject.Provider) JavaIoFileSystemAccess(org.eclipse.xtext.generator.JavaIoFileSystemAccess) Issue(org.eclipse.xtext.validation.Issue) CancelIndicator(org.eclipse.xtext.util.CancelIndicator) Resource(org.eclipse.emf.ecore.resource.Resource) Path(java.nio.file.Path) FileConfig(org.lflang.FileConfig) Mode(org.lflang.generator.LFGeneratorContext.Mode) CheckMode(org.eclipse.xtext.validation.CheckMode) ErrorReporter(org.lflang.ErrorReporter) EObject(org.eclipse.emf.ecore.EObject)

Example 4 with FileConfig

use of org.lflang.FileConfig in project lingua-franca by lf-lang.

the class TestBase method configure.

/**
 * Configure a test by applying the given configurator and return a
 * generator context. Also, if the given level is less than
 * `TestLevel.BUILD`, add a `no-compile` flag to the generator context. If
 * the configurator was not applied successfully, throw an AssertionError.
 *
 * @param test the test to configure.
 * @param configurator The configurator to apply to the test.
 * @param level The level of testing in which the generator context will be
 * used.
 * @return a generator context with a fresh resource, unaffected by any AST
 * transformation that may have occured in other tests.
 * @throws IOException if there is any file access problem
 */
private LFGeneratorContext configure(LFTest test, Configurator configurator, TestLevel level) throws IOException {
    var context = new MainContext(LFGeneratorContext.Mode.STANDALONE, CancelIndicator.NullImpl, (m, p) -> {
    }, new Properties(), true, fileConfig -> new DefaultErrorReporter());
    var r = resourceSetProvider.get().getResource(URI.createFileURI(test.srcFile.toFile().getAbsolutePath()), true);
    if (r.getErrors().size() > 0) {
        test.result = Result.PARSE_FAIL;
        throw new AssertionError("Test did not parse correctly.");
    }
    fileAccess.setOutputPath(FileConfig.findPackageRoot(test.srcFile, s -> {
    }).resolve(FileConfig.DEFAULT_SRC_GEN_DIR).toString());
    test.context = context;
    test.fileConfig = new FileConfig(r, FileConfig.getSrcGenRoot(fileAccess), context.useHierarchicalBin());
    // Set the no-compile flag the test is not supposed to reach the build stage.
    if (level.compareTo(TestLevel.BUILD) < 0) {
        context.getArgs().setProperty("no-compile", "");
    }
    addExtraLfcArgs(context.getArgs());
    // Update the test by applying the configuration. E.g., to carry out an AST transformation.
    if (configurator != null && !configurator.configure(test)) {
        test.result = Result.CONFIG_FAIL;
        throw new AssertionError("Test configuration unsuccessful.");
    }
    return context;
}
Also used : Arrays(java.util.Arrays) Inject(com.google.inject.Inject) LFGeneratorContext(org.lflang.generator.LFGeneratorContext) InjectionExtension(org.eclipse.xtext.testing.extensions.InjectionExtension) Result(org.lflang.tests.LFTest.Result) GeneratorResult(org.lflang.generator.GeneratorResult) Assertions.assertFalse(org.junit.jupiter.api.Assertions.assertFalse) ExtendWith(org.junit.jupiter.api.extension.ExtendWith) Map(java.util.Map) Path(java.nio.file.Path) PrintWriter(java.io.PrintWriter) Predicate(java.util.function.Predicate) TestCategory(org.lflang.tests.TestRegistry.TestCategory) Set(java.util.Set) LFCommand(org.lflang.util.LFCommand) Collectors(java.util.stream.Collectors) InvocationTargetException(java.lang.reflect.InvocationTargetException) Objects(java.util.Objects) List(java.util.List) Target(org.lflang.Target) LFStandaloneSetup(org.lflang.LFStandaloneSetup) FileConfig(org.lflang.FileConfig) IGeneratorContext(org.eclipse.xtext.generator.IGeneratorContext) CheckMode(org.eclipse.xtext.validation.CheckMode) URI(org.eclipse.emf.common.util.URI) HashMap(java.util.HashMap) Configurator(org.lflang.tests.Configurators.Configurator) Constructor(java.lang.reflect.Constructor) ResourceSet(org.eclipse.emf.ecore.resource.ResourceSet) ArrayList(java.util.ArrayList) JavaIoFileSystemAccess(org.eclipse.xtext.generator.JavaIoFileSystemAccess) RuntimeIOException(org.eclipse.xtext.util.RuntimeIOException) CancelIndicator(org.eclipse.xtext.util.CancelIndicator) LFGenerator(org.lflang.generator.LFGenerator) PrintStream(java.io.PrintStream) Properties(java.util.Properties) LFRuntimeModule(org.lflang.LFRuntimeModule) BufferedWriter(java.io.BufferedWriter) Severity(org.eclipse.xtext.diagnostics.Severity) StringWriter(java.io.StringWriter) FileWriter(java.io.FileWriter) DefaultErrorReporter(org.lflang.DefaultErrorReporter) IResourceValidator(org.eclipse.xtext.validation.IResourceValidator) MainContext(org.lflang.generator.MainContext) IOException(java.io.IOException) File(java.io.File) Assertions.assertSame(org.junit.jupiter.api.Assertions.assertSame) TimeUnit(java.util.concurrent.TimeUnit) Injector(com.google.inject.Injector) Provider(com.google.inject.Provider) FileFilter(java.io.FileFilter) InjectWith(org.eclipse.xtext.testing.InjectWith) Collections(java.util.Collections) DefaultErrorReporter(org.lflang.DefaultErrorReporter) FileConfig(org.lflang.FileConfig) MainContext(org.lflang.generator.MainContext) Properties(java.util.Properties)

Example 5 with FileConfig

use of org.lflang.FileConfig in project lingua-franca by lf-lang.

the class GeneratorUtils method getLFResource.

/**
 * Return the {@code LFResource} representation of the
 * given resource.
 * @param resource The {@code Resource} to be
 *                 represented as an {@code LFResource}
 * @param srcGenBasePath The root directory for any
 * generated sources associated with the resource.
 * @param context The generator invocation context.
 * @param errorReporter An error message acceptor.
 * @return the {@code LFResource} representation of the
 * given resource.
 */
public static LFResource getLFResource(Resource resource, Path srcGenBasePath, LFGeneratorContext context, ErrorReporter errorReporter) {
    TargetDecl target = GeneratorUtils.findTarget(resource);
    KeyValuePairs config = target.getConfig();
    var targetConfig = new TargetConfig();
    if (config != null) {
        List<KeyValuePair> pairs = config.getPairs();
        TargetProperty.set(targetConfig, pairs != null ? pairs : List.of(), errorReporter);
    }
    try {
        FileConfig fc = new FileConfig(resource, srcGenBasePath, context.useHierarchicalBin());
        return new LFResource(resource, fc, targetConfig);
    } catch (IOException e) {
        throw new RuntimeException("Failed to instantiate an imported resource because an I/O error " + "occurred.");
    }
}
Also used : TargetDecl(org.lflang.lf.TargetDecl) FileConfig(org.lflang.FileConfig) KeyValuePair(org.lflang.lf.KeyValuePair) KeyValuePairs(org.lflang.lf.KeyValuePairs) IOException(java.io.IOException) TargetConfig(org.lflang.TargetConfig)

Aggregations

FileConfig (org.lflang.FileConfig)6 IOException (java.io.IOException)5 Path (java.nio.file.Path)4 List (java.util.List)3 CancelIndicator (org.eclipse.xtext.util.CancelIndicator)3 ErrorReporter (org.lflang.ErrorReporter)3 Inject (com.google.inject.Inject)2 Provider (com.google.inject.Provider)2 File (java.io.File)2 ArrayList (java.util.ArrayList)2 HashMap (java.util.HashMap)2 Map (java.util.Map)2 Properties (java.util.Properties)2 Set (java.util.Set)2 Collectors (java.util.stream.Collectors)2 URI (org.eclipse.emf.common.util.URI)2 EObject (org.eclipse.emf.ecore.EObject)2 Resource (org.eclipse.emf.ecore.resource.Resource)2 ResourceSet (org.eclipse.emf.ecore.resource.ResourceSet)2 Severity (org.eclipse.xtext.diagnostics.Severity)2