@@ -44,7 +44,7 @@ import dotty.tools.dotc.util.SourceFile
4444 val metacSb : StringBuilder = StringBuilder (5000 )
4545 val semanticdbPath = inputFile()
4646 val doc = Tools .loadTextDocumentUnsafe(sourceSrc.toAbsolutePath, semanticdbPath)
47- Tools .metac(doc, Paths .get(doc.uri))(using metacSb)
47+ SemanticdbTests .metac(doc, Paths .get(doc.uri))(using metacSb)
4848 Files .write(rootSrc.resolve(" metac.expect" ), metacSb.toString.getBytes(StandardCharsets .UTF_8 ))
4949
5050
@@ -86,7 +86,7 @@ class SemanticdbTests:
8686 .resolveSibling(filename + " .semanticdb" )
8787 val expectPath = source.resolveSibling(filename.replace(" .scala" , " .expect.scala" ))
8888 val doc = Tools .loadTextDocument(source, relpath, semanticdbPath)
89- Tools .metac(doc, rootSrc.relativize(source))(using metacSb)
89+ SemanticdbTests .metac(doc, rootSrc.relativize(source))(using metacSb)
9090 val obtained = trimTrailingWhitespace(SemanticdbTests .printTextDocument(doc))
9191 collectErrorOrUpdate(expectPath, obtained)
9292 collectErrorOrUpdate(metacExpectFile, metacSb.toString)
@@ -157,4 +157,101 @@ object SemanticdbTests:
157157 out.flush()
158158 DocumentPrinter .textDocumentPrettyPrint(byteStream.toByteArray.nn)
159159 end printTextDocument
160+
161+ def metac (doc : TextDocument , realPath : Path )(using sb : StringBuilder ): StringBuilder =
162+ val symtab = PrinterSymtab .fromTextDocument(doc)
163+ val symPrinter = SymbolInformationPrinter (symtab)
164+ val realURI = realPath.toString
165+ given sourceFile : SourceFile = SourceFile .virtual(doc.uri, doc.text)
166+ val synthPrinter = SyntheticPrinter (symtab, sourceFile)
167+ sb.append(realURI).nl
168+ sb.append(" -" * realURI.length).nl
169+ sb.nl
170+ sb.append(" Summary:" ).nl
171+ sb.append(" Schema => " ).append(schemaString(doc.schema)).nl
172+ sb.append(" Uri => " ).append(doc.uri).nl
173+ sb.append(" Text => empty" ).nl
174+ sb.append(" Language => " ).append(languageString(doc.language)).nl
175+ sb.append(" Symbols => " ).append(doc.symbols.length).append(" entries" ).nl
176+ sb.append(" Occurrences => " ).append(doc.occurrences.length).append(" entries" ).nl
177+ if doc.diagnostics.nonEmpty then
178+ sb.append(" Diagnostics => " ).append(doc.diagnostics.length).append(" entries" ).nl
179+ if doc.synthetics.nonEmpty then
180+ sb.append(" Synthetics => " ).append(doc.synthetics.length).append(" entries" ).nl
181+ sb.nl
182+ sb.append(" Symbols:" ).nl
183+ doc.symbols.sorted.foreach(s => processSymbol(s, symPrinter))
184+ sb.nl
185+ sb.append(" Occurrences:" ).nl
186+ doc.occurrences.sorted.foreach(processOccurrence)
187+ sb.nl
188+ if doc.diagnostics.nonEmpty then
189+ sb.append(" Diagnostics:" ).nl
190+ doc.diagnostics.sorted.foreach(d => processDiag(d))
191+ sb.nl
192+ if doc.synthetics.nonEmpty then
193+ sb.append(" Synthetics:" ).nl
194+ doc.synthetics.sorted.foreach(s => processSynth(s, synthPrinter))
195+ sb.nl
196+ sb
197+ end metac
198+
199+ private def schemaString (schema : Schema ) =
200+ import Schema .*
201+ schema match
202+ case SEMANTICDB3 => " SemanticDB v3"
203+ case SEMANTICDB4 => " SemanticDB v4"
204+ case LEGACY => " SemanticDB legacy"
205+ case Unrecognized (_) => " unknown"
206+ end schemaString
207+
208+ private def languageString (language : Language ) =
209+ import Language .*
210+ language match
211+ case SCALA => " Scala"
212+ case JAVA => " Java"
213+ case UNKNOWN_LANGUAGE | Unrecognized (_) => " unknown"
214+ end languageString
215+
216+ private def processSymbol (info : SymbolInformation , printer : SymbolInformationPrinter )(using sb : StringBuilder ): Unit =
217+ sb.append(printer.pprintSymbolInformation(info)).nl
218+
219+ private def processSynth (synth : Synthetic , printer : SyntheticPrinter )(using sb : StringBuilder ): Unit =
220+ sb.append(printer.pprint(synth)).nl
221+
222+ private def processDiag (d : Diagnostic )(using sb : StringBuilder ): Unit =
223+ d.range match
224+ case Some (range) => processRange(sb, range)
225+ case _ => sb.append(" [):" )
226+ sb.append(" " )
227+ d.severity match
228+ case Diagnostic .Severity .ERROR => sb.append(" [error]" )
229+ case Diagnostic .Severity .WARNING => sb.append(" [warning]" )
230+ case Diagnostic .Severity .INFORMATION => sb.append(" [info]" )
231+ case _ => sb.append(" [unknown]" )
232+ sb.append(" " )
233+ sb.append(d.message)
234+ sb.nl
235+
236+ private def processOccurrence (occ : SymbolOccurrence )(using sb : StringBuilder , sourceFile : SourceFile ): Unit =
237+ occ.range match
238+ case Some (range) =>
239+ processRange(sb, range)
240+ if range.endLine == range.startLine
241+ && range.startCharacter != range.endCharacter
242+ && ! (occ.symbol.isConstructor && occ.role.isDefinition) then
243+ val line = sourceFile.lineContent(sourceFile.lineToOffset(range.startLine))
244+ assert(range.startCharacter <= line.length && range.endCharacter <= line.length,
245+ s " Line is only ${line.length} - start line was ${range.startLine} in source ${sourceFile.file.name}"
246+ )
247+ sb.append(" " ).append(line.substring(range.startCharacter, range.endCharacter))
248+ case _ =>
249+ sb.append(" [):" )
250+ end match
251+ sb.append(if occ.role.isReference then " -> " else " <- " ).append(occ.symbol).nl
252+ end processOccurrence
253+
254+ extension (sb : StringBuilder )
255+ private inline def nl = sb.append(System .lineSeparator)
256+
160257end SemanticdbTests
0 commit comments