Skip to content

Commit 4ca307a

Browse files
authored
convert to public API (#618)
1 parent 6f17cbe commit 4ca307a

File tree

65 files changed

+2036
-1807
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+2036
-1807
lines changed

semanticdb-javac/src/main/java/com/sourcegraph/semanticdb_javac/CompilerRange.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ public enum CompilerRange {
1818
/** Map the compiler start/end positions to SemanticDB start/end positions. */
1919
FROM_START_TO_END,
2020

21+
/**
22+
* Map the compiler point position to SemanticDB end and use (point - symbol name length) for the
23+
* SemanticDB start position.
24+
*/
25+
FROM_END_TO_SYMBOL_NAME,
26+
2127
/**
2228
* Map the compiler point position to SemanticDB start and use (point + symbol name length) for
2329
* the SemanticDB end position.
@@ -59,6 +65,16 @@ public boolean isFromPoint() {
5965
}
6066
}
6167

68+
public boolean isFromEndPoint() {
69+
switch (this) {
70+
case FROM_END_TO_SYMBOL_NAME:
71+
case FROM_END_WITH_TEXT_SEARCH:
72+
return true;
73+
default:
74+
return false;
75+
}
76+
}
77+
6278
public boolean isFromTextSearch() {
6379
switch (this) {
6480
case FROM_TEXT_SEARCH:
@@ -70,6 +86,15 @@ public boolean isFromTextSearch() {
7086
}
7187
}
7288

89+
public boolean isPlusOne() {
90+
switch (this) {
91+
case FROM_POINT_TO_SYMBOL_NAME_PLUS_ONE:
92+
return true;
93+
default:
94+
return false;
95+
}
96+
}
97+
7398
public boolean isFromEnd() {
7499
return this == CompilerRange.FROM_END_WITH_TEXT_SEARCH;
75100
}

semanticdb-javac/src/main/java/com/sourcegraph/semanticdb_javac/EmptyEndPosTable.java

Lines changed: 0 additions & 22 deletions
This file was deleted.

semanticdb-javac/src/main/java/com/sourcegraph/semanticdb_javac/GlobalSymbolsCache.java

Lines changed: 61 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,30 @@
11
package com.sourcegraph.semanticdb_javac;
22

3-
import com.sun.tools.javac.code.Symbol;
4-
53
import javax.lang.model.element.Element;
64
import javax.lang.model.element.ElementKind;
75
import javax.lang.model.element.ExecutableElement;
8-
import java.util.*;
6+
import javax.lang.model.element.TypeElement;
7+
import javax.lang.model.element.PackageElement;
8+
import javax.lang.model.element.TypeParameterElement;
9+
import javax.lang.model.element.VariableElement;
10+
import javax.lang.model.element.QualifiedNameable;
11+
import javax.lang.model.type.NoType;
12+
import java.util.IdentityHashMap;
13+
import java.util.ArrayList;
914

1015
import static com.sourcegraph.semanticdb_javac.Debugging.pprint;
1116

1217
/** Cache of SemanticDB symbols that can be referenced between files. */
1318
public final class GlobalSymbolsCache {
1419

15-
private final IdentityHashMap<Symbol, String> globals = new IdentityHashMap<>();
20+
private final IdentityHashMap<Element, String> globals = new IdentityHashMap<>();
1621
private final SemanticdbJavacOptions options;
1722

1823
public GlobalSymbolsCache(SemanticdbJavacOptions options) {
1924
this.options = options;
2025
}
2126

22-
public String semanticdbSymbol(Symbol sym, LocalSymbolsCache locals) {
27+
public String semanticdbSymbol(Element sym, LocalSymbolsCache locals) {
2328
String result = globals.get(sym);
2429
if (result != null) return result;
2530
String localResult = locals.get(sym);
@@ -31,33 +36,54 @@ public String semanticdbSymbol(Symbol sym, LocalSymbolsCache locals) {
3136
return result;
3237
}
3338

34-
public String semanticdbSymbol(Element element, LocalSymbolsCache locals) {
35-
return semanticdbSymbol((Symbol) element, locals);
36-
}
37-
38-
public boolean isNone(Symbol sym) {
39+
public boolean isNone(Element sym) {
3940
return sym == null;
4041
}
4142

42-
private String uncachedSemanticdbSymbol(Symbol sym, LocalSymbolsCache locals) {
43-
if (isNone(sym)) return SemanticdbSymbols.NONE;
44-
String owner = semanticdbSymbol(sym.owner, locals);
45-
if (owner.equals(SemanticdbSymbols.NONE)) {
46-
return SemanticdbSymbols.ROOT_PACKAGE;
47-
} else if (SemanticdbSymbols.isLocal(owner) || isAnonymousClass(sym) || isLocalVariable(sym)) {
48-
return locals.put(sym);
49-
}
43+
private String uncachedSemanticdbSymbol(Element sym, LocalSymbolsCache locals) {
44+
if (isNone(sym)) return SemanticdbSymbols.ROOT_PACKAGE;
45+
46+
if (sym instanceof PackageElement) {
47+
if (((PackageElement) sym).isUnnamed()) return SemanticdbSymbols.ROOT_PACKAGE;
48+
49+
StringBuilder sb = new StringBuilder();
50+
String qualifiedName = ((PackageElement) sym).getQualifiedName().toString();
51+
int i = 0;
52+
int j = 0;
53+
while (j < qualifiedName.length()) {
54+
if (i == qualifiedName.length() || qualifiedName.charAt(i) == '.') {
55+
final String name = qualifiedName.substring(j, i);
56+
SemanticdbSymbols.Descriptor desc =
57+
new SemanticdbSymbols.Descriptor(SemanticdbSymbols.Descriptor.Kind.Package, name);
58+
sb.append(desc.encode());
59+
j = i + 1;
60+
}
61+
i++;
62+
}
63+
64+
return sb.toString();
65+
} else
66+
// check for Module without referring to Module as it doesn't exist < JDK 9
67+
if (sym.asType() instanceof NoType) return SemanticdbSymbols.ROOT_PACKAGE;
68+
69+
if (isAnonymousClass(sym) || isLocalVariable(sym)) return locals.put(sym);
70+
71+
String owner = semanticdbSymbol(sym.getEnclosingElement(), locals);
72+
if (SemanticdbSymbols.isLocal(owner)) return locals.put(sym);
73+
5074
SemanticdbSymbols.Descriptor desc = semanticdbDescriptor(sym);
5175
if (options.verboseEnabled && desc.kind == SemanticdbSymbols.Descriptor.Kind.None) {
52-
pprint(sym.getQualifiedName().toString());
76+
if (sym instanceof QualifiedNameable)
77+
pprint(((QualifiedNameable) sym).getQualifiedName().toString());
78+
else pprint(sym.getSimpleName().toString());
5379
pprint(
5480
String.format(
5581
"sym: %s (%s - superclass %s)", sym, sym.getClass(), sym.getClass().getSuperclass()));
5682
}
5783
return SemanticdbSymbols.global(owner, desc);
5884
}
5985

60-
private boolean isLocalVariable(Symbol sym) {
86+
private boolean isLocalVariable(Element sym) {
6187
switch (sym.getKind()) {
6288
case PARAMETER:
6389
case EXCEPTION_PARAMETER:
@@ -68,28 +94,25 @@ private boolean isLocalVariable(Symbol sym) {
6894
}
6995
}
7096

71-
private boolean isAnonymousClass(Symbol sym) {
72-
return sym instanceof Symbol.ClassSymbol && sym.name.isEmpty();
97+
private boolean isAnonymousClass(Element sym) {
98+
return sym instanceof TypeElement && sym.getSimpleName().length() == 0;
7399
}
74100

75-
private SemanticdbSymbols.Descriptor semanticdbDescriptor(Symbol sym) {
76-
if (sym instanceof Symbol.ClassSymbol) {
101+
private SemanticdbSymbols.Descriptor semanticdbDescriptor(Element sym) {
102+
if (sym instanceof TypeElement) {
77103
return new SemanticdbSymbols.Descriptor(
78-
SemanticdbSymbols.Descriptor.Kind.Type, sym.name.toString());
79-
} else if (sym instanceof Symbol.MethodSymbol) {
104+
SemanticdbSymbols.Descriptor.Kind.Type, sym.getSimpleName().toString());
105+
} else if (sym instanceof ExecutableElement) {
80106
return new SemanticdbSymbols.Descriptor(
81107
SemanticdbSymbols.Descriptor.Kind.Method,
82-
sym.name.toString(),
83-
methodDisambiguator((Symbol.MethodSymbol) sym));
84-
} else if (sym instanceof Symbol.PackageSymbol) {
85-
return new SemanticdbSymbols.Descriptor(
86-
SemanticdbSymbols.Descriptor.Kind.Package, sym.name.toString());
87-
} else if (sym instanceof Symbol.TypeVariableSymbol) {
108+
sym.getSimpleName().toString(),
109+
methodDisambiguator((ExecutableElement) sym));
110+
} else if (sym instanceof TypeParameterElement) {
88111
return new SemanticdbSymbols.Descriptor(
89-
SemanticdbSymbols.Descriptor.Kind.TypeParameter, sym.name.toString());
90-
} else if (sym instanceof Symbol.VarSymbol) {
112+
SemanticdbSymbols.Descriptor.Kind.TypeParameter, sym.getSimpleName().toString());
113+
} else if (sym instanceof VariableElement) {
91114
return new SemanticdbSymbols.Descriptor(
92-
SemanticdbSymbols.Descriptor.Kind.Term, sym.name.toString());
115+
SemanticdbSymbols.Descriptor.Kind.Term, sym.getSimpleName().toString());
93116
} else {
94117
return SemanticdbSymbols.Descriptor.NONE;
95118
}
@@ -113,11 +136,11 @@ private SemanticdbSymbols.Descriptor semanticdbDescriptor(Symbol sym) {
113136
* <p><a href="https://scalameta.org/docs/semanticdb/specification.html#symbol-2">Link to
114137
* SemanticDB spec</a>.
115138
*/
116-
private String methodDisambiguator(Symbol.MethodSymbol sym) {
117-
Iterable<? extends Element> elements = sym.owner.getEnclosedElements();
139+
private String methodDisambiguator(ExecutableElement sym) {
140+
Iterable<? extends Element> elements = sym.getEnclosingElement().getEnclosedElements();
118141
ArrayList<ExecutableElement> methods = new ArrayList<>();
119142
for (Element e : elements) {
120-
if (e instanceof ExecutableElement && e.getSimpleName() == sym.name) {
143+
if (e instanceof ExecutableElement && e.getSimpleName() == sym.getSimpleName()) {
121144
methods.add((ExecutableElement) e);
122145
}
123146
}

semanticdb-javac/src/main/java/com/sourcegraph/semanticdb_javac/LocalSymbolsCache.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
package com.sourcegraph.semanticdb_javac;
22

3-
import com.sun.tools.javac.code.Symbol;
3+
import javax.lang.model.element.Element;
44

55
import java.util.IdentityHashMap;
66

77
/** Cache of SemanticDB symbols that are local to a single file. */
88
public final class LocalSymbolsCache {
99

10-
private final IdentityHashMap<Symbol, String> symbols = new IdentityHashMap<>();
10+
private final IdentityHashMap<Element, String> symbols = new IdentityHashMap<>();
1111
private int localsCounter = -1;
1212

13-
public String get(Symbol sym) {
13+
public String get(Element sym) {
1414
return symbols.get(sym);
1515
}
1616

17-
public String put(Symbol sym) {
17+
public String put(Element sym) {
1818
localsCounter++;
1919
String result = SemanticdbSymbols.local(localsCounter);
2020
symbols.put(sym, result);

semanticdb-javac/src/main/java/com/sourcegraph/semanticdb_javac/RangeFinder.java

Lines changed: 71 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,93 @@
11
package com.sourcegraph.semanticdb_javac;
22

3-
import com.sun.source.tree.CompilationUnitTree;
4-
import com.sun.source.tree.LineMap;
5-
import com.sun.source.util.TreePath;
6-
import com.sun.source.util.Trees;
3+
import javax.tools.Diagnostic;
74

85
import javax.lang.model.element.Element;
9-
import javax.lang.model.element.Name;
10-
import java.io.IOException;
11-
import java.util.HashMap;
126
import java.util.Optional;
13-
import java.util.regex.Matcher;
14-
import java.util.regex.Pattern;
15-
16-
import static com.sourcegraph.semanticdb_javac.Debugging.pprint;
177

188
public class RangeFinder {
19-
public static Optional<Semanticdb.Range> findRange(
20-
TreePath path,
21-
Trees trees,
22-
CompilationUnitTree root,
9+
public static class StartEndRange {
10+
public int start;
11+
public int end;
12+
13+
StartEndRange(int start, int end) {
14+
this.start = start;
15+
this.end = end;
16+
}
17+
}
18+
19+
public static Optional<StartEndRange> findRange(
2320
Element element,
24-
int startPos,
21+
String name,
22+
int originalStartPos,
23+
int originalEndPos,
2524
String source,
2625
boolean fromEnd) {
27-
LineMap lineMap = root.getLineMap();
28-
Name name = element.getSimpleName();
29-
if (name.contentEquals("<init>")) name = element.getEnclosingElement().getSimpleName();
30-
31-
int endPos = (int) trees.getSourcePositions().getEndPosition(root, path.getLeaf());
32-
// false for anonymous classes
33-
if (name.length() != 0) {
34-
startPos = findNameIn(name, fromEnd ? endPos : startPos, source, fromEnd);
35-
endPos = startPos + name.length();
36-
}
26+
int startPos = findNameIn(name, originalStartPos, originalEndPos, element, source, fromEnd);
27+
int endPos = startPos + name.length();
3728

3829
if (endPos == -1 || startPos == -1) {
3930
return Optional.empty();
4031
}
4132

42-
Semanticdb.Range range =
43-
Semanticdb.Range.newBuilder()
44-
.setStartLine((int) lineMap.getLineNumber(startPos) - 1)
45-
.setStartCharacter((int) lineMap.getColumnNumber(startPos) - 1)
46-
.setEndLine((int) lineMap.getLineNumber(endPos) - 1)
47-
.setEndCharacter((int) lineMap.getColumnNumber(endPos) - 1)
48-
.build();
49-
return Optional.of(range);
33+
return Optional.of(new StartEndRange(startPos, endPos));
34+
}
35+
36+
private static int findNameFromEnd(
37+
String name,
38+
int originalStartPos,
39+
int originalEndPos,
40+
int end,
41+
Element element,
42+
String source) {
43+
if (end < 0) return -1;
44+
int offset = source.lastIndexOf(name, end);
45+
if (offset == -1 && originalStartPos != Diagnostic.NOPOS && originalEndPos != Diagnostic.NOPOS)
46+
return originalStartPos;
47+
if (offset == -1) {
48+
return -1;
49+
}
50+
int endOfWord = offset + name.length();
51+
// found name in wrong word? e.g. finding `"A"` in `A("A")`
52+
if (offset > 0 && Character.isJavaIdentifierPart(source.charAt(offset - 1)))
53+
return findNameFromEnd(name, originalStartPos, originalEndPos, offset - 1, element, source);
54+
if (endOfWord < source.length() && Character.isJavaIdentifierPart(source.charAt(endOfWord)))
55+
return findNameFromEnd(name, originalStartPos, originalEndPos, offset - 1, element, source);
56+
57+
return offset;
58+
}
59+
60+
private static int findNameFromStart(
61+
String name,
62+
int start,
63+
int originalStartPos,
64+
int originalEndPos,
65+
Element element,
66+
String source) {
67+
if (start >= source.length()) return -1;
68+
int offset = source.indexOf(name, start);
69+
if (offset == -1 && originalStartPos != Diagnostic.NOPOS && originalEndPos != Diagnostic.NOPOS)
70+
return originalStartPos;
71+
if (offset == -1) {
72+
return -1;
73+
}
74+
int end = offset + name.length();
75+
// found name in wrong word? e.g. finding `"A"` in `A("A")`
76+
if (offset > 0 && Character.isJavaIdentifierPart(source.charAt(offset - 1)))
77+
return findNameFromStart(name, end + 1, originalStartPos, originalEndPos, element, source);
78+
if (end < source.length() && Character.isJavaIdentifierPart(source.charAt(end)))
79+
return findNameFromStart(name, end + 1, originalStartPos, originalEndPos, element, source);
80+
81+
return offset;
5082
}
5183

52-
private static int findNameIn(CharSequence name, int start, String source, boolean fromEnd) {
53-
if (source.equals("")) return -1;
84+
private static int findNameIn(
85+
String name, int start, int end, Element element, String source, boolean fromEnd) {
86+
if (source.length() == 0) return -1;
5487

5588
int offset;
56-
if (fromEnd) offset = source.lastIndexOf(name.toString(), start);
57-
else offset = source.indexOf(name.toString(), start);
89+
if (fromEnd) offset = findNameFromEnd(name, start, start, end, element, source);
90+
else offset = findNameFromStart(name, start, end, end, element, source);
5891
if (offset > -1) {
5992
return offset;
6093
}

0 commit comments

Comments
 (0)