77import com .sourcegraph .semanticdb_javac .Semanticdb .SymbolOccurrence ;
88import com .sourcegraph .semanticdb_javac .Semanticdb .SymbolOccurrence .Role ;
99import com .sourcegraph .semanticdb_javac .SemanticdbSymbols ;
10+ import lib .codeintel .lsif_typed .LsifTyped ;
1011
1112import java .io .IOException ;
13+ import java .net .URI ;
1214import java .nio .file .Files ;
1315import java .nio .file .Path ;
16+ import java .nio .file .Paths ;
1417import java .util .*;
1518import java .util .concurrent .ConcurrentHashMap ;
1619import java .util .stream .Collectors ;
1720import java .util .stream .Stream ;
21+ import java .util .stream .StreamSupport ;
1822
1923/** The core logic that converts SemanticDB into LSIF. */
2024public class LsifSemanticdb {
@@ -49,6 +53,114 @@ private void run() throws IOException {
4953 return ;
5054 }
5155 options .reporter .startProcessing (files .size ());
56+ if (options .format .isTyped ()) {
57+ runTyped (files , packages );
58+ } else {
59+ runGraph (files , packages );
60+ }
61+ writer .build ();
62+ options .reporter .endProcessing ();
63+ }
64+
65+ private void runTyped (List <Path > files , PackageTable packages ) {
66+ writer .emitTyped (typedMetadata ());
67+ filesStream (files ).forEach (document -> processTypedDocument (document , packages ));
68+ }
69+
70+ private String typedSymbol (String symbol , Package pkg ) {
71+ if (symbol .startsWith ("local" )) {
72+ return "local " + symbol .substring ("local" .length ());
73+ }
74+ return "semanticdb maven " + pkg .repoName () + " " + pkg .version () + " " + symbol ;
75+ }
76+
77+ private void processTypedDocument (Path path , PackageTable packages ) {
78+ for (LsifTextDocument doc : parseTextDocument (path ).collect (Collectors .toList ())) {
79+ if (doc .semanticdb .getOccurrencesCount () == 0 ) {
80+ continue ;
81+ }
82+
83+ Path absolutePath = Paths .get (URI .create (doc .semanticdb .getUri ()));
84+ String relativePath =
85+ StreamSupport .stream (options .sourceroot .relativize (absolutePath ).spliterator (), false )
86+ .map (p -> p .getFileName ().toString ())
87+ .collect (Collectors .joining ("/" ));
88+ LsifTyped .Document .Builder tdoc =
89+ LsifTyped .Document .newBuilder ().setRelativePath (relativePath );
90+ for (SymbolOccurrence occ : doc .sortedSymbolOccurrences ()) {
91+ int role = 0 ;
92+ if (occ .getRole () == Role .DEFINITION ) {
93+ role |= LsifTyped .SymbolRole .Definition_VALUE ;
94+ }
95+ boolean isSingleLineRange = occ .getRange ().getStartLine () == occ .getRange ().getEndLine ();
96+ Iterable <Integer > range =
97+ isSingleLineRange
98+ ? Arrays .asList (
99+ occ .getRange ().getStartLine (),
100+ occ .getRange ().getStartCharacter (),
101+ occ .getRange ().getEndCharacter ())
102+ : Arrays .asList (
103+ occ .getRange ().getStartLine (),
104+ occ .getRange ().getStartCharacter (),
105+ occ .getRange ().getEndLine (),
106+ occ .getRange ().getEndCharacter ());
107+ Package pkg = packages .packageForSymbol (occ .getSymbol ()).orElse (Package .EMPTY );
108+ tdoc .addOccurrences (
109+ LsifTyped .Occurrence .newBuilder ()
110+ .addAllRange (range )
111+ .setSymbol (typedSymbol (occ .getSymbol (), pkg ))
112+ .setSymbolRoles (role ));
113+ }
114+ Symtab symtab = new Symtab (doc .semanticdb );
115+ for (SymbolInformation info : doc .semanticdb .getSymbolsList ()) {
116+ Package pkg = packages .packageForSymbol (info .getSymbol ()).orElse (Package .EMPTY );
117+ LsifTyped .SymbolInformation .Builder tinfo =
118+ LsifTyped .SymbolInformation .newBuilder ().setSymbol (typedSymbol (info .getSymbol (), pkg ));
119+
120+ for (String overriddenSymbol : info .getOverriddenSymbolsList ()) {
121+ if (isIgnoredOverriddenSymbol (overriddenSymbol )) {
122+ continue ;
123+ }
124+ Package overriddenSymbolPkg =
125+ packages .packageForSymbol (overriddenSymbol ).orElse (Package .EMPTY );
126+ tinfo .addRelationships (
127+ LsifTyped .Relationship .newBuilder ()
128+ .setSymbol (typedSymbol (overriddenSymbol , overriddenSymbolPkg ))
129+ .setIsImplementation (true )
130+ .setIsReference (SemanticdbSymbols .isMethod (info .getSymbol ())));
131+ }
132+ if (info .hasSignature ()) {
133+ String language =
134+ doc .semanticdb .getLanguage ().toString ().toLowerCase (Locale .ROOT ).intern ();
135+ String signature = new SignatureFormatter (info , symtab ).formatSymbol ();
136+ tinfo .addDocumentation ("```" + language + "\n " + signature + "\n ```" );
137+ }
138+ String documentation = info .getDocumentation ().getMessage ();
139+ if (!documentation .isEmpty ()) {
140+ tinfo .addDocumentation (documentation );
141+ }
142+ tdoc .addSymbols (tinfo );
143+ }
144+ writer .emitTyped (LsifTyped .Index .newBuilder ().addDocuments (tdoc ).build ());
145+ }
146+ }
147+
148+ private LsifTyped .Index typedMetadata () {
149+ return LsifTyped .Index .newBuilder ()
150+ .setMetadata (
151+ LsifTyped .Metadata .newBuilder ()
152+ .setVersion (LsifTyped .ProtocolVersion .UnspecifiedProtocolVersion )
153+ .setProjectRoot (options .sourceroot .toUri ().toString ())
154+ .setTextDocumentEncoding (LsifTyped .TextEncoding .UTF8 )
155+ .setToolInfo (
156+ LsifTyped .ToolInfo .newBuilder ()
157+ .setName (options .toolInfo .getName ())
158+ .setVersion (options .toolInfo .getVersion ())
159+ .addAllArguments (options .toolInfo .getArgsList ())))
160+ .build ();
161+ }
162+
163+ private void runGraph (List <Path > files , PackageTable packages ) {
52164 writer .emitMetaData ();
53165 int projectId = writer .emitProject (options .language );
54166
@@ -57,11 +169,7 @@ private void run() throws IOException {
57169 filesStream (files )
58170 .flatMap (d -> processPath (d , isExportedSymbol , packages ))
59171 .collect (Collectors .toList ());
60-
61172 writer .emitContains (projectId , documentIds );
62-
63- writer .build ();
64- options .reporter .endProcessing ();
65173 }
66174
67175 private Stream <Path > filesStream (List <Path > files ) {
@@ -170,16 +278,22 @@ private Integer processDocumentUnsafe(
170278
171279 // Overrides
172280 if (symbolInformation .getOverriddenSymbolsCount () > 0 ) {
173- int [] overriddenReferenceResultIds = new int [symbolInformation .getOverriddenSymbolsCount ()];
281+ List <Integer > overriddenReferenceResultIds =
282+ new ArrayList <>(symbolInformation .getOverriddenSymbolsCount ());
174283 for (int i = 0 ; i < symbolInformation .getOverriddenSymbolsCount (); i ++) {
175284 String overriddenSymbol = symbolInformation .getOverriddenSymbols (i );
285+ if (isIgnoredOverriddenSymbol (overriddenSymbol )) {
286+ continue ;
287+ }
176288 ResultIds overriddenIds = results .getOrInsertResultSet (overriddenSymbol );
177- overriddenReferenceResultIds [ i ] = overriddenIds .referenceResult ;
289+ overriddenReferenceResultIds . add ( overriddenIds .referenceResult ) ;
178290 writer .emitReferenceResultsItemEdge (
179- overriddenIds .referenceResult , new int [] {rangeId }, doc .id );
291+ overriddenIds .referenceResult , Collections .singletonList (rangeId ), doc .id );
292+ }
293+ if (overriddenReferenceResultIds .size () > 0 ) {
294+ writer .emitReferenceResultsItemEdge (
295+ ids .referenceResult , overriddenReferenceResultIds , doc .id );
180296 }
181- writer .emitReferenceResultsItemEdge (
182- ids .referenceResult , overriddenReferenceResultIds , doc .id );
183297 }
184298 }
185299 writer .emitContains (doc .id , new ArrayList <>(rangeIds ));
@@ -214,4 +328,10 @@ private Semanticdb.TextDocuments textDocumentsParseFrom(Path semanticdbPath) thr
214328 return Semanticdb .TextDocuments .parseFrom (bytes );
215329 }
216330 }
331+
332+ private boolean isIgnoredOverriddenSymbol (String symbol ) {
333+ // Skip java/lang/Object# since it's the parent of all classes
334+ // making it noisy for "find implementations" results.
335+ return symbol .equals ("java/lang/Object#" );
336+ }
217337}
0 commit comments