From 1879e28fd317d5e77a1cfd23824544c52b5226ac Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Wed, 5 Oct 2016 08:54:20 -0700 Subject: [PATCH] Add helper functions for detecting 'this' identifiers --- src/compiler/binder.ts | 3 +-- src/compiler/checker.ts | 20 +++----------------- src/compiler/transformers/ts.ts | 2 +- src/compiler/utilities.ts | 28 ++++++++++++++++++++++++---- src/services/classifier.ts | 3 +-- src/services/utilities.ts | 2 +- 6 files changed, 31 insertions(+), 27 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 2fe7d30ab56..04b115b4dd9 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -2432,8 +2432,7 @@ namespace ts { } // If the parameter's name is 'this', then it is TypeScript syntax. - if (subtreeFlags & TransformFlags.ContainsDecorators - || (name && isIdentifier(name) && name.originalKeywordKind === SyntaxKind.ThisKeyword)) { + if (subtreeFlags & TransformFlags.ContainsDecorators || isThisIdentifier(name)) { transformFlags |= TransformFlags.AssertTypeScript; } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0b5c3963079..5e71234b700 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -9373,7 +9373,7 @@ namespace ts { captureLexicalThis(node, container); } if (isFunctionLike(container) && - (!isInParameterInitializerBeforeContainingFunction(node) || getFunctionLikeThisParameter(container))) { + (!isInParameterInitializerBeforeContainingFunction(node) || getThisParameter(container))) { // Note: a parameter initializer should refer to class-this unless function-this is explicitly annotated. // If this is a function in a JS file, it might be a class method. Check if it's the RHS @@ -15557,10 +15557,6 @@ namespace ts { } } - function parameterIsThisKeyword(parameter: ParameterDeclaration) { - return parameter.name && (parameter.name).originalKeywordKind === SyntaxKind.ThisKeyword; - } - function parameterNameStartsWithUnderscore(parameter: ParameterDeclaration) { return parameter.name && parameter.name.kind === SyntaxKind.Identifier && (parameter.name).text.charCodeAt(0) === CharacterCodes._; } @@ -20141,18 +20137,8 @@ namespace ts { } function getAccessorThisParameter(accessor: AccessorDeclaration): ParameterDeclaration { - if (accessor.parameters.length === (accessor.kind === SyntaxKind.GetAccessor ? 1 : 2) && - accessor.parameters[0].name.kind === SyntaxKind.Identifier && - (accessor.parameters[0].name).originalKeywordKind === SyntaxKind.ThisKeyword) { - return accessor.parameters[0]; - } - } - - function getFunctionLikeThisParameter(func: FunctionLikeDeclaration) { - if (func.parameters.length && - func.parameters[0].name.kind === SyntaxKind.Identifier && - (func.parameters[0].name).originalKeywordKind === SyntaxKind.ThisKeyword) { - return func.parameters[0]; + if (accessor.parameters.length === (accessor.kind === SyntaxKind.GetAccessor ? 1 : 2)) { + return getThisParameter(accessor); } } diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index f6e8074cb07..9b36067f538 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -2374,7 +2374,7 @@ namespace ts { * @param node The parameter declaration node. */ function visitParameter(node: ParameterDeclaration) { - if (node.name && isIdentifier(node.name) && node.name.originalKeywordKind === SyntaxKind.ThisKeyword) { + if (parameterIsThisKeyword(node)) { return undefined; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 1a4d95feca5..62813e9447c 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2707,15 +2707,35 @@ namespace ts { }); } - export function getSetAccessorTypeAnnotationNode(accessor: AccessorDeclaration): TypeNode { + /** Get the type annotaion for the value parameter. */ + export function getSetAccessorTypeAnnotationNode(accessor: SetAccessorDeclaration): TypeNode { if (accessor && accessor.parameters.length > 0) { - const hasThis = accessor.parameters.length === 2 && - accessor.parameters[0].name.kind === SyntaxKind.Identifier && - (accessor.parameters[0].name as Identifier).originalKeywordKind === SyntaxKind.ThisKeyword; + const hasThis = accessor.parameters.length === 2 && parameterIsThisKeyword(accessor.parameters[0]); return accessor.parameters[hasThis ? 1 : 0].type; } } + export function getThisParameter(signature: SignatureDeclaration): ParameterDeclaration | undefined { + if (signature.parameters.length) { + const thisParameter = signature.parameters[0]; + if (parameterIsThisKeyword(thisParameter)) { + return thisParameter; + } + } + } + + export function parameterIsThisKeyword(parameter: ParameterDeclaration): boolean { + return isThisIdentifier(parameter.name); + } + + export function isThisIdentifier(node: Node | undefined): boolean { + return node && node.kind === SyntaxKind.Identifier && identifierIsThisKeyword(node as Identifier); + } + + export function identifierIsThisKeyword(id: Identifier): boolean { + return id.originalKeywordKind === SyntaxKind.ThisKeyword; + } + export interface AllAccessorDeclarations { firstAccessor: AccessorDeclaration; secondAccessor: AccessorDeclaration; diff --git a/src/services/classifier.ts b/src/services/classifier.ts index 29a878224cd..c22aec6a786 100644 --- a/src/services/classifier.ts +++ b/src/services/classifier.ts @@ -954,8 +954,7 @@ namespace ts { return; case SyntaxKind.Parameter: if ((token.parent).name === token) { - const isThis = token.kind === SyntaxKind.Identifier && (token).originalKeywordKind === SyntaxKind.ThisKeyword; - return isThis ? ClassificationType.keyword : ClassificationType.parameterName; + return isThisIdentifier(token) ? ClassificationType.keyword : ClassificationType.parameterName; } return; } diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 829048fc081..b58c4188e0d 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -376,7 +376,7 @@ namespace ts { return true; case SyntaxKind.Identifier: // 'this' as a parameter - return (node as Identifier).originalKeywordKind === SyntaxKind.ThisKeyword && node.parent.kind === SyntaxKind.Parameter; + return identifierIsThisKeyword(node as Identifier) && node.parent.kind === SyntaxKind.Parameter; default: return false; }