-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Report the correct errors in the IDE and add test infrastructure for diagnostics #5484
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
f3cf401
7469d59
a3e8e95
15d9af3
38c6d46
d180287
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,4 +7,3 @@ scala> val x: Foo[String] = res0 | |
| ^^^^ | ||
| found: Foo[Int](res0) | ||
| required: Foo[String] | ||
| |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package dotty.tools.languageserver | ||
|
||
import org.junit.Test | ||
|
||
import dotty.tools.dotc.reporting.diagnostic.ErrorMessageID._ | ||
import dotty.tools.languageserver.util.Code._ | ||
import org.eclipse.lsp4j.DiagnosticSeverity._ | ||
|
||
class DiagnosticsTest { | ||
@Test def diagnosticWrongType: Unit = | ||
code"""object Test { | ||
| val x: Int = $m1"foo"$m2 | ||
|}""".withSource | ||
.diagnostics(m1, | ||
(m1 to m2, """found: String("foo") | ||
|required: Int""".stripMargin, Error, Some(TypeMismatchID)) | ||
) | ||
|
||
@Test def diagnosticMissingLambdaBody: Unit = | ||
code"""object Test { | ||
| Nil.map(x => x).filter(x$m1 =>$m2) | ||
|$m3}""".withSource | ||
.diagnostics(m1, | ||
(m2 to m3, "illegal start of simple expression", Error, Some(IllegalStartSimpleExprID)), | ||
(m1 to m1, """found: Null | ||
|required: Boolean""".stripMargin, Error, Some(TypeMismatchID)) | ||
) | ||
|
||
@Test def diagnosticPureExpression: Unit = | ||
code"""object Test { | ||
| ${m1}1$m2 | ||
|}""".withSource | ||
.diagnostics(m1, | ||
(m1 to m2, | ||
"a pure expression does nothing in statement position; you may be omitting necessary parentheses", | ||
Warning, Some(PureExpressionInStatementPositionID))) | ||
|
||
@Test def diagnosticWorksheetPureExpression: Unit = | ||
ws"""${m1}1""".withSource | ||
.diagnostics(m1 /* no "pure expression" warning because this is a worksheet */) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,9 +5,12 @@ import dotty.tools.languageserver.util.actions._ | |
import dotty.tools.languageserver.util.embedded.CodeMarker | ||
import dotty.tools.languageserver.util.server.{TestFile, TestServer} | ||
|
||
import dotty.tools.dotc.reporting.diagnostic.ErrorMessageID | ||
import dotty.tools.dotc.util.Signatures.Signature | ||
|
||
import org.eclipse.lsp4j.{CompletionItemKind, DocumentHighlightKind} | ||
import org.eclipse.lsp4j.{ CompletionItemKind, DocumentHighlightKind, Diagnostic, DiagnosticSeverity } | ||
|
||
import org.junit.Assert.assertEquals | ||
|
||
/** | ||
* Simulates an LSP client for test in a project defined by `sources`. | ||
|
@@ -30,6 +33,31 @@ class CodeTester(projects: List[Project]) { | |
|
||
private val positions: PositionContext = getPositions(files) | ||
|
||
/** Check that the last diagnostics that have been published so far by the server | ||
* for a given file match `expected`. | ||
* | ||
* @param marker The marker defining the source file from which to query. | ||
* @param expected The expected diagnostics to be found | ||
*/ | ||
def diagnostics(marker: CodeMarker, | ||
expected: (CodeRange, String, DiagnosticSeverity, Option[ErrorMessageID])*): this.type = { | ||
implicit val posCtx = positions | ||
|
||
def toDiagnostic(range: CodeRange, message: String, severity: DiagnosticSeverity, | ||
errorCode: Option[ErrorMessageID]): Diagnostic = { | ||
new Diagnostic(range.toRange, message, severity, /*source =*/"", | ||
errorCode.map(_.errorNumber.toString).orNull) | ||
} | ||
|
||
val expectedParams = marker.toPublishDiagnosticsParams(expected.toList.map(toDiagnostic)) | ||
// Find the latest published diagnostics for the current source file | ||
val actualParams = testServer.client.diagnostics.get.reverse.find(_.getUri == marker.uri) | ||
.getOrElse(throw new Exception(s"No published diagnostics for ${marker.uri}")) | ||
assertEquals(expectedParams, actualParams) | ||
|
||
this | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The other "actions" in this file usually do def foo(marker: CodeMarker, expected: ...) = doAction(new Foo(marker, expected)) Any reason for not following the same pattern? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mostly because there's no action (request sent to the server) involved here, the request is "didOpen" but it's done implicitly. But if you think this could be refactored, please do! |
||
|
||
/** | ||
* Perform a hover over `range`, verifies that result matches `expected`. | ||
* | ||
|
Uh oh!
There was an error while loading. Please reload this page.