import { SymbolKind , SymbolInformation , DocumentSymbolParams , Range , Position , Location , Files as VscodeFiles } from 'vscode-languageserver' ; import { ILogger } from '../interfaces' ; import { AbstractTagsSymbolProvider } from './abstractTagsSymbolProvider' ; const fileUrl = require ( 'file-url' ) ; export class HaskTagsSymbolProvider extends AbstractTagsSymbolProvider { public constructor ( executable , workspaceRoot , logger ) { super ( executable || 'hasktags' , workspaceRoot , logger ) ; } protected getFileSymbolsCommand ( documentSymbolParams ) { let uri = documentSymbolParams . textDocument . uri ; return `${ this . executable } -c -x -o - ${ VscodeFiles . uriToFilePath ( uri ) }` ; } protected getWorkspaceSymbolsCommand ( ) { return `${ this . executable } -c -x -o - ${ this . workspaceRoot }` ; } protected parseTags ( rawTags ) { let symbolInformation = rawTags . split ( '\n' ) . slice ( 3 ) . map ( ( tagLine ) => { return tagLine . split ( '\t' ) ; } ) . filter ( ( line ) => line . length === 6 ) . map ( ( [ name , path , , kind , line , ] ) => { let uri = fileUrl ( path , { resolve : true } ) ; let lineNumber = parseInt ( line . replace ( 'line:' , '' ) , 10 ) - 1 ; let range = Range . create ( Position . create ( lineNumber , 0 ) , Position . create ( lineNumber , 0 ) ) ; let symbolKind = HaskTagsSymbolProvider . toSymbolKind ( kind ) ; return < SymbolInformation > { name : name , kind : symbolKind , location : Location . create ( uri , range ) } ; } ) . filter ( HaskTagsSymbolProvider . onlyUnique ) . filter ( HaskTagsSymbolProvider . noBackToBack ) ; this . logger . log ( `Found ${ symbolInformation . length } tags` ) ; return symbolInformation ; } private static toSymbolKind ( rawKind ) { switch ( rawKind . trim ( ) ) { case 'm' : return SymbolKind . Module ; case 'ft' : return SymbolKind . Function ; case 'c' : return SymbolKind . Class ; case 'cons' : return SymbolKind . Constructor ; case 't' : case 'nt' : return SymbolKind . Interface ; case 'o' : return SymbolKind . Method ; default : return SymbolKind . Function ; } } private static onlyUnique ( value , index , self ) { return self . indexOf ( value ) === index ; } private static noBackToBack ( value , index , self ) { return index === 0 ? true : ! ( value . name === self [ index - 1 ] . name && value . location . range . start . line - self [ index - 1 ] . location . range . start . line <= 1 ) ; } }