import { Input } from './Input' import * as lsif from './lsif' import { Range } from './Range' const lsiftyped = lsif.lib.codeintel.lsiftyped export function formatSnapshot( input: Input, document: lsif.lib.codeintel.lsiftyped.Document ): string { const out: string[] = [] document.occurrences.sort(occurrencesByLine) const symbolTable = new Map< string, lsif.lib.codeintel.lsiftyped.SymbolInformation >() for (const symbolInfo of document.symbols) { symbolTable.set(symbolInfo.symbol, symbolInfo) } let occurrenceIndex = 0 for (const [lineNumber, line] of input.lines.entries()) { out.push(' ') out.push(line) out.push('\n') while ( occurrenceIndex < document.occurrences.length && document.occurrences[occurrenceIndex].range[0] === lineNumber ) { const occurrence = document.occurrences[occurrenceIndex] occurrenceIndex++ if (occurrence.range.length > 3) { // Skip multiline occurrences for now. continue } const range = Range.fromLsif(occurrence.range) out.push('//') out.push(' '.repeat(range.start.character)) const length = range.end.character - range.start.character if (length < 0) { throw new Error(input.format(range, 'negative length occurrence!')) } out.push('^'.repeat(length)) out.push(' ') const isDefinition = (occurrence.symbol_roles & lsiftyped.SymbolRole.Definition) > 0 out.push(isDefinition ? 'definition' : 'reference') out.push(' ') const symbol = occurrence.symbol.startsWith('lsif-typescript npm ') ? occurrence.symbol.slice('lsif-typescript npm '.length) : occurrence.symbol out.push(symbol) const info = symbolTable.get(occurrence.symbol) if (!isDefinition || !info) { out.push('\n') continue } const prefix = '\n//' + ' '.repeat(range.start.character) for (const documentation of info.documentation) { out.push(prefix) out.push('documentation ') out.push(documentation.replace(/\n/g, '\\n')) } info.relationships.sort((a, b) => a.symbol.localeCompare(b.symbol)) for (const relationship of info.relationships) { out.push(prefix) out.push('relationship') if (relationship.is_implementation) { out.push(' implementation') } if (relationship.is_reference) { out.push(' reference') } if (relationship.is_type_definition) { out.push(' type_definition') } out.push(' ' + relationship.symbol) } out.push('\n') } } return out.join('') } function occurrencesByLine( a: lsif.lib.codeintel.lsiftyped.Occurrence, b: lsif.lib.codeintel.lsiftyped.Occurrence ): number { return Range.fromLsif(a.range).compare(Range.fromLsif(b.range)) }