namespace ts . Rename { export function getRenameInfo ( program , sourceFile , position , options ? ) { const node = getAdjustedRenameLocation ( getTouchingPropertyName ( sourceFile , position ) ) ; if ( nodeIsEligibleForRename ( node ) ) { const renameInfo = getRenameInfoForNode ( node , program . getTypeChecker ( ) , sourceFile , program , options ) ; if ( renameInfo ) { return renameInfo ; } } return getRenameInfoError ( Diagnostics . You_cannot_rename_this_element ) ; } function getRenameInfoForNode ( node , typeChecker , sourceFile , program , options ? ) { const symbol = typeChecker . getSymbolAtLocation ( node ) ; if ( ! symbol ) { if ( isStringLiteralLike ( node ) ) { const type = getContextualTypeFromParentOrAncestorTypeNode ( node , typeChecker ) ; if ( type && ( ( type . flags & TypeFlags . StringLiteral ) || ( ( type . flags & TypeFlags . Union ) && every ( ( type as UnionType ) . types , type => ! ! ( type . flags & TypeFlags . StringLiteral ) ) ) ) ) { return getRenameInfoSuccess ( node . text , node . text , ScriptElementKind . string , "" , node , sourceFile ) ; } } else if ( isLabelName ( node ) ) { const name = getTextOfNode ( node ) ; return getRenameInfoSuccess ( name , name , ScriptElementKind . label , ScriptElementKindModifier . none , node , sourceFile ) ; } return undefined ; } const { declarations } = symbol ; if ( ! declarations || declarations . length === 0 ) return ; if ( declarations . some ( declaration => isDefinedInLibraryFile ( program , declaration ) ) ) { return getRenameInfoError ( Diagnostics . You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library ) ; } if ( isIdentifier ( node ) && node . originalKeywordKind === SyntaxKind . DefaultKeyword && symbol . parent && symbol . parent . flags & SymbolFlags . Module ) { return undefined ; } if ( isStringLiteralLike ( node ) && tryGetImportFromModuleSpecifier ( node ) ) { return options && options . allowRenameOfImportPath ? getRenameInfoForModule ( node , sourceFile , symbol ) : undefined ; } const kind = SymbolDisplay . getSymbolKind ( typeChecker , symbol , node ) ; const specifierName = ( isImportOrExportSpecifierName ( node ) || isStringOrNumericLiteralLike ( node ) && node . parent . kind === SyntaxKind . ComputedPropertyName ) ? stripQuotes ( getTextOfIdentifierOrLiteral ( node ) ) : undefined ; const displayName = specifierName || typeChecker . symbolToString ( symbol ) ; const fullDisplayName = specifierName || typeChecker . getFullyQualifiedName ( symbol ) ; return getRenameInfoSuccess ( displayName , fullDisplayName , kind , SymbolDisplay . getSymbolModifiers ( typeChecker , symbol ) , node , sourceFile ) ; } function isDefinedInLibraryFile ( program , declaration ) { const sourceFile = declaration . getSourceFile ( ) ; return program . isSourceFileDefaultLibrary ( sourceFile ) && fileExtensionIs ( sourceFile . fileName , Extension . Dts ) ; } function getRenameInfoForModule ( node , sourceFile , moduleSymbol ) { if ( ! isExternalModuleNameRelative ( node . text ) ) { return getRenameInfoError ( Diagnostics . You_cannot_rename_a_module_via_a_global_import ) ; } const moduleSourceFile = moduleSymbol . declarations && find ( moduleSymbol . declarations , isSourceFile ) ; if ( ! moduleSourceFile ) return undefined ; const withoutIndex = endsWith ( node . text , "/index" ) || endsWith ( node . text , "/index.js" ) ? undefined : tryRemoveSuffix ( removeFileExtension ( moduleSourceFile . fileName ) , "/index" ) ; const name = withoutIndex === undefined ? moduleSourceFile . fileName : withoutIndex ; const kind = withoutIndex === undefined ? ScriptElementKind . moduleElement : ScriptElementKind . directory ; const indexAfterLastSlash = node . text . lastIndexOf ( "/" ) + 1 ; const triggerSpan = createTextSpan ( node . getStart ( sourceFile ) + 1 + indexAfterLastSlash , node . text . length - indexAfterLastSlash ) ; return { canRename : true , fileToRename : name , kind , displayName : name , fullDisplayName : name , kindModifiers : ScriptElementKindModifier . none , triggerSpan , } ; } function getRenameInfoSuccess ( displayName , fullDisplayName , kind , kindModifiers , node , sourceFile ) { return { canRename : true , fileToRename : undefined , kind , displayName , fullDisplayName , kindModifiers , triggerSpan : createTriggerSpanForNode ( node , sourceFile ) } ; } function getRenameInfoError ( diagnostic ) { return { canRename : false , localizedErrorMessage : getLocaleSpecificMessage ( diagnostic ) } ; } function createTriggerSpanForNode ( node , sourceFile ) { let start = node . getStart ( sourceFile ) ; let width = node . getWidth ( sourceFile ) ; if ( isStringLiteralLike ( node ) ) { start += 1 ; width -= 2 ; } return createTextSpan ( start , width ) ; } export function nodeIsEligibleForRename ( node ) { switch ( node . kind ) { case SyntaxKind . Identifier : case SyntaxKind . PrivateIdentifier : case SyntaxKind . StringLiteral : case SyntaxKind . NoSubstitutionTemplateLiteral : case SyntaxKind . ThisKeyword : return true ; case SyntaxKind . NumericLiteral : return isLiteralNameOfPropertyDeclarationOrIndexAccess ( node as NumericLiteral ) ; default : return false ; } } }