From a478bfddd2233d3579a2b037fc0df32807cb0ebe Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Tue, 24 Jan 2017 13:44:36 -0800 Subject: [PATCH] Simplify code in 'rename' --- src/services/rename.ts | 172 ++++++++++++++++++++--------------------- 1 file changed, 84 insertions(+), 88 deletions(-) diff --git a/src/services/rename.ts b/src/services/rename.ts index 6f28e505f79..afb16618b03 100644 --- a/src/services/rename.ts +++ b/src/services/rename.ts @@ -1,98 +1,94 @@ /* @internal */ namespace ts.Rename { export function getRenameInfo(typeChecker: TypeChecker, defaultLibFileName: string, getCanonicalFileName: (fileName: string) => string, sourceFile: SourceFile, position: number): RenameInfo { - const canonicalDefaultLibName = getCanonicalFileName(ts.normalizePath(defaultLibFileName)); - const node = getTouchingWord(sourceFile, position, /*includeJsDocComment*/ true); + const renameInfo = node && nodeIsEligibleForRename(node) + ? getRenameInfoForNode(node, typeChecker, sourceFile, getIsDefinedInLibraryFile(defaultLibFileName, getCanonicalFileName)) + : undefined; + return renameInfo || getRenameInfoError(Diagnostics.You_cannot_rename_this_element); + } - if (node) { - if (node.kind === SyntaxKind.Identifier || - node.kind === SyntaxKind.StringLiteral || - isLiteralNameOfPropertyDeclarationOrIndexAccess(node) || - isThis(node)) { - const symbol = typeChecker.getSymbolAtLocation(node); - - // Only allow a symbol to be renamed if it actually has at least one declaration. - if (symbol) { - const declarations = symbol.getDeclarations(); - if (declarations && declarations.length > 0) { - // Disallow rename for elements that are defined in the standard TypeScript library. - if (forEach(declarations, isDefinedInLibraryFile)) { - return getRenameInfoError(getLocaleSpecificMessage(Diagnostics.You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library)); - } - - const displayName = stripQuotes(getDeclaredName(typeChecker, symbol, node)); - const kind = SymbolDisplay.getSymbolKind(typeChecker, symbol, node); - if (kind) { - return { - canRename: true, - kind, - displayName, - localizedErrorMessage: undefined, - fullDisplayName: typeChecker.getFullyQualifiedName(symbol), - kindModifiers: SymbolDisplay.getSymbolModifiers(symbol), - triggerSpan: createTriggerSpanForNode(node, sourceFile) - }; - } - } - } - else if (node.kind === SyntaxKind.StringLiteral) { - const type = getStringLiteralTypeForNode(node, typeChecker); - if (type) { - if (isDefinedInLibraryFile(node)) { - return getRenameInfoError(getLocaleSpecificMessage(Diagnostics.You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library)); - } - else { - const displayName = stripQuotes(type.text); - return { - canRename: true, - kind: ScriptElementKind.variableElement, - displayName, - localizedErrorMessage: undefined, - fullDisplayName: displayName, - kindModifiers: ScriptElementKindModifier.none, - triggerSpan: createTriggerSpanForNode(node, sourceFile) - }; - } - } - } - } + function getIsDefinedInLibraryFile(defaultLibFileName: string, getCanonicalFileName: (fileName: string) => string): (declaration: Node) => boolean { + if (!defaultLibFileName) { + return () => false; } - return getRenameInfoError(getLocaleSpecificMessage(Diagnostics.You_cannot_rename_this_element)); - - function getRenameInfoError(localizedErrorMessage: string): RenameInfo { - return { - canRename: false, - localizedErrorMessage: localizedErrorMessage, - displayName: undefined, - fullDisplayName: undefined, - kind: undefined, - kindModifiers: undefined, - triggerSpan: undefined - }; - } - - function isDefinedInLibraryFile(declaration: Node) { - if (defaultLibFileName) { - const sourceFile = declaration.getSourceFile(); - const canonicalName = getCanonicalFileName(ts.normalizePath(sourceFile.fileName)); - if (canonicalName === canonicalDefaultLibName) { - return true; - } - } - return false; - } - - function createTriggerSpanForNode(node: Node, sourceFile: SourceFile) { - let start = node.getStart(sourceFile); - let width = node.getWidth(sourceFile); - if (node.kind === SyntaxKind.StringLiteral) { - // Exclude the quotes - start += 1; - width -= 2; - } - return createTextSpan(start, width); + const canonicalDefaultLibName = getCanonicalFileName(ts.normalizePath(defaultLibFileName)); + return declaration => { + const sourceFile = declaration.getSourceFile(); + const canonicalName = getCanonicalFileName(ts.normalizePath(sourceFile.fileName)); + return canonicalName === canonicalDefaultLibName; } } + + function getRenameInfoForNode(node: Node, typeChecker: TypeChecker, sourceFile: SourceFile, isDefinedInLibraryFile: (declaration: Node) => boolean): RenameInfo | undefined { + const symbol = typeChecker.getSymbolAtLocation(node); + + // Only allow a symbol to be renamed if it actually has at least one declaration. + if (symbol) { + const declarations = symbol.getDeclarations(); + if (declarations && declarations.length > 0) { + // Disallow rename for elements that are defined in the standard TypeScript library. + if (some(declarations, isDefinedInLibraryFile)) { + return getRenameInfoError(Diagnostics.You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library); + } + + const displayName = stripQuotes(getDeclaredName(typeChecker, symbol, node)); + const kind = SymbolDisplay.getSymbolKind(typeChecker, symbol, node); + return kind ? getRenameInfoSuccess(displayName, typeChecker.getFullyQualifiedName(symbol), kind, SymbolDisplay.getSymbolModifiers(symbol), node, sourceFile) : undefined; + } + } + else if (node.kind === SyntaxKind.StringLiteral) { + const type = getStringLiteralTypeForNode(node, typeChecker); + if (type) { + if (isDefinedInLibraryFile(node)) { + return getRenameInfoError(Diagnostics.You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library); + } + + const displayName = stripQuotes(type.text); + return getRenameInfoSuccess(displayName, displayName, ScriptElementKind.variableElement, ScriptElementKindModifier.none, node, sourceFile); + } + } + } + + function getRenameInfoSuccess(displayName: string, fullDisplayName: string, kind: string, kindModifiers: string, node: Node, sourceFile: SourceFile): RenameInfo { + return { + canRename: true, + kind, + displayName, + localizedErrorMessage: undefined, + fullDisplayName, + kindModifiers, + triggerSpan: createTriggerSpanForNode(node, sourceFile) + }; + } + + function getRenameInfoError(diagnostic: DiagnosticMessage): RenameInfo { + return { + canRename: false, + localizedErrorMessage: getLocaleSpecificMessage(diagnostic), + displayName: undefined, + fullDisplayName: undefined, + kind: undefined, + kindModifiers: undefined, + triggerSpan: undefined + }; + } + + function createTriggerSpanForNode(node: Node, sourceFile: SourceFile) { + let start = node.getStart(sourceFile); + let width = node.getWidth(sourceFile); + if (node.kind === SyntaxKind.StringLiteral) { + // Exclude the quotes + start += 1; + width -= 2; + } + return createTextSpan(start, width); + } + + function nodeIsEligibleForRename(node: Node) { + return node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.StringLiteral || + isLiteralNameOfPropertyDeclarationOrIndexAccess(node) || + isThis(node); + } }