import { Commands } from '../commands/commands' ; import { DiagnosticLevel } from './configOptions' ; import { Range } from './textRange' ; const defaultMaxDepth = 5 ; const defaultMaxLineCount = 8 ; const maxRecursionCount = 64 ; export const enum DiagnosticCategory { Error , Warning , Information , UnusedCode , Deprecated } export function convertLevelToCategory ( level ) { switch ( level ) { case 'error' : return DiagnosticCategory . Error ; case 'warning' : return DiagnosticCategory . Warning ; case 'information' : return DiagnosticCategory . Information ; default : throw new Error ( `${ level } is not expected` ) ; } } export interface DiagnosticAction { action : string ; } export interface DiagnosticWithinFile { filePath : string ; diagnostic : Diagnostic ; } export interface CreateTypeStubFileAction extends DiagnosticAction { action : Commands . createTypeStub ; moduleName : string ; } export interface AddMissingOptionalToParamAction extends DiagnosticAction { action : Commands . addMissingOptionalToParam ; offsetOfTypeNode : number ; } export interface DiagnosticRelatedInfo { message : string ; filePath : string ; range : Range ; } export class Diagnostic { private _actions : DiagnosticAction [ ] | undefined ; private _rule : string | undefined ; private _relatedInfo : DiagnosticRelatedInfo [ ] = [ ] ; constructor ( readonly category , readonly message , readonly range ) { } addAction ( action ) { if ( this . _actions === undefined ) { this . _actions = [ action ] ; } else { this . _actions . push ( action ) ; } } getActions ( ) { return this . _actions ; } setRule ( rule ) { this . _rule = rule ; } getRule ( ) { return this . _rule ; } addRelatedInfo ( message , filePath , range ) { this . _relatedInfo . push ( { filePath , message , range } ) ; } getRelatedInfo ( ) { return this . _relatedInfo ; } } export class DiagnosticAddendum { private _messages : string [ ] = [ ] ; private _childAddenda : DiagnosticAddendum [ ] = [ ] ; addMessage ( message ) { this . _messages . push ( message ) ; } createAddendum ( ) { const newAddendum = new DiagnosticAddendum ( ) ; this . addAddendum ( newAddendum ) ; return newAddendum ; } getString ( maxDepth = defaultMaxDepth , maxLineCount = defaultMaxLineCount ) { let lines = this . _getLinesRecursive ( maxDepth , maxLineCount ) ; if ( lines . length > maxLineCount ) { lines = lines . slice ( 0 , maxLineCount ) ; lines . push ( '  ...' ) ; } const text = lines . join ( '\n' ) ; if ( text . length > 0 ) { return '\n' + text ; } return '' ; } isEmpty ( ) { return this . _getMessageCount ( ) === 0 ; } addAddendum ( addendum ) { this . _childAddenda . push ( addendum ) ; } getChildren ( ) { return this . _childAddenda ; } getMessages ( ) { return this . _messages ; } private _getMessageCount ( recursionCount = 0 ) { if ( recursionCount > maxRecursionCount ) { return 0 ; } let messageCount = this . _messages . length ; for ( const diag of this . _childAddenda ) { messageCount += diag . _getMessageCount ( recursionCount + 1 ) ; } return messageCount ; } private _getLinesRecursive ( maxDepth , maxLineCount , recursionCount = 0 ) { if ( maxDepth <= 0 || recursionCount > maxRecursionCount ) { return [ ] ; } let childLines = [ ] ; for ( const addendum of this . _childAddenda ) { const maxDepthRemaining = this . _messages . length > 0 ? maxDepth - 1 : maxDepth ; childLines . push ( ... addendum . _getLinesRecursive ( maxDepthRemaining , maxLineCount , recursionCount + 1 ) ) ; if ( childLines . length >= maxLineCount ) { childLines = childLines . slice ( 0 , maxLineCount ) ; break ; } } const extraSpace = this . _messages . length > 0 ? '  ' : '' ; return this . _messages . concat ( childLines ) . map ( ( line ) => extraSpace + line ) ; } }