Skip to content

Commit f6b5d50

Browse files
authored
Merge pull request #4861 from dotty-staging/fix-4306-scansource-java
Fix #4306: Implement -scansource for Java files
2 parents a63eef1 + 1387795 commit f6b5d50

File tree

10 files changed

+115
-20
lines changed

10 files changed

+115
-20
lines changed

compiler/src/dotty/tools/dotc/Run.scala

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@ import transform.TreeChecker
1919
import rewrite.Rewrites
2020
import java.io.{BufferedWriter, OutputStreamWriter}
2121

22-
import dotty.tools.dotc.profile.Profiler
22+
import profile.Profiler
2323
import printing.XprintMode
2424
import parsing.Parsers.Parser
25+
import parsing.JavaParsers.JavaParser
2526
import typer.ImplicitRunInfo
2627
import collection.mutable
2728

@@ -209,7 +210,9 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
209210
lateFiles += file
210211
val unit = new CompilationUnit(getSource(file.path))
211212
def process()(implicit ctx: Context) = {
212-
unit.untpdTree = new Parser(unit.source).parse()
213+
unit.untpdTree =
214+
if (unit.isJava) new JavaParser(unit.source).parse()
215+
else new Parser(unit.source).parse()
213216
ctx.typer.lateEnter(unit.untpdTree)
214217
def typeCheckUnit() = unit.tpdTree = ctx.typer.typedExpr(unit.untpdTree)
215218
if (typeCheck)

compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import Decorators._
1616
import scala.util.control.NonFatal
1717
import ast.Trees._
1818
import ast.tpd
19+
import parsing.JavaParsers.OutlineJavaParser
1920
import parsing.Parsers.OutlineParser
2021
import reporting.trace
2122

@@ -154,7 +155,10 @@ object SymbolLoaders {
154155
case _ =>
155156
}
156157

157-
traverse(new OutlineParser(unit.source).parse(), Nil)
158+
traverse(
159+
if (unit.isJava) new OutlineJavaParser(unit.source).parse()
160+
else new OutlineParser(unit.source).parse(),
161+
Nil)
158162
}
159163

160164
val unit = new CompilationUnit(ctx.run.getSource(src.path))

compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -907,4 +907,18 @@ object JavaParsers {
907907
unit
908908
}
909909
}
910+
911+
912+
/** OutlineJavaParser parses top-level declarations in `source` to find declared classes, ignoring their bodies (which
913+
* must only have balanced braces). This is used to map class names to defining sources.
914+
* This is necessary even for Java, because the filename defining a non-public classes cannot be determined from the
915+
* classname alone.
916+
*/
917+
class OutlineJavaParser(source: SourceFile)(implicit ctx: Context) extends JavaParser(source) with OutlineParserCommon {
918+
override def skipBracesHook() = None
919+
override def typeBody(leadingToken: Int, parentName: Name, parentTParams: List[TypeDef]): (List[Tree], List[Tree]) = {
920+
skipBraces()
921+
(List(EmptyValDef), List(EmptyTree))
922+
}
923+
}
910924
}

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,23 @@ object Parsers {
130130
ctx.error(msg, source atPos pos)
131131
}
132132

