metaborg / spoofax-pie

Spoofax implementation using PIE pipelines
Apache License 2.0
12 stars 9 forks source link

Exception when editing during startup in Eclipse LWB #59

Open Gohla opened 3 years ago

Gohla commented 3 years ago

Summary

An exception occurs when editing (and thus running an editor update job) during startup in Eclipse LWB.

What you did

Edit during startup.

What you expected to happen

No exception to be thrown.

What actually happened

The following exception was thrown:

!ENTRY org.eclipse.core.jobs 4 2 2021-09-17 11:40:24.455
!MESSAGE An internal error occurred during: "SDF3 editor update".
!STACK 0
java.lang.IllegalArgumentException: Attempted to beginRule: P/chocopy.reference, does not match outer scope rule: MultiRule[P/test,Startup read lock]
    at org.eclipse.core.runtime.Assert.isLegal(Assert.java:66)
    at org.eclipse.core.internal.jobs.ThreadJob.illegalPush(ThreadJob.java:137)
    at org.eclipse.core.internal.jobs.ThreadJob.push(ThreadJob.java:392)
    at org.eclipse.core.internal.jobs.ImplicitJobs.begin(ImplicitJobs.java:88)
    at org.eclipse.core.internal.jobs.JobManager.beginRule(JobManager.java:299)
    at org.eclipse.core.internal.resources.WorkManager.checkIn(WorkManager.java:124)
    at org.eclipse.core.internal.resources.Workspace.prepareOperation(Workspace.java:2242)
    at org.eclipse.core.internal.resources.Resource.refreshLocal(Resource.java:1554)
    at mb.spoofax.eclipse.resource.EclipseResource.walk(EclipseResource.java:380)
    at mb.pie.api.stamp.resource.Modified.modifiedDirRec(Modified.java:70)
    at mb.pie.api.stamp.resource.Modified.modifiedRec(Modified.java:39)
    at mb.pie.api.stamp.resource.ModifiedWalkResourceStamper.stamp(ModifiedWalkResourceStamper.java:27)
    at mb.pie.api.stamp.resource.ModifiedWalkResourceStamper.stamp(ModifiedWalkResourceStamper.java:12)
    at mb.pie.runtime.exec.ExecContextImpl.require(ExecContextImpl.java:162)
    at mb.pie.api.ExecContext.require(ExecContext.java:351)
    at mb.sdf3.task.spec.Sdf3CheckSpec.exec(Sdf3CheckSpec.java:70)
    at mb.sdf3.task.spec.Sdf3CheckSpec.exec(Sdf3CheckSpec.java:38)
    at mb.pie.api.Task.exec(Task.java:56)
    at mb.pie.runtime.exec.TaskExecutor.execInternal(TaskExecutor.java:126)
    at mb.pie.runtime.exec.TaskExecutor.exec(TaskExecutor.java:82)
    at mb.pie.runtime.exec.BottomUpRunner.exec(BottomUpRunner.java:369)
    at mb.pie.runtime.exec.BottomUpRunner.execAndSchedule(BottomUpRunner.java:133)
    at mb.pie.runtime.exec.BottomUpRunner.execScheduled(BottomUpRunner.java:120)
    at mb.pie.runtime.exec.BottomUpRunner.requireInitial(BottomUpRunner.java:83)
    at mb.pie.runtime.MixedSessionImpl.lambda$updateAffectedBy$0(MixedSessionImpl.java:59)
    at mb.pie.runtime.SessionImpl.handleException(SessionImpl.java:161)
    at mb.pie.runtime.MixedSessionImpl.updateAffectedBy(MixedSessionImpl.java:59)
    at mb.spoofax.eclipse.pie.PieRunner.updateAffectedBy(PieRunner.java:458)
    at mb.spoofax.eclipse.pie.PieRunner.addOrUpdateEditor(PieRunner.java:132)
    at mb.spoofax.eclipse.editor.EditorUpdateJob.update(EditorUpdateJob.java:89)
    at mb.spoofax.eclipse.editor.EditorUpdateJob.run(EditorUpdateJob.java:74)
    at org.eclipse.core.internal.jobs.Worker.run(Worker.java:63)

Context

Additional information

Console log can be found here: https://gist.github.com/Gohla/52d67ec582d3dd902520a475df8afe00

Virtlink commented 1 year ago

