From ab2da9e43691b9797bbfdcc8b9677099fab30ef9 Mon Sep 17 00:00:00 2001 From: Hubert Plociniczak Date: Wed, 18 Oct 2023 23:51:58 +0200 Subject: [PATCH] Ambiguous imports warnings/errors are serializable (#8093) `AmbgiuousImport` error and `DuplicatedImport` warning must not have `Source` as one of its fields or compiler will crash during a serialization attempt. Changed the implementation to provide it as a parameter to the `message` method instead. Fixes #8089 --- .../instrument/job/EnsureCompiledJob.scala | 5 +- .../enso/compiler/core/ir/Diagnostic.scala | 13 ++-- .../org/enso/compiler/core/ir/Empty.scala | 3 +- .../org/enso/compiler/core/ir/Warning.scala | 15 ++--- .../compiler/core/ir/expression/Error.scala | 3 +- .../ir/expression/errors/Conversion.scala | 3 +- .../ir/expression/errors/ImportExport.scala | 35 +++++----- .../core/ir/expression/errors/Pattern.scala | 3 +- .../core/ir/expression/errors/Redefined.scala | 13 ++-- .../ir/expression/errors/Resolution.scala | 5 +- .../core/ir/expression/errors/Syntax.scala | 5 +- .../ir/expression/errors/Unexpected.scala | 3 +- .../ir/expression/warnings/Shadowed.scala | 9 +-- .../ir/expression/warnings/Unreachable.scala | 5 +- .../core/ir/expression/warnings/Unused.scala | 11 ++- .../scala/org/enso/compiler/Compiler.scala | 6 +- .../enso/compiler/codegen/IrToTruffle.scala | 20 +++--- .../analyse/AmbiguousImportsAnalysis.scala | 19 +----- .../org/enso/compiler/ErrorCompilerTest.java | 2 +- .../pass/analyse/GatherDiagnosticsTest.scala | 4 +- .../test/semantic/ImportExportTest.scala | 67 ++++++++++++++++++- 21 files changed, 160 insertions(+), 89 deletions(-) diff --git a/engine/runtime-instrument-common/src/main/scala/org/enso/interpreter/instrument/job/EnsureCompiledJob.scala b/engine/runtime-instrument-common/src/main/scala/org/enso/interpreter/instrument/job/EnsureCompiledJob.scala index 295fc346f733..0fdc4bece24b 100644 --- a/engine/runtime-instrument-common/src/main/scala/org/enso/interpreter/instrument/job/EnsureCompiledJob.scala +++ b/engine/runtime-instrument-common/src/main/scala/org/enso/interpreter/instrument/job/EnsureCompiledJob.scala @@ -199,14 +199,15 @@ final class EnsureCompiledJob( module: Module, diagnostic: Diagnostic ): Api.ExecutionResult.Diagnostic = { + val source = module.getSource Api.ExecutionResult.Diagnostic( kind, - Option(diagnostic.formattedMessage), + Option(diagnostic.formattedMessage(source)), Option(module.getPath).map(new File(_)), diagnostic.location .map(loc => LocationResolver - .locationToRange(loc.location, module.getSource.getCharacters) + .locationToRange(loc.location, source.getCharacters) ), diagnostic.location .flatMap(LocationResolver.getExpressionId(module.getIr, _)) diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Diagnostic.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Diagnostic.scala index a55f2852d053..ad3f08eab7c3 100644 --- a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Diagnostic.scala +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Diagnostic.scala @@ -1,14 +1,19 @@ package org.enso.compiler.core.ir +import com.oracle.truffle.api.source.Source + /** A representation of various kinds of diagnostic in the IR. */ trait Diagnostic extends Serializable { - /** @return a human-readable description of this error condition. + /** @param source Location of the diagnostic. + * @return a human-readable description of this error condition. */ - def message: String + def message(source: Source): String - /** @return a human-readable description of this error condition, formatted for immediate reporting. */ - def formattedMessage: String = message + /** @param source Location of the diagnostic. + * @return a human-readable description of this error condition, formatted for immediate reporting. + */ + def formattedMessage(source: Source): String = message(source) /** The location at which the diagnostic occurs. */ val location: Option[IdentifiedLocation] diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Empty.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Empty.scala index db4e1d9babd3..0f922b12f4c8 100644 --- a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Empty.scala +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Empty.scala @@ -1,5 +1,6 @@ package org.enso.compiler.core.ir +import com.oracle.truffle.api.source.Source import org.enso.compiler.core.IR import org.enso.compiler.core.IR.{randomId, ToStringHelper} @@ -75,7 +76,7 @@ sealed case class Empty( override def children: List[IR] = List() /** @inheritdoc */ - override def message: String = + override def message(source: Source): String = "Empty IR: Please report this as a compiler bug." /** @inheritdoc */ diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Warning.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Warning.scala index 60738bd86ec3..40380c4068ff 100644 --- a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Warning.scala +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Warning.scala @@ -12,10 +12,9 @@ object Warning { case class DuplicatedImport( override val location: Option[IdentifiedLocation], originalImport: ir.module.scope.Import, - symbolName: String, - source: Source + symbolName: String ) extends Warning { - override def message: String = { + override def message(source: Source): String = { val originalImportRepr = originalImport.location match { case Some(location) => @@ -35,7 +34,7 @@ object Warning { */ case class WrongTco(override val location: Option[IdentifiedLocation]) extends Warning { - override def message: String = + override def message(source: Source): String = "A @Tail_Call annotation was placed in a non-tail-call position." override def diagnosticKeys(): Array[Any] = Array() @@ -49,7 +48,7 @@ object Warning { case class WrongBuiltinMethod( override val location: Option[IdentifiedLocation] ) extends Warning { - override def message: String = + override def message(source: Source): String = "A @Builtin_Method annotation allows only the name of the builtin node in the body." override def diagnosticKeys(): Array[Any] = Array() @@ -68,7 +67,7 @@ object Warning { ) extends Warning { override val location: Option[IdentifiedLocation] = ir.location - override def message: String = + override def message(source: Source): String = s"${funName.name}: Self parameter should be declared as the first parameter. Instead its position is: ${paramPosition + 1}." override def diagnosticKeys(): Array[Any] = @@ -87,7 +86,7 @@ object Warning { ) extends Warning { override val location: Option[IdentifiedLocation] = ir.location - override def message: String = + override def message(source: Source): String = s"The expression ${ir.showCode()} could not be parallelised: $reason." override def diagnosticKeys(): Array[Any] = Array(ir.showCode(), reason) @@ -98,7 +97,7 @@ object Warning { /** @return a human-readable description of this error condition. */ - override def message: String = + override def message(source: Source): String = s"A non-unit type ${ir.name} is used on value level (in ${context})." + " This is probably an error." diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/Error.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/Error.scala index 71fece0e7458..a4f61982495c 100644 --- a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/Error.scala +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/Error.scala @@ -1,6 +1,7 @@ package org.enso.compiler.core.ir package expression +import com.oracle.truffle.api.source.Source import org.enso.compiler.core.IR.{randomId, Identifier, ToStringHelper} import org.enso.compiler.core.ir.Expression import org.enso.compiler.core.{ir, IR} @@ -107,7 +108,7 @@ object Error { override def children: List[IR] = List(ir) /** @inheritdoc */ - override def message: String = + override def message(source: Source): String = "InvalidIR: Please report this as a compiler bug." override def diagnosticKeys(): Array[Any] = Array() diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Conversion.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Conversion.scala index 4852679f08d2..15dc1a9da493 100644 --- a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Conversion.scala +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Conversion.scala @@ -2,6 +2,7 @@ package org.enso.compiler.core.ir package expression package errors +import com.oracle.truffle.api.source.Source import org.enso.compiler.core.IR import org.enso.compiler.core.IR.{randomId, Identifier} @@ -85,7 +86,7 @@ sealed case class Conversion( s"(Error: ${storedIr.showCode(indent)})" /** @inheritdoc */ - override def message: String = reason.explain + override def message(source: Source): String = reason.explain override def diagnosticKeys(): Array[Any] = Array(reason.explain) diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/ImportExport.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/ImportExport.scala index 9039ae7883cd..2978a52e230a 100644 --- a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/ImportExport.scala +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/ImportExport.scala @@ -97,7 +97,7 @@ sealed case class ImportExport( override def children: List[IR] = List(ir) /** @inheritdoc */ - override def message: String = reason.message + override def message(source: Source): String = reason.message(source) override def diagnosticKeys(): Array[Any] = Array(reason) @@ -111,9 +111,10 @@ object ImportExport { */ sealed trait Reason { - /** @return A human-readable description of the error. + /** @param source Location of the original import/export IR. + * @return A human-readable description of the error. */ - def message: String + def message(source: Source): String } /** Used when the `project` keyword is used in an impossible position. @@ -123,7 +124,7 @@ object ImportExport { */ case class ProjectKeywordUsedButNotInProject(statementType: String) extends Reason { - override def message: String = + override def message(source: Source): String = s"The `project` keyword was used in an $statementType statement," + " but the module does not belong to a project." } @@ -135,7 +136,8 @@ object ImportExport { */ case class PackageCouldNotBeLoaded(name: String, reason: String) extends Reason { - override def message: String = s"Package containing the module $name" + + override def message(source: Source): String = + s"Package containing the module $name" + s" could not be loaded: $reason" } @@ -144,14 +146,15 @@ object ImportExport { * @param name the module name. */ case class ModuleDoesNotExist(name: String) extends Reason { - override def message: String = s"The module $name does not exist." + override def message(source: Source): String = + s"The module $name does not exist." } case class TypeDoesNotExist( typeName: String, moduleName: String ) extends Reason { - override def message: String = + override def message(source: Source): String = s"The type $typeName does not exist in module $moduleName" } @@ -159,7 +162,7 @@ object ImportExport { symbolName: String, moduleOrTypeName: String ) extends Reason { - override def message: String = + override def message(source: Source): String = s"The symbol $symbolName (module, type, or constructor) does not exist in $moduleOrTypeName." } @@ -167,28 +170,28 @@ object ImportExport { typeName: String, constructorName: String ) extends Reason { - override def message: String = + override def message(source: Source): String = s"No such constructor ${constructorName} in type $typeName" } case class ExportSymbolsFromPrivateModule( moduleName: String ) extends Reason { - override def message: String = + override def message(source: Source): String = s"Cannot export any symbol from module '$moduleName': The module is private" } case class ExportPrivateModule( moduleName: String ) extends Reason { - override def message: String = + override def message(source: Source): String = s"Cannot export private module '$moduleName'" } case class ImportPrivateModule( moduleName: String ) extends Reason { - override def message: String = + override def message(source: Source): String = s"Cannot import private module '$moduleName'" } @@ -198,7 +201,7 @@ object ImportExport { moduleVisibility: String, submoduleVisibility: String ) extends Reason { - override def message: String = + override def message(source: Source): String = s"Cannot export submodule '$submoduleName' of module '$moduleName': " + s"the submodule is $submoduleVisibility, but the module is $moduleVisibility" } @@ -210,16 +213,14 @@ object ImportExport { * @param originalSymbolPath the original symbol path. * @param symbolName the symbol name that is ambiguous. * @param symbolPath the symbol path that is different than [[originalSymbolPath]]. - * @param source Location of the original import. */ case class AmbiguousImport( originalImport: module.scope.Import, originalSymbolPath: String, symbolName: String, - symbolPath: String, - source: Source + symbolPath: String ) extends Reason { - override def message: String = { + override def message(source: Source): String = { val originalImportRepr = originalImport.location match { case Some(location) => diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Pattern.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Pattern.scala index a70113d28f7b..147802addfbc 100644 --- a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Pattern.scala +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Pattern.scala @@ -2,6 +2,7 @@ package org.enso.compiler.core.ir package expression package errors +import com.oracle.truffle.api.source.Source import org.enso.compiler.core.IR import org.enso.compiler.core.IR.{randomId, Identifier} @@ -69,7 +70,7 @@ sealed case class Pattern( id = if (keepIdentifiers) id else randomId ) - override def message: String = reason.explain + override def message(source: Source): String = reason.explain override def diagnosticKeys(): Array[Any] = Array(reason) diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Redefined.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Redefined.scala index dd25ae7c4089..066711d86b2f 100644 --- a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Redefined.scala +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Redefined.scala @@ -2,6 +2,7 @@ package org.enso.compiler.core.ir package expression package errors +import com.oracle.truffle.api.source.Source import org.enso.compiler.core.IR import org.enso.compiler.core.IR.{randomId, Identifier} @@ -87,7 +88,7 @@ object Redefined { this /** @inheritdoc */ - override def message: String = + override def message(source: Source): String = "Methods must have only one definition of the `this` argument, and " + "it must be the first." @@ -186,7 +187,7 @@ object Redefined { copy(location = location) /** @inheritdoc */ - override def message: String = + override def message(source: Source): String = s"Method overloads are not supported: ${targetType.map(_.name + ".").getOrElse("")}from " + s"${sourceType.showCode()} is defined multiple times in this module." @@ -305,7 +306,7 @@ object Redefined { copy(location = location) /** @inheritdoc */ - override def message: String = + override def message(source: Source): String = s"Method overloads are not supported: ${atomName.map(_.name + ".").getOrElse("")}" + s"${methodName.name} is defined multiple times in this module." @@ -431,7 +432,7 @@ object Redefined { copy(location = location) /** @inheritdoc */ - override def message: String = + override def message(source: Source): String = s"Method definitions with the same name as atoms are not supported. " + s"Method ${methodName.name} clashes with the atom ${atomName.name} in this module." @@ -534,7 +535,7 @@ object Redefined { copy(location = location) /** @inheritdoc */ - override def message: String = + override def message(source: Source): String = s"Redefining atoms is not supported: ${typeName.name} is " + s"defined multiple times in this module." @@ -650,7 +651,7 @@ object Redefined { override def children: List[IR] = List(invalidBinding) /** @inheritdoc */ - override def message: String = + override def message(source: Source): String = s"Variable ${invalidBinding.name.name} is being redefined." override def diagnosticKeys(): Array[Any] = Array( diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Resolution.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Resolution.scala index 6f73ab864aef..0793ca743a54 100644 --- a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Resolution.scala +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Resolution.scala @@ -2,6 +2,7 @@ package org.enso.compiler.core.ir package expression package errors +import com.oracle.truffle.api.source.Source import org.enso.compiler.core.IR import org.enso.compiler.core.IR.{randomId, Identifier} @@ -83,10 +84,10 @@ sealed case class Resolution( override def showCode(indent: Int): String = originalName.showCode(indent) /** @inheritdoc */ - override def message: String = reason.explain(originalName) + override def message(source: Source): String = reason.explain(originalName) /** @inheritdoc */ - override def formattedMessage: String = s"${message}." + override def formattedMessage(source: Source): String = s"${message(source)}." override def diagnosticKeys(): Array[Any] = Array(reason) diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Syntax.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Syntax.scala index 6cc2224dbc15..d237a0c67e76 100644 --- a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Syntax.scala +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Syntax.scala @@ -2,6 +2,7 @@ package org.enso.compiler.core.ir package expression package errors +import com.oracle.truffle.api.source.Source import org.enso.compiler.core.IR import org.enso.compiler.core.IR.{randomId, Identifier, ToStringHelper} @@ -89,10 +90,10 @@ sealed case class Syntax( override def children: List[IR] = List() /** @inheritdoc */ - override def message: String = reason.explanation + override def message(source: Source): String = reason.explanation /** @inheritdoc */ - override def formattedMessage: String = s"${message}." + override def formattedMessage(source: Source): String = s"${message(source)}." override def diagnosticKeys(): Array[Any] = Array(reason) diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Unexpected.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Unexpected.scala index 8f138b4554e3..bfbf8ede46d6 100644 --- a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Unexpected.scala +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Unexpected.scala @@ -2,6 +2,7 @@ package org.enso.compiler.core.ir package expression package errors +import com.oracle.truffle.api.source.Source import org.enso.compiler.core.IR import org.enso.compiler.core.IR.{randomId, Identifier} @@ -17,7 +18,7 @@ sealed trait Unexpected extends Error { override val location: Option[IdentifiedLocation] = ir.location /** @inheritdoc */ - override def message: String = s"Unexpected $entity." + override def message(source: Source): String = s"Unexpected $entity." /** @inheritdoc */ override def diagnosticKeys(): Array[Any] = Array(entity) diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/warnings/Shadowed.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/warnings/Shadowed.scala index 28b9ff7e443b..7dd560b24b6a 100644 --- a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/warnings/Shadowed.scala +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/warnings/Shadowed.scala @@ -2,6 +2,7 @@ package org.enso.compiler.core.ir package expression package warnings +import com.oracle.truffle.api.source.Source import org.enso.compiler.core.IR /** Warnings about shadowing names. */ @@ -25,7 +26,7 @@ object Shadowed { override val shadower: IR, override val location: Option[IdentifiedLocation] ) extends Shadowed { - override def message: String = + override def message(source: Source): String = s"The argument $shadowedName is shadowed by $shadower" override def diagnosticKeys(): Array[Any] = @@ -44,7 +45,7 @@ object Shadowed { override val shadower: IR, override val location: Option[IdentifiedLocation] ) extends Shadowed { - override def message: String = + override def message(source: Source): String = s"The pattern field $shadowedName is shadowed by $shadower." override def diagnosticKeys(): Array[Any] = @@ -65,7 +66,7 @@ object Shadowed { override val shadower: IR, override val location: Option[IdentifiedLocation] ) extends Shadowed { - override def message: String = + override def message(source: Source): String = s"""Declaration of type $typeName shadows module ${moduleName.name} making it inaccessible via a qualified name.""" override def diagnosticKeys(): Array[Any] = @@ -88,7 +89,7 @@ object Shadowed { override val shadower: IR, override val location: Option[IdentifiedLocation] ) extends Shadowed { - override def message: String = + override def message(source: Source): String = s"The exported type `$tpeName` in `$name` module will cause name conflict " + s"when attempting to use a fully qualified name of the `$firstConflict` module." diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/warnings/Unreachable.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/warnings/Unreachable.scala index 3a6ff656dc9f..a8db0d3d1307 100644 --- a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/warnings/Unreachable.scala +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/warnings/Unreachable.scala @@ -2,6 +2,8 @@ package org.enso.compiler.core.ir package expression package warnings +import com.oracle.truffle.api.source.Source + /** Warnings for unreachable code. */ sealed trait Unreachable extends Warning { val location: Option[IdentifiedLocation] @@ -23,7 +25,8 @@ object Unreachable { "" } - override def message: String = s"Unreachable case branches$atLocation." + override def message(source: Source): String = + s"Unreachable case branches$atLocation." override def diagnosticKeys(): Array[Any] = Array(atLocation) } diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/warnings/Unused.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/warnings/Unused.scala index c309c949f4d7..ff47231bc1ce 100644 --- a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/warnings/Unused.scala +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/warnings/Unused.scala @@ -2,6 +2,8 @@ package org.enso.compiler.core.ir package expression package warnings +import com.oracle.truffle.api.source.Source + /** Warnings about unused language entities. */ sealed trait Unused extends Warning { val name: Name @@ -14,7 +16,8 @@ object Unused { * @param name the name that is unused */ sealed case class FunctionArgument(override val name: Name) extends Unused { - override def message: String = s"Unused function argument ${name.name}." + override def message(source: Source): String = + s"Unused function argument ${name.name}." override def diagnosticKeys(): Array[Any] = Array(name.name) @@ -24,7 +27,8 @@ object Unused { } sealed case class PatternBinding(override val name: Name) extends Unused { - override def message: String = s"Unused pattern binding ${name.name}." + override def message(source: Source): String = + s"Unused pattern binding ${name.name}." override def diagnosticKeys(): Array[Any] = Array(name.name) @@ -38,7 +42,8 @@ object Unused { * @param name the name that is unused */ sealed case class Binding(override val name: Name) extends Unused { - override def message: String = s"Unused variable ${name.name}." + override def message(source: Source): String = + s"Unused variable ${name.name}." override def diagnosticKeys(): Array[Any] = Array(name.name) diff --git a/engine/runtime/src/main/scala/org/enso/compiler/Compiler.scala b/engine/runtime/src/main/scala/org/enso/compiler/Compiler.scala index 8733d3955fbc..b9d6f70e19f2 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/Compiler.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/Compiler.scala @@ -1085,7 +1085,7 @@ class Compiler( .Str(srcPath + ":" + lineNumber + ":" + startColumn + ": ") .overlay(fansi.Bold.On) str ++= fansi.Str(subject).overlay(textAttrs) - str ++= diagnostic.formattedMessage + str ++= diagnostic.formattedMessage(source) str ++= "\n" str ++= oneLineFromSourceColored(lineNumber, startColumn, endColumn) str ++= "\n" @@ -1103,7 +1103,7 @@ class Compiler( ) .overlay(fansi.Bold.On) str ++= fansi.Str(subject).overlay(textAttrs) - str ++= diagnostic.formattedMessage + str ++= diagnostic.formattedMessage(source) str ++= "\n" val printAllSourceLines = section.getEndLine - section.getStartLine <= maxSourceLinesToPrint @@ -1138,7 +1138,7 @@ class Compiler( .overlay(fansi.Bold.On) str ++= ": " str ++= fansi.Str(subject).overlay(textAttrs) - str ++= diagnostic.formattedMessage + str ++= diagnostic.formattedMessage(source) if (outSupportsAnsiColors) { str.render.stripLineEnd } else { diff --git a/engine/runtime/src/main/scala/org/enso/compiler/codegen/IrToTruffle.scala b/engine/runtime/src/main/scala/org/enso/compiler/codegen/IrToTruffle.scala index 2935a8522088..d85b9b0e3384 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/codegen/IrToTruffle.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/codegen/IrToTruffle.scala @@ -1738,43 +1738,43 @@ class IrToTruffle( case err: errors.Syntax => context.getBuiltins .error() - .makeSyntaxError(Text.create(err.message)) + .makeSyntaxError(Text.create(err.message(source))) case err: errors.Redefined.Binding => context.getBuiltins .error() - .makeCompileError(Text.create(err.message)) + .makeCompileError(Text.create(err.message(source))) case err: errors.Redefined.Method => context.getBuiltins .error() - .makeCompileError(Text.create(err.message)) + .makeCompileError(Text.create(err.message(source))) case err: errors.Redefined.MethodClashWithAtom => context.getBuiltins .error() - .makeCompileError(Text.create(err.message)) + .makeCompileError(Text.create(err.message(source))) case err: errors.Redefined.Conversion => context.getBuiltins .error() - .makeCompileError(Text.create(err.message)) + .makeCompileError(Text.create(err.message(source))) case err: errors.Redefined.Type => context.getBuiltins .error() - .makeCompileError(Text.create(err.message)) + .makeCompileError(Text.create(err.message(source))) case err: errors.Redefined.SelfArg => context.getBuiltins .error() - .makeCompileError(Text.create(err.message)) + .makeCompileError(Text.create(err.message(source))) case err: errors.Unexpected.TypeSignature => context.getBuiltins .error() - .makeCompileError(Text.create(err.message)) + .makeCompileError(Text.create(err.message(source))) case err: errors.Resolution => context.getBuiltins .error() - .makeCompileError(Text.create(err.message)) + .makeCompileError(Text.create(err.message(source))) case err: errors.Conversion => context.getBuiltins .error() - .makeCompileError(Text.create(err.message)) + .makeCompileError(Text.create(err.message(source))) case _: errors.Pattern => throw new CompilerError( "Impossible here, should be handled in the pattern match." diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/AmbiguousImportsAnalysis.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/AmbiguousImportsAnalysis.scala index 6abdadb0bc5a..27efac5a8753 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/AmbiguousImportsAnalysis.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/AmbiguousImportsAnalysis.scala @@ -68,7 +68,6 @@ case object AmbiguousImportsAnalysis extends IRPass { imports = ir.imports.flatMap(imp => { analyseAmbiguousSymbols( imp, - moduleContext, bindingMap, encounteredSymbols ).fold(identity, imp => List(imp)) @@ -86,7 +85,6 @@ case object AmbiguousImportsAnalysis extends IRPass { */ private def analyseAmbiguousSymbols( imp: Import, - module: ModuleContext, bindingMap: BindingsMap, encounteredSymbols: EncounteredSymbols ): Either[List[errors.ImportExport], Import] = { @@ -114,7 +112,6 @@ case object AmbiguousImportsAnalysis extends IRPass { case Right(resolvedName) => val symbolPath = resolvedName.qualifiedName.toString tryAddEncounteredSymbol( - module, encounteredSymbols, imp, symbolName, @@ -176,7 +173,6 @@ case object AmbiguousImportsAnalysis extends IRPass { ) case Right(resolvedName) => tryAddEncounteredSymbol( - module, encounteredSymbols, imp, symbolName, @@ -213,7 +209,6 @@ case object AmbiguousImportsAnalysis extends IRPass { ) => val symbolPath = importPath.name tryAddEncounteredSymbol( - module, encounteredSymbols, moduleImport, rename.name, @@ -236,7 +231,6 @@ case object AmbiguousImportsAnalysis extends IRPass { _ ) => tryAddEncounteredSymbol( - module, encounteredSymbols, moduleImport, importPath.parts.last.name, @@ -254,7 +248,6 @@ case object AmbiguousImportsAnalysis extends IRPass { packageName + "." + className } tryAddEncounteredSymbol( - module, encounteredSymbols, polyImport, symbolName, @@ -284,7 +277,6 @@ case object AmbiguousImportsAnalysis extends IRPass { * in the map, checks whether the underlying entity path is the same as the original entity path. * Based on that, either attaches a warning for a duplicated import, or returns an [[errors.ImportExport]]. * - * @param module Current module * @param encounteredSymbols Encountered symbols in the current module * @param currentImport Currently iterated import * @param symbolName Name of the symbol that is about to be processed @@ -292,7 +284,6 @@ case object AmbiguousImportsAnalysis extends IRPass { * @return */ private def tryAddEncounteredSymbol( - module: ModuleContext, encounteredSymbols: EncounteredSymbols, currentImport: Import, symbolName: String, @@ -306,7 +297,6 @@ case object AmbiguousImportsAnalysis extends IRPass { if (symbolPath == encounteredFullName) { val warn = createWarningForDuplicatedImport( - module, originalImport, currentImport, symbolName @@ -315,7 +305,6 @@ case object AmbiguousImportsAnalysis extends IRPass { } else { Left( createErrorForAmbiguousImport( - module, originalImport, encounteredFullName, currentImport, @@ -331,7 +320,6 @@ case object AmbiguousImportsAnalysis extends IRPass { } private def createErrorForAmbiguousImport( - module: ModuleContext, originalImport: Import, originalSymbolPath: String, duplicatingImport: Import, @@ -344,14 +332,12 @@ case object AmbiguousImportsAnalysis extends IRPass { originalImport, originalSymbolPath, ambiguousSymbol, - ambiguousSymbolPath, - module.getSource() + ambiguousSymbolPath ) ) } private def createWarningForDuplicatedImport( - module: ModuleContext, originalImport: Import, duplicatingImport: Import, duplicatedSymbol: String @@ -359,8 +345,7 @@ case object AmbiguousImportsAnalysis extends IRPass { Warning.DuplicatedImport( duplicatingImport.location, originalImport, - duplicatedSymbol, - module.getSource() + duplicatedSymbol ) } diff --git a/engine/runtime/src/test/java/org/enso/compiler/ErrorCompilerTest.java b/engine/runtime/src/test/java/org/enso/compiler/ErrorCompilerTest.java index 259aabad3b3b..806f557270d6 100644 --- a/engine/runtime/src/test/java/org/enso/compiler/ErrorCompilerTest.java +++ b/engine/runtime/src/test/java/org/enso/compiler/ErrorCompilerTest.java @@ -424,7 +424,7 @@ private void assertSingleSyntaxError( var errors = assertIR(ir, Syntax.class, 1); assertEquals(type, errors.head().reason()); if (msg != null) { - assertEquals(msg, errors.head().message()); + assertEquals(msg, errors.head().message(null)); } assertEquals(new Location(start, end), errors.head().location().get().location()); } diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/analyse/GatherDiagnosticsTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/analyse/GatherDiagnosticsTest.scala index 3d18c660bc19..61fe398b6d65 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/analyse/GatherDiagnosticsTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/analyse/GatherDiagnosticsTest.scala @@ -132,7 +132,9 @@ class GatherDiagnosticsTest extends CompilerTest { .unsafeGetMetadata(GatherDiagnostics, "Impossible") .diagnostics diagnostics should have size 2 - diagnostics.map(_.message).toSet shouldEqual Set( + diagnostics + .map(_.message(null)) + .toSet shouldEqual Set( "Unused variable unused.", "Unused function argument x." ) diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/semantic/ImportExportTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/semantic/ImportExportTest.scala index e965729dff8e..5fe03e62c9c1 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/semantic/ImportExportTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/semantic/ImportExportTest.scala @@ -14,7 +14,7 @@ import org.scalatest.BeforeAndAfter import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpecLike -import java.io.ByteArrayOutputStream +import java.io.{ByteArrayOutputStream, ObjectOutputStream} import java.nio.file.Paths /** Tests a single package with multiple modules for import/export resolution. @@ -121,7 +121,8 @@ class ImportExportTest mainIr.imports.head match { case importErr: errors.ImportExport => fail( - s"Import should be resolved, but instead produced errors.ImportExport with ${importErr.reason.message}" + s"Import should be resolved, but instead produced errors.ImportExport with ${importErr.reason + .message(null)}" ) case _ => () } @@ -884,6 +885,65 @@ class ImportExportTest allWarns.foreach(_.symbolName shouldEqual "A_Type") allWarns.foreach(_.originalImport shouldEqual origImport) } + + "serialize duplicated import warning" in { + s""" + |type A_Type + |""".stripMargin + .createModule(packageQualifiedName.createChild("A_Module")) + val mainIr = + s""" + |import $namespace.$packageName.A_Module.A_Type + |from $namespace.$packageName.A_Module import A_Type + |""".stripMargin + .createModule(packageQualifiedName.createChild("Main_Module")) + .getIr + mainIr.imports.size shouldEqual 2 + val warn = mainIr + .imports(1) + .diagnostics + .collect({ case w: Warning.DuplicatedImport => w }) + warn.size shouldEqual 1 + val baos = new ByteArrayOutputStream() + val stream = new ObjectOutputStream(baos) + mainIr.preorder.foreach( + _.passData.prepareForSerialization(langCtx.getCompiler) + ) + stream.writeObject(mainIr) + baos.toByteArray should not be empty + } + + "serialize ambiguous import error" in { + s""" + |type A_Type + |""".stripMargin + .createModule(packageQualifiedName.createChild("A_Module")) + s""" + |type B_Type + |""".stripMargin + .createModule(packageQualifiedName.createChild("B_Module")) + val mainIr = + s""" + |from $namespace.$packageName.A_Module import A_Type + |import $namespace.$packageName.B_Module.B_Type as A_Type + |""".stripMargin + .createModule(packageQualifiedName.createChild("Main_Module")) + .getIr + mainIr.imports.size shouldEqual 2 + val ambiguousImport = mainIr + .imports(1) + .asInstanceOf[errors.ImportExport] + .reason + .asInstanceOf[errors.ImportExport.AmbiguousImport] + ambiguousImport.symbolName shouldEqual "A_Type" + val baos = new ByteArrayOutputStream() + val stream = new ObjectOutputStream(baos) + mainIr.preorder.foreach( + _.passData.prepareForSerialization(langCtx.getCompiler) + ) + stream.writeObject(mainIr) + baos.toByteArray should not be empty + } } "Import resolution for three modules" should { @@ -928,7 +988,8 @@ class ImportExportTest mainIr.imports.head .asInstanceOf[errors.ImportExport] .reason - .message should include("A_Type") + .message(null) should include("A_Type") + } "resolve all symbols (types and static module methods) from the module" in {