133+
trait OutlineParserCommon extends ParserCommon {
134+
def accept(token: Int): Int
135+
136+
def skipBracesHook(): Option[Tree]
137+
def skipBraces(): Unit = {
138+
accept(LBRACE)
139+
var openBraces = 1
140+
while (in.token != EOF && openBraces > 0) {
141+
skipBracesHook() getOrElse {
142+
if (in.token == LBRACE) openBraces += 1
143+
else if (in.token == RBRACE) openBraces -= 1
144+
in.nextToken()
145+
}
146+
}
147+
}
148+
}
149+
133150
class Parser(source: SourceFile)(implicit ctx: Context) extends ParserCommon(source) {
134151

135152
val in: Scanner = new Scanner(source)
@@ -2638,24 +2655,22 @@ object Parsers {
26382655
}
26392656

26402657

2641-
class OutlineParser(source: SourceFile)(implicit ctx: Context) extends Parser(source) {
2658+
/** OutlineParser parses top-level declarations in `source` to find declared classes, ignoring their bodies (which
2659+
* must only have balanced braces). This is used to map class names to defining sources.
2660+
*/
2661+
class OutlineParser(source: SourceFile)(implicit ctx: Context) extends Parser(source) with OutlineParserCommon {
26422662

2643-
def skipBraces[T](body: T): T = {
2644-
accept(LBRACE)
2645-
var openBraces = 1
2646-
while (in.token != EOF && openBraces > 0) {
2647-
if (in.token == XMLSTART) xmlLiteral()
2648-
else {
2649-
if (in.token == LBRACE) openBraces += 1
2650-
else if (in.token == RBRACE) openBraces -= 1
2651-
in.nextToken()
2652-
}
2653-
}
2654-
body
2655-
}
2663+
def skipBracesHook(): Option[Tree] =
2664+
if (in.token == XMLSTART) Some(xmlLiteral()) else None
26562665

2657-
override def blockExpr(): Tree = skipBraces(EmptyTree)
2666+
override def blockExpr(): Tree = {
2667+
skipBraces()
2668+
EmptyTree
2669+
}
26582670

2659-
override def templateBody() = skipBraces((EmptyValDef, List(EmptyTree)))
2671+
override def templateBody() = {
2672+
skipBraces()
2673+
(EmptyValDef, List(EmptyTree))
2674+
}
26602675
}
26612676
}

compiler/src/dotty/tools/dotc/parsing/Scanners.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ object Scanners {
5757

5858
abstract class ScannerCommon(source: SourceFile)(implicit ctx: Context) extends CharArrayReader with TokenData {
5959
val buf = source.content
60+
def nextToken(): Unit
6061

6162
// Errors -----------------------------------------------------------------
6263

compiler/test/dotty/tools/dotc/CompilationTests.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ class CompilationTests extends ParallelTesting {
4747
compileFile("tests/pos-special/completeFromSource/Test.scala", defaultOptions.and("-sourcepath", "tests/pos-special")) +
4848
compileFile("tests/pos-special/completeFromSource/Test2.scala", defaultOptions.and("-sourcepath", "tests/pos-special")) +
4949
compileFile("tests/pos-special/completeFromSource/Test3.scala", defaultOptions.and("-sourcepath", "tests/pos-special", "-scansource")) +
50+
compileFile("tests/pos-special/completeFromSource/nested/Test4.scala", defaultOptions.and("-sourcepath", "tests/pos-special", "-scansource")) +
5051
compileFilesInDir("tests/pos-special/fatal-warnings", defaultOptions.and("-Xfatal-warnings")) +
5152
compileList(
5253
"compileMixed",
@@ -158,7 +159,8 @@ class CompilationTests extends ParallelTesting {
158159
compileFile("tests/neg-custom-args/i4372.scala", allowDeepSubtypes) +
159160
compileFile("tests/neg-custom-args/i1754.scala", allowDeepSubtypes) +
160161
compileFilesInDir("tests/neg-custom-args/isInstanceOf", allowDeepSubtypes and "-Xfatal-warnings") +
161-
compileFile("tests/neg-custom-args/i3627.scala", allowDeepSubtypes)
162+
compileFile("tests/neg-custom-args/i3627.scala", allowDeepSubtypes) +
163+
compileFile("tests/neg-custom-args/completeFromSource/nested/Test1.scala", defaultOptions.and("-sourcepath", "tests/neg-custom-args", "-scansource"))
162164
}.checkExpectedErrors()
163165

164166
// Run tests -----------------------------------------------------------------
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package completeFromSource.nested;
2+
3+
public class D {
4+
public D(int i) {
5+
6+
}
7+
public String thisIsD(int i) {
8+
return java.lang.Integer.toString(i);
9+
}
10+
}
11+
12+
class E {
13+
public E(String s) {}
14+
15+
public String thisIsE(int i) {
16+
return java.lang.Integer.toString(i);
17+
}
18+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package completeFromSource.nested
2+
3+
class Test4 {
4+
5+
val d = new D(1)
6+
val e = new E("xx")
7+
8+
d.thisIsD(1)
9+
e.thisIsE() // error
10+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package completeFromSource.nested;
2+
3+
public class D {
4+
public D(int i) {
5+
6+
}
7+
public String thisIsD(int i) {
8+
return java.lang.Integer.toString(i);
9+
}
10+
}
11+
12+
class E {
13+
public E(String s) {}
14+
15+
public String thisIsE(int i) {
16+
return java.lang.Integer.toString(i);
17+
}
18+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package completeFromSource.nested
2+
3+
class Test4 {
4+
5+
val d = new D(1)
6+
val e = new E("xx")
7+
8+
d.thisIsD(1)
9+
e.thisIsE(2)
10+
}

0 commit comments

Comments
 (0)