This bug also happens when I try to run a command on a resource in the Eclipse LWB.

Command definition (in spoofaxc.cfg):

let inlineMethodTaskDef = task-def mb.tiger.task.TigerInlineMethodCallTaskDef
let inlineMethodCommand = command-def {
  task-def = inlineMethodTaskDef
  type = java mb.tiger.command.TigerInlineMethodCallCommand
  display-name = "Inline method call"
  description = "Inline a method call."
  parameters = [
    resource {
      type = java mb.resource.ResourceKey
      required = true
      argument-providers = [ Context(ReadableResource) ]
    }
    region {
      type = java mb.common.region.Region
      required = false
      argument-providers = [ Context(Region) ]
    }
  ]
}
editor-context-menu [
  menu "Debug" [
    command-action {
      command-def = inlineMethodCommand
      execution-type = Once
    }
  ]
]

resource-context-menu [
  menu "Debug" [
    command-action {
      command-def = inlineMethodCommand
      execution-type = Once
      required-resource-types = [File]
    }
  ]
]

Stack trace:

14:18:44.995 | INFO  | Worker-39: Inline method call                      | mb.pie.runtime.tracer.LoggingTracer                | ← [4.460319] exception: java.lang.IllegalArgumentException: Attempted to beginRule: F/tiger.spoofax3/build/generated/resources/metalang/mb/tiger/src-gen, does not match outer scope rule: MultiRule[L/tiger.spoofax3/test/simple-fact.tig,F/tiger.spoofax3/test]
java.lang.IllegalArgumentException: Attempted to beginRule: F/tiger.spoofax3/build/generated/resources/metalang/mb/tiger/src-gen, does not match outer scope rule: MultiRule[L/tiger.spoofax3/test/simple-fact.tig,F/tiger.spoofax3/test]
    at org.eclipse.core.runtime.Assert.isLegal(Assert.java:66)
    at org.eclipse.core.internal.jobs.ThreadJob.illegalPush(ThreadJob.java:137)
    at org.eclipse.core.internal.jobs.ThreadJob.push(ThreadJob.java:392)
    at org.eclipse.core.internal.jobs.ImplicitJobs.begin(ImplicitJobs.java:88)
    at org.eclipse.core.internal.jobs.JobManager.beginRule(JobManager.java:299)
    at org.eclipse.core.internal.resources.WorkManager.checkIn(WorkManager.java:124)
    at org.eclipse.core.internal.resources.Workspace.prepareOperation(Workspace.java:2242)
    at org.eclipse.core.internal.resources.Resource.refreshLocal(Resource.java:1554)
    at mb.spoofax.eclipse.resource.EclipseResource.walk(EclipseResource.java:381)
    at mb.resource.hierarchical.HierarchicalResource.walkForEach(HierarchicalResource.java:381)
    at mb.resource.hierarchical.HierarchicalResource.walkForEach(HierarchicalResource.java:375)
    at mb.tiger.task.TigerAnalyze.lambda$analyze$1(%2Ftiger.spoofax3%2Fbuild%2Fgenerated%2Fsources%2Fadapter%2Fmb%2Ftiger%2Ftask%2FTigerAnalyze.java:52)
    at mb.spoofax.resource.ClassLoaderResources.performWithDefinitionResourceLocationsTryAsNative(ClassLoaderResources.java:122)
    at mb.tiger.task.TigerAnalyze.analyze(%2Ftiger.spoofax3%2Fbuild%2Fgenerated%2Fsources%2Fadapter%2Fmb%2Ftiger%2Ftask%2FTigerAnalyze.java:50)
    at mb.constraint.pie.ConstraintAnalyzeTaskDef.lambda$exec$0(ConstraintAnalyzeTaskDef.java:75)
    at mb.common.result.Result.lambda$mapCatchingOrRethrow$4(Result.java:332)
    at mb.common.result.ResultUtil.tryCatchOrRethrow(ResultUtil.java:39)
    at mb.common.result.Result.mapCatchingOrRethrow(Result.java:332)
    at mb.constraint.pie.ConstraintAnalyzeTaskDef.exec(ConstraintAnalyzeTaskDef.java:73)
    at mb.constraint.pie.ConstraintAnalyzeTaskDef.exec(ConstraintAnalyzeTaskDef.java:17)
    at mb.pie.api.Task.exec(Task.java:56)
    at mb.pie.runtime.exec.TaskExecutor.execInternal(TaskExecutor.java:130)
    at mb.pie.runtime.exec.TaskExecutor.exec(TaskExecutor.java:87)
    at mb.pie.runtime.exec.TopDownRunner.exec(TopDownRunner.java:194)
    at mb.pie.runtime.exec.TopDownRunner.executeOrGetExisting(TopDownRunner.java:139)
    at mb.pie.runtime.exec.TopDownRunner.require(TopDownRunner.java:81)
    at mb.pie.runtime.exec.ExecContextImpl.require(ExecContextImpl.java:118)
    at mb.pie.runtime.exec.ExecContextImpl.require(ExecContextImpl.java:141)
    at mb.pie.api.STask.get(STask.java:61)
    at mb.pie.runtime.exec.ExecContextImpl.require(ExecContextImpl.java:151)
    at mb.statix.referenceretention.pie.InlineMethodCallTaskDef.exec(InlineMethodCallTaskDef.java:113)
    at mb.tiger.task.TigerInlineMethodCallTaskDef.exec(%2Ftiger.spoofax3%2Fsrc%2Fmain%2Fjava%2Fmb%2Ftiger%2Ftask%2FTigerInlineMethodCallTaskDef.java:46)
    at mb.tiger.task.TigerInlineMethodCallTaskDef.exec(%2Ftiger.spoofax3%2Fsrc%2Fmain%2Fjava%2Fmb%2Ftiger%2Ftask%2FTigerInlineMethodCallTaskDef.java:16)
    at mb.pie.api.Task.exec(Task.java:56)
    at mb.pie.runtime.exec.TaskExecutor.execInternal(TaskExecutor.java:130)
    at mb.pie.runtime.exec.TaskExecutor.exec(TaskExecutor.java:87)
    at mb.pie.runtime.exec.TopDownRunner.exec(TopDownRunner.java:194)
    at mb.pie.runtime.exec.TopDownRunner.executeOrGetExisting(TopDownRunner.java:139)
    at mb.pie.runtime.exec.TopDownRunner.require(TopDownRunner.java:81)
    at mb.pie.runtime.exec.TopDownRunner.requireInitial(TopDownRunner.java:59)
    at mb.pie.runtime.MixedSessionImpl.lambda$requireWithoutObserving$2(MixedSessionImpl.java:110)
    at mb.pie.runtime.SessionImpl.handleException(SessionImpl.java:221)
    at mb.pie.runtime.MixedSessionImpl.requireWithoutObserving(MixedSessionImpl.java:110)
    at mb.spoofax.eclipse.pie.PieRunner.requireWithoutObserving(PieRunner.java:494)
    at mb.spoofax.eclipse.pie.PieRunner.requireCommand(PieRunner.java:322)
    at mb.spoofax.eclipse.command.RunCommandJob.run(RunCommandJob.java:67)
    at org.eclipse.core.internal.jobs.Worker.run(Worker.java:63)
