mirror of
https://github.com/enso-org/enso.git
synced 2024-12-23 15:12:15 +03:00
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
This commit is contained in:
parent
28fc183f92
commit
ab2da9e436
@ -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, _))
|
||||
|
@ -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]
|
||||
|
@ -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 */
|
||||
|
@ -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."
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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) =>
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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(
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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."
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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."
|
||||
|
@ -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
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -424,7 +424,7 @@ public class ErrorCompilerTest extends CompilerTest {
|
||||
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());
|
||||
}
|
||||
|
@ -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."
|
||||
)
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user