Skip to content

Commit 923efaf

Browse files
authored
Merge pull request #398 from olafurpg/synthetic-symbols
2 parents 604e3b0 + 23c3387 commit 923efaf

File tree

16 files changed

+251
-6
lines changed

16 files changed

+251
-6
lines changed

lsif-java/src/main/scala/com/sourcegraph/lsif_java/SemanticdbPrinters.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ object SemanticdbPrinters {
1717
comments: CommentSyntax = CommentSyntax.default
1818
): String = {
1919
val occurrencesByLine = LsifTextDocument
20-
.sortedSymbolOccurrences(doc)
20+
.sortedSymbolOccurrences(
21+
LsifTextDocument.manifestOccurrencesForSyntheticSymbols(doc)
22+
)
2123
.asScala
2224
.groupBy(_.getRange.getStartLine)
2325
val out = new StringBuilder()

lsif-semanticdb/src/main/java/com/sourcegraph/lsif_semanticdb/LsifTextDocument.java

Lines changed: 70 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
package com.sourcegraph.lsif_semanticdb;
22

33
import com.sourcegraph.semanticdb_javac.Semanticdb;
4+
import com.sourcegraph.semanticdb_javac.SemanticdbSymbols;
5+
46
import java.nio.file.Path;
5-
import java.util.ArrayList;
6-
import java.util.HashMap;
7-
import java.util.List;
8-
import java.util.Map;
7+
import java.util.*;
98

109
/** Wrapper around a SemanticDB TextDocument with LSIF-related utilities. */
1110
public class LsifTextDocument {
@@ -74,9 +73,75 @@ void visitIdTree(Semanticdb.IdTree tree) {
7473
}
7574

7675
private void setSemanticdb(Semanticdb.TextDocument semanticdb) {
77-
this.semanticdb = semanticdb;
76+
this.semanticdb = manifestOccurrencesForSyntheticSymbols(semanticdb);
7877
for (Semanticdb.SymbolInformation info : semanticdb.getSymbolsList()) {
7978
symbols.put(info.getSymbol(), info);
8079
}
8180
}
81+
82+
public static Semanticdb.TextDocument manifestOccurrencesForSyntheticSymbols(
83+
Semanticdb.TextDocument semanticdb) {
84+
if (semanticdb.getLanguage() != Semanticdb.Language.SCALA) {
85+
// It's only semanticdb-scalac that emits SymbolInformation for symbols that have no
86+
// definition occurrences.
87+
return semanticdb;
88+
}
89+
Semanticdb.TextDocument.Builder builder = Semanticdb.TextDocument.newBuilder(semanticdb);
90+
HashMap<String, Semanticdb.SymbolOccurrence> definitionOccurrences = new HashMap<>();
91+
for (Semanticdb.SymbolOccurrence occ : semanticdb.getOccurrencesList()) {
92+
if (occ.getRole() == Semanticdb.SymbolOccurrence.Role.DEFINITION) {
93+
definitionOccurrences.put(occ.getSymbol(), occ);
94+
}
95+
}
96+
for (Semanticdb.SymbolInformation info : semanticdb.getSymbolsList()) {
97+
Semanticdb.SymbolOccurrence definition = definitionOccurrences.get(info.getSymbol());
98+
if (definition != null) {
99+
continue;
100+
}
101+
for (String alternativeSymbol : alternativeSymbols(info)) {
102+
Semanticdb.SymbolOccurrence alternativeDefinition =
103+
definitionOccurrences.get(alternativeSymbol);
104+
if (alternativeDefinition != null) {
105+
builder.addOccurrences(
106+
Semanticdb.SymbolOccurrence.newBuilder(alternativeDefinition)
107+
.setSymbol(info.getSymbol()));
108+
break;
109+
}
110+
}
111+
}
112+
return builder.build();
113+
}
114+
115+
public static final Set<String> syntheticCaseClassMethodNames =
116+
new HashSet<>(Arrays.asList("copy", "productElement", "productElementName"));
117+
public static final Set<String> syntheticCompanionObjectNames =
118+
new HashSet<>(Arrays.asList("apply", "copy"));
119+
120+
public static List<String> alternativeSymbols(Semanticdb.SymbolInformation info) {
121+
ArrayList<String> alternatives = new ArrayList<>();
122+
SymbolDescriptor sym = SymbolDescriptor.parseFromSymbol(info.getSymbol());
123+
switch (sym.descriptor.kind) {
124+
case Method:
125+
if (sym.descriptor.name.endsWith("_=")) {
126+
String newName = sym.descriptor.name.substring(0, sym.descriptor.name.length() - 2);
127+
alternatives.add(SemanticdbSymbols.global(sym.owner, sym.descriptor.withName(newName)));
128+
} else if (syntheticCaseClassMethodNames.contains(sym.descriptor.name)) {
129+
alternatives.add(sym.owner);
130+
} else if (syntheticCompanionObjectNames.contains(sym.descriptor.name)) {
131+
alternatives.add(sym.owner);
132+
SymbolDescriptor owner = SymbolDescriptor.parseFromSymbol(sym.owner);
133+
alternatives.add(
134+
SemanticdbSymbols.global(
135+
owner.owner, owner.descriptor.withKind(SemanticdbSymbols.Descriptor.Kind.Type)));
136+
}
137+
break;
138+
case Term:
139+
alternatives.add(
140+
SemanticdbSymbols.global(
141+
sym.owner, sym.descriptor.withKind(SemanticdbSymbols.Descriptor.Kind.Type)));
142+
break;
143+
default:
144+
}
145+
return alternatives;
146+
}
82147
}

semanticdb-java/src/main/java/com/sourcegraph/semanticdb_javac/SemanticdbSymbols.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,14 @@ public Descriptor(Kind kind, String name, String disambiguator) {
7979
this.disambiguator = disambiguator;
8080
}
8181

82+
public Descriptor withName(String newName) {
83+
return new Descriptor(kind, newName, disambiguator);
84+
}
85+
86+
public Descriptor withKind(Kind newKind) {
87+
return new Descriptor(newKind, name, disambiguator);
88+
}
89+
8290
public static Descriptor local(String name) {
8391
return new Descriptor(Kind.Local, name);
8492
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package minimized
2+
3+
case class Issue396(a: Int)
4+
object Issue396App {
5+
println(Issue396)
6+
Issue396.apply(42).copy(a = 41)
7+
Issue396.apply(42).productElement(0)
8+
Issue396.apply(42).productElementName(0)
9+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package minimized
2+
3+
class Issue397 {
4+
var blah = Set("abc")
5+
blah = Set.empty[String]
6+
}

tests/snapshots/src/main/generated/BaseByteRenderer.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import upickle.core.{ArrVisitor, ObjVisitor}
2323
*/
2424
class BaseByteRenderer[T <: upickle.core.ByteOps.Output]
2525
// ^^^^^^^^^^^^^^^^ definition ujson/BaseByteRenderer# class BaseByteRenderer[T <: Output]
26+
// ^^^^^^^^^^^^^^^^ definition ujson/BaseByteRenderer. object BaseByteRenderer
2627
// ^ definition ujson/BaseByteRenderer#[T] T <: Output
2728
// ^^^^^^^ reference upickle/
2829
// ^^^^ reference upickle/core/
@@ -65,11 +66,13 @@ class BaseByteRenderer[T <: upickle.core.ByteOps.Output]
6566

6667
private[this] var depth: Int = 0
6768
// ^^^^^ definition ujson/BaseByteRenderer#depth(). private[this] var depth: Int
69+
// ^^^^^ definition ujson/BaseByteRenderer#`depth_=`(). private[this] var depth_=(x$1: Int): Unit
6870
// ^^^ reference scala/Int#
6971

7072

7173
private[this] var commaBuffered = false
7274
// ^^^^^^^^^^^^^ definition ujson/BaseByteRenderer#commaBuffered(). private[this] var commaBuffered: Boolean
75+
// ^^^^^^^^^^^^^ definition ujson/BaseByteRenderer#`commaBuffered_=`(). private[this] var commaBuffered_=(x$1: Boolean): Unit
7376

7477
def flushBuffer() = {
7578
// ^^^^^^^^^^^ definition ujson/BaseByteRenderer#flushBuffer(). def flushBuffer(): Unit

tests/snapshots/src/main/generated/BaseCharRenderer.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import upickle.core.{ArrVisitor, ObjVisitor}
2323
*/
2424
class BaseCharRenderer[T <: upickle.core.CharOps.Output]
2525
// ^^^^^^^^^^^^^^^^ definition ujson/BaseCharRenderer# class BaseCharRenderer[T <: Output]
26+
// ^^^^^^^^^^^^^^^^ definition ujson/BaseCharRenderer. object BaseCharRenderer
2627
// ^ definition ujson/BaseCharRenderer#[T] T <: Output
2728
// ^^^^^^^ reference upickle/
2829
// ^^^^ reference upickle/core/
@@ -65,11 +66,13 @@ class BaseCharRenderer[T <: upickle.core.CharOps.Output]
6566

6667
private[this] var depth: Int = 0
6768
// ^^^^^ definition ujson/BaseCharRenderer#depth(). private[this] var depth: Int
69+
// ^^^^^ definition ujson/BaseCharRenderer#`depth_=`(). private[this] var depth_=(x$1: Int): Unit
6870
// ^^^ reference scala/Int#
6971

7072

7173
private[this] var commaBuffered = false
7274
// ^^^^^^^^^^^^^ definition ujson/BaseCharRenderer#commaBuffered(). private[this] var commaBuffered: Boolean
75+
// ^^^^^^^^^^^^^ definition ujson/BaseCharRenderer#`commaBuffered_=`(). private[this] var commaBuffered_=(x$1: Boolean): Unit
7376

7477
def flushBuffer() = {
7578
// ^^^^^^^^^^^ definition ujson/BaseCharRenderer#flushBuffer(). def flushBuffer(): Unit
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package minimized
2+
// ^^^^^^^^^ definition minimized/
3+
4+
case class Issue396(a: Int)
5+
// ^^^^^^^^ definition minimized/Issue396# case class Issue396(a: Int)
6+
// ^^^^^^^^ definition minimized/Issue396#copy(). def copy(a: Int): Issue396
7+
// ^^^^^^^^ definition minimized/Issue396#productElement(). def productElement(x$1: Int): Any
8+
// ^^^^^^^^ definition minimized/Issue396. object Issue396
9+
// ^^^^^^^^ definition minimized/Issue396.apply(). def apply(a: Int): Issue396
10+
// ^^^^^^^^ definition minimized/Issue396#productElementName(). def productElementName(x$1: Int): String
11+
// definition minimized/Issue396#`<init>`(). def this(a: Int)
12+
// ^ definition minimized/Issue396#a. val a: Int
13+
// ^^^ reference scala/Int#
14+
object Issue396App {
15+
// ^^^^^^^^^^^ definition minimized/Issue396App. object Issue396App
16+
println(Issue396)
17+
//^^^^^^^ reference scala/Predef.println(+1).
18+
// ^^^^^^^^ reference minimized/Issue396.
19+
Issue396.apply(42).copy(a = 41)
20+
//^^^^^^^^ reference minimized/Issue396.
21+
// ^^^^^ reference minimized/Issue396.apply().
22+
// ^^^^ reference minimized/Issue396#copy().
23+
// ^ reference minimized/Issue396#copy().(a)
24+
Issue396.apply(42).productElement(0)
25+
//^^^^^^^^ reference minimized/Issue396.
26+
// ^^^^^ reference minimized/Issue396.apply().
27+
// ^^^^^^^^^^^^^^ reference minimized/Issue396#productElement().
28+
Issue396.apply(42).productElementName(0)
29+
//^^^^^^^^ reference minimized/Issue396.
30+
// ^^^^^ reference minimized/Issue396.apply().
31+
// ^^^^^^^^^^^^^^^^^^ reference minimized/Issue396#productElementName().
32+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package minimized
2+
// ^^^^^^^^^ definition minimized/
3+
4+
class Issue397 {
5+
// ^^^^^^^^ definition minimized/Issue397# class Issue397
6+
// definition minimized/Issue397#`<init>`(). def this()
7+
var blah = Set("abc")
8+
// ^^^^ definition minimized/Issue397#blah(). var blah: Set[String]
9+
// ^^^^ definition minimized/Issue397#`blah_=`(). var blah_=(x$1: Set[String]): Unit
10+
// ^^^ reference scala/Predef.Set.
11+
// reference scala/collection/IterableFactory#apply().
12+
blah = Set.empty[String]
13+
//^^^^ reference minimized/Issue397#`blah_=`().
14+
// ^^^ reference scala/Predef.Set.
15+
// ^^^^^ reference scala/collection/immutable/Set.empty().
16+
// ^^^^^^ reference scala/Predef.String#
17+
}

tests/snapshots/src/main/generated/minimized/MinimizedScalaSignatures.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ package minimized
66

77
case class MinimizedCaseClass(value: String) {
88
// ^^^^^^^^^^^^^^^^^^ definition minimized/MinimizedCaseClass# case class MinimizedCaseClass(value: String)
9+
// ^^^^^^^^^^^^^^^^^^ definition minimized/MinimizedCaseClass.apply(). def apply(value: String): MinimizedCaseClass
10+
// ^^^^^^^^^^^^^^^^^^ definition minimized/MinimizedCaseClass#productElement(). def productElement(x$1: Int): Any
11+
// ^^^^^^^^^^^^^^^^^^ definition minimized/MinimizedCaseClass. object MinimizedCaseClass
12+
// ^^^^^^^^^^^^^^^^^^ definition minimized/MinimizedCaseClass#productElementName(). def productElementName(x$1: Int): String
13+
// ^^^^^^^^^^^^^^^^^^ definition minimized/MinimizedCaseClass#copy(). def copy(value: String): MinimizedCaseClass
914
// definition minimized/MinimizedCaseClass#`<init>`(). def this(value: String)
1015
// ^^^^^ definition minimized/MinimizedCaseClass#value. val value: String
1116
// ^^^^^^ reference scala/Predef.String#

0 commit comments

Comments
 (0)