Virtlink commented 1 year ago

The cause seems to be that the IContainer retrieved in the code is different from the one Eclipse expects. Spoofax uses a similar approach to EGit, and they fixed the same issue at some point. EGit Diff

Gohla commented 1 year ago

I think this is a different kind of bug with a similar error message, as the one of this bug report only happens on startup.

I don't think it has anything to do with a different kind of IContainer object. The problem is that when a language is dynamically loaded, using parts of that language sometimes requires reading files from its build directory, and when Eclipse is not made aware of this dependency (called scheduling rules), these kinds of errors are thrown.

In your case, executing a command of tiger.spoofax3 requires constraint analysis, which in turn requires reading constraint analyzer aterm files from the tiger.spoofax3/build/generated/resources/metalang/mb/tiger/src-gen directory. Eclipse is not made aware of this dependency, so an error is triggered.

To work around the problem, you can make your command depend on the project as an enclosing project by adding several things to spoofaxc.cfg.

  1. Add a project parameter to your command-def:
    project {
      type = java mb.resource.hierarchical.ResourcePath
      argument-providers = [EnclosingContext(Project)]
    }
  1. Add required-enclosing-resource-types = [Project] to all command-action menu items of your command.
  2. Add public final ResourcePath project to your Args class, accept it in the constructor, and update equals/hashCode/toString.

A proper solution would be to add the correct scheduling rules when a language is dynamically loaded, to: