'use strict' ; import { URI } from 'vscode-uri' ; import { lsp , Id , Vertex , E , Edge , Project , Document , HoverResult , ReferenceResult , contains , textDocument_definition , textDocument_references , textDocument_diagnostic , textDocument_hover , item , DiagnosticResult , Range , RangeTag , DeclarationRange , ReferenceRange , DocumentSymbolResult , textDocument_documentSymbol , ReferenceTag , DeclarationTag , UnknownTag , DefinitionResult , ImplementationResult , textDocument_implementation , textDocument_typeDefinition , TypeDefinitionResult , FoldingRangeResult , textDocument_foldingRange , RangeBasedDocumentSymbol , DefinitionTag , DefinitionRange , ResultSet , MetaData , Location , ElementTypes , VertexLabels , EdgeLabels , Moniker , PackageInformation , moniker , packageInformation , MonikerKind , ItemEdgeProperties , Event , EventKind , EventScope , DocumentEvent , ProjectEvent , DeclarationResult , textDocument_declaration , next , UniquenessLevel , Uri , MonikerAttachEvent , attach , Source , Capabilities } from 'lsif-protocol' ; export interface BuilderOptions { idGenerator ? : ( ) => Id ; emitSource ? : boolean ; } export interface ResolvedBuilderOptions { idGenerator : ( ) => Id ; emitSource : boolean ; } export class VertexBuilder { constructor ( private options ) { } private nextId ( ) { return this . options . idGenerator ( ) ; } private get emitSource ( ) : boolean { return this . options . emitSource ; } public metaData ( version ) { return { id : this . nextId ( ) , type : ElementTypes . vertex , label : VertexLabels . metaData , version , positionEncoding : 'utf-16' } ; } public event ( scope , kind , data ) ; public event ( scope , kind , data ) ; public event ( scope , kind ) ; public event ( scope , kind , data ? ) { const id = this . nextId ( ) ; const dataId = data !== undefined ? data . id : id ; const result = { id : id , type : ElementTypes . vertex , label : VertexLabels . event , scope : scope , kind , data : dataId } ; return result ; } public source ( workspaceRoot ) { const result = { id : this . nextId ( ) , type : ElementTypes . vertex , label : VertexLabels . source , workspaceRoot } ; return result ; } public capabilities ( defaultValue = false ) { return { id : this . nextId ( ) , type : ElementTypes . vertex , label : VertexLabels . capabilities , hoverProvider : defaultValue , declarationProvider : defaultValue , definitionProvider : defaultValue , typeDefinitionProvider : defaultValue , referencesProvider : defaultValue , documentSymbolProvider : defaultValue , foldingRangeProvider : defaultValue , diagnosticProvider : defaultValue } ; } public project ( name , contents ? ) { const result = { id : this . nextId ( ) , type : ElementTypes . vertex , label : VertexLabels . project , kind : 'typescript' , name } ; if ( contents ) { result . contents = this . encodeString ( contents ) ; } return result ; } public document ( path , contents ? ) { const result = { id : this . nextId ( ) , type : ElementTypes . vertex , label : VertexLabels . document , uri : URI . file ( path ) . toString ( true ) , languageId : 'typescript' } ; if ( contents ) { result . contents = this . encodeString ( contents ) ; } return result ; } public moniker ( scheme , identifier , unique , kind ? ) { const result = { id : this . nextId ( ) , type : ElementTypes . vertex , label : VertexLabels . moniker , scheme , identifier , unique } ; if ( kind !== undefined ) { result . kind = kind ; } return result ; } public packageInformation ( name , manager ) { return { id : this . nextId ( ) , type : ElementTypes . vertex , label : VertexLabels . packageInformation , name , manager } ; } public resultSet ( ) { const result = { id : this . nextId ( ) , type : ElementTypes . vertex , label : VertexLabels . resultSet } ; return result ; } public range ( range , tag ) ; public range ( range , tag ) ; public range ( range , tag ) ; public range ( range , tag ) ; public range ( range , tag ? ) { const result = { id : this . nextId ( ) , type : ElementTypes . vertex , label : VertexLabels . range , start : range . start , end : range . end , } ; if ( tag !== undefined ) { result . tag = tag ; } return result ; } public location ( range ) { return { id : this . nextId ( ) , type : ElementTypes . vertex , label : VertexLabels . location , range : range } ; } public documentSymbolResult ( values ) { return { id : this . nextId ( ) , type : ElementTypes . vertex , label : VertexLabels . documentSymbolResult , result : values } ; } public diagnosticResult ( values ) { return { id : this . nextId ( ) , type : ElementTypes . vertex , label : VertexLabels . diagnosticResult , result : values } ; } public foldingRangeResult ( values ) { return { id : this . nextId ( ) , type : ElementTypes . vertex , label : VertexLabels . foldingRangeResult , result : values } ; } public hoverResult ( value ) ; public hoverResult ( contents ) ; public hoverResult ( value ) { if ( lsp . Hover . is ( value ) ) { return { id : this . nextId ( ) , type : ElementTypes . vertex , label : VertexLabels . hoverResult , result : { contents : value . contents , range : value . range } } ; } else { return { id : this . nextId ( ) , type : ElementTypes . vertex , label : VertexLabels . hoverResult , result : { contents : value as ( lsp . MarkupContent | lsp . MarkedString | lsp . MarkedString [ ] ) } } ; } } public declarationResult ( ) { return { id : this . nextId ( ) , type : ElementTypes . vertex , label : VertexLabels . declarationResult } ; } public definitionResult ( ) { return { id : this . nextId ( ) , type : ElementTypes . vertex , label : VertexLabels . definitionResult } ; } public typeDefinitionResult ( ) { return { id : this . nextId ( ) , type : ElementTypes . vertex , label : VertexLabels . typeDefinitionResult } ; } public referencesResult ( ) { return { id : this . nextId ( ) , type : ElementTypes . vertex , label : VertexLabels . referenceResult } ; } public implementationResult ( ) { return { id : this . nextId ( ) , type : ElementTypes . vertex , label : VertexLabels . implementationResult } ; } private encodeString ( contents ) { return this . emitSource ? Buffer . from ( contents ) . toString ( 'base64' ) : undefined ; } } export class EdgeBuilder { private _options : ResolvedBuilderOptions ; constructor ( options ) { this . _options = options ; } private nextId ( ) { return this . _options . idGenerator ( ) ; } public raw ( kind , from , to ) { return { id : this . nextId ( ) , type : ElementTypes . edge , label : kind , outV : from , inV : to } ; } public contains ( from , to ) ; public contains ( from , to ) ; public contains ( from , to ) { return { id : this . nextId ( ) , type : ElementTypes . edge , label : EdgeLabels . contains , outV : from . id , inVs : to . map ( v => v . id ) } ; } public next ( from , to ) ; public next ( from , to ) ; public next ( from , to ) { return { id : this . nextId ( ) , type : ElementTypes . edge , label : EdgeLabels . next , outV : from . id , inV : to . id } ; } public moniker ( from , to ) ; public moniker ( from , to ) ; public moniker ( from , to ) { return { id : this . nextId ( ) , type : ElementTypes . edge , label : EdgeLabels . moniker , outV : from . id , inV : to . id } ; } public packageInformation ( from , to ) { return { id : this . nextId ( ) , type : ElementTypes . edge , label : EdgeLabels . packageInformation , outV : from . id , inV : to . id } ; } public documentSymbols ( from , to ) { return { id : this . nextId ( ) , type : ElementTypes . edge , label : EdgeLabels . textDocument_documentSymbol , outV : from . id , inV : to . id } ; } public foldingRange ( from , to ) { return { id : this . nextId ( ) , type : ElementTypes . edge , label : EdgeLabels . textDocument_foldingRange , outV : from . id , inV : to . id } ; } public diagnostic ( from , to ) { return { id : this . nextId ( ) , type : ElementTypes . edge , label : EdgeLabels . textDocument_diagnostic , outV : from . id , inV : to . id } ; } public hover ( from , to ) { return { id : this . nextId ( ) , type : ElementTypes . edge , label : EdgeLabels . textDocument_hover , outV : from . id , inV : to . id } ; } public declaration ( from , to ) { return { id : this . nextId ( ) , type : ElementTypes . edge , label : EdgeLabels . textDocument_declaration , outV : from . id , inV : to . id } ; } public definition ( from , to ) { return { id : this . nextId ( ) , type : ElementTypes . edge , label : EdgeLabels . textDocument_definition , outV : from . id , inV : to . id } ; } public typeDefinition ( from , to ) { return { id : this . nextId ( ) , type : ElementTypes . edge , label : EdgeLabels . textDocument_typeDefinition , outV : from . id , inV : to . id } ; } public references ( from , to ) { return { id : this . nextId ( ) , type : ElementTypes . edge , label : EdgeLabels . textDocument_references , outV : from . id , inV : to . id } ; } public implementation ( from , to ) { return { id : this . nextId ( ) , type : ElementTypes . edge , label : EdgeLabels . textDocument_implementation , outV : from . id , inV : to . id } ; } public item ( from , to , shard ) ; public item ( from , to , shard ) ; public item ( from , to , shard ) ; public item ( from , to , shard ) ; public item ( from , to , shard , property ) ; public item ( from , to , shard ) ; public item ( from , to , shard ) ; public item ( from , to , shard ) ; public item ( from , to , shard , property ? ) { if ( to . length === 0 ) { const result = { id : this . nextId ( ) , type : ElementTypes . edge , label : EdgeLabels . item , outV : from . id , inVs : [ ] , shard : shard . id } ; if ( from . label === 'referenceResult' ) { result . property = property !== undefined ? property : ItemEdgeProperties . references ; } return result ; } const toKind = to [ 0 ] . label ; const result = { id : this . nextId ( ) , type : ElementTypes . edge , label : EdgeLabels . item , outV : from . id , inVs : to . map ( v => v . id ) , shard : shard . id } ; switch ( from . label ) { case 'declarationResult' : break ; case 'definitionResult' : break ; case 'referenceResult' : switch ( toKind ) { case VertexLabels . range : if ( property === undefined ) { throw new Error ( `An item edge pointing to ranges needs to define a property.` ) ; } result . property = property ; break ; case VertexLabels . referenceResult : result . property = ItemEdgeProperties . referenceResults ; break ; case VertexLabels . moniker : result . property = ItemEdgeProperties . referenceLinks ; break ; default : throw new Error ( 'Should never happen.' ) ; } break ; case 'implementationResult' : switch ( toKind ) { case VertexLabels . implementationResult : result . property = ItemEdgeProperties . implementationResults ; break ; case VertexLabels . moniker : result . property = ItemEdgeProperties . implementationLinks ; break ; } break ; default : throw new Error ( 'Shouldn\'t happen' ) ; } return result ; } public attach ( from , to ) { return { id : this . nextId ( ) , type : ElementTypes . edge , label : EdgeLabels . attach , outV : from . id , inV : to . id } ; } } export class Builder { private _vertex : VertexBuilder ; private _edge : EdgeBuilder ; constructor ( options ) { this . _vertex = new VertexBuilder ( options ) ; this . _edge = new EdgeBuilder ( options ) ; } public get vertex ( ) : VertexBuilder { return this . _vertex ; } public get edge ( ) : EdgeBuilder { return this . _edge ; } } export interface EmitterContext { vertex : VertexBuilder ; edge : EdgeBuilder ; emit ( element ) : void ; flush ( ) : Promise < void > ; }