Skip to content

Commit c5be5dc

Browse files
SuperCl4shtgodzik
authored andcommitted
First draft of add nn quick fix
1 parent ed80ad8 commit c5be5dc

File tree

2 files changed

+70
-0
lines changed

2 files changed

+70
-0
lines changed

compiler/src/dotty/tools/dotc/reporting/messages.scala

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,10 @@ extends NotFoundMsg(MissingIdentID) {
295295
class TypeMismatch(val found: Type, expected: Type, val inTree: Option[untpd.Tree], addenda: => String*)(using Context)
296296
extends TypeMismatchMsg(found, expected)(TypeMismatchID):
297297

298+
private var shouldSuggestNN = false
299+
// Ensures that shouldSuggestNN will always be correctly computed before `actions` is called
300+
msg
301+
298302
def msg(using Context) =
299303
// replace constrained TypeParamRefs and their typevars by their bounds where possible
300304
// and the bounds are not f-bounds.
@@ -339,6 +343,7 @@ class TypeMismatch(val found: Type, expected: Type, val inTree: Option[untpd.Tre
339343
val (found2, expected2) =
340344
if (found1 frozen_<:< expected1) || reported.fbounded then (found, expected)
341345
else (found1, expected1)
346+
if found2 frozen_<:< OrNull(expected) then shouldSuggestNN = true
342347
val (foundStr, expectedStr) = Formatting.typeDiff(found2.normalized, expected2.normalized)
343348
i"""|Found: $foundStr
344349
|Required: $expectedStr${reported.notes}"""
@@ -355,6 +360,28 @@ class TypeMismatch(val found: Type, expected: Type, val inTree: Option[untpd.Tre
355360
val treeStr = inTree.map(x => s"\nTree:\n\n${x.show}\n").getOrElse("")
356361
treeStr + "\n" + super.explain
357362

363+
override def actions(using Context) =
364+
if shouldSuggestNN then
365+
inTree match {
366+
case Some(tree) if tree != null =>
367+
val content = tree.source.content().slice(tree.srcPos.startPos.start, tree.srcPos.endPos.end).mkString
368+
val replacement = tree match
369+
case a @ Apply(fun, args) => "(" + content + ").nn"
370+
case _ => content
371+
List(
372+
CodeAction(title = """Add .nn""",
373+
description = None,
374+
patches = List(
375+
ActionPatch(tree.srcPos.sourcePos, replacement)
376+
)
377+
)
378+
)
379+
case _ =>
380+
List()
381+
}
382+
else
383+
List()
384+
358385
end TypeMismatch
359386

360387
class NotAMember(site: Type, val name: Name, selected: String, proto: Type, addendum: => String = "")(using Context)

compiler/test/dotty/tools/dotc/reporting/CodeActionTest.scala

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,49 @@ class CodeActionTest extends DottyTest:
136136
afterPhase = "patternMatcher"
137137
)
138138

139+
@Test def removeNN =
140+
val ctxx = newContext
141+
ctxx.setSetting(ctxx.settings.YexplicitNulls, true)
142+
checkCodeAction(
143+
code =
144+
"""|val s: String|Null = "foo".nn
145+
|""".stripMargin,
146+
title = "Remove unnecessary .nn",
147+
expected =
148+
"""|val s: String|Null = "foo"
149+
|""".stripMargin,
150+
ctxx = ctxx
151+
)
152+
153+
154+
@Test def removeNN2 =
155+
val ctxx = newContext
156+
ctxx.setSetting(ctxx.settings.YexplicitNulls, true)
157+
checkCodeAction(
158+
code =
159+
"""val s: String|Null = null.nn
160+
|""".stripMargin,
161+
title = "Remove unnecessary .nn",
162+
expected =
163+
"""val s: String|Null = null
164+
|""".stripMargin,
165+
ctxx = ctxx
166+
)
167+
168+
@Test def addNN =
169+
val ctxx = newContext
170+
ctxx.setSetting(ctxx.settings.YexplicitNulls, true)
171+
checkCodeAction(
172+
code =
173+
"""val s: String|Null = ???
174+
| val t: String = s""".stripMargin,
175+
title = "Add .nn",
176+
expected =
177+
"""val s: String|Null = ???
178+
| val t: String = (s).nn""".stripMargin,
179+
ctxx = ctxx
180+
)
181+
139182
// Make sure we're not using the default reporter, which is the ConsoleReporter,
140183
// meaning they will get reported in the test run and that's it.
141184
private def newContext =

0 commit comments

Comments
 (0)