Skip to content

Add line number magic comment support #23549

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

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@ private sealed trait XSettings:
val Xdumpclasses: Setting[String] = StringSetting(AdvancedSetting, "Xdump-classes", "dir", "Dump the generated bytecode to .class files (useful for reflective compilation that utilizes in-memory classloaders).", "")
val XjarCompressionLevel: Setting[Int] = IntChoiceSetting(AdvancedSetting, "Xjar-compression-level", "compression level to use when writing jar files", Deflater.DEFAULT_COMPRESSION to Deflater.BEST_COMPRESSION, Deflater.DEFAULT_COMPRESSION)
val XkindProjector: Setting[String] = ChoiceSetting(AdvancedSetting, "Xkind-projector", "[underscores, enable, disable]", "Allow `*` as type lambda placeholder to be compatible with kind projector. When invoked as -Xkind-projector:underscores will repurpose `_` to be a type parameter placeholder, this will disable usage of underscore as a wildcard.", List("disable", "", "underscores"), "disable", legacyArgs = true)
val XmagicOffsetHeader: Setting[String] = StringSetting(AdvancedSetting, "Xmagic-offset-header", "header", "Specify the magic header comment that marks the start of the actual code in generated wrapper scripts. Example: -Xmagic-offset-header:///SOURCE_CODE_START", "")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like it should be the in the Y category, so the experimental and tooling specific


/** Documentation related settings */
val XdropComments: Setting[Boolean] = BooleanSetting(AdvancedSetting, "Xdrop-docs", "Drop documentation when scanning source files.", aliases = List("-Xdrop-comments"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import core.Decorators.*
import printing.Highlighting.{Blue, Red, Yellow}
import printing.SyntaxHighlighting
import Diagnostic.*
import util.{ SourcePosition, NoSourcePosition }
import util.{ SourcePosition, NoSourcePosition, WrappedSourceFile }
import util.Chars.{ LF, CR, FF, SU }
import scala.annotation.switch

Expand Down Expand Up @@ -44,7 +44,10 @@ trait MessageRendering {
var maxLen = Int.MinValue
def render(offsetAndLine: (Int, String)): String = {
val (offset1, line) = offsetAndLine
val lineNbr = (pos.source.offsetToLine(offset1) + 1).toString
var magicOffset = WrappedSourceFile.locateMagicHeader(pos.source).getOrElse(0)
val lineId = pos.source.offsetToLine(offset1)
if lineId < magicOffset then magicOffset = 0
val lineNbr = (lineId + 1 - magicOffset).toString
val prefix = String.format(s"%${offset - 2}s |", lineNbr)
maxLen = math.max(maxLen, prefix.length)
val lnum = hl(" " * math.max(0, maxLen - prefix.length - 1) + prefix)
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import core.Contexts.*
import collection.mutable
import scala.annotation.tailrec
import dotty.tools.dotc.reporting.Reporter
import dotty.tools.dotc.util.SourcePosition;
import dotty.tools.dotc.util.SourcePosition

import java.io.OutputStreamWriter
import java.nio.charset.StandardCharsets.UTF_8
Expand Down
15 changes: 15 additions & 0 deletions compiler/src/dotty/tools/dotc/util/SourceFile.scala
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,21 @@ object ScriptSourceFile {
}
}

object WrappedSourceFile:
private val cache: mutable.HashMap[SourceFile, Int] = mutable.HashMap.empty
def locateMagicHeader(sourceFile: SourceFile)(using Context): Option[Int] =
def findOffset: Int =
val magicHeader = ctx.settings.XmagicOffsetHeader.value
if magicHeader.isEmpty then
-1
else
val s = new String(sourceFile.content)
val regex = ("(?m)^" + java.util.regex.Pattern.quote(magicHeader) + "$").r
val pos = regex.findFirstMatchIn(s).map(_.start).map(sourceFile.offsetToLine(_))
pos.getOrElse(-1)
val result = cache.getOrElseUpdate(sourceFile, findOffset)
if result >= 0 then Some(result + 1) else None

class SourceFile(val file: AbstractFile, computeContent: => Array[Char]) extends interfaces.SourceFile {
import SourceFile.*

Expand Down
7 changes: 7 additions & 0 deletions tests/neg/magic-offset-header-a.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
-- [E007] Type Mismatch Error: tests/neg/magic-offset-header-a.scala:6:19 ----------------------------------------------
1 |def test1(): Int = "无穷" // error
| ^^^^
| Found: ("无穷" : String)
| Required: Int
|
| longer explanation available when compiling with `-explain`
6 changes: 6 additions & 0 deletions tests/neg/magic-offset-header-a.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
//> using options -Xmagic-offset-header:///TEST_MARKER
val t1 = 1
val t2 = 2
val t3 = 3
///TEST_MARKER
def test1(): Int = "无穷" // error
14 changes: 14 additions & 0 deletions tests/neg/magic-offset-header-b.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
-- [E007] Type Mismatch Error: tests/neg/magic-offset-header-b.scala:3:13 ----------------------------------------------
3 |def x: Int = true // error
| ^^^^
| Found: (true : Boolean)
| Required: Int
|
| longer explanation available when compiling with `-explain`
-- [E007] Type Mismatch Error: tests/neg/magic-offset-header-b.scala:7:13 ----------------------------------------------
2 |def y: Int = false // error
| ^^^^^
| Found: (false : Boolean)
| Required: Int
|
| longer explanation available when compiling with `-explain`
7 changes: 7 additions & 0 deletions tests/neg/magic-offset-header-b.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//> using options -Xmagic-offset-header:///TEST_MARKER

def x: Int = true // error

///TEST_MARKER

def y: Int = false // error
7 changes: 7 additions & 0 deletions tests/neg/magic-offset-header-c.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
-- [E007] Type Mismatch Error: tests/neg/magic-offset-header-c.scala:8:18 ----------------------------------------------
3 | val x: String = 0 // error
| ^
| Found: (0 : Int)
| Required: String
|
| longer explanation available when compiling with `-explain`
8 changes: 8 additions & 0 deletions tests/neg/magic-offset-header-c.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
//> using options -Xmagic-offset-header:///SOURCE_CODE_START_MARKER

val generatedCode = 123

///SOURCE_CODE_START_MARKER

def userCode =
val x: String = 0 // error
Loading