Skip to content

Commit 98ff433

Browse files
committed
Bug fixes on types, this overloading and super statement
1 parent 4f2a5ff commit 98ff433

File tree

7 files changed

+136
-59
lines changed

7 files changed

+136
-59
lines changed
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package example
22

33
class BinaryOp {
4-
1 #:: 2 #:: Stream.empty[Int]
4+
val y = 1 #:: 2 #:: Stream.empty[Int]
5+
val x = 1 + 2 + 3
56
}

semanticdb/input/src/main/scala/example/Flags.scala

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
package example
21

3-
package object p {
2+
package object example {
43
private lazy val x = 1
5-
protected implicit var y: Int = 2
4+
/*protected implicit var y: Int = 2
65
def z(pp: Int) = 3
76
def m[TT] = ???
8-
abstract class C[+T, -U, V](x: T, y: U, z: V) {
7+
abstract class Cex[+T, -U, V](x: T, y: U, z: V) {
98
def this() = this(???, ???, ???)
109
def w: Int
1110
}
@@ -20,5 +19,5 @@ package object p {
2019
class S[@specialized T]
2120
val List(xs1) = ???
2221
??? match { case List(xs2) => ??? }
23-
??? match { case _: List[t] => ??? }
22+
??? match { case _: List[t] => ??? }*/
2423
}

semanticdb/input/src/main/scala/example/Imports.scala

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,20 @@
1+
/*
2+
// This text is deactivated for now as macro annotations require to enable
3+
// macro paradise
4+
15
package example
26
3-
//@MacroAnnotation
7+
8+
import scala.annotation.StaticAnnotation
9+
import scala.annotation.compileTimeOnly
10+
import scala.language.experimental.macros
11+
12+
@compileTimeOnly("enable macro paradise to expand macro annotations")
13+
class MacroAnnotation extends StaticAnnotation {
14+
def macroTransform(annottees: Any*): Any = ???
15+
}
16+
17+
@MacroAnnotation
418
class MacroAnnotations
519
object MacroAnnotations
20+
*/

semanticdb/input/src/main/scala/example/Types.scala

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,13 @@ package example
33
import scala.language.existentials
44
import scala.language.higherKinds
55

6-
class ann[T](x: T) extends scala.annotation.StaticAnnotation
7-
class ann1 extends scala.annotation.StaticAnnotation
8-
class ann2 extends scala.annotation.StaticAnnotation
6+
class TypeM {
7+
def m: Int = ???
8+
}
9+
10+
class TypeC extends TypeM {
11+
val superType = super[TypeM].m
12+
}
913

1014
class TypB
1115

@@ -59,9 +63,6 @@ object TypTest {
5963
val compoundType5 = new M with N
6064
val compoundType6 = new M with N { def k: Int = ??? }
6165

62-
val annType1: T @ann(42) = ???
63-
val annType2: T @ann1 @ann2 = ???
64-
6566
val existentialType2: List[_] = ???
6667
val existentialType3 = Class.forName("foo.Bar")
6768
val existentialType4 = Class.forName("foo.Bar")

semanticdb/src/dotty/semanticdb/SemanticdbConsumer.scala

Lines changed: 101 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ class SemanticdbConsumer(sourceFile: java.nio.file.Path) extends TastyConsumer {
106106
case _ => false
107107
}
108108

109-
def isTypeParameter: Boolean = symbol.flags.is(Flags.Param) && symbol.isType
109+
def isTypeParameter: Boolean = symbol.isParameter && symbol.isType
110110

111111
def isType: Boolean = symbol match {
112112
case IsTypeSymbol(_) => true
@@ -128,13 +128,21 @@ class SemanticdbConsumer(sourceFile: java.nio.file.Path) extends TastyConsumer {
128128
def isDefaultGetter: Boolean =
129129
symbol.name.contains(tpnme.DEFAULT_GETTER.toString)
130130

131+
def isReservedName : Boolean = {
132+
val keywords =
133+
List("ev$", "evidence$", "$_lazy_implicit_$", "$lzy", "$lzyINIT",
134+
"$OFFSET", "bitmap$", "_$", "$tailLocal", "tmp", "$doc",
135+
"$superArg$", "$scrutinee", "$elem")
136+
return keywords.exists(symbol.name.contains(_))
137+
}
138+
131139
def isParameter: Boolean = symbol.flags.is(Flags.Param)
132140

133141
def isObject: Boolean = symbol.flags.is(Flags.Object)
134142

135143
def isTrait: Boolean = symbol.flags.is(Flags.Trait)
136144

137-
def isValueParameter: Boolean = symbol.flags.is(Flags.Param)
145+
def isValueParameter: Boolean = symbol.isParameter && !symbol.isType
138146

139147
def isJavaClass: Boolean = symbol.isClass && symbol.flags.is(Flags.JavaDefined)
140148

@@ -263,6 +271,7 @@ class SemanticdbConsumer(sourceFile: java.nio.file.Path) extends TastyConsumer {
263271

264272
def isUseless(implicit ctx: Context): Boolean = {
265273
symbol == NoSymbol ||
274+
symbol.isReservedName ||
266275
//symbol.isInitChild ||
267276
symbol.isAnonymousInit ||
268277
symbol.isDefaultGetter ||
@@ -347,14 +356,14 @@ class SemanticdbConsumer(sourceFile: java.nio.file.Path) extends TastyConsumer {
347356
case _ =>
348357
d.Term(symbol.trueName)
349358
}
359+
} else if (symbol.isValueParameter) {
360+
d.Parameter(symbol.trueName)
350361
} else if (symbol.isMethod || symbol.isUsefulField) {
351362
d.Method(symbol.trueName,
352363
disimbiguate(previous_symbol + symbol.trueName, symbol))
353364
} else if (symbol.isTypeParameter) {
354365
d.TypeParameter(symbol.trueName)
355-
} else if (symbol.isValueParameter) {
356-
d.Parameter(symbol.trueName)
357-
} else if (symbol.isType || symbol.isTrait) {
366+
} else if (symbol.isType || symbol.isTrait) {
358367
d.Type(symbol.trueName)
359368
} else {
360369
d.Term(symbol.trueName)
@@ -413,6 +422,8 @@ class SemanticdbConsumer(sourceFile: java.nio.file.Path) extends TastyConsumer {
413422
case _ =>
414423
symbolToSymbolString(symbol)
415424
}
425+
426+
println(symbol_path)
416427
// We want to add symbols coming from our file
417428
// if (symbol.pos.sourceFile != sourceFile) return
418429
if (symbol_path == "" || symbol.isUselessOccurrence) return
@@ -426,9 +437,9 @@ class SemanticdbConsumer(sourceFile: java.nio.file.Path) extends TastyConsumer {
426437
// dotty will generate a ValDef for the x, but the x will also
427438
// be present in the constructor, thus making a double definition
428439
if (symbolPathsMap.contains(key)) return
429-
if (is_global) {
440+
//if (is_global) {
430441
symbolPathsMap += key
431-
}
442+
//}
432443
println(symbol_path,
433444
range,
434445
symbol.flags,
@@ -589,13 +600,50 @@ class SemanticdbConsumer(sourceFile: java.nio.file.Path) extends TastyConsumer {
589600
s.SymbolOccurrence.Role.REFERENCE,
590601
range)
591602
super.traverseTypeTree(typetree)
592-
}/*
603+
}
604+
605+
case TypeTree.Projection(qualifier, x) => {
606+
val typetree = extractTypeTree(tree)
607+
val range = rangeSelect(typetree.symbol.trueName, typetree.pos)
608+
addOccurenceTypeTree(typetree,
609+
s.SymbolOccurrence.Role.REFERENCE,
610+
range)
611+
super.traverseTypeTree(typetree)
612+
}
613+
593614
case TypeTree.Inferred() => {
615+
/* In theory no inferred types should be put in the semanticdb file.
616+
However, take the case where a typed is refered from an imported class:
617+
class PrefC {
618+
object N {
619+
type U
620+
}
621+
}
622+
623+
object PrefTest {
624+
val c: PrefC = ???
625+
import c.N._
626+
def k3: U = ???
627+
}
628+
629+
The type corresponding to U in the definition of k3 is marked as
630+
inferred even though it is present in the source code. We use a
631+
workaround for this specific case, by checking if the name of the
632+
inferred type corresponds to the one put in the source code at this
633+
position
634+
*/
635+
594636
val typetree = extractTypeTree(tree)
595-
addOccurenceTypeTree(typetree,
637+
val start = typetree.pos.start
638+
val end = typetree.pos.end
639+
if (end < sourceCode.length
640+
&& sourceCode.substring(start, end) == typetree.symbol.name) {
641+
addOccurenceTypeTree(typetree,
596642
s.SymbolOccurrence.Role.REFERENCE,
597643
posToRange(typetree.pos).get)
598-
}*/
644+
}
645+
}
646+
599647
case _ => {
600648
super.traverseTypeTree(tree)
601649
}
@@ -622,6 +670,7 @@ class SemanticdbConsumer(sourceFile: java.nio.file.Path) extends TastyConsumer {
622670

623671
var fittedInitClassRange: Option[s.Range] = None
624672
var forceAddBecauseParents: Boolean = false
673+
var classStacks : List[Symbol] = Nil
625674

626675
def getNumberParametersInit(defdef: DefDef)(implicit ctx: Context): Int = {
627676
defdef match {
@@ -646,7 +695,6 @@ class SemanticdbConsumer(sourceFile: java.nio.file.Path) extends TastyConsumer {
646695
super.traverseTree(tree)
647696
}
648697
case ClassDef(classname, constr, parents, selfopt, statements) => {
649-
650698
// we first add the class to the symbol list
651699
addOccurenceTree(tree,
652700
s.SymbolOccurrence.Role.DEFINITION,
@@ -677,39 +725,46 @@ class SemanticdbConsumer(sourceFile: java.nio.file.Path) extends TastyConsumer {
677725
}
678726
})
679727
forceAddBecauseParents = false
680-
681728
selfopt match {
682-
case Some(vdef @ ValDef(name, type_, _)) if name != "_" => {
683-
// To find the current position, we will heuristically
684-
// reparse the source code.
685-
// The process is done in three steps:
686-
// 1) Find a position before the '{' of the self but after any
687-
// non related '{'. Here, it will be the largest end pos of a parent
688-
// 2) Find the first '{'
689-
// 3) Iterate until the character we are seeing is a letter
690-
val startPosSearch: Int = parents.foldLeft(tree.pos.end)(
691-
(old: Int, ct: TermOrTypeTree) =>
692-
ct match {
693-
case IsTerm(t) if t.pos.end < old => t.pos.end
694-
case _ => old
695-
})
696-
var posColumn = sourceCode.indexOf("{", if (startPosSearch == tree.pos.end) tree.pos.start else startPosSearch)
697-
698-
while (posColumn < sourceCode.length && !sourceCode(posColumn).isLetter) posColumn += 1
699-
700-
addSelfDefinition(name,
701-
s.Range(0,
702-
posColumn,
703-
0,
704-
posColumn + name.length))
729+
case Some(vdef @ ValDef(name, type_, _)) => {
730+
// If name is "_" then it means it is in fact "this". We don't
731+
// want to had a symbol for it in semanticdb
732+
if (name != "_") {
733+
// The tree does not include a position to the overloaded version of
734+
// this. We find it heuristically by "parsing" the source code.
735+
// The process is done in three steps:
736+
// 1) Find a position before the '{' of the self but after any
737+
// non related '{'. Here, it will be the largest end pos of a parent
738+
// 2) Find the first '{'
739+
// 3) Iterate until the character we are seeing is a letter
740+
val startPosSearch: Int = parents.foldLeft(tree.pos.end)(
741+
(old: Int, ct: TermOrTypeTree) =>
742+
ct match {
743+
case IsTerm(t) if t.pos.end < old => t.pos.end
744+
case _ => old
745+
})
746+
var posColumn = sourceCode.indexOf("{", if (startPosSearch == tree.pos.end) tree.pos.start else startPosSearch)
747+
748+
while (posColumn < sourceCode.length && !sourceCode(posColumn).isLetter) posColumn += 1
749+
750+
addSelfDefinition(name,
751+
s.Range(0,
752+
posColumn,
753+
0,
754+
posColumn + name.length))
755+
}
705756
println(type_)
706757
traverseTypeTree(type_)
707758
}
708759
case _ =>
709760
}
710761

762+
classStacks = tree.symbol :: classStacks
763+
711764
statements.takeRight(statements.length - getNumberParametersInit(constr)).foreach(traverseTree)
712765

766+
classStacks = classStacks.tail
767+
713768
}
714769
case IsDefinition(cdef) => {
715770

@@ -761,12 +816,22 @@ class SemanticdbConsumer(sourceFile: java.nio.file.Path) extends TastyConsumer {
761816
super.traverseTree(cdef)
762817
}
763818

764-
case Term.This(what) =>
819+
case Term.This(Some(_)) => {
765820
addOccurenceTree(tree,
766821
s.SymbolOccurrence.Role.REFERENCE,
767822
posToRange(tree.pos).get)
823+
}
824+
825+
case Term.Super(_, Some(id)) =>
826+
{
827+
addOccurence(classStacks.head,
828+
s.SymbolOccurrence.Role.DEFINITION,
829+
posToRange(id.pos).get)
830+
super.traverseTree(tree)
831+
}
768832

769833
case Term.Select(qualifier, _) => {
834+
println("SELECT => " + tree)
770835
val range = {
771836
val r = rangeSelect(tree.symbol.trueName, tree.pos)
772837
if (tree.symbol.trueName == "<init>")

semanticdb/test/dotty/semanticdb/Tests.scala

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,10 @@ class Tests {
9292
@Test def testExample2(): Unit = checkFile("example/Example2.scala")
9393
@Test def testExclude(): Unit = checkFile("example/Exclude.scala")
9494
@Test def testFlags(): Unit = checkFile("example/Flags.scala")
95-
@Test def testImports(): Unit = checkFile("example/Imports.scala")
9695
@Test def testIssue1749(): Unit = checkFile("example/Issue1749.scala")
9796
@Test def testLocalFile(): Unit = checkFile("example/local-file.scala")
9897
@Test def testLocals(): Unit = checkFile("example/Locals.scala")
99-
@Test def testMacroAnnotations(): Unit = checkFile("example/MacroAnnotations.scala")
98+
//deactivated @Test def testMacroAnnotations(): Unit = checkFile("example/MacroAnnotations.scala")
10099
@Test def testMethods(): Unit = checkFile("example/Methods.scala")
101100
@Test def testMultiArguments(): Unit = checkFile("example/MultiArguments.scala")
102101
@Test def testObjects(): Unit = checkFile("example/Objects.scala")
@@ -106,6 +105,7 @@ class Tests {
106105
@Test def testSelfUse(): Unit = checkFile("example/SelfUse.scala")
107106
@Test def testTraits(): Unit = checkFile("example/Traits.scala")
108107
@Test def testTypes(): Unit = checkFile("example/Types.scala")
108+
@Test def testTypesAnnotations() : Unit = checkFile("example/TypesAnnotations.scala") // Crash, has to deal with init symbols
109109
@Test def testVals(): Unit = checkFile("example/Vals.scala")
110110
@Test def testDependantModule(): Unit = checkFile("example/DependantModule.scala")
111111
@Test def testNew(): Unit = checkFile("example/New.scala")
@@ -114,13 +114,10 @@ class Tests {
114114
@Test def testApply(): Unit = checkFile("example/Apply.scala")
115115
@Test def testMethodUsages(): Unit = checkFile("example/MethodUsages.scala")
116116
@Test def testSuper(): Unit = checkFile("example/Super.scala")
117-
@Test def testTypeBug(): Unit = checkFile("example/TypeBug.scala")*/
118-
//@Test def testTraits(): Unit = checkFile("example/Traits.scala")
117+
@Test def testTypeBug(): Unit = checkFile("example/TypeBug.scala")
119118
@Test def testSynthetic(): Unit = checkFile("example/Synthetic.scala")
120-
//@Test def testBinaryOp(): Unit = checkFile("example/BinaryOp.scala")
121-
//@Test def testAnonymous(): Unit = checkFile("example/Anonymous.scala")
119+
@Test def testBinaryOp(): Unit = checkFile("example/BinaryOp.scala") // Failure
122120
@Test def testDottyPredef(): Unit = checkFile("example/DottyPredef.scala")
123-
@Test def testCase(): Unit = checkFile("example/Case.scala")
124-
121+
*/
125122

126-
}
123+
}

0 commit comments

Comments
 (0)