namespace ts { /** The version of the language service API */ export const servicesVersion = "0.8" ; function createNode < TKind extends SyntaxKind > ( kind , pos , end , parent ) { const node = isNodeKind ( kind ) ? new NodeObject ( kind , pos , end ) : kind === SyntaxKind . Identifier ? new IdentifierObject ( SyntaxKind . Identifier , pos , end ) : kind === SyntaxKind . PrivateIdentifier ? new PrivateIdentifierObject ( SyntaxKind . PrivateIdentifier , pos , end ) : new TokenObject ( kind , pos , end ) ; node . parent = parent ; node . flags = parent . flags & NodeFlags . ContextFlags ; return node ; } class NodeObject implements Node { public kind : SyntaxKind ; public pos : number ; public end : number ; public flags : NodeFlags ; public modifierFlagsCache : ModifierFlags ; public transformFlags : TransformFlags ; public parent : Node ; public symbol ! : Symbol ; public jsDoc ? : JSDoc [ ] ; public original ? : Node ; private _children : Node [ ] | undefined ; constructor ( kind , pos , end ) { this . pos = pos ; this . end = end ; this . flags = NodeFlags . None ; this . modifierFlagsCache = ModifierFlags . None ; this . transformFlags = TransformFlags . None ; this . parent = undefined ! ; this . kind = kind ; } private assertHasRealPosition ( message ? ) { Debug . assert ( ! positionIsSynthesized ( this . pos ) && ! positionIsSynthesized ( this . end ) , message || "Node must have a real position for this operation" ) ; } public getSourceFile ( ) { return getSourceFileOfNode ( this ) ; } public getStart ( sourceFile ? , includeJsDocComment ? ) { this . assertHasRealPosition ( ) ; return getTokenPosOfNode ( this , sourceFile , includeJsDocComment ) ; } public getFullStart ( ) { this . assertHasRealPosition ( ) ; return this . pos ; } public getEnd ( ) { this . assertHasRealPosition ( ) ; return this . end ; } public getWidth ( sourceFile ? ) { this . assertHasRealPosition ( ) ; return this . getEnd ( ) - this . getStart ( sourceFile ) ; } public getFullWidth ( ) { this . assertHasRealPosition ( ) ; return this . end - this . pos ; } public getLeadingTriviaWidth ( sourceFile ? ) { this . assertHasRealPosition ( ) ; return this . getStart ( sourceFile ) - this . pos ; } public getFullText ( sourceFile ? ) { this . assertHasRealPosition ( ) ; return ( sourceFile || this . getSourceFile ( ) ) . text . substring ( this . pos , this . end ) ; } public getText ( sourceFile ? ) { this . assertHasRealPosition ( ) ; if ( ! sourceFile ) { sourceFile = this . getSourceFile ( ) ; } return sourceFile . text . substring ( this . getStart ( sourceFile ) , this . getEnd ( ) ) ; } public getChildCount ( sourceFile ? ) { return this . getChildren ( sourceFile ) . length ; } public getChildAt ( index , sourceFile ? ) { return this . getChildren ( sourceFile ) [ index ] ; } public getChildren ( sourceFile ? ) { this . assertHasRealPosition ( "Node without a real position cannot be scanned and thus has no token nodes - use forEachChild and collect the result if that's fine" ) ; return this . _children || ( this . _children = createChildren ( this , sourceFile ) ) ; } public getFirstToken ( sourceFile ? ) { this . assertHasRealPosition ( ) ; const children = this . getChildren ( sourceFile ) ; if ( ! children . length ) { return undefined ; } const child = find ( children , kid => kid . kind < SyntaxKind . FirstJSDocNode || kid . kind > SyntaxKind . LastJSDocNode ) ! ; return child . kind < SyntaxKind . FirstNode ? child : child . getFirstToken ( sourceFile ) ; } public getLastToken ( sourceFile ? ) { this . assertHasRealPosition ( ) ; const children = this . getChildren ( sourceFile ) ; const child = lastOrUndefined ( children ) ; if ( ! child ) { return undefined ; } return child . kind < SyntaxKind . FirstNode ? child : child . getLastToken ( sourceFile ) ; } public forEachChild < T > ( cbNode , cbNodeArray ? ) { return forEachChild ( this , cbNode , cbNodeArray ) ; } } function createChildren ( node , sourceFile ) { if ( ! isNodeKind ( node . kind ) ) { return emptyArray ; } const children = [ ] ; if ( isJSDocCommentContainingNode ( node ) ) { /** Don't add trivia for "tokens" since this is in a comment. */ node . forEachChild ( child => { children . push ( child ) ; } ) ; return children ; } scanner . setText ( ( sourceFile || node . getSourceFile ( ) ) . text ) ; let pos = node . pos ; const processNode = ( child ) => { addSyntheticNodes ( children , pos , child . pos , node ) ; children . push ( child ) ; pos = child . end ; } ; const processNodes = ( nodes ) => { addSyntheticNodes ( children , pos , nodes . pos , node ) ; children . push ( createSyntaxList ( nodes , node ) ) ; pos = nodes . end ; } ; forEach ( ( node as JSDocContainer ) . jsDoc , processNode ) ; pos = node . pos ; node . forEachChild ( processNode , processNodes ) ; addSyntheticNodes ( children , pos , node . end , node ) ; scanner . setText ( undefined ) ; return children ; } function addSyntheticNodes ( nodes , pos , end , parent ) { scanner . setTextPos ( pos ) ; while ( pos < end ) { const token = scanner . scan ( ) ; const textPos = scanner . getTextPos ( ) ; if ( textPos <= end ) { if ( token === SyntaxKind . Identifier ) { Debug . fail ( `Did not expect ${ Debug . formatSyntaxKind ( parent . kind ) } to have an Identifier in its trivia` ) ; } nodes . push ( createNode ( token , pos , textPos , parent ) ) ; } pos = textPos ; if ( token === SyntaxKind . EndOfFileToken ) { break ; } } } function createSyntaxList ( nodes , parent ) { const list = createNode ( SyntaxKind . SyntaxList , nodes . pos , nodes . end , parent ) as any as SyntaxList ; list . _children = [ ] ; let pos = nodes . pos ; for ( const node of nodes ) { addSyntheticNodes ( list . _children , pos , node . pos , parent ) ; list . _children . push ( node ) ; pos = node . end ; } addSyntheticNodes ( list . _children , pos , nodes . end , parent ) ; return list ; } class TokenOrIdentifierObject implements Node { public kind ! : SyntaxKind ; public pos : number ; public end : number ; public flags : NodeFlags ; public modifierFlagsCache : ModifierFlags ; public transformFlags : TransformFlags ; public parent : Node ; public symbol ! : Symbol ; public jsDocComments ? : JSDoc [ ] ; constructor ( pos , end ) { this . pos = pos ; this . end = end ; this . flags = NodeFlags . None ; this . modifierFlagsCache = ModifierFlags . None ; this . transformFlags = TransformFlags . None ; this . parent = undefined ! ; } public getSourceFile ( ) { return getSourceFileOfNode ( this ) ; } public getStart ( sourceFile ? , includeJsDocComment ? ) { return getTokenPosOfNode ( this , sourceFile , includeJsDocComment ) ; } public getFullStart ( ) { return this . pos ; } public getEnd ( ) { return this . end ; } public getWidth ( sourceFile ? ) { return this . getEnd ( ) - this . getStart ( sourceFile ) ; } public getFullWidth ( ) { return this . end - this . pos ; } public getLeadingTriviaWidth ( sourceFile ? ) { return this . getStart ( sourceFile ) - this . pos ; } public getFullText ( sourceFile ? ) { return ( sourceFile || this . getSourceFile ( ) ) . text . substring ( this . pos , this . end ) ; } public getText ( sourceFile ? ) { if ( ! sourceFile ) { sourceFile = this . getSourceFile ( ) ; } return sourceFile . text . substring ( this . getStart ( sourceFile ) , this . getEnd ( ) ) ; } public getChildCount ( ) { return this . getChildren ( ) . length ; } public getChildAt ( index ) { return this . getChildren ( ) [ index ] ; } public getChildren ( ) { return this . kind === SyntaxKind . EndOfFileToken ? ( this as EndOfFileToken ) . jsDoc || emptyArray : emptyArray ; } public getFirstToken ( ) { return undefined ; } public getLastToken ( ) { return undefined ; } public forEachChild < T > ( ) { return undefined ; } } class SymbolObject implements Symbol { flags : SymbolFlags ; escapedName : __String ; declarations ! : Declaration [ ] ; valueDeclaration ! : Declaration ; documentationComment ? : SymbolDisplayPart [ ] ; tags ? : JSDocTagInfo [ ] ; contextualGetAccessorDocumentationComment ? : SymbolDisplayPart [ ] ; contextualSetAccessorDocumentationComment ? : SymbolDisplayPart [ ] ; constructor ( flags , name ) { this . flags = flags ; this . escapedName = name ; } getFlags ( ) { return this . flags ; } get name ( ) : string { return symbolName ( this ) ; } getEscapedName ( ) { return this . escapedName ; } getName ( ) { return this . name ; } getDeclarations ( ) { return this . declarations ; } getDocumentationComment ( checker ) { if ( ! this . documentationComment ) { this . documentationComment = emptyArray ; if ( ! this . declarations && ( this as Symbol as TransientSymbol ) . target && ( ( this as Symbol as TransientSymbol ) . target as TransientSymbol ) . tupleLabelDeclaration ) { const labelDecl = ( ( this as Symbol as TransientSymbol ) . target as TransientSymbol ) . tupleLabelDeclaration ! ; this . documentationComment = getDocumentationComment ( [ labelDecl ] , checker ) ; } else { this . documentationComment = getDocumentationComment ( this . declarations , checker ) ; } } return this . documentationComment ; } getContextualDocumentationComment ( context , checker ) { switch ( context ?. kind ) { case SyntaxKind . GetAccessor : if ( ! this . contextualGetAccessorDocumentationComment ) { this . contextualGetAccessorDocumentationComment = emptyArray ; this . contextualGetAccessorDocumentationComment = getDocumentationComment ( filter ( this . declarations , isGetAccessor ) , checker ) ; } return this . contextualGetAccessorDocumentationComment ; case SyntaxKind . SetAccessor : if ( ! this . contextualSetAccessorDocumentationComment ) { this . contextualSetAccessorDocumentationComment = emptyArray ; this . contextualSetAccessorDocumentationComment = getDocumentationComment ( filter ( this . declarations , isSetAccessor ) , checker ) ; } return this . contextualSetAccessorDocumentationComment ; default : return this . getDocumentationComment ( checker ) ; } } getJsDocTags ( checker ? ) { if ( this . tags === undefined ) { this . tags = JsDoc . getJsDocTagsFromDeclarations ( this . declarations , checker ) ; } return this . tags ; } } class TokenObject < TKind extends SyntaxKind > extends TokenOrIdentifierObject implements Token < TKind > { public kind : TKind ; constructor ( kind , pos , end ) { super ( pos , end ) ; this . kind = kind ; } } class IdentifierObject extends TokenOrIdentifierObject implements Identifier { public kind : SyntaxKind . Identifier = SyntaxKind . Identifier ; public escapedText ! : __String ; public autoGenerateFlags ! : GeneratedIdentifierFlags ; _primaryExpressionBrand : any ; _memberExpressionBrand : any ; _leftHandSideExpressionBrand : any ; _updateExpressionBrand : any ; _unaryExpressionBrand : any ; _expressionBrand : any ; _declarationBrand : any ; typeArguments ! : NodeArray < TypeNode > ; constructor ( _kind , pos , end ) { super ( pos , end ) ; } get text ( ) : string { return idText ( this ) ; } } IdentifierObject . prototype . kind = SyntaxKind . Identifier ; class PrivateIdentifierObject extends TokenOrIdentifierObject implements PrivateIdentifier { public kind ! : SyntaxKind . PrivateIdentifier ; public escapedText ! : __String ; public symbol ! : Symbol ; _primaryExpressionBrand : any ; _memberExpressionBrand : any ; _leftHandSideExpressionBrand : any ; _updateExpressionBrand : any ; _unaryExpressionBrand : any ; _expressionBrand : any ; constructor ( _kind , pos , end ) { super ( pos , end ) ; } get text ( ) : string { return idText ( this ) ; } } PrivateIdentifierObject . prototype . kind = SyntaxKind . PrivateIdentifier ; class TypeObject implements Type { checker : TypeChecker ; flags : TypeFlags ; objectFlags ? : ObjectFlags ; id ! : number ; symbol ! : Symbol ; constructor ( checker , flags ) { this . checker = checker ; this . flags = flags ; } getFlags ( ) { return this . flags ; } getSymbol ( ) { return this . symbol ; } getProperties ( ) { return this . checker . getPropertiesOfType ( this ) ; } getProperty ( propertyName ) { return this . checker . getPropertyOfType ( this , propertyName ) ; } getApparentProperties ( ) { return this . checker . getAugmentedPropertiesOfType ( this ) ; } getCallSignatures ( ) { return this . checker . getSignaturesOfType ( this , SignatureKind . Call ) ; } getConstructSignatures ( ) { return this . checker . getSignaturesOfType ( this , SignatureKind . Construct ) ; } getStringIndexType ( ) { return this . checker . getIndexTypeOfType ( this , IndexKind . String ) ; } getNumberIndexType ( ) { return this . checker . getIndexTypeOfType ( this , IndexKind . Number ) ; } getBaseTypes ( ) { return this . isClassOrInterface ( ) ? this . checker . getBaseTypes ( this ) : undefined ; } isNullableType ( ) { return this . checker . isNullableType ( this ) ; } getNonNullableType ( ) { return this . checker . getNonNullableType ( this ) ; } getNonOptionalType ( ) { return this . checker . getNonOptionalType ( this ) ; } getConstraint ( ) { return this . checker . getBaseConstraintOfType ( this ) ; } getDefault ( ) { return this . checker . getDefaultFromTypeParameter ( this ) ; } isUnion ( ) { return ! ! ( this . flags & TypeFlags . Union ) ; } isIntersection ( ) { return ! ! ( this . flags & TypeFlags . Intersection ) ; } isUnionOrIntersection ( ) { return ! ! ( this . flags & TypeFlags . UnionOrIntersection ) ; } isLiteral ( ) { return ! ! ( this . flags & TypeFlags . StringOrNumberLiteral ) ; } isStringLiteral ( ) { return ! ! ( this . flags & TypeFlags . StringLiteral ) ; } isNumberLiteral ( ) { return ! ! ( this . flags & TypeFlags . NumberLiteral ) ; } isTypeParameter ( ) { return ! ! ( this . flags & TypeFlags . TypeParameter ) ; } isClassOrInterface ( ) { return ! ! ( getObjectFlags ( this ) & ObjectFlags . ClassOrInterface ) ; } isClass ( ) { return ! ! ( getObjectFlags ( this ) & ObjectFlags . Class ) ; } isIndexType ( ) { return ! ! ( this . flags & TypeFlags . Index ) ; } /**
         * This polyfills `referenceType.typeArguments` for API consumers
         */ get typeArguments ( ) { if ( getObjectFlags ( this ) & ObjectFlags . Reference ) { return this . checker . getTypeArguments ( this as Type as TypeReference ) ; } return undefined ; } } class SignatureObject implements Signature { flags : SignatureFlags ; checker : TypeChecker ; declaration ! : SignatureDeclaration ; typeParameters ? : TypeParameter [ ] ; parameters ! : Symbol [ ] ; thisParameter ! : Symbol ; resolvedReturnType ! : Type ; resolvedTypePredicate : TypePredicate | undefined ; minTypeArgumentCount ! : number ; minArgumentCount ! : number ; documentationComment ? : SymbolDisplayPart [ ] ; jsDocTags ? : JSDocTagInfo [ ] ; constructor ( checker , flags ) { this . checker = checker ; this . flags = flags ; } getDeclaration ( ) { return this . declaration ; } getTypeParameters ( ) { return this . typeParameters ; } getParameters ( ) { return this . parameters ; } getReturnType ( ) { return this . checker . getReturnTypeOfSignature ( this ) ; } getTypeParameterAtPosition ( pos ) { const type = this . checker . getParameterType ( this , pos ) ; if ( type . isIndexType ( ) && isThisTypeParameter ( type . type ) ) { const constraint = type . type . getConstraint ( ) ; if ( constraint ) { return this . checker . getIndexType ( constraint ) ; } } return type ; } getDocumentationComment ( ) { return this . documentationComment || ( this . documentationComment = getDocumentationComment ( singleElementArray ( this . declaration ) , this . checker ) ) ; } getJsDocTags ( ) { if ( this . jsDocTags === undefined ) { this . jsDocTags = this . declaration ? getJsDocTagsOfSignature ( this . declaration , this . checker ) : [ ] ; } return this . jsDocTags ; } } param node returns function hasJSDocInheritDocTag ( node ) { return getJSDocTags ( node ) . some ( tag => tag . tagName . text === "inheritDoc" ) ; } function getJsDocTagsOfSignature ( declaration , checker ) { let tags = JsDoc . getJsDocTagsFromDeclarations ( [ declaration ] , checker ) ; if ( tags . length === 0 || hasJSDocInheritDocTag ( declaration ) ) { const inheritedTags = findBaseOfDeclaration ( checker , declaration , symbol => symbol . declarations ?. length === 1 ? symbol . getJsDocTags ( ) : undefined ) ; if ( inheritedTags ) { tags = [ ... inheritedTags , ... tags ] ; } } return tags ; } function getDocumentationComment ( declarations , checker ) { if ( ! declarations ) return emptyArray ; let doc = JsDoc . getJsDocCommentsFromDeclarations ( declarations , checker ) ; if ( checker && ( doc . length === 0 || declarations . some ( hasJSDocInheritDocTag ) ) ) { const seenSymbols = new Set < Symbol > ( ) ; for ( const declaration of declarations ) { const inheritedDocs = findBaseOfDeclaration ( checker , declaration , symbol => { if ( ! seenSymbols . has ( symbol ) ) { seenSymbols . add ( symbol ) ; return symbol . getDocumentationComment ( checker ) ; } } ) ; if ( inheritedDocs ) doc = doc . length === 0 ? inheritedDocs . slice ( ) : inheritedDocs . concat ( lineBreakPart ( ) , doc ) ; } } return doc ; } function findBaseOfDeclaration < T > ( checker , declaration , cb ) { if ( hasStaticModifier ( declaration ) ) return ; const classOrInterfaceDeclaration = declaration . parent ?. kind === SyntaxKind . Constructor ? declaration . parent . parent : declaration . parent ; if ( ! classOrInterfaceDeclaration ) return ; return firstDefined ( getAllSuperTypeNodes ( classOrInterfaceDeclaration ) , superTypeNode => { const symbol = checker . getPropertyOfType ( checker . getTypeAtLocation ( superTypeNode ) , declaration . symbol . name ) ; return symbol ? cb ( symbol ) : undefined ; } ) ; } class SourceFileObject extends NodeObject implements SourceFile { public kind : SyntaxKind . SourceFile = SyntaxKind . SourceFile ; public _declarationBrand : any ; public fileName ! : string ; public path ! : Path ; public resolvedPath ! : Path ; public originalFileName ! : string ; public text ! : string ; public scriptSnapshot ! : IScriptSnapshot ; public lineMap ! : readonly number [ ] ; public statements ! : NodeArray < Statement > ; public endOfFileToken ! : Token < SyntaxKind . EndOfFileToken > ; public amdDependencies ! : { name : string ; path : string ; } [ ] ; public moduleName ! : string ; public referencedFiles ! : FileReference [ ] ; public typeReferenceDirectives ! : FileReference [ ] ; public libReferenceDirectives ! : FileReference [ ] ; public syntacticDiagnostics ! : DiagnosticWithLocation [ ] ; public parseDiagnostics ! : DiagnosticWithLocation [ ] ; public bindDiagnostics ! : DiagnosticWithLocation [ ] ; public bindSuggestionDiagnostics ? : DiagnosticWithLocation [ ] ; public isDeclarationFile ! : boolean ; public isDefaultLib ! : boolean ; public hasNoDefaultLib ! : boolean ; public externalModuleIndicator ! : Node ; public commonJsModuleIndicator ! : Node ; public nodeCount ! : number ; public identifierCount ! : number ; public symbolCount ! : number ; public version ! : string ; public scriptKind ! : ScriptKind ; public languageVersion ! : ScriptTarget ; public languageVariant ! : LanguageVariant ; public identifiers ! : ESMap < string , string > ; public nameTable : UnderscoreEscapedMap < number > | undefined ; public resolvedModules : ModeAwareCache < ResolvedModuleFull > | undefined ; public resolvedTypeReferenceDirectiveNames ! : ModeAwareCache < ResolvedTypeReferenceDirective > ; public imports ! : readonly StringLiteralLike [ ] ; public moduleAugmentations ! : StringLiteral [ ] ; private namedDeclarations : ESMap < string , Declaration [ ] > | undefined ; public ambientModuleNames ! : string [ ] ; public checkJsDirective : CheckJsDirective | undefined ; public errorExpectations : TextRange [ ] | undefined ; public possiblyContainDynamicImport ? : boolean ; public pragmas ! : PragmaMap ; public localJsxFactory : EntityName | undefined ; public localJsxNamespace : __String | undefined ; constructor ( kind , pos , end ) { super ( kind , pos , end ) ; } public update ( newText , textChangeRange ) { return updateSourceFile ( this , newText , textChangeRange ) ; } public getLineAndCharacterOfPosition ( position ) { return getLineAndCharacterOfPosition ( this , position ) ; } public getLineStarts ( ) { return getLineStarts ( this ) ; } public getPositionOfLineAndCharacter ( line , character , allowEdits ? ) { return computePositionOfLineAndCharacter ( getLineStarts ( this ) , line , character , this . text , allowEdits ) ; } public getLineEndOfPosition ( pos ) { const { line } = this . getLineAndCharacterOfPosition ( pos ) ; const lineStarts = this . getLineStarts ( ) ; let lastCharPos ; if ( line + 1 >= lineStarts . length ) { lastCharPos = this . getEnd ( ) ; } if ( ! lastCharPos ) { lastCharPos = lineStarts [ line + 1 ] - 1 ; } const fullText = this . getFullText ( ) ; return fullText [ lastCharPos ] === "\n" && fullText [ lastCharPos - 1 ] === "\r" ? lastCharPos - 1 : lastCharPos ; } public getNamedDeclarations ( ) { if ( ! this . namedDeclarations ) { this . namedDeclarations = this . computeNamedDeclarations ( ) ; } return this . namedDeclarations ; } private computeNamedDeclarations ( ) { const result = createMultiMap < Declaration > ( ) ; this . forEachChild ( visit ) ; return result ; function addDeclaration ( declaration ) { const name = getDeclarationName ( declaration ) ; if ( name ) { result . add ( name , declaration ) ; } } function getDeclarations ( name ) { let declarations = result . get ( name ) ; if ( ! declarations ) { result . set ( name , declarations = [ ] ) ; } return declarations ; } function getDeclarationName ( declaration ) { const name = getNonAssignedNameOfDeclaration ( declaration ) ; return name && ( isComputedPropertyName ( name ) && isPropertyAccessExpression ( name . expression ) ? name . expression . name . text : isPropertyName ( name ) ? getNameFromPropertyName ( name ) : undefined ) ; } function visit ( node ) { switch ( node . kind ) { case SyntaxKind . FunctionDeclaration : case SyntaxKind . FunctionExpression : case SyntaxKind . MethodDeclaration : case SyntaxKind . MethodSignature : const functionDeclaration = node as FunctionLikeDeclaration ; const declarationName = getDeclarationName ( functionDeclaration ) ; if ( declarationName ) { const declarations = getDeclarations ( declarationName ) ; const lastDeclaration = lastOrUndefined ( declarations ) ; if ( lastDeclaration && functionDeclaration . parent === lastDeclaration . parent && functionDeclaration . symbol === lastDeclaration . symbol ) { if ( functionDeclaration . body && ! ( lastDeclaration as FunctionLikeDeclaration ) . body ) { declarations [ declarations . length - 1 ] = functionDeclaration ; } } else { declarations . push ( functionDeclaration ) ; } } forEachChild ( node , visit ) ; break ; case SyntaxKind . ClassDeclaration : case SyntaxKind . ClassExpression : case SyntaxKind . InterfaceDeclaration : case SyntaxKind . TypeAliasDeclaration : case SyntaxKind . EnumDeclaration : case SyntaxKind . ModuleDeclaration : case SyntaxKind . ImportEqualsDeclaration : case SyntaxKind . ExportSpecifier : case SyntaxKind . ImportSpecifier : case SyntaxKind . ImportClause : case SyntaxKind . NamespaceImport : case SyntaxKind . GetAccessor : case SyntaxKind . SetAccessor : case SyntaxKind . TypeLiteral : addDeclaration ( node as Declaration ) ; forEachChild ( node , visit ) ; break ; case SyntaxKind . Parameter : if ( ! hasSyntacticModifier ( node , ModifierFlags . ParameterPropertyModifier ) ) { break ; } case SyntaxKind . VariableDeclaration : case SyntaxKind . BindingElement : { const decl = node as VariableDeclaration ; if ( isBindingPattern ( decl . name ) ) { forEachChild ( decl . name , visit ) ; break ; } if ( decl . initializer ) { visit ( decl . initializer ) ; } } case SyntaxKind . EnumMember : case SyntaxKind . PropertyDeclaration : case SyntaxKind . PropertySignature : addDeclaration ( node as Declaration ) ; break ; case SyntaxKind . ExportDeclaration : const exportDeclaration = node as ExportDeclaration ; if ( exportDeclaration . exportClause ) { if ( isNamedExports ( exportDeclaration . exportClause ) ) { forEach ( exportDeclaration . exportClause . elements , visit ) ; } else { visit ( exportDeclaration . exportClause . name ) ; } } break ; case SyntaxKind . ImportDeclaration : const importClause = ( node as ImportDeclaration ) . importClause ; if ( importClause ) { if ( importClause . name ) { addDeclaration ( importClause . name ) ; } if ( importClause . namedBindings ) { if ( importClause . namedBindings . kind === SyntaxKind . NamespaceImport ) { addDeclaration ( importClause . namedBindings ) ; } else { forEach ( importClause . namedBindings . elements , visit ) ; } } } break ; case SyntaxKind . BinaryExpression : if ( getAssignmentDeclarationKind ( node as BinaryExpression ) !== AssignmentDeclarationKind . None ) { addDeclaration ( node as BinaryExpression ) ; } default : forEachChild ( node , visit ) ; } } } } class SourceMapSourceObject implements SourceMapSource { lineMap ! : number [ ] ; constructor ( public fileName , public text , public skipTrivia ? ) { } public getLineAndCharacterOfPosition ( pos ) { return getLineAndCharacterOfPosition ( this , pos ) ; } } function getServicesObjectAllocator ( ) { return { getNodeConstructor : ( ) => NodeObject , getTokenConstructor : ( ) => TokenObject , getIdentifierConstructor : ( ) => IdentifierObject , getPrivateIdentifierConstructor : ( ) => PrivateIdentifierObject , getSourceFileConstructor : ( ) => SourceFileObject , getSymbolConstructor : ( ) => SymbolObject , getTypeConstructor : ( ) => TypeObject , getSignatureConstructor : ( ) => SignatureObject , getSourceMapSourceConstructor : ( ) => SourceMapSourceObject , } ; } interface HostFileInformation { hostFileName : string ; version : string ; scriptSnapshot : IScriptSnapshot ; scriptKind : ScriptKind ; } export interface DisplayPartsSymbolWriter extends EmitTextWriter { displayParts ( ) : SymbolDisplayPart [ ] ; } export function toEditorSettings ( options ) ; export function toEditorSettings ( options ) ; export function toEditorSettings ( optionsAsMap ) { let allPropertiesAreCamelCased = true ; for ( const key in optionsAsMap ) { if ( hasProperty ( optionsAsMap , key ) && ! isCamelCase ( key ) ) { allPropertiesAreCamelCased = false ; break ; } } if ( allPropertiesAreCamelCased ) { return optionsAsMap ; } const settings = { } ; for ( const key in optionsAsMap ) { if ( hasProperty ( optionsAsMap , key ) ) { const newKey = isCamelCase ( key ) ? key : key . charAt ( 0 ) . toLowerCase ( ) + key . substr ( 1 ) ; settings [ newKey ] = optionsAsMap [ key ] ; } } return settings ; } function isCamelCase ( s ) { return ! s . length || s . charAt ( 0 ) === s . charAt ( 0 ) . toLowerCase ( ) ; } export function displayPartsToString ( displayParts ) { if ( displayParts ) { return map ( displayParts , displayPart => displayPart . text ) . join ( "" ) ; } return "" ; } export function getDefaultCompilerOptions ( ) { return { target : ScriptTarget . ES5 , jsx : JsxEmit . Preserve } ; } export function getSupportedCodeFixes ( ) { return codefix . getSupportedErrorCodes ( ) ; } type CachedHostFileInformation = HostFileInformation | string ; class HostCache { private fileNameToEntry : ESMap < Path , CachedHostFileInformation > ; private currentDirectory : string ; constructor ( private host , getCanonicalFileName ) { this . currentDirectory = host . getCurrentDirectory ( ) ; this . fileNameToEntry = new Map ( ) ; const rootFileNames = host . getScriptFileNames ( ) ; for ( const fileName of rootFileNames ) { this . createEntry ( fileName , toPath ( fileName , this . currentDirectory , getCanonicalFileName ) ) ; } } private createEntry ( fileName , path ) { let entry ; const scriptSnapshot = this . host . getScriptSnapshot ( fileName ) ; if ( scriptSnapshot ) { entry = { hostFileName : fileName , version : this . host . getScriptVersion ( fileName ) , scriptSnapshot , scriptKind : getScriptKind ( fileName , this . host ) } ; } else { entry = fileName ; } this . fileNameToEntry . set ( path , entry ) ; return entry ; } public getEntryByPath ( path ) { return this . fileNameToEntry . get ( path ) ; } public getHostFileInformation ( path ) { const entry = this . fileNameToEntry . get ( path ) ; return ! isString ( entry ) ? entry : undefined ; } public getOrCreateEntryByPath ( fileName , path ) { const info = this . getEntryByPath ( path ) || this . createEntry ( fileName , path ) ; return isString ( info ) ? undefined ! : info ; } public getRootFileNames ( ) { const names = [ ] ; this . fileNameToEntry . forEach ( entry => { if ( isString ( entry ) ) { names . push ( entry ) ; } else { names . push ( entry . hostFileName ) ; } } ) ; return names ; } public getScriptSnapshot ( path ) { const file = this . getHostFileInformation ( path ) ; return ( file && file . scriptSnapshot ) ! ; } } class SyntaxTreeCache { private currentFileName : string | undefined ; private currentFileVersion : string | undefined ; private currentFileScriptSnapshot : IScriptSnapshot | undefined ; private currentSourceFile : SourceFile | undefined ; constructor ( private host ) { } public getCurrentSourceFile ( fileName ) { const scriptSnapshot = this . host . getScriptSnapshot ( fileName ) ; if ( ! scriptSnapshot ) { throw new Error ( "Could not find file: '" + fileName + "'." ) ; } const scriptKind = getScriptKind ( fileName , this . host ) ; const version = this . host . getScriptVersion ( fileName ) ; let sourceFile ; if ( this . currentFileName !== fileName ) { sourceFile = createLanguageServiceSourceFile ( fileName , scriptSnapshot , ScriptTarget . Latest , version , true , scriptKind ) ; } else if ( this . currentFileVersion !== version ) { const editRange = scriptSnapshot . getChangeRange ( this . currentFileScriptSnapshot ! ) ; sourceFile = updateLanguageServiceSourceFile ( this . currentSourceFile ! , scriptSnapshot , version , editRange ) ; } if ( sourceFile ) { this . currentFileVersion = version ; this . currentFileName = fileName ; this . currentFileScriptSnapshot = scriptSnapshot ; this . currentSourceFile = sourceFile ; } return this . currentSourceFile ! ; } } function setSourceFileFields ( sourceFile , scriptSnapshot , version ) { sourceFile . version = version ; sourceFile . scriptSnapshot = scriptSnapshot ; } export function createLanguageServiceSourceFile ( fileName , scriptSnapshot , scriptTarget , version , setNodeParents , scriptKind ? ) { const sourceFile = createSourceFile ( fileName , getSnapshotText ( scriptSnapshot ) , scriptTarget , setNodeParents , scriptKind ) ; setSourceFileFields ( sourceFile , scriptSnapshot , version ) ; return sourceFile ; } export function updateLanguageServiceSourceFile ( sourceFile , scriptSnapshot , version , textChangeRange , aggressiveChecks ? ) { if ( textChangeRange ) { if ( version !== sourceFile . version ) { let newText ; const prefix = textChangeRange . span . start !== 0 ? sourceFile . text . substr ( 0 , textChangeRange . span . start ) : "" ; const suffix = textSpanEnd ( textChangeRange . span ) !== sourceFile . text . length ? sourceFile . text . substr ( textSpanEnd ( textChangeRange . span ) ) : "" ; if ( textChangeRange . newLength === 0 ) { newText = prefix && suffix ? prefix + suffix : prefix || suffix ; } else { const changedText = scriptSnapshot . getText ( textChangeRange . span . start , textChangeRange . span . start + textChangeRange . newLength ) ; newText = prefix && suffix ? prefix + changedText + suffix : prefix ? ( prefix + changedText ) : ( changedText + suffix ) ; } const newSourceFile = updateSourceFile ( sourceFile , newText , textChangeRange , aggressiveChecks ) ; setSourceFileFields ( newSourceFile , scriptSnapshot , version ) ; newSourceFile . nameTable = undefined ; if ( sourceFile !== newSourceFile && sourceFile . scriptSnapshot ) { if ( sourceFile . scriptSnapshot . dispose ) { sourceFile . scriptSnapshot . dispose ( ) ; } sourceFile . scriptSnapshot = undefined ; } return newSourceFile ; } } return createLanguageServiceSourceFile ( sourceFile . fileName , scriptSnapshot , sourceFile . languageVersion , version , true , sourceFile . scriptKind ) ; } const NoopCancellationToken = { isCancellationRequested : returnFalse , throwIfCancellationRequested : noop , } ; class CancellationTokenObject implements CancellationToken { constructor ( private cancellationToken ) { } public isCancellationRequested ( ) { return this . cancellationToken . isCancellationRequested ( ) ; } public throwIfCancellationRequested ( ) { if ( this . isCancellationRequested ( ) ) { tracing ?. instant ( tracing . Phase . Session , "cancellationThrown" , { kind : "CancellationTokenObject" } ) ; throw new OperationCanceledException ( ) ; } } } /** A cancellation that throttles calls to the host */ export class ThrottledCancellationToken implements CancellationToken { private lastCancellationCheckTime = 0 ; constructor ( private hostCancellationToken , private readonly throttleWaitMilliseconds = 20 ) { } public isCancellationRequested ( ) { const time = timestamp ( ) ; const duration = Math . abs ( time - this . lastCancellationCheckTime ) ; if ( duration >= this . throttleWaitMilliseconds ) { this . lastCancellationCheckTime = time ; return this . hostCancellationToken . isCancellationRequested ( ) ; } return false ; } public throwIfCancellationRequested ( ) { if ( this . isCancellationRequested ( ) ) { tracing ?. instant ( tracing . Phase . Session , "cancellationThrown" , { kind : "ThrottledCancellationToken" } ) ; throw new OperationCanceledException ( ) ; } } } const invalidOperationsInPartialSemanticMode = [ "getSemanticDiagnostics" , "getSuggestionDiagnostics" , "getCompilerOptionsDiagnostics" , "getSemanticClassifications" , "getEncodedSemanticClassifications" , "getCodeFixesAtPosition" , "getCombinedCodeFix" , "applyCodeActionCommand" , "organizeImports" , "getEditsForFileRename" , "getEmitOutput" , "getApplicableRefactors" , "getEditsForRefactor" , "prepareCallHierarchy" , "provideCallHierarchyIncomingCalls" , "provideCallHierarchyOutgoingCalls" , "provideInlayHints" ] ; const invalidOperationsInSyntacticMode = [ ... invalidOperationsInPartialSemanticMode , "getCompletionsAtPosition" , "getCompletionEntryDetails" , "getCompletionEntrySymbol" , "getSignatureHelpItems" , "getQuickInfoAtPosition" , "getDefinitionAtPosition" , "getDefinitionAndBoundSpan" , "getImplementationAtPosition" , "getTypeDefinitionAtPosition" , "getReferencesAtPosition" , "findReferences" , "getOccurrencesAtPosition" , "getDocumentHighlights" , "getNavigateToItems" , "getRenameInfo" , "findRenameLocations" , "getApplicableRefactors" , ] ; export function createLanguageService ( host , documentRegistry = createDocumentRegistry ( host . useCaseSensitiveFileNames && host . useCaseSensitiveFileNames ( ) , host . getCurrentDirectory ( ) ) , syntaxOnlyOrLanguageServiceMode ? ) { let languageServiceMode ; if ( syntaxOnlyOrLanguageServiceMode === undefined ) { languageServiceMode = LanguageServiceMode . Semantic ; } else if ( typeof syntaxOnlyOrLanguageServiceMode === "boolean" ) { languageServiceMode = syntaxOnlyOrLanguageServiceMode ? LanguageServiceMode . Syntactic : LanguageServiceMode . Semantic ; } else { languageServiceMode = syntaxOnlyOrLanguageServiceMode ; } const syntaxTreeCache = new SyntaxTreeCache ( host ) ; let program ; let lastProjectVersion ; let lastTypesRootVersion = 0 ; const cancellationToken = host . getCancellationToken ? new CancellationTokenObject ( host . getCancellationToken ( ) ) : NoopCancellationToken ; const currentDirectory = host . getCurrentDirectory ( ) ; if ( ! localizedDiagnosticMessages && host . getLocalizedDiagnosticMessages ) { setLocalizedDiagnosticMessages ( host . getLocalizedDiagnosticMessages ( ) ) ; } function log ( message ) { if ( host . log ) { host . log ( message ) ; } } const useCaseSensitiveFileNames = hostUsesCaseSensitiveFileNames ( host ) ; const getCanonicalFileName = createGetCanonicalFileName ( useCaseSensitiveFileNames ) ; const sourceMapper = getSourceMapper ( { useCaseSensitiveFileNames : ( ) => useCaseSensitiveFileNames , getCurrentDirectory : ( ) => currentDirectory , getProgram , fileExists : maybeBind ( host , host . fileExists ) , readFile : maybeBind ( host , host . readFile ) , getDocumentPositionMapper : maybeBind ( host , host . getDocumentPositionMapper ) , getSourceFileLike : maybeBind ( host , host . getSourceFileLike ) , log } ) ; function getValidSourceFile ( fileName ) { const sourceFile = program . getSourceFile ( fileName ) ; if ( ! sourceFile ) { const error = new Error ( `Could not find source file: '${ fileName }'.` ) ; error . ProgramFiles = program . getSourceFiles ( ) . map ( f => f . fileName ) ; throw error ; } return sourceFile ; } function synchronizeHostData ( ) { Debug . assert ( languageServiceMode !== LanguageServiceMode . Syntactic ) ; if ( host . getProjectVersion ) { const hostProjectVersion = host . getProjectVersion ( ) ; if ( hostProjectVersion ) { if ( lastProjectVersion === hostProjectVersion && ! host . hasChangedAutomaticTypeDirectiveNames ?. ( ) ) { return ; } lastProjectVersion = hostProjectVersion ; } } const typeRootsVersion = host . getTypeRootsVersion ? host . getTypeRootsVersion ( ) : 0 ; if ( lastTypesRootVersion !== typeRootsVersion ) { log ( "TypeRoots version has changed; provide new program" ) ; program = undefined ! ; lastTypesRootVersion = typeRootsVersion ; } let hostCache = new HostCache ( host , getCanonicalFileName ) ; const rootFileNames = hostCache . getRootFileNames ( ) ; const newSettings = host . getCompilationSettings ( ) || getDefaultCompilerOptions ( ) ; const hasInvalidatedResolution = host . hasInvalidatedResolution || returnFalse ; const hasChangedAutomaticTypeDirectiveNames = maybeBind ( host , host . hasChangedAutomaticTypeDirectiveNames ) ; const projectReferences = host . getProjectReferences ?. ( ) ; let parsedCommandLines ; const parseConfigHost = { useCaseSensitiveFileNames , fileExists , readFile , readDirectory , trace : maybeBind ( host , host . trace ) , getCurrentDirectory : ( ) => currentDirectory , onUnRecoverableConfigFileDiagnostic : noop , } ; if ( isProgramUptoDate ( program , rootFileNames , newSettings , ( _path , fileName ) => host . getScriptVersion ( fileName ) , fileExists , hasInvalidatedResolution , hasChangedAutomaticTypeDirectiveNames , getParsedCommandLine , projectReferences ) ) { return ; } const compilerHost = { getSourceFile : getOrCreateSourceFile , getSourceFileByPath : getOrCreateSourceFileByPath , getCancellationToken : ( ) => cancellationToken , getCanonicalFileName , useCaseSensitiveFileNames : ( ) => useCaseSensitiveFileNames , getNewLine : ( ) => getNewLineCharacter ( newSettings , ( ) => getNewLineOrDefaultFromHost ( host ) ) , getDefaultLibFileName : options => host . getDefaultLibFileName ( options ) , writeFile : noop , getCurrentDirectory : ( ) => currentDirectory , fileExists , readFile , getSymlinkCache : maybeBind ( host , host . getSymlinkCache ) , realpath : maybeBind ( host , host . realpath ) , directoryExists : directoryName => { return directoryProbablyExists ( directoryName , host ) ; } , getDirectories : path => { return host . getDirectories ? host . getDirectories ( path ) : [ ] ; } , readDirectory , onReleaseOldSourceFile , onReleaseParsedCommandLine , hasInvalidatedResolution , hasChangedAutomaticTypeDirectiveNames , trace : parseConfigHost . trace , resolveModuleNames : maybeBind ( host , host . resolveModuleNames ) , resolveTypeReferenceDirectives : maybeBind ( host , host . resolveTypeReferenceDirectives ) , useSourceOfProjectReferenceRedirect : maybeBind ( host , host . useSourceOfProjectReferenceRedirect ) , getParsedCommandLine , } ; host . setCompilerHost ?. ( compilerHost ) ; const documentRegistryBucketKey = documentRegistry . getKeyForCompilationSettings ( newSettings ) ; const options = { rootNames : rootFileNames , options : newSettings , host : compilerHost , oldProgram : program , projectReferences } ; program = createProgram ( options ) ; hostCache = undefined ; parsedCommandLines = undefined ; sourceMapper . clearCache ( ) ; program . getTypeChecker ( ) ; return ; function getParsedCommandLine ( fileName ) { const path = toPath ( fileName , currentDirectory , getCanonicalFileName ) ; const existing = parsedCommandLines ?. get ( path ) ; if ( existing !== undefined ) return existing || undefined ; const result = host . getParsedCommandLine ? host . getParsedCommandLine ( fileName ) : getParsedCommandLineOfConfigFileUsingSourceFile ( fileName ) ; ( parsedCommandLines ||= new Map ( ) ) . set ( path , result || false ) ; return result ; } function getParsedCommandLineOfConfigFileUsingSourceFile ( configFileName ) { const result = getOrCreateSourceFile ( configFileName , ScriptTarget . JSON ) as JsonSourceFile | undefined ; if ( ! result ) return undefined ; result . path = toPath ( configFileName , currentDirectory , getCanonicalFileName ) ; result . resolvedPath = result . path ; result . originalFileName = result . fileName ; return parseJsonSourceFileConfigFileContent ( result , parseConfigHost , getNormalizedAbsolutePath ( getDirectoryPath ( configFileName ) , currentDirectory ) , undefined , getNormalizedAbsolutePath ( configFileName , currentDirectory ) ) ; } function onReleaseParsedCommandLine ( configFileName , oldResolvedRef , oldOptions ) { if ( host . getParsedCommandLine ) { host . onReleaseParsedCommandLine ?. ( configFileName , oldResolvedRef , oldOptions ) ; } else if ( oldResolvedRef ) { onReleaseOldSourceFile ( oldResolvedRef . sourceFile , oldOptions ) ; } } function fileExists ( fileName ) { const path = toPath ( fileName , currentDirectory , getCanonicalFileName ) ; const entry = hostCache && hostCache . getEntryByPath ( path ) ; return entry ? ! isString ( entry ) : ( ! ! host . fileExists && host . fileExists ( fileName ) ) ; } function readFile ( fileName ) { const path = toPath ( fileName , currentDirectory , getCanonicalFileName ) ; const entry = hostCache && hostCache . getEntryByPath ( path ) ; if ( entry ) { return isString ( entry ) ? undefined : getSnapshotText ( entry . scriptSnapshot ) ; } return host . readFile && host . readFile ( fileName ) ; } function readDirectory ( path , extensions ? , exclude ? , include ? , depth ? ) { Debug . checkDefined ( host . readDirectory , "'LanguageServiceHost.readDirectory' must be implemented to correctly process 'projectReferences'" ) ; return host . readDirectory ! ( path , extensions , exclude , include , depth ) ; } function onReleaseOldSourceFile ( oldSourceFile , oldOptions ) { const oldSettingsKey = documentRegistry . getKeyForCompilationSettings ( oldOptions ) ; documentRegistry . releaseDocumentWithKey ( oldSourceFile . resolvedPath , oldSettingsKey , oldSourceFile . scriptKind ) ; } function getOrCreateSourceFile ( fileName , languageVersion , onError ? , shouldCreateNewSourceFile ? ) { return getOrCreateSourceFileByPath ( fileName , toPath ( fileName , currentDirectory , getCanonicalFileName ) , languageVersion , onError , shouldCreateNewSourceFile ) ; } function getOrCreateSourceFileByPath ( fileName , path , _languageVersion , _onError ? , shouldCreateNewSourceFile ? ) { Debug . assert ( hostCache !== undefined , "getOrCreateSourceFileByPath called after typical CompilerHost lifetime, check the callstack something with a reference to an old host." ) ; const hostFileInformation = hostCache && hostCache . getOrCreateEntryByPath ( fileName , path ) ; if ( ! hostFileInformation ) { return undefined ; } if ( ! shouldCreateNewSourceFile ) { const oldSourceFile = program && program . getSourceFileByPath ( path ) ; if ( oldSourceFile ) { if ( hostFileInformation . scriptKind === oldSourceFile . scriptKind ) { return documentRegistry . updateDocumentWithKey ( fileName , path , newSettings , documentRegistryBucketKey , hostFileInformation . scriptSnapshot , hostFileInformation . version , hostFileInformation . scriptKind ) ; } else { documentRegistry . releaseDocumentWithKey ( oldSourceFile . resolvedPath , documentRegistry . getKeyForCompilationSettings ( program . getCompilerOptions ( ) ) , oldSourceFile . scriptKind ) ; } } } return documentRegistry . acquireDocumentWithKey ( fileName , path , newSettings , documentRegistryBucketKey , hostFileInformation . scriptSnapshot , hostFileInformation . version , hostFileInformation . scriptKind ) ; } } function getProgram ( ) { if ( languageServiceMode === LanguageServiceMode . Syntactic ) { Debug . assert ( program === undefined ) ; return undefined ; } synchronizeHostData ( ) ; return program ; } function getAutoImportProvider ( ) { return host . getPackageJsonAutoImportProvider ?. ( ) ; } function cleanupSemanticCache ( ) { program = undefined ! ; } function dispose ( ) { if ( program ) { const key = documentRegistry . getKeyForCompilationSettings ( program . getCompilerOptions ( ) ) ; forEach ( program . getSourceFiles ( ) , f => documentRegistry . releaseDocumentWithKey ( f . resolvedPath , key , f . scriptKind ) ) ; program = undefined ! ; } host = undefined ! ; } function getSyntacticDiagnostics ( fileName ) { synchronizeHostData ( ) ; return program . getSyntacticDiagnostics ( getValidSourceFile ( fileName ) , cancellationToken ) . slice ( ) ; } /**
         * getSemanticDiagnostics return array of Diagnostics. If '-d' is not enabled, only report semantic errors
         * If '-d' enabled, report both semantic and emitter errors
         */ function getSemanticDiagnostics ( fileName ) { synchronizeHostData ( ) ; const targetSourceFile = getValidSourceFile ( fileName ) ; const semanticDiagnostics = program . getSemanticDiagnostics ( targetSourceFile , cancellationToken ) ; if ( ! getEmitDeclarations ( program . getCompilerOptions ( ) ) ) { return semanticDiagnostics . slice ( ) ; } const declarationDiagnostics = program . getDeclarationDiagnostics ( targetSourceFile , cancellationToken ) ; return [ ... semanticDiagnostics , ... declarationDiagnostics ] ; } function getSuggestionDiagnostics ( fileName ) { synchronizeHostData ( ) ; return computeSuggestionDiagnostics ( getValidSourceFile ( fileName ) , program , cancellationToken ) ; } function getCompilerOptionsDiagnostics ( ) { synchronizeHostData ( ) ; return [ ... program . getOptionsDiagnostics ( cancellationToken ) , ... program . getGlobalDiagnostics ( cancellationToken ) ] ; } function getCompletionsAtPosition ( fileName , position , options = emptyOptions , formattingSettings ? ) { const fullPreferences = { ... identity < UserPreferences > ( options ) , includeCompletionsForModuleExports : options . includeCompletionsForModuleExports || options . includeExternalModuleExports , includeCompletionsWithInsertText : options . includeCompletionsWithInsertText || options . includeInsertTextCompletions , } ; synchronizeHostData ( ) ; return Completions . getCompletionsAtPosition ( host , program , log , getValidSourceFile ( fileName ) , position , fullPreferences , options . triggerCharacter , options . triggerKind , cancellationToken , formattingSettings && formatting . getFormatContext ( formattingSettings , host ) ) ; } function getCompletionEntryDetails ( fileName , position , name , formattingOptions , source , preferences = emptyOptions , data ? ) { synchronizeHostData ( ) ; return Completions . getCompletionEntryDetails ( program , log , getValidSourceFile ( fileName ) , position , { name , source , data } , host , ( formattingOptions && formatting . getFormatContext ( formattingOptions , host ) ) ! , preferences , cancellationToken ) ; } function getCompletionEntrySymbol ( fileName , position , name , source ? , preferences = emptyOptions ) { synchronizeHostData ( ) ; return Completions . getCompletionEntrySymbol ( program , log , getValidSourceFile ( fileName ) , position , { name , source } , host , preferences ) ; } function getQuickInfoAtPosition ( fileName , position ) { synchronizeHostData ( ) ; const sourceFile = getValidSourceFile ( fileName ) ; const node = getTouchingPropertyName ( sourceFile , position ) ; if ( node === sourceFile ) { return undefined ; } const typeChecker = program . getTypeChecker ( ) ; const nodeForQuickInfo = getNodeForQuickInfo ( node ) ; const symbol = getSymbolAtLocationForQuickInfo ( nodeForQuickInfo , typeChecker ) ; if ( ! symbol || typeChecker . isUnknownSymbol ( symbol ) ) { const type = shouldGetType ( sourceFile , nodeForQuickInfo , position ) ? typeChecker . getTypeAtLocation ( nodeForQuickInfo ) : undefined ; return type && { kind : ScriptElementKind . unknown , kindModifiers : ScriptElementKindModifier . none , textSpan : createTextSpanFromNode ( nodeForQuickInfo , sourceFile ) , displayParts : typeChecker . runWithCancellationToken ( cancellationToken , typeChecker => typeToDisplayParts ( typeChecker , type , getContainerNode ( nodeForQuickInfo ) ) ) , documentation : type . symbol ? type . symbol . getDocumentationComment ( typeChecker ) : undefined , tags : type . symbol ? type . symbol . getJsDocTags ( typeChecker ) : undefined } ; } const { symbolKind , displayParts , documentation , tags } = typeChecker . runWithCancellationToken ( cancellationToken , typeChecker => SymbolDisplay . getSymbolDisplayPartsDocumentationAndSymbolKind ( typeChecker , symbol , sourceFile , getContainerNode ( nodeForQuickInfo ) , nodeForQuickInfo ) ) ; return { kind : symbolKind , kindModifiers : SymbolDisplay . getSymbolModifiers ( typeChecker , symbol ) , textSpan : createTextSpanFromNode ( nodeForQuickInfo , sourceFile ) , displayParts , documentation , tags , } ; } function getNodeForQuickInfo ( node ) { if ( isNewExpression ( node . parent ) && node . pos === node . parent . pos ) { return node . parent . expression ; } if ( isNamedTupleMember ( node . parent ) && node . pos === node . parent . pos ) { return node . parent ; } return node ; } function shouldGetType ( sourceFile , node , position ) { switch ( node . kind ) { case SyntaxKind . Identifier : return ! isLabelName ( node ) && ! isTagName ( node ) && ! isConstTypeReference ( node . parent ) ; case SyntaxKind . PropertyAccessExpression : case SyntaxKind . QualifiedName : return ! isInComment ( sourceFile , position ) ; case SyntaxKind . ThisKeyword : case SyntaxKind . ThisType : case SyntaxKind . SuperKeyword : case SyntaxKind . NamedTupleMember : return true ; default : return false ; } } function getDefinitionAtPosition ( fileName , position ) { synchronizeHostData ( ) ; return GoToDefinition . getDefinitionAtPosition ( program , getValidSourceFile ( fileName ) , position ) ; } function getDefinitionAndBoundSpan ( fileName , position ) { synchronizeHostData ( ) ; return GoToDefinition . getDefinitionAndBoundSpan ( program , getValidSourceFile ( fileName ) , position ) ; } function getTypeDefinitionAtPosition ( fileName , position ) { synchronizeHostData ( ) ; return GoToDefinition . getTypeDefinitionAtPosition ( program . getTypeChecker ( ) , getValidSourceFile ( fileName ) , position ) ; } function getImplementationAtPosition ( fileName , position ) { synchronizeHostData ( ) ; return FindAllReferences . getImplementationsAtPosition ( program , cancellationToken , program . getSourceFiles ( ) , getValidSourceFile ( fileName ) , position ) ; } function getOccurrencesAtPosition ( fileName , position ) { return flatMap ( getDocumentHighlights ( fileName , position , [ fileName ] ) , entry => entry . highlightSpans . map < ReferenceEntry > ( highlightSpan => ( { fileName : entry . fileName , textSpan : highlightSpan . textSpan , isWriteAccess : highlightSpan . kind === HighlightSpanKind . writtenReference , isDefinition : false , ... highlightSpan . isInString && { isInString : true } , ... highlightSpan . contextSpan && { contextSpan : highlightSpan . contextSpan } } ) ) ) ; } function getDocumentHighlights ( fileName , position , filesToSearch ) { const normalizedFileName = normalizePath ( fileName ) ; Debug . assert ( filesToSearch . some ( f => normalizePath ( f ) === normalizedFileName ) ) ; synchronizeHostData ( ) ; const sourceFilesToSearch = mapDefined ( filesToSearch , fileName => program . getSourceFile ( fileName ) ) ; const sourceFile = getValidSourceFile ( fileName ) ; return DocumentHighlights . getDocumentHighlights ( program , cancellationToken , sourceFile , position , sourceFilesToSearch ) ; } function findRenameLocations ( fileName , position , findInStrings , findInComments , providePrefixAndSuffixTextForRename ? ) { synchronizeHostData ( ) ; const sourceFile = getValidSourceFile ( fileName ) ; const node = getAdjustedRenameLocation ( getTouchingPropertyName ( sourceFile , position ) ) ; if ( ! Rename . nodeIsEligibleForRename ( node ) ) return undefined ; if ( isIdentifier ( node ) && ( isJsxOpeningElement ( node . parent ) || isJsxClosingElement ( node . parent ) ) && isIntrinsicJsxName ( node . escapedText ) ) { const { openingElement , closingElement } = node . parent . parent ; return [ openingElement , closingElement ] . map ( ( node ) : RenameLocation => { const textSpan = createTextSpanFromNode ( node . tagName , sourceFile ) ; return { fileName : sourceFile . fileName , textSpan , ... FindAllReferences . toContextSpan ( textSpan , sourceFile , node . parent ) } ; } ) ; } else { return getReferencesWorker ( node , position , { findInStrings , findInComments , providePrefixAndSuffixTextForRename , use : FindAllReferences . FindReferencesUse . Rename } , ( entry , originalNode , checker ) => FindAllReferences . toRenameLocation ( entry , originalNode , checker , providePrefixAndSuffixTextForRename || false ) ) ; } } function getReferencesAtPosition ( fileName , position ) { synchronizeHostData ( ) ; return getReferencesWorker ( getTouchingPropertyName ( getValidSourceFile ( fileName ) , position ) , position , { use : FindAllReferences . FindReferencesUse . References } , ( entry , node , checker ) => FindAllReferences . toReferenceEntry ( entry , checker . getSymbolAtLocation ( node ) ) ) ; } function getReferencesWorker < T > ( node , position , options , cb ) { synchronizeHostData ( ) ; const sourceFiles = options && options . use === FindAllReferences . FindReferencesUse . Rename ? program . getSourceFiles ( ) . filter ( sourceFile => ! program . isSourceFileDefaultLibrary ( sourceFile ) ) : program . getSourceFiles ( ) ; return FindAllReferences . findReferenceOrRenameEntries ( program , cancellationToken , sourceFiles , node , position , options , cb ) ; } function findReferences ( fileName , position ) { synchronizeHostData ( ) ; return FindAllReferences . findReferencedSymbols ( program , cancellationToken , program . getSourceFiles ( ) , getValidSourceFile ( fileName ) , position ) ; } function getFileReferences ( fileName ) { synchronizeHostData ( ) ; const moduleSymbol = program . getSourceFile ( fileName ) ?. symbol ; return FindAllReferences . Core . getReferencesForFileName ( fileName , program , program . getSourceFiles ( ) ) . map ( r => FindAllReferences . toReferenceEntry ( r , moduleSymbol ) ) ; } function getNavigateToItems ( searchValue , maxResultCount ? , fileName ? , excludeDtsFiles = false ) { synchronizeHostData ( ) ; const sourceFiles = fileName ? [ getValidSourceFile ( fileName ) ] : program . getSourceFiles ( ) ; return NavigateTo . getNavigateToItems ( sourceFiles , program . getTypeChecker ( ) , cancellationToken , searchValue , maxResultCount , excludeDtsFiles ) ; } function getEmitOutput ( fileName , emitOnlyDtsFiles ? , forceDtsEmit ? ) { synchronizeHostData ( ) ; const sourceFile = getValidSourceFile ( fileName ) ; const customTransformers = host . getCustomTransformers && host . getCustomTransformers ( ) ; return getFileEmitOutput ( program , sourceFile , ! ! emitOnlyDtsFiles , cancellationToken , customTransformers , forceDtsEmit ) ; } /**
         * This is a semantic operation.
         */ function getSignatureHelpItems ( fileName , position , { triggerReason } = emptyOptions ) { synchronizeHostData ( ) ; const sourceFile = getValidSourceFile ( fileName ) ; return SignatureHelp . getSignatureHelpItems ( program , sourceFile , position , triggerReason , cancellationToken ) ; } function getNonBoundSourceFile ( fileName ) { return syntaxTreeCache . getCurrentSourceFile ( fileName ) ; } function getNameOrDottedNameSpan ( fileName , startPos , _endPos ) { const sourceFile = syntaxTreeCache . getCurrentSourceFile ( fileName ) ; const node = getTouchingPropertyName ( sourceFile , startPos ) ; if ( node === sourceFile ) { return undefined ; } switch ( node . kind ) { case SyntaxKind . PropertyAccessExpression : case SyntaxKind . QualifiedName : case SyntaxKind . StringLiteral : case SyntaxKind . FalseKeyword : case SyntaxKind . TrueKeyword : case SyntaxKind . NullKeyword : case SyntaxKind . SuperKeyword : case SyntaxKind . ThisKeyword : case SyntaxKind . ThisType : case SyntaxKind . Identifier : break ; default : return undefined ; } let nodeForStartPos = node ; while ( true ) { if ( isRightSideOfPropertyAccess ( nodeForStartPos ) || isRightSideOfQualifiedName ( nodeForStartPos ) ) { nodeForStartPos = nodeForStartPos . parent ; } else if ( isNameOfModuleDeclaration ( nodeForStartPos ) ) { if ( nodeForStartPos . parent . parent . kind === SyntaxKind . ModuleDeclaration && ( nodeForStartPos . parent . parent as ModuleDeclaration ) . body === nodeForStartPos . parent ) { nodeForStartPos = ( nodeForStartPos . parent . parent as ModuleDeclaration ) . name ; } else { break ; } } else { break ; } } return createTextSpanFromBounds ( nodeForStartPos . getStart ( ) , node . getEnd ( ) ) ; } function getBreakpointStatementAtPosition ( fileName , position ) { const sourceFile = syntaxTreeCache . getCurrentSourceFile ( fileName ) ; return BreakpointResolver . spanInSourceFileAtLocation ( sourceFile , position ) ; } function getNavigationBarItems ( fileName ) { return NavigationBar . getNavigationBarItems ( syntaxTreeCache . getCurrentSourceFile ( fileName ) , cancellationToken ) ; } function getNavigationTree ( fileName ) { return NavigationBar . getNavigationTree ( syntaxTreeCache . getCurrentSourceFile ( fileName ) , cancellationToken ) ; } function getSemanticClassifications ( fileName , span ) ; function getSemanticClassifications ( fileName , span , format ? ) { synchronizeHostData ( ) ; const responseFormat = format || SemanticClassificationFormat . Original ; if ( responseFormat === SemanticClassificationFormat . TwentyTwenty ) { return classifier . v2020 . getSemanticClassifications ( program , cancellationToken , getValidSourceFile ( fileName ) , span ) ; } else { return ts . getSemanticClassifications ( program . getTypeChecker ( ) , cancellationToken , getValidSourceFile ( fileName ) , program . getClassifiableNames ( ) , span ) ; } } function getEncodedSemanticClassifications ( fileName , span , format ? ) { synchronizeHostData ( ) ; const responseFormat = format || SemanticClassificationFormat . Original ; if ( responseFormat === SemanticClassificationFormat . Original ) { return ts . getEncodedSemanticClassifications ( program . getTypeChecker ( ) , cancellationToken , getValidSourceFile ( fileName ) , program . getClassifiableNames ( ) , span ) ; } else { return classifier . v2020 . getEncodedSemanticClassifications ( program , cancellationToken , getValidSourceFile ( fileName ) , span ) ; } } function getSyntacticClassifications ( fileName , span ) { return ts . getSyntacticClassifications ( cancellationToken , syntaxTreeCache . getCurrentSourceFile ( fileName ) , span ) ; } function getEncodedSyntacticClassifications ( fileName , span ) { return ts . getEncodedSyntacticClassifications ( cancellationToken , syntaxTreeCache . getCurrentSourceFile ( fileName ) , span ) ; } function getOutliningSpans ( fileName ) { const sourceFile = syntaxTreeCache . getCurrentSourceFile ( fileName ) ; return OutliningElementsCollector . collectElements ( sourceFile , cancellationToken ) ; } const braceMatching = new Map ( getEntries ( { [ SyntaxKind . OpenBraceToken ] : SyntaxKind . CloseBraceToken , [ SyntaxKind . OpenParenToken ] : SyntaxKind . CloseParenToken , [ SyntaxKind . OpenBracketToken ] : SyntaxKind . CloseBracketToken , [ SyntaxKind . GreaterThanToken ] : SyntaxKind . LessThanToken , } ) ) ; braceMatching . forEach ( ( value , key ) => braceMatching . set ( value . toString ( ) , Number ( key ) as SyntaxKind ) ) ; function getBraceMatchingAtPosition ( fileName , position ) { const sourceFile = syntaxTreeCache . getCurrentSourceFile ( fileName ) ; const token = getTouchingToken ( sourceFile , position ) ; const matchKind = token . getStart ( sourceFile ) === position ? braceMatching . get ( token . kind . toString ( ) ) : undefined ; const match = matchKind && findChildOfKind ( token . parent , matchKind , sourceFile ) ; return match ? [ createTextSpanFromNode ( token , sourceFile ) , createTextSpanFromNode ( match , sourceFile ) ] . sort ( ( a , b ) => a . start - b . start ) : emptyArray ; } function getIndentationAtPosition ( fileName , position , editorOptions ) { let start = timestamp ( ) ; const settings = toEditorSettings ( editorOptions ) ; const sourceFile = syntaxTreeCache . getCurrentSourceFile ( fileName ) ; log ( "getIndentationAtPosition: getCurrentSourceFile: " + ( timestamp ( ) - start ) ) ; start = timestamp ( ) ; const result = formatting . SmartIndenter . getIndentation ( position , sourceFile , settings ) ; log ( "getIndentationAtPosition: computeIndentation  : " + ( timestamp ( ) - start ) ) ; return result ; } function getFormattingEditsForRange ( fileName , start , end , options ) { const sourceFile = syntaxTreeCache . getCurrentSourceFile ( fileName ) ; return formatting . formatSelection ( start , end , sourceFile , formatting . getFormatContext ( toEditorSettings ( options ) , host ) ) ; } function getFormattingEditsForDocument ( fileName , options ) { return formatting . formatDocument ( syntaxTreeCache . getCurrentSourceFile ( fileName ) , formatting . getFormatContext ( toEditorSettings ( options ) , host ) ) ; } function getFormattingEditsAfterKeystroke ( fileName , position , key , options ) { const sourceFile = syntaxTreeCache . getCurrentSourceFile ( fileName ) ; const formatContext = formatting . getFormatContext ( toEditorSettings ( options ) , host ) ; if ( ! isInComment ( sourceFile , position ) ) { switch ( key ) { case "{" : return formatting . formatOnOpeningCurly ( position , sourceFile , formatContext ) ; case "}" : return formatting . formatOnClosingCurly ( position , sourceFile , formatContext ) ; case ";" : return formatting . formatOnSemicolon ( position , sourceFile , formatContext ) ; case "\n" : return formatting . formatOnEnter ( position , sourceFile , formatContext ) ; } } return [ ] ; } function getCodeFixesAtPosition ( fileName , start , end , errorCodes , formatOptions , preferences = emptyOptions ) { synchronizeHostData ( ) ; const sourceFile = getValidSourceFile ( fileName ) ; const span = createTextSpanFromBounds ( start , end ) ; const formatContext = formatting . getFormatContext ( formatOptions , host ) ; return flatMap ( deduplicate < number > ( errorCodes , equateValues , compareValues ) , errorCode => { cancellationToken . throwIfCancellationRequested ( ) ; return codefix . getFixes ( { errorCode , sourceFile , span , program , host , cancellationToken , formatContext , preferences } ) ; } ) ; } function getCombinedCodeFix ( scope , fixId , formatOptions , preferences = emptyOptions ) { synchronizeHostData ( ) ; Debug . assert ( scope . type === "file" ) ; const sourceFile = getValidSourceFile ( scope . fileName ) ; const formatContext = formatting . getFormatContext ( formatOptions , host ) ; return codefix . getAllFixes ( { fixId , sourceFile , program , host , cancellationToken , formatContext , preferences } ) ; } function organizeImports ( args , formatOptions , preferences = emptyOptions ) { synchronizeHostData ( ) ; Debug . assert ( args . type === "file" ) ; const sourceFile = getValidSourceFile ( args . fileName ) ; const formatContext = formatting . getFormatContext ( formatOptions , host ) ; return OrganizeImports . organizeImports ( sourceFile , formatContext , host , program , preferences , args . skipDestructiveCodeActions ) ; } function getEditsForFileRename ( oldFilePath , newFilePath , formatOptions , preferences = emptyOptions ) { return ts . getEditsForFileRename ( getProgram ( ) ! , oldFilePath , newFilePath , host , formatting . getFormatContext ( formatOptions , host ) , preferences , sourceMapper ) ; } function applyCodeActionCommand ( action , formatSettings ? ) ; function applyCodeActionCommand ( action , formatSettings ? ) ; function applyCodeActionCommand ( action , formatSettings ? ) ; function applyCodeActionCommand ( fileName , action ) ; function applyCodeActionCommand ( fileName , action ) ; function applyCodeActionCommand ( fileName , actionOrFormatSettingsOrUndefined ? ) { const action = typeof fileName === "string" ? actionOrFormatSettingsOrUndefined as CodeActionCommand | CodeActionCommand [ ] : fileName as CodeActionCommand [ ] ; return isArray ( action ) ? Promise . all ( action . map ( a => applySingleCodeActionCommand ( a ) ) ) : applySingleCodeActionCommand ( action ) ; } function applySingleCodeActionCommand ( action ) { const getPath = ( path ) : Path => toPath ( path , currentDirectory , getCanonicalFileName ) ; Debug . assertEqual ( action . type , "install package" ) ; return host . installPackage ? host . installPackage ( { fileName : getPath ( action . file ) , packageName : action . packageName } ) : Promise . reject ( "Host does not implement `installPackage`" ) ; } function getDocCommentTemplateAtPosition ( fileName , position , options ? ) { return JsDoc . getDocCommentTemplateAtPosition ( getNewLineOrDefaultFromHost ( host ) , syntaxTreeCache . getCurrentSourceFile ( fileName ) , position , options ) ; } function isValidBraceCompletionAtPosition ( fileName , position , openingBrace ) { if ( openingBrace === CharacterCodes . lessThan ) { return false ; } const sourceFile = syntaxTreeCache . getCurrentSourceFile ( fileName ) ; if ( isInString ( sourceFile , position ) ) { return false ; } if ( isInsideJsxElementOrAttribute ( sourceFile , position ) ) { return openingBrace === CharacterCodes . openBrace ; } if ( isInTemplateString ( sourceFile , position ) ) { return false ; } switch ( openingBrace ) { case CharacterCodes . singleQuote : case CharacterCodes . doubleQuote : case CharacterCodes . backtick : return ! isInComment ( sourceFile , position ) ; } return true ; } function getJsxClosingTagAtPosition ( fileName , position ) { const sourceFile = syntaxTreeCache . getCurrentSourceFile ( fileName ) ; const token = findPrecedingToken ( position , sourceFile ) ; if ( ! token ) return undefined ; const element = token . kind === SyntaxKind . GreaterThanToken && isJsxOpeningElement ( token . parent ) ? token . parent . parent : isJsxText ( token ) && isJsxElement ( token . parent ) ? token . parent : undefined ; if ( element && isUnclosedTag ( element ) ) { return { newText : `</${ element . openingElement . tagName . getText ( sourceFile ) }>` } ; } const fragment = token . kind === SyntaxKind . GreaterThanToken && isJsxOpeningFragment ( token . parent ) ? token . parent . parent : isJsxText ( token ) && isJsxFragment ( token . parent ) ? token . parent : undefined ; if ( fragment && isUnclosedFragment ( fragment ) ) { return { newText : "</>" } ; } } function getLinesForRange ( sourceFile , textRange ) { return { lineStarts : sourceFile . getLineStarts ( ) , firstLine : sourceFile . getLineAndCharacterOfPosition ( textRange . pos ) . line , lastLine : sourceFile . getLineAndCharacterOfPosition ( textRange . end ) . line } ; } function toggleLineComment ( fileName , textRange , insertComment ? ) { const sourceFile = syntaxTreeCache . getCurrentSourceFile ( fileName ) ; const textChanges = [ ] ; const { lineStarts , firstLine , lastLine } = getLinesForRange ( sourceFile , textRange ) ; let isCommenting = insertComment || false ; let leftMostPosition = Number . MAX_VALUE ; const lineTextStarts = new Map < string , number > ( ) ; const firstNonWhitespaceCharacterRegex = new RegExp ( /\S/ ) ; const isJsx = isInsideJsxElement ( sourceFile , lineStarts [ firstLine ] ) ; const openComment = isJsx ? "{/*" : "//" ; for ( let i = firstLine ; i <= lastLine ; i ++ ) { const lineText = sourceFile . text . substring ( lineStarts [ i ] , sourceFile . getLineEndOfPosition ( lineStarts [ i ] ) ) ; const regExec = firstNonWhitespaceCharacterRegex . exec ( lineText ) ; if ( regExec ) { leftMostPosition = Math . min ( leftMostPosition , regExec . index ) ; lineTextStarts . set ( i . toString ( ) , regExec . index ) ; if ( lineText . substr ( regExec . index , openComment . length ) !== openComment ) { isCommenting = insertComment === undefined || insertComment ; } } } for ( let i = firstLine ; i <= lastLine ; i ++ ) { if ( firstLine !== lastLine && lineStarts [ i ] === textRange . end ) { continue ; } const lineTextStart = lineTextStarts . get ( i . toString ( ) ) ; if ( lineTextStart !== undefined ) { if ( isJsx ) { textChanges . push . apply ( textChanges , toggleMultilineComment ( fileName , { pos : lineStarts [ i ] + leftMostPosition , end : sourceFile . getLineEndOfPosition ( lineStarts [ i ] ) } , isCommenting , isJsx ) ) ; } else if ( isCommenting ) { textChanges . push ( { newText : openComment , span : { length : 0 , start : lineStarts [ i ] + leftMostPosition } } ) ; } else if ( sourceFile . text . substr ( lineStarts [ i ] + lineTextStart , openComment . length ) === openComment ) { textChanges . push ( { newText : "" , span : { length : openComment . length , start : lineStarts [ i ] + lineTextStart } } ) ; } } } return textChanges ; } function toggleMultilineComment ( fileName , textRange , insertComment ? , isInsideJsx ? ) { const sourceFile = syntaxTreeCache . getCurrentSourceFile ( fileName ) ; const textChanges = [ ] ; const { text } = sourceFile ; let hasComment = false ; let isCommenting = insertComment || false ; const positions = [ ] as number [ ] as SortedArray < number > ; let { pos } = textRange ; const isJsx = isInsideJsx !== undefined ? isInsideJsx : isInsideJsxElement ( sourceFile , pos ) ; const openMultiline = isJsx ? "{/*" : "/*" ; const closeMultiline = isJsx ? "*/}" : "*/" ; const openMultilineRegex = isJsx ? "\\{\\/\\*" : "\\/\\*" ; const closeMultilineRegex = isJsx ? "\\*\\/\\}" : "\\*\\/" ; while ( pos <= textRange . end ) { const offset = text . substr ( pos , openMultiline . length ) === openMultiline ? openMultiline . length : 0 ; const commentRange = isInComment ( sourceFile , pos + offset ) ; if ( commentRange ) { if ( isJsx ) { commentRange . pos -- ; commentRange . end ++ ; } positions . push ( commentRange . pos ) ; if ( commentRange . kind === SyntaxKind . MultiLineCommentTrivia ) { positions . push ( commentRange . end ) ; } hasComment = true ; pos = commentRange . end + 1 ; } else { const newPos = text . substring ( pos , textRange . end ) . search ( `(${ openMultilineRegex })|(${ closeMultilineRegex })` ) ; isCommenting = insertComment !== undefined ? insertComment : isCommenting || ! isTextWhiteSpaceLike ( text , pos , newPos === - 1 ? textRange . end : pos + newPos ) ; pos = newPos === - 1 ? textRange . end + 1 : pos + newPos + closeMultiline . length ; } } if ( isCommenting || ! hasComment ) { if ( isInComment ( sourceFile , textRange . pos ) ?. kind !== SyntaxKind . SingleLineCommentTrivia ) { insertSorted ( positions , textRange . pos , compareValues ) ; } insertSorted ( positions , textRange . end , compareValues ) ; const firstPos = positions [ 0 ] ; if ( text . substr ( firstPos , openMultiline . length ) !== openMultiline ) { textChanges . push ( { newText : openMultiline , span : { length : 0 , start : firstPos } } ) ; } for ( let i = 1 ; i < positions . length - 1 ; i ++ ) { if ( text . substr ( positions [ i ] - closeMultiline . length , closeMultiline . length ) !== closeMultiline ) { textChanges . push ( { newText : closeMultiline , span : { length : 0 , start : positions [ i ] } } ) ; } if ( text . substr ( positions [ i ] , openMultiline . length ) !== openMultiline ) { textChanges . push ( { newText : openMultiline , span : { length : 0 , start : positions [ i ] } } ) ; } } if ( textChanges . length % 2 !== 0 ) { textChanges . push ( { newText : closeMultiline , span : { length : 0 , start : positions [ positions . length - 1 ] } } ) ; } } else { for ( const pos of positions ) { const from = pos - closeMultiline . length > 0 ? pos - closeMultiline . length : 0 ; const offset = text . substr ( from , closeMultiline . length ) === closeMultiline ? closeMultiline . length : 0 ; textChanges . push ( { newText : "" , span : { length : openMultiline . length , start : pos - offset } } ) ; } } return textChanges ; } function commentSelection ( fileName , textRange ) { const sourceFile = syntaxTreeCache . getCurrentSourceFile ( fileName ) ; const { firstLine , lastLine } = getLinesForRange ( sourceFile , textRange ) ; return firstLine === lastLine && textRange . pos !== textRange . end ? toggleMultilineComment ( fileName , textRange , true ) : toggleLineComment ( fileName , textRange , true ) ; } function uncommentSelection ( fileName , textRange ) { const sourceFile = syntaxTreeCache . getCurrentSourceFile ( fileName ) ; const textChanges = [ ] ; const { pos } = textRange ; let { end } = textRange ; if ( pos === end ) { end += isInsideJsxElement ( sourceFile , pos ) ? 2 : 1 ; } for ( let i = pos ; i <= end ; i ++ ) { const commentRange = isInComment ( sourceFile , i ) ; if ( commentRange ) { switch ( commentRange . kind ) { case SyntaxKind . SingleLineCommentTrivia : textChanges . push . apply ( textChanges , toggleLineComment ( fileName , { end : commentRange . end , pos : commentRange . pos + 1 } , false ) ) ; break ; case SyntaxKind . MultiLineCommentTrivia : textChanges . push . apply ( textChanges , toggleMultilineComment ( fileName , { end : commentRange . end , pos : commentRange . pos + 1 } , false ) ) ; } i = commentRange . end + 1 ; } } return textChanges ; } function isUnclosedTag ( { openingElement , closingElement , parent } ) { return ! tagNamesAreEquivalent ( openingElement . tagName , closingElement . tagName ) || isJsxElement ( parent ) && tagNamesAreEquivalent ( openingElement . tagName , parent . openingElement . tagName ) && isUnclosedTag ( parent ) ; } function isUnclosedFragment ( { closingFragment , parent } ) { return ! ! ( closingFragment . flags & NodeFlags . ThisNodeHasError ) || ( isJsxFragment ( parent ) && isUnclosedFragment ( parent ) ) ; } function getSpanOfEnclosingComment ( fileName , position , onlyMultiLine ) { const sourceFile = syntaxTreeCache . getCurrentSourceFile ( fileName ) ; const range = formatting . getRangeOfEnclosingComment ( sourceFile , position ) ; return range && ( ! onlyMultiLine || range . kind === SyntaxKind . MultiLineCommentTrivia ) ? createTextSpanFromRange ( range ) : undefined ; } function getTodoComments ( fileName , descriptors ) { synchronizeHostData ( ) ; const sourceFile = getValidSourceFile ( fileName ) ; cancellationToken . throwIfCancellationRequested ( ) ; const fileContents = sourceFile . text ; const result = [ ] ; if ( descriptors . length > 0 && ! isNodeModulesFile ( sourceFile . fileName ) ) { const regExp = getTodoCommentsRegExp ( ) ; let matchArray ; while ( matchArray = regExp . exec ( fileContents ) ) { cancellationToken . throwIfCancellationRequested ( ) ; const firstDescriptorCaptureIndex = 3 ; Debug . assert ( matchArray . length === descriptors . length + firstDescriptorCaptureIndex ) ; const preamble = matchArray [ 1 ] ; const matchPosition = matchArray . index + preamble . length ; if ( ! isInComment ( sourceFile , matchPosition ) ) { continue ; } let descriptor ; for ( let i = 0 ; i < descriptors . length ; i ++ ) { if ( matchArray [ i + firstDescriptorCaptureIndex ] ) { descriptor = descriptors [ i ] ; } } if ( descriptor === undefined ) return Debug . fail ( ) ; if ( isLetterOrDigit ( fileContents . charCodeAt ( matchPosition + descriptor . text . length ) ) ) { continue ; } const message = matchArray [ 2 ] ; result . push ( { descriptor , message , position : matchPosition } ) ; } } return result ; function escapeRegExp ( str ) { return str . replace ( /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g , "\\$&" ) ; } function getTodoCommentsRegExp ( ) { const singleLineCommentStart = /(?:\/\/+\s*)/ . source ; const multiLineCommentStart = /(?:\/\*+\s*)/ . source ; const anyNumberOfSpacesAndAsterisksAtStartOfLine = /(?:^(?:\s|\*)*)/ . source ; const preamble = "(" + anyNumberOfSpacesAndAsterisksAtStartOfLine + "|" + singleLineCommentStart + "|" + multiLineCommentStart + ")" ; const literals = "(?:" + map ( descriptors , d => "(" + escapeRegExp ( d . text ) + ")" ) . join ( "|" ) + ")" ; const endOfLineOrEndOfComment = /(?:$|\*\/)/ . source ; const messageRemainder = /(?:.*?)/ . source ; const messagePortion = "(" + literals + messageRemainder + ")" ; const regExpString = preamble + messagePortion + endOfLineOrEndOfComment ; return new RegExp ( regExpString , "gim" ) ; } function isLetterOrDigit ( char ) { return ( char >= CharacterCodes . a && char <= CharacterCodes . z ) || ( char >= CharacterCodes . A && char <= CharacterCodes . Z ) || ( char >= CharacterCodes . _0 && char <= CharacterCodes . _9 ) ; } function isNodeModulesFile ( path ) { return stringContains ( path , "/node_modules/" ) ; } } function getRenameInfo ( fileName , position , options ? ) { synchronizeHostData ( ) ; return Rename . getRenameInfo ( program , getValidSourceFile ( fileName ) , position , options ) ; } function getRefactorContext ( file , positionOrRange , preferences , formatOptions ? , triggerReason ? , kind ? ) { const [ startPosition , endPosition ] = typeof positionOrRange === "number" ? [ positionOrRange , undefined ] : [ positionOrRange . pos , positionOrRange . end ] ; return { file , startPosition , endPosition , program : getProgram ( ) ! , host , formatContext : formatting . getFormatContext ( formatOptions ! , host ) , cancellationToken , preferences , triggerReason , kind } ; } function getInlayHintsContext ( file , span , preferences ) { return { file , program : getProgram ( ) ! , host , span , preferences , cancellationToken , } ; } function getSmartSelectionRange ( fileName , position ) { return SmartSelectionRange . getSmartSelectionRange ( position , syntaxTreeCache . getCurrentSourceFile ( fileName ) ) ; } function getApplicableRefactors ( fileName , positionOrRange , preferences = emptyOptions , triggerReason , kind ) { synchronizeHostData ( ) ; const file = getValidSourceFile ( fileName ) ; return refactor . getApplicableRefactors ( getRefactorContext ( file , positionOrRange , preferences , emptyOptions , triggerReason , kind ) ) ; } function getEditsForRefactor ( fileName , formatOptions , positionOrRange , refactorName , actionName , preferences = emptyOptions ) { synchronizeHostData ( ) ; const file = getValidSourceFile ( fileName ) ; return refactor . getEditsForRefactor ( getRefactorContext ( file , positionOrRange , preferences , formatOptions ) , refactorName , actionName ) ; } function toLineColumnOffset ( fileName , position ) { if ( position === 0 ) { return { line : 0 , character : 0 } ; } return sourceMapper . toLineColumnOffset ( fileName , position ) ; } function prepareCallHierarchy ( fileName , position ) { synchronizeHostData ( ) ; const declarations = CallHierarchy . resolveCallHierarchyDeclaration ( program , getTouchingPropertyName ( getValidSourceFile ( fileName ) , position ) ) ; return declarations && mapOneOrMany ( declarations , declaration => CallHierarchy . createCallHierarchyItem ( program , declaration ) ) ; } function provideCallHierarchyIncomingCalls ( fileName , position ) { synchronizeHostData ( ) ; const sourceFile = getValidSourceFile ( fileName ) ; const declaration = firstOrOnly ( CallHierarchy . resolveCallHierarchyDeclaration ( program , position === 0 ? sourceFile : getTouchingPropertyName ( sourceFile , position ) ) ) ; return declaration ? CallHierarchy . getIncomingCalls ( program , declaration , cancellationToken ) : [ ] ; } function provideCallHierarchyOutgoingCalls ( fileName , position ) { synchronizeHostData ( ) ; const sourceFile = getValidSourceFile ( fileName ) ; const declaration = firstOrOnly ( CallHierarchy . resolveCallHierarchyDeclaration ( program , position === 0 ? sourceFile : getTouchingPropertyName ( sourceFile , position ) ) ) ; return declaration ? CallHierarchy . getOutgoingCalls ( program , declaration ) : [ ] ; } function provideInlayHints ( fileName , span , preferences = emptyOptions ) { synchronizeHostData ( ) ; const sourceFile = getValidSourceFile ( fileName ) ; return InlayHints . provideInlayHints ( getInlayHintsContext ( sourceFile , span , preferences ) ) ; } const ls = { dispose , cleanupSemanticCache , getSyntacticDiagnostics , getSemanticDiagnostics , getSuggestionDiagnostics , getCompilerOptionsDiagnostics , getSyntacticClassifications , getSemanticClassifications , getEncodedSyntacticClassifications , getEncodedSemanticClassifications , getCompletionsAtPosition , getCompletionEntryDetails , getCompletionEntrySymbol , getSignatureHelpItems , getQuickInfoAtPosition , getDefinitionAtPosition , getDefinitionAndBoundSpan , getImplementationAtPosition , getTypeDefinitionAtPosition , getReferencesAtPosition , findReferences , getFileReferences , getOccurrencesAtPosition , getDocumentHighlights , getNameOrDottedNameSpan , getBreakpointStatementAtPosition , getNavigateToItems , getRenameInfo , getSmartSelectionRange , findRenameLocations , getNavigationBarItems , getNavigationTree , getOutliningSpans , getTodoComments , getBraceMatchingAtPosition , getIndentationAtPosition , getFormattingEditsForRange , getFormattingEditsForDocument , getFormattingEditsAfterKeystroke , getDocCommentTemplateAtPosition , isValidBraceCompletionAtPosition , getJsxClosingTagAtPosition , getSpanOfEnclosingComment , getCodeFixesAtPosition , getCombinedCodeFix , applyCodeActionCommand , organizeImports , getEditsForFileRename , getEmitOutput , getNonBoundSourceFile , getProgram , getAutoImportProvider , getApplicableRefactors , getEditsForRefactor , toLineColumnOffset , getSourceMapper : ( ) => sourceMapper , clearSourceMapperCache : ( ) => sourceMapper . clearCache ( ) , prepareCallHierarchy , provideCallHierarchyIncomingCalls , provideCallHierarchyOutgoingCalls , toggleLineComment , toggleMultilineComment , commentSelection , uncommentSelection , provideInlayHints , } ; switch ( languageServiceMode ) { case LanguageServiceMode . Semantic : break ; case LanguageServiceMode . PartialSemantic : invalidOperationsInPartialSemanticMode . forEach ( key => ls [ key ] = ( ) => { throw new Error ( `LanguageService Operation: ${ key } not allowed in LanguageServiceMode.PartialSemantic` ) ; } ) ; break ; case LanguageServiceMode . Syntactic : invalidOperationsInSyntacticMode . forEach ( key => ls [ key ] = ( ) => { throw new Error ( `LanguageService Operation: ${ key } not allowed in LanguageServiceMode.Syntactic` ) ; } ) ; break ; default : Debug . assertNever ( languageServiceMode ) ; } return ls ; } /** Names in the name table are escaped, so an identifier `__foo` will have a name table entry `___foo`. */ export function getNameTable ( sourceFile ) { if ( ! sourceFile . nameTable ) { initializeNameTable ( sourceFile ) ; } return sourceFile . nameTable ! ; } function initializeNameTable ( sourceFile ) { const nameTable = sourceFile . nameTable = new Map ( ) ; sourceFile . forEachChild ( function walk ( node ) { if ( isIdentifier ( node ) && ! isTagName ( node ) && node . escapedText || isStringOrNumericLiteralLike ( node ) && literalIsName ( node ) ) { const text = getEscapedTextOfIdentifierOrLiteral ( node ) ; nameTable . set ( text , nameTable . get ( text ) === undefined ? node . pos : - 1 ) ; } else if ( isPrivateIdentifier ( node ) ) { const text = node . escapedText ; nameTable . set ( text , nameTable . get ( text ) === undefined ? node . pos : - 1 ) ; } forEachChild ( node , walk ) ; if ( hasJSDocNodes ( node ) ) { for ( const jsDoc of node . jsDoc ! ) { forEachChild ( jsDoc , walk ) ; } } } ) ; } /**
     * We want to store any numbers/strings if they were a name that could be
     * related to a declaration.  So, if we have 'import x = require("something")'
     * then we want 'something' to be in the name table.  Similarly, if we have
     * "a['propname']" then we want to store "propname" in the name table.
     */ function literalIsName ( node ) { return isDeclarationName ( node ) || node . parent . kind === SyntaxKind . ExternalModuleReference || isArgumentOfElementAccessExpression ( node ) || isLiteralComputedPropertyDeclarationName ( node ) ; } /**
     * Returns the containing object literal property declaration given a possible name node, e.g. "a" in x = { "a": 1 }
     */ export function getContainingObjectLiteralElement ( node ) { const element = getContainingObjectLiteralElementWorker ( node ) ; return element && ( isObjectLiteralExpression ( element . parent ) || isJsxAttributes ( element . parent ) ) ? element as ObjectLiteralElementWithName : undefined ; } function getContainingObjectLiteralElementWorker ( node ) { switch ( node . kind ) { case SyntaxKind . StringLiteral : case SyntaxKind . NoSubstitutionTemplateLiteral : case SyntaxKind . NumericLiteral : if ( node . parent . kind === SyntaxKind . ComputedPropertyName ) { return isObjectLiteralElement ( node . parent . parent ) ? node . parent . parent : undefined ; } case SyntaxKind . Identifier : return isObjectLiteralElement ( node . parent ) && ( node . parent . parent . kind === SyntaxKind . ObjectLiteralExpression || node . parent . parent . kind === SyntaxKind . JsxAttributes ) && node . parent . name === node ? node . parent : undefined ; } return undefined ; } export type ObjectLiteralElementWithName = ObjectLiteralElement & { name : PropertyName ; parent : ObjectLiteralExpression | JsxAttributes ; } ; function getSymbolAtLocationForQuickInfo ( node , checker ) { const object = getContainingObjectLiteralElement ( node ) ; if ( object ) { const contextualType = checker . getContextualType ( object . parent ) ; const properties = contextualType && getPropertySymbolsFromContextualType ( object , checker , contextualType , false ) ; if ( properties && properties . length === 1 ) { return first ( properties ) ; } } return checker . getSymbolAtLocation ( node ) ; } /** Gets all symbols for one property. Does not get symbols for every property. */ export function getPropertySymbolsFromContextualType ( node , checker , contextualType , unionSymbolOk ) { const name = getNameFromPropertyName ( node . name ) ; if ( ! name ) return emptyArray ; if ( ! contextualType . isUnion ( ) ) { const symbol = contextualType . getProperty ( name ) ; return symbol ? [ symbol ] : emptyArray ; } const discriminatedPropertySymbols = mapDefined ( contextualType . types , t => ( isObjectLiteralExpression ( node . parent ) || isJsxAttributes ( node . parent ) ) && checker . isTypeInvalidDueToUnionDiscriminant ( t , node . parent ) ? undefined : t . getProperty ( name ) ) ; if ( unionSymbolOk && ( discriminatedPropertySymbols . length === 0 || discriminatedPropertySymbols . length === contextualType . types . length ) ) { const symbol = contextualType . getProperty ( name ) ; if ( symbol ) return [ symbol ] ; } if ( discriminatedPropertySymbols . length === 0 ) { return mapDefined ( contextualType . types , t => t . getProperty ( name ) ) ; } return discriminatedPropertySymbols ; } function isArgumentOfElementAccessExpression ( node ) { return node && node . parent && node . parent . kind === SyntaxKind . ElementAccessExpression && ( node . parent as ElementAccessExpression ) . argumentExpression === node ; } declare const __dirname ; /**
     * Get the path of the default library files (lib.d.ts) as distributed with the typescript
     * node package.
     * The functionality is not supported if the ts module is consumed outside of a node module.
     */ export function getDefaultLibFilePath ( options ) { if ( typeof __dirname !== "undefined" ) { return __dirname + directorySeparator + getDefaultLibFileName ( options ) ; } throw new Error ( "getDefaultLibFilePath is only supported when consumed as a node module. " ) ; } setObjectAllocator ( getServicesObjectAllocator ( ) ) ; }