Gather diagnostics from annotations (#8380)

close #8289

Changelog
- feat: `GatherDiagnostics` compiler pass works with annotations
This commit is contained in:
Dmitry Bushev 2023-11-23 17:18:39 +00:00 committed by GitHub
parent ce584862ff
commit f1825f3f32
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 55 additions and 12 deletions

View File

@ -12,7 +12,7 @@ import org.enso.compiler.core.ir.{
import org.enso.compiler.core.ir.module.scope.definition
import org.enso.compiler.core.ir.MetadataStorage._
import org.enso.compiler.pass.IRPass
import org.enso.compiler.pass.resolve.TypeSignatures
import org.enso.compiler.pass.resolve.{GenericAnnotations, TypeSignatures}
/** A pass that traverses the given root IR and accumulates all the encountered
* diagnostic nodes in the root.
@ -69,25 +69,23 @@ case object GatherDiagnostics extends IRPass {
val typeSignatureDiagnostics =
arg
.getMetadata(TypeSignatures)
.map(_.signature.preorder.collect { case err: Diagnostic =>
err
})
.map(_.signature.preorder.collect(collectDiagnostics))
.getOrElse(Nil)
typeSignatureDiagnostics ++ arg.diagnostics.toList
case x: definition.Method =>
val typeSignatureDiagnostics =
x.getMetadata(TypeSignatures)
.map(_.signature.preorder.collect { case err: Diagnostic =>
err
})
.map(_.signature.preorder.collect(collectDiagnostics))
.getOrElse(Nil)
typeSignatureDiagnostics ++ x.diagnostics.toList
val annotationsDiagnostics =
x.getMetadata(GenericAnnotations)
.map(_.annotations.flatMap(_.preorder.collect(collectDiagnostics)))
.getOrElse(Nil)
typeSignatureDiagnostics ++ annotationsDiagnostics ++ x.diagnostics.toList
case x: Expression =>
val typeSignatureDiagnostics =
x.getMetadata(TypeSignatures)
.map(_.signature.preorder.collect { case err: Diagnostic =>
err
})
.map(_.signature.preorder.collect(collectDiagnostics))
.getOrElse(Nil)
typeSignatureDiagnostics ++ x.diagnostics.toList
case x =>
@ -98,6 +96,10 @@ case object GatherDiagnostics extends IRPass {
)
}
private val collectDiagnostics: PartialFunction[IR, Diagnostic] = {
case err: Diagnostic => err
}
final private class DiagnosticKeys(private val diagnostic: Diagnostic) {
/** Equals is based on type of diagnostic, its location and its diagnostic keys.
@ -119,7 +121,8 @@ case object GatherDiagnostics extends IRPass {
for (k <- diagnostic.diagnosticKeys()) {
sum += k.hashCode
}
return sum
sum
}
}

View File

@ -428,6 +428,24 @@ public class ErrorCompilerTest extends CompilerTest {
assertEquals(errors.head().location().get().length(), 6);
}
@Test
public void testAnnotation1() throws Exception {
var ir = parse("""
@x `
id x = x
""");
assertSingleSyntaxError(ir, Syntax.UnexpectedExpression$.MODULE$, "Unexpected expression", 3, 4);
}
@Test
public void testAnnotation2() throws Exception {
var ir = parse("""
@` foo
id x = x
""");
assertSingleSyntaxError(ir, Syntax.UnexpectedExpression$.MODULE$, "Unexpected expression", 0, 6);
}
private void assertSingleSyntaxError(
Module ir, Syntax.Reason type,
String msg, int start, int end

View File

@ -109,6 +109,28 @@ class GatherDiagnosticsTest extends CompilerTest {
gatheredErrros.toSet shouldEqual Set(error1, error2, error3)
}
"work with annotations" in {
implicit val passManager: PassManager =
new Passes(defaultConfig).passManager
implicit val moduleContext: ModuleContext =
buildModuleContext(freshNameSupply = Some(new FreshNameSupply))
val ir =
"""@x bar
|foo x = x
|""".stripMargin.preprocessModule
val result = GatherDiagnostics.runModule(ir, moduleContext)
val diagnostics = result
.unsafeGetMetadata(GatherDiagnostics, "Impossible")
.diagnostics
diagnostics should have size 1
diagnostics.map(_.message(null)) should contain theSameElementsAs Seq(
"The name `bar` could not be found"
)
}
"avoid duplication" in {
implicit val passManager: PassManager =
new Passes(defaultConfig).passManager