From 1898e15ac532deb039ace85425f79040dadf4c12 Mon Sep 17 00:00:00 2001 From: zju_wyx Date: Wed, 16 Apr 2025 14:18:12 +0800 Subject: [PATCH] TSC annotation bugfix Signed-off-by: zju_wyx Change-Id: Icbf90b82429dff3af9de63d543ecad4746333843 --- lib/tsc.js | 185 ++++++++++++++-- lib/tsserver.js | 205 ++++++++++++++++-- lib/tsserverlibrary.d.ts | 2 + lib/tsserverlibrary.js | 205 ++++++++++++++++-- lib/typescript.d.ts | 2 + lib/typescript.js | 205 ++++++++++++++++-- lib/typescriptServices.d.ts | 2 + lib/typescriptServices.js | 205 ++++++++++++++++-- lib/typingsInstaller.js | 205 ++++++++++++++++-- src/compiler/checker.ts | 131 ++++++++++- src/compiler/emitter.ts | 4 +- src/compiler/factory/nodeTests.ts | 4 + src/compiler/ohApi.ts | 32 ++- src/compiler/transformers/declarations.ts | 27 ++- src/compiler/transformers/ts.ts | 2 +- src/compiler/utilitiesPublic.ts | 8 +- .../reference/api/tsserverlibrary.d.ts | 2 + tests/baselines/reference/api/typescript.d.ts | 2 + 18 files changed, 1283 insertions(+), 145 deletions(-) diff --git a/lib/tsc.js b/lib/tsc.js index 907a9903a4..1037ef1da8 100644 --- a/lib/tsc.js +++ b/lib/tsc.js @@ -10080,6 +10080,12 @@ var ts; } } ts.getDecorators = getDecorators; + function getAnnotations(node) { + if (ts.hasAnnotations(node)) { + return ts.filter(node.modifiers, ts.isAnnotation); + } + } + ts.getAnnotations = getAnnotations; function getModifiers(node) { if (ts.hasSyntacticModifier(node, 126975)) { return ts.filter(node.modifiers, isModifier); @@ -10685,7 +10691,7 @@ var ts; } ts.isNamedClassElement = isNamedClassElement; function isModifierLike(node) { - return isModifier(node) || ts.isDecorator(node); + return isModifier(node) || ts.isDecoratorOrAnnotation(node); } ts.isModifierLike = isModifierLike; function isTypeElement(node) { @@ -24056,6 +24062,10 @@ var ts; return node.kind === 168; } ts.isParameter = isParameter; + function isDecoratorOrAnnotation(node) { + return node.kind === 169; + } + ts.isDecoratorOrAnnotation = isDecoratorOrAnnotation; function isDecorator(node) { return node.kind === 169 && node.annotationDeclaration === undefined; } @@ -39083,19 +39093,31 @@ var ts; } function visitAnnotations(node) { switch (node.kind) { + case 279: + return visitImportSpecifier(node); case 169: return visitAnnotation(node); default: return ts.visitEachChild(node, visitAnnotations, context); } } + function visitImportSpecifier(node) { + if (node.isTypeOnly || !resolver.isReferredToAnnotation(node)) { + return node; + } + var magicPrefixName = addMagicPrefixToAnnotationNameIdentifier(node.name); + ts.Debug.assert(ts.isIdentifier(magicPrefixName)); + return ts.factory.updateImportSpecifier(node, node.isTypeOnly, node.propertyName, magicPrefixName); + } function visitAnnotationDeclaration(node) { + var magicPrefixName = addMagicPrefixToAnnotationNameIdentifier(node.name); + ts.Debug.assert(ts.isIdentifier(magicPrefixName)); var members = node.members.map(function (node) { var type = resolver.getAnnotationPropertyInferredType(node); var initializer = resolver.getAnnotationPropertyEvaluatedInitializer(node); return ts.factory.updateAnnotationPropertyDeclaration(node, node.name, type, initializer); }); - return ts.factory.updateAnnotationDeclaration(node, node.modifiers, node.name, members); + return ts.factory.updateAnnotationDeclaration(node, node.modifiers, magicPrefixName, members); } function visitAnnotation(node) { if (!node.annotationDeclaration) { @@ -39109,7 +39131,7 @@ var ts; return ts.factory.createIdentifier(ts.annotationMagicNamePrefix + expr.escapedText); case 211: var propAccessExpr = expr; - return ts.factory.updatePropertyAccessExpression(propAccessExpr, addMagicPrefixToAnnotationNameIdentifier(propAccessExpr.expression), propAccessExpr.name); + return ts.factory.updatePropertyAccessExpression(propAccessExpr, propAccessExpr.expression, addMagicPrefixToAnnotationNameIdentifier(propAccessExpr.name)); case 213: var callExpr = expr; return ts.factory.updateCallExpression(callExpr, addMagicPrefixToAnnotationNameIdentifier(callExpr.expression), callExpr.typeArguments, callExpr.arguments); @@ -39125,6 +39147,7 @@ var ts; for (var i = 0; i < members.length; ++i) { var member = members[i]; var initializer = resolver.getAnnotationPropertyEvaluatedInitializer(member); + ts.Debug.assert(initializer !== undefined); defaultValues[i] = ts.factory.createPropertyAssignment(member.name, initializer); } var newCallExpr = ts.factory.createCallExpression(annotation.expression, undefined, [ts.factory.createObjectLiteralExpression(defaultValues, false)]); @@ -49491,6 +49514,7 @@ var ts; case 263: case 269: case 274: + case 266: if (ts.isExternalModuleAugmentation(node)) { return true; } @@ -78797,16 +78821,125 @@ var ts; }, isImportRequiredByAugmentation: isImportRequiredByAugmentation, getAnnotationObjectLiteralEvaluatedProps: function (node) { - return getNodeLinks(node).annotationObjectLiteralEvaluatedProps; + var links = getNodeLinks(node); + if (!links.annotationObjectLiteralEvaluatedProps) { + if (!ts.isCallExpression(node.expression)) { + return undefined; + } + if (!node.expression.arguments || + node.expression.arguments.length !== 1 || + !ts.isObjectLiteralExpression(node.expression.arguments[0])) { + return undefined; + } + var funcType = checkExpression(node.expression); + var apparentType = getApparentType(funcType); + if (isErrorType(apparentType)) { + return undefined; + } + var arg = node.expression.arguments[0]; + var evaluatedProps = new ts.Map(); + for (var _i = 0, _a = arg.properties; _i < _a.length; _i++) { + var prop = _a[_i]; + if (!ts.isPropertyAssignment(prop)) { + return undefined; + } + var evaluated = evaluateAnnotationPropertyConstantExpression(prop.initializer); + if (evaluated === undefined) { + return undefined; + } + evaluatedProps.set(ts.tryGetTextOfPropertyName(prop.name), evaluated); + } + var members = node.annotationDeclaration.members; + for (var _b = 0, members_9 = members; _b < members_9.length; _b++) { + var m = members_9[_b]; + var memberName = ts.tryGetTextOfPropertyName(m.name); + if (evaluatedProps.has(memberName)) { + var propValue = annotationEvaluatedValueToExpr(evaluatedProps.get(memberName), getTypeOfNode(m)); + if (links.annotationObjectLiteralEvaluatedProps === undefined) { + links.annotationObjectLiteralEvaluatedProps = new ts.Map(); + } + links.annotationObjectLiteralEvaluatedProps.set(memberName, propValue); + } + } + } + return links.annotationObjectLiteralEvaluatedProps; }, getAnnotationPropertyEvaluatedInitializer: function (node) { - return getNodeLinks(node).annotationPropertyEvaluatedInitializer; + var links = getNodeLinks(node); + if (!links.annotationPropertyEvaluatedInitializer) { + var propType = getTypeOfNode(node); + if (!isAllowedAnnotationPropertyType(propType)) { + return undefined; + } + if (node.initializer) { + var evaluated = evaluateAnnotationPropertyConstantExpression(node.initializer); + if (evaluated === undefined) { + return undefined; + } + else { + var evaluatedExpr = annotationEvaluatedValueToExpr(evaluated, getTypeOfNode(node)); + links.annotationPropertyEvaluatedInitializer = evaluatedExpr; + } + } + if (!node.initializer) { + var initializer = addAnnotationPropertyEnumInitalizer(propType); + if (initializer) { + links.annotationPropertyEvaluatedInitializer = initializer; + } + } + } + return links.annotationPropertyEvaluatedInitializer; }, getAnnotationPropertyInferredType: function (node) { - return getNodeLinks(node).annotationPropertyInferredType; + var links = getNodeLinks(node); + if (!links.annotationPropertyInferredType) { + var propType = getTypeOfNode(node); + if (!isAllowedAnnotationPropertyType(propType)) { + return undefined; + } + links.annotationPropertyInferredType = nodeBuilder.typeToTypeNode(propType); + } + return links.annotationPropertyInferredType; }, isReferredToAnnotation: function (node) { - return getNodeLinks(node).exportOrImportRefersToAnnotation; + var links = getNodeLinks(node); + if (!links.exportOrImportRefersToAnnotation) { + var ident = undefined; + if ((ts.isExportAssignment(node))) { + switch (node.expression.kind) { + case 79: + ident = node.expression; + break; + case 211: + ident = node.expression; + break; + default: + return undefined; + } + if (!ident) { + return undefined; + } + var symbol = getSymbolOfNameOrPropertyAccessExpression(ident); + if (!symbol) { + return undefined; + } + if (getAllSymbolFlags(symbol) & 268435456) { + links.exportOrImportRefersToAnnotation = true; + } + } + if ((ts.isImportSpecifier(node) || ts.isExportSpecifier(node))) { + var symbol = getSymbolOfNode(node); + if (!symbol) { + return undefined; + } + var target = resolveAlias(symbol); + var targetFlags = getAllSymbolFlags(target); + if (targetFlags & 268435456) { + links.exportOrImportRefersToAnnotation = true; + } + } + } + return links.exportOrImportRefersToAnnotation; } }; function isImportRequiredByAugmentation(node) { @@ -79152,7 +79285,7 @@ var ts; var flags = 0; for (var _i = 0, _a = node.modifiers; _i < _a.length; _i++) { var modifier = _a[_i]; - if (ts.isDecorator(modifier)) + if (ts.isDecoratorOrAnnotation(modifier)) continue; if (modifier.kind !== 147) { if (node.kind === 170 || node.kind === 173) { @@ -79494,7 +79627,7 @@ var ts; function nodeHasAnyModifiersExcept(node, allowedModifier) { for (var _i = 0, _a = node.modifiers; _i < _a.length; _i++) { var modifier = _a[_i]; - if (ts.isDecorator(modifier)) + if (ts.isDecoratorOrAnnotation(modifier)) continue; return modifier.kind !== allowedModifier; } @@ -82945,7 +83078,7 @@ var ts; } } function modifierVisitor(node) { - if (ts.isDecorator(node)) + if (ts.isDecoratorOrAnnotation(node)) return undefined; if (ts.modifierToFlag(node.kind) & 117086) { return undefined; @@ -86068,8 +86201,8 @@ var ts; function generateClassElementDecorationExpressions(node, isStatic) { var members = getDecoratedClassElements(node, isStatic); var expressions; - for (var _i = 0, members_9 = members; _i < members_9.length; _i++) { - var member = members_9[_i]; + for (var _i = 0, members_10 = members; _i < members_10.length; _i++) { + var member = members_10[_i]; expressions = ts.append(expressions, generateClassElementDecorationExpression(node, member)); } return expressions; @@ -95170,6 +95303,7 @@ var ts; case 265: case 268: case 269: + case 266: return !resolver.isDeclarationVisible(node); case 261: return !getBindingNameVisible(node); @@ -95360,6 +95494,19 @@ var ts; return statement; } } + function checkAnnotationVisibilityByDecorator(input) { + ts.forEach(input, function (decorator) { + if (!ts.isAnnotation(decorator)) { + return; + } + if (ts.isCallExpression(decorator.expression)) { + checkEntityNameVisibility((decorator.expression.expression), enclosingDeclaration); + } + else if (ts.isIdentifier(decorator.expression)) { + checkEntityNameVisibility((decorator.expression), enclosingDeclaration); + } + }); + } function visitDeclarationSubtree(input) { if (shouldStripInternal(input)) return; @@ -95423,7 +95570,8 @@ var ts; if (ts.isPrivateIdentifier(input.name)) { return cleanup(undefined); } - var reservedDecorators_1 = ts.getReservedDecoratorsOfStructDeclaration(input, host); + var reservedDecorators_1 = ts.concatenate(ts.getReservedDecoratorsOfStructDeclaration(input, host), ts.getAnnotations(input)); + checkAnnotationVisibilityByDecorator(reservedDecorators_1); var sig = factory.createMethodDeclaration(ts.concatenateDecoratorsAndModifiers(reservedDecorators_1, ensureModifiers(input)), undefined, input.name, input.questionToken, ts.inEtsStylesContext(input, host) ? undefined : ensureTypeParams(input, input.typeParameters), updateParamsList(input, input.parameters), ensureType(input, input.type), undefined); return cleanup(sig); } @@ -95804,13 +95952,14 @@ var ts; } return factory.updateHeritageClause(clause, ts.visitNodes(factory.createNodeArray(ts.filter(clause.types, function (t) { return ts.isEntityNameExpression(t.expression) || t.expression.kind === 105; })), visitDeclarationSubtree)); })); - var reservedDecorators = ts.getReservedDecoratorsOfEtsFile(input, host); + var reservedDecorators = ts.concatenate(ts.getReservedDecoratorsOfEtsFile(input, host), ts.getAnnotations(input)); + checkAnnotationVisibilityByDecorator(reservedDecorators); return [statement, cleanup(factory.updateClassDeclaration(input, ts.concatenateDecoratorsAndModifiers(reservedDecorators, modifiers), input.name, typeParameters, heritageClauses, members))]; } else { var heritageClauses = transformHeritageClauses(input.heritageClauses); - var reservedDecorators = ts.getReservedDecoratorsOfEtsFile(input, host); - ; + var reservedDecorators = ts.concatenate(ts.getReservedDecoratorsOfEtsFile(input, host), ts.getAnnotations(input)); + checkAnnotationVisibilityByDecorator(reservedDecorators); return cleanup(factory.updateClassDeclaration(input, ts.concatenateDecoratorsAndModifiers(reservedDecorators, modifiers), input.name, typeParameters, heritageClauses, members)); } } @@ -100063,7 +100212,7 @@ var ts; if (ts.every(modifiers, ts.isModifier)) { return emitModifiers(node, modifiers); } - if (ts.every(modifiers, ts.isDecorator)) { + if (ts.every(modifiers, ts.isDecoratorOrAnnotation)) { return emitDecorators(node, modifiers); } onBeforeEmitNodeArray === null || onBeforeEmitNodeArray === void 0 ? void 0 : onBeforeEmitNodeArray(modifiers); @@ -100074,7 +100223,7 @@ var ts; while (start < modifiers.length) { while (pos < modifiers.length) { var modifier = modifiers[pos]; - mode = ts.isDecorator(modifier) ? "decorators" : "modifiers"; + mode = ts.isDecoratorOrAnnotation(modifier) ? "decorators" : "modifiers"; if (lastMode === undefined) { lastMode = mode; } diff --git a/lib/tsserver.js b/lib/tsserver.js index 1f8dc2acce..6c182694e5 100644 --- a/lib/tsserver.js +++ b/lib/tsserver.js @@ -13370,6 +13370,12 @@ var ts; } } ts.getDecorators = getDecorators; + function getAnnotations(node) { + if (ts.hasAnnotations(node)) { + return ts.filter(node.modifiers, ts.isAnnotation); + } + } + ts.getAnnotations = getAnnotations; function getModifiers(node) { if (ts.hasSyntacticModifier(node, 126975 /* ModifierFlags.Modifier */)) { return ts.filter(node.modifiers, isModifier); @@ -14123,7 +14129,7 @@ var ts; ts.isNamedClassElement = isNamedClassElement; // Type members function isModifierLike(node) { - return isModifier(node) || ts.isDecorator(node); + return isModifier(node) || ts.isDecoratorOrAnnotation(node); } ts.isModifierLike = isModifierLike; function isTypeElement(node) { @@ -29931,6 +29937,10 @@ var ts; return node.kind === 168 /* SyntaxKind.Parameter */; } ts.isParameter = isParameter; + function isDecoratorOrAnnotation(node) { + return node.kind === 169 /* SyntaxKind.Decorator */; + } + ts.isDecoratorOrAnnotation = isDecoratorOrAnnotation; function isDecorator(node) { return node.kind === 169 /* SyntaxKind.Decorator */ && node.annotationDeclaration === undefined; } @@ -47428,7 +47438,7 @@ var ts; } // Firstly, visit declarations var updatedSource = ts.factory.updateSourceFile(node, ts.visitLexicalEnvironment(node.statements, visitAnnotationsDeclarations, context)); - // Secondly, visit usage of annotations + // Secondly, visit import and usage of annotations return ts.factory.updateSourceFile(node, ts.visitLexicalEnvironment(updatedSource.statements, visitAnnotations, context)); } function visitAnnotationsDeclarations(node) { @@ -47441,13 +47451,30 @@ var ts; } function visitAnnotations(node) { switch (node.kind) { + case 279 /* SyntaxKind.ImportSpecifier */: + return visitImportSpecifier(node); case 169 /* SyntaxKind.Decorator */: return visitAnnotation(node); default: return ts.visitEachChild(node, visitAnnotations, context); } } + function visitImportSpecifier(node) { + // Return if the import has type or not refered to Annotation + if (node.isTypeOnly || !resolver.isReferredToAnnotation(node)) { + return node; + } + var magicPrefixName = addMagicPrefixToAnnotationNameIdentifier(node.name); + ts.Debug.assert(ts.isIdentifier(magicPrefixName)); + // Add magic prefix for import Annotation. For example, + // import {Anno} from "xxx" ---> import {__$$ETS_ANNOTATION$$__Anno} from "xxx" + return ts.factory.updateImportSpecifier(node, node.isTypeOnly, node.propertyName, magicPrefixName); + } function visitAnnotationDeclaration(node) { + // Add magic prefix for AnnotationDeclaration. For example, + // @interface Anno {} ---> @interface __$$ETS_ANNOTATION$$__Anno {} + var magicPrefixName = addMagicPrefixToAnnotationNameIdentifier(node.name); + ts.Debug.assert(ts.isIdentifier(magicPrefixName)); // Add explicit type annotation and initializer. For example, // @interface Anno { // a = 10 + 5 @@ -47455,7 +47482,7 @@ var ts; // // will be transformed to // - // @interface Anno { + // @interface __$$ETS_ANNOTATION$$__Anno { // a: number = 15 // } var members = node.members.map(function (node) { @@ -47463,7 +47490,7 @@ var ts; var initializer = resolver.getAnnotationPropertyEvaluatedInitializer(node); return ts.factory.updateAnnotationPropertyDeclaration(node, node.name, type, initializer); }); - return ts.factory.updateAnnotationDeclaration(node, node.modifiers, node.name, members); + return ts.factory.updateAnnotationDeclaration(node, node.modifiers, magicPrefixName, members); } function visitAnnotation(node) { if (!node.annotationDeclaration) { @@ -47481,7 +47508,7 @@ var ts; // and // // Add the magic prefix for annotation name. For example, - // @myModule.Anno({a: 10, b: "abc"}) --- > @#myModule.Anno({a: 10, b: "abc"}) + // @myModule.Anno({a: 10, b: "abc"}) --- > @myModule.__$$ETS_ANNOTATION$$__Anno({a: 10, b: "abc"}) return ts.factory.updateDecorator(node, addMagicPrefixToAnnotationNameIdentifier(addDefaultValuesIntoAnnotationObjectLiteral(node))); } function addMagicPrefixToAnnotationNameIdentifier(expr) { @@ -47490,7 +47517,7 @@ var ts; return ts.factory.createIdentifier(ts.annotationMagicNamePrefix + expr.escapedText); case 211 /* SyntaxKind.PropertyAccessExpression */: var propAccessExpr = expr; - return ts.factory.updatePropertyAccessExpression(propAccessExpr, addMagicPrefixToAnnotationNameIdentifier(propAccessExpr.expression), propAccessExpr.name); + return ts.factory.updatePropertyAccessExpression(propAccessExpr, propAccessExpr.expression, addMagicPrefixToAnnotationNameIdentifier(propAccessExpr.name)); case 213 /* SyntaxKind.CallExpression */: var callExpr = expr; return ts.factory.updateCallExpression(callExpr, addMagicPrefixToAnnotationNameIdentifier(callExpr.expression), callExpr.typeArguments, callExpr.arguments); @@ -47506,6 +47533,7 @@ var ts; for (var i = 0; i < members.length; ++i) { var member = members[i]; var initializer = resolver.getAnnotationPropertyEvaluatedInitializer(member); + ts.Debug.assert(initializer !== undefined); defaultValues[i] = ts.factory.createPropertyAssignment(member.name, initializer); } var newCallExpr = ts.factory.createCallExpression(annotation.expression, @@ -59596,6 +59624,7 @@ var ts; case 263 /* SyntaxKind.FunctionDeclaration */: case 269 /* SyntaxKind.EnumDeclaration */: case 274 /* SyntaxKind.ImportEqualsDeclaration */: + case 266 /* SyntaxKind.AnnotationDeclaration */: // external module augmentation is always visible if (ts.isExternalModuleAugmentation(node)) { return true; @@ -93380,16 +93409,132 @@ var ts; }, isImportRequiredByAugmentation: isImportRequiredByAugmentation, getAnnotationObjectLiteralEvaluatedProps: function (node) { - return getNodeLinks(node).annotationObjectLiteralEvaluatedProps; + var links = getNodeLinks(node); + if (!links.annotationObjectLiteralEvaluatedProps) { + if (!ts.isCallExpression(node.expression)) { + return undefined; + } + // let d = {} + // @Anno(d) + // class C {} + if (!node.expression.arguments || + node.expression.arguments.length !== 1 || + !ts.isObjectLiteralExpression(node.expression.arguments[0])) { + return undefined; + } + // let bar = goo() + // @Anno({foo: bar}) + // class C {} + var funcType = checkExpression(node.expression); + var apparentType = getApparentType(funcType); + if (isErrorType(apparentType)) { + return undefined; + } + var arg = node.expression.arguments[0]; + var evaluatedProps = new ts.Map(); + for (var _i = 0, _a = arg.properties; _i < _a.length; _i++) { + var prop = _a[_i]; + if (!ts.isPropertyAssignment(prop)) { + return undefined; + } + var evaluated = evaluateAnnotationPropertyConstantExpression(prop.initializer); + if (evaluated === undefined) { + return undefined; + } + evaluatedProps.set(ts.tryGetTextOfPropertyName(prop.name), evaluated); + } + var members = node.annotationDeclaration.members; + for (var _b = 0, members_9 = members; _b < members_9.length; _b++) { + var m = members_9[_b]; + var memberName = ts.tryGetTextOfPropertyName(m.name); + if (evaluatedProps.has(memberName)) { + var propValue = annotationEvaluatedValueToExpr(evaluatedProps.get(memberName), getTypeOfNode(m)); + if (links.annotationObjectLiteralEvaluatedProps === undefined) { + links.annotationObjectLiteralEvaluatedProps = new ts.Map(); + } + links.annotationObjectLiteralEvaluatedProps.set(memberName, propValue); + } + } + } + return links.annotationObjectLiteralEvaluatedProps; }, getAnnotationPropertyEvaluatedInitializer: function (node) { - return getNodeLinks(node).annotationPropertyEvaluatedInitializer; + var links = getNodeLinks(node); + if (!links.annotationPropertyEvaluatedInitializer) { + var propType = getTypeOfNode(node); + if (!isAllowedAnnotationPropertyType(propType)) { + return undefined; + } + if (node.initializer) { + var evaluated = evaluateAnnotationPropertyConstantExpression(node.initializer); + if (evaluated === undefined) { + return undefined; + } + else { + var evaluatedExpr = annotationEvaluatedValueToExpr(evaluated, getTypeOfNode(node)); + links.annotationPropertyEvaluatedInitializer = evaluatedExpr; + } + } + // Special cases for enums + if (!node.initializer) { + var initializer = addAnnotationPropertyEnumInitalizer(propType); + if (initializer) { + links.annotationPropertyEvaluatedInitializer = initializer; + } + } + } + return links.annotationPropertyEvaluatedInitializer; }, getAnnotationPropertyInferredType: function (node) { - return getNodeLinks(node).annotationPropertyInferredType; + var links = getNodeLinks(node); + if (!links.annotationPropertyInferredType) { + var propType = getTypeOfNode(node); + if (!isAllowedAnnotationPropertyType(propType)) { + return undefined; + } + links.annotationPropertyInferredType = nodeBuilder.typeToTypeNode(propType); + } + return links.annotationPropertyInferredType; }, isReferredToAnnotation: function (node) { - return getNodeLinks(node).exportOrImportRefersToAnnotation; + var links = getNodeLinks(node); + if (!links.exportOrImportRefersToAnnotation) { + var ident = undefined; + if ((ts.isExportAssignment(node))) { + switch (node.expression.kind) { + case 79 /* SyntaxKind.Identifier */: + ident = node.expression; + break; + case 211 /* SyntaxKind.PropertyAccessExpression */: + ident = node.expression; + break; + default: + return undefined; + } + if (!ident) { + return undefined; + } + var symbol = getSymbolOfNameOrPropertyAccessExpression(ident); + if (!symbol) { + return undefined; + } + if (getAllSymbolFlags(symbol) & 268435456 /* SymbolFlags.Annotation */) { + links.exportOrImportRefersToAnnotation = true; + } + } + if ((ts.isImportSpecifier(node) || ts.isExportSpecifier(node))) { + var symbol = getSymbolOfNode(node); + if (!symbol) { + return undefined; + } + var target = resolveAlias(symbol); + var targetFlags = getAllSymbolFlags(target); + if (targetFlags & 268435456 /* SymbolFlags.Annotation */) { + links.exportOrImportRefersToAnnotation = true; + } + } + } + return links.exportOrImportRefersToAnnotation; } }; function isImportRequiredByAugmentation(node) { @@ -93782,7 +93927,7 @@ var ts; var flags = 0 /* ModifierFlags.None */; for (var _i = 0, _a = node.modifiers; _i < _a.length; _i++) { var modifier = _a[_i]; - if (ts.isDecorator(modifier)) + if (ts.isDecoratorOrAnnotation(modifier)) continue; if (modifier.kind !== 147 /* SyntaxKind.ReadonlyKeyword */) { if (node.kind === 170 /* SyntaxKind.PropertySignature */ || node.kind === 173 /* SyntaxKind.MethodSignature */) { @@ -94130,7 +94275,7 @@ var ts; function nodeHasAnyModifiersExcept(node, allowedModifier) { for (var _i = 0, _a = node.modifiers; _i < _a.length; _i++) { var modifier = _a[_i]; - if (ts.isDecorator(modifier)) + if (ts.isDecoratorOrAnnotation(modifier)) continue; return modifier.kind !== allowedModifier; } @@ -98145,7 +98290,7 @@ var ts; } } function modifierVisitor(node) { - if (ts.isDecorator(node)) + if (ts.isDecoratorOrAnnotation(node)) return undefined; if (ts.modifierToFlag(node.kind) & 117086 /* ModifierFlags.TypeScriptModifier */) { return undefined; @@ -102369,8 +102514,8 @@ var ts; function generateClassElementDecorationExpressions(node, isStatic) { var members = getDecoratedClassElements(node, isStatic); var expressions; - for (var _i = 0, members_9 = members; _i < members_9.length; _i++) { - var member = members_9[_i]; + for (var _i = 0, members_10 = members; _i < members_10.length; _i++) { + var member = members_10[_i]; expressions = ts.append(expressions, generateClassElementDecorationExpression(node, member)); } return expressions; @@ -115331,6 +115476,7 @@ var ts; case 265 /* SyntaxKind.StructDeclaration */: case 268 /* SyntaxKind.TypeAliasDeclaration */: case 269 /* SyntaxKind.EnumDeclaration */: + case 266 /* SyntaxKind.AnnotationDeclaration */: return !resolver.isDeclarationVisible(node); // The following should be doing their own visibility checks based on filtering their members case 261 /* SyntaxKind.VariableDeclaration */: @@ -115553,6 +115699,21 @@ var ts; return statement; } } + function checkAnnotationVisibilityByDecorator(input) { + ts.forEach(input, function (decorator) { + if (!ts.isAnnotation(decorator)) { + return; + } + if (ts.isCallExpression(decorator.expression)) { + // @Anno({}) + checkEntityNameVisibility((decorator.expression.expression), enclosingDeclaration); + } + else if (ts.isIdentifier(decorator.expression)) { + // @Anno + checkEntityNameVisibility((decorator.expression), enclosingDeclaration); + } + }); + } function visitDeclarationSubtree(input) { if (shouldStripInternal(input)) return; @@ -115625,7 +115786,8 @@ var ts; if (ts.isPrivateIdentifier(input.name)) { return cleanup(/*returnValue*/ undefined); } - var reservedDecorators_1 = ts.getReservedDecoratorsOfStructDeclaration(input, host); + var reservedDecorators_1 = ts.concatenate(ts.getReservedDecoratorsOfStructDeclaration(input, host), ts.getAnnotations(input)); + checkAnnotationVisibilityByDecorator(reservedDecorators_1); var sig = factory.createMethodDeclaration(ts.concatenateDecoratorsAndModifiers(reservedDecorators_1, ensureModifiers(input)), /*asteriskToken*/ undefined, input.name, input.questionToken, ts.inEtsStylesContext(input, host) ? undefined : ensureTypeParams(input, input.typeParameters), updateParamsList(input, input.parameters), ensureType(input, input.type), /*body*/ undefined); @@ -116047,13 +116209,14 @@ var ts; } return factory.updateHeritageClause(clause, ts.visitNodes(factory.createNodeArray(ts.filter(clause.types, function (t) { return ts.isEntityNameExpression(t.expression) || t.expression.kind === 105 /* SyntaxKind.NullKeyword */; })), visitDeclarationSubtree)); })); - var reservedDecorators = ts.getReservedDecoratorsOfEtsFile(input, host); + var reservedDecorators = ts.concatenate(ts.getReservedDecoratorsOfEtsFile(input, host), ts.getAnnotations(input)); + checkAnnotationVisibilityByDecorator(reservedDecorators); return [statement, cleanup(factory.updateClassDeclaration(input, ts.concatenateDecoratorsAndModifiers(reservedDecorators, modifiers), input.name, typeParameters, heritageClauses, members))]; // TODO: GH#18217 } else { var heritageClauses = transformHeritageClauses(input.heritageClauses); - var reservedDecorators = ts.getReservedDecoratorsOfEtsFile(input, host); - ; + var reservedDecorators = ts.concatenate(ts.getReservedDecoratorsOfEtsFile(input, host), ts.getAnnotations(input)); + checkAnnotationVisibilityByDecorator(reservedDecorators); return cleanup(factory.updateClassDeclaration(input, ts.concatenateDecoratorsAndModifiers(reservedDecorators, modifiers), input.name, typeParameters, heritageClauses, members)); } } @@ -120690,7 +120853,7 @@ var ts; // if all modifier-likes are `Modifier`, simply emit the array as modifiers. return emitModifiers(node, modifiers); } - if (ts.every(modifiers, ts.isDecorator)) { + if (ts.every(modifiers, ts.isDecoratorOrAnnotation)) { // if all modifier-likes are `Decorator`, simply emit the array as decorators. return emitDecorators(node, modifiers); } @@ -120703,7 +120866,7 @@ var ts; while (start < modifiers.length) { while (pos < modifiers.length) { var modifier = modifiers[pos]; - mode = ts.isDecorator(modifier) ? "decorators" : "modifiers"; + mode = ts.isDecoratorOrAnnotation(modifier) ? "decorators" : "modifiers"; if (lastMode === undefined) { lastMode = mode; } diff --git a/lib/tsserverlibrary.d.ts b/lib/tsserverlibrary.d.ts index b86d15474f..463b30f132 100644 --- a/lib/tsserverlibrary.d.ts +++ b/lib/tsserverlibrary.d.ts @@ -4821,6 +4821,7 @@ declare namespace ts { function getNameOfJSDocTypedef(declaration: JSDocTypedefTag): Identifier | PrivateIdentifier | undefined; function getNameOfDeclaration(declaration: Declaration | Expression | undefined): DeclarationName | undefined; function getDecorators(node: HasDecorators): readonly Decorator[] | undefined; + function getAnnotations(node: HasDecorators): readonly Decorator[] | undefined; function getModifiers(node: HasModifiers): readonly Modifier[] | undefined; function getAllDecorators(node: Node | undefined): readonly Decorator[]; function getIllegalDecorators(node: HasIllegalDecorators): readonly Decorator[] | undefined; @@ -5114,6 +5115,7 @@ declare namespace ts { function isComputedPropertyName(node: Node): node is ComputedPropertyName; function isTypeParameterDeclaration(node: Node): node is TypeParameterDeclaration; function isParameter(node: Node): node is ParameterDeclaration; + function isDecoratorOrAnnotation(node: Node): node is Decorator; function isDecorator(node: Node): node is Decorator; function isAnnotation(node: Node): node is Annotation; function isPropertySignature(node: Node): node is PropertySignature; diff --git a/lib/tsserverlibrary.js b/lib/tsserverlibrary.js index b4c7798f23..8bb5e5697c 100644 --- a/lib/tsserverlibrary.js +++ b/lib/tsserverlibrary.js @@ -13369,6 +13369,12 @@ var ts; } } ts.getDecorators = getDecorators; + function getAnnotations(node) { + if (ts.hasAnnotations(node)) { + return ts.filter(node.modifiers, ts.isAnnotation); + } + } + ts.getAnnotations = getAnnotations; function getModifiers(node) { if (ts.hasSyntacticModifier(node, 126975 /* ModifierFlags.Modifier */)) { return ts.filter(node.modifiers, isModifier); @@ -14122,7 +14128,7 @@ var ts; ts.isNamedClassElement = isNamedClassElement; // Type members function isModifierLike(node) { - return isModifier(node) || ts.isDecorator(node); + return isModifier(node) || ts.isDecoratorOrAnnotation(node); } ts.isModifierLike = isModifierLike; function isTypeElement(node) { @@ -29930,6 +29936,10 @@ var ts; return node.kind === 168 /* SyntaxKind.Parameter */; } ts.isParameter = isParameter; + function isDecoratorOrAnnotation(node) { + return node.kind === 169 /* SyntaxKind.Decorator */; + } + ts.isDecoratorOrAnnotation = isDecoratorOrAnnotation; function isDecorator(node) { return node.kind === 169 /* SyntaxKind.Decorator */ && node.annotationDeclaration === undefined; } @@ -47427,7 +47437,7 @@ var ts; } // Firstly, visit declarations var updatedSource = ts.factory.updateSourceFile(node, ts.visitLexicalEnvironment(node.statements, visitAnnotationsDeclarations, context)); - // Secondly, visit usage of annotations + // Secondly, visit import and usage of annotations return ts.factory.updateSourceFile(node, ts.visitLexicalEnvironment(updatedSource.statements, visitAnnotations, context)); } function visitAnnotationsDeclarations(node) { @@ -47440,13 +47450,30 @@ var ts; } function visitAnnotations(node) { switch (node.kind) { + case 279 /* SyntaxKind.ImportSpecifier */: + return visitImportSpecifier(node); case 169 /* SyntaxKind.Decorator */: return visitAnnotation(node); default: return ts.visitEachChild(node, visitAnnotations, context); } } + function visitImportSpecifier(node) { + // Return if the import has type or not refered to Annotation + if (node.isTypeOnly || !resolver.isReferredToAnnotation(node)) { + return node; + } + var magicPrefixName = addMagicPrefixToAnnotationNameIdentifier(node.name); + ts.Debug.assert(ts.isIdentifier(magicPrefixName)); + // Add magic prefix for import Annotation. For example, + // import {Anno} from "xxx" ---> import {__$$ETS_ANNOTATION$$__Anno} from "xxx" + return ts.factory.updateImportSpecifier(node, node.isTypeOnly, node.propertyName, magicPrefixName); + } function visitAnnotationDeclaration(node) { + // Add magic prefix for AnnotationDeclaration. For example, + // @interface Anno {} ---> @interface __$$ETS_ANNOTATION$$__Anno {} + var magicPrefixName = addMagicPrefixToAnnotationNameIdentifier(node.name); + ts.Debug.assert(ts.isIdentifier(magicPrefixName)); // Add explicit type annotation and initializer. For example, // @interface Anno { // a = 10 + 5 @@ -47454,7 +47481,7 @@ var ts; // // will be transformed to // - // @interface Anno { + // @interface __$$ETS_ANNOTATION$$__Anno { // a: number = 15 // } var members = node.members.map(function (node) { @@ -47462,7 +47489,7 @@ var ts; var initializer = resolver.getAnnotationPropertyEvaluatedInitializer(node); return ts.factory.updateAnnotationPropertyDeclaration(node, node.name, type, initializer); }); - return ts.factory.updateAnnotationDeclaration(node, node.modifiers, node.name, members); + return ts.factory.updateAnnotationDeclaration(node, node.modifiers, magicPrefixName, members); } function visitAnnotation(node) { if (!node.annotationDeclaration) { @@ -47480,7 +47507,7 @@ var ts; // and // // Add the magic prefix for annotation name. For example, - // @myModule.Anno({a: 10, b: "abc"}) --- > @#myModule.Anno({a: 10, b: "abc"}) + // @myModule.Anno({a: 10, b: "abc"}) --- > @myModule.__$$ETS_ANNOTATION$$__Anno({a: 10, b: "abc"}) return ts.factory.updateDecorator(node, addMagicPrefixToAnnotationNameIdentifier(addDefaultValuesIntoAnnotationObjectLiteral(node))); } function addMagicPrefixToAnnotationNameIdentifier(expr) { @@ -47489,7 +47516,7 @@ var ts; return ts.factory.createIdentifier(ts.annotationMagicNamePrefix + expr.escapedText); case 211 /* SyntaxKind.PropertyAccessExpression */: var propAccessExpr = expr; - return ts.factory.updatePropertyAccessExpression(propAccessExpr, addMagicPrefixToAnnotationNameIdentifier(propAccessExpr.expression), propAccessExpr.name); + return ts.factory.updatePropertyAccessExpression(propAccessExpr, propAccessExpr.expression, addMagicPrefixToAnnotationNameIdentifier(propAccessExpr.name)); case 213 /* SyntaxKind.CallExpression */: var callExpr = expr; return ts.factory.updateCallExpression(callExpr, addMagicPrefixToAnnotationNameIdentifier(callExpr.expression), callExpr.typeArguments, callExpr.arguments); @@ -47505,6 +47532,7 @@ var ts; for (var i = 0; i < members.length; ++i) { var member = members[i]; var initializer = resolver.getAnnotationPropertyEvaluatedInitializer(member); + ts.Debug.assert(initializer !== undefined); defaultValues[i] = ts.factory.createPropertyAssignment(member.name, initializer); } var newCallExpr = ts.factory.createCallExpression(annotation.expression, @@ -59595,6 +59623,7 @@ var ts; case 263 /* SyntaxKind.FunctionDeclaration */: case 269 /* SyntaxKind.EnumDeclaration */: case 274 /* SyntaxKind.ImportEqualsDeclaration */: + case 266 /* SyntaxKind.AnnotationDeclaration */: // external module augmentation is always visible if (ts.isExternalModuleAugmentation(node)) { return true; @@ -93379,16 +93408,132 @@ var ts; }, isImportRequiredByAugmentation: isImportRequiredByAugmentation, getAnnotationObjectLiteralEvaluatedProps: function (node) { - return getNodeLinks(node).annotationObjectLiteralEvaluatedProps; + var links = getNodeLinks(node); + if (!links.annotationObjectLiteralEvaluatedProps) { + if (!ts.isCallExpression(node.expression)) { + return undefined; + } + // let d = {} + // @Anno(d) + // class C {} + if (!node.expression.arguments || + node.expression.arguments.length !== 1 || + !ts.isObjectLiteralExpression(node.expression.arguments[0])) { + return undefined; + } + // let bar = goo() + // @Anno({foo: bar}) + // class C {} + var funcType = checkExpression(node.expression); + var apparentType = getApparentType(funcType); + if (isErrorType(apparentType)) { + return undefined; + } + var arg = node.expression.arguments[0]; + var evaluatedProps = new ts.Map(); + for (var _i = 0, _a = arg.properties; _i < _a.length; _i++) { + var prop = _a[_i]; + if (!ts.isPropertyAssignment(prop)) { + return undefined; + } + var evaluated = evaluateAnnotationPropertyConstantExpression(prop.initializer); + if (evaluated === undefined) { + return undefined; + } + evaluatedProps.set(ts.tryGetTextOfPropertyName(prop.name), evaluated); + } + var members = node.annotationDeclaration.members; + for (var _b = 0, members_9 = members; _b < members_9.length; _b++) { + var m = members_9[_b]; + var memberName = ts.tryGetTextOfPropertyName(m.name); + if (evaluatedProps.has(memberName)) { + var propValue = annotationEvaluatedValueToExpr(evaluatedProps.get(memberName), getTypeOfNode(m)); + if (links.annotationObjectLiteralEvaluatedProps === undefined) { + links.annotationObjectLiteralEvaluatedProps = new ts.Map(); + } + links.annotationObjectLiteralEvaluatedProps.set(memberName, propValue); + } + } + } + return links.annotationObjectLiteralEvaluatedProps; }, getAnnotationPropertyEvaluatedInitializer: function (node) { - return getNodeLinks(node).annotationPropertyEvaluatedInitializer; + var links = getNodeLinks(node); + if (!links.annotationPropertyEvaluatedInitializer) { + var propType = getTypeOfNode(node); + if (!isAllowedAnnotationPropertyType(propType)) { + return undefined; + } + if (node.initializer) { + var evaluated = evaluateAnnotationPropertyConstantExpression(node.initializer); + if (evaluated === undefined) { + return undefined; + } + else { + var evaluatedExpr = annotationEvaluatedValueToExpr(evaluated, getTypeOfNode(node)); + links.annotationPropertyEvaluatedInitializer = evaluatedExpr; + } + } + // Special cases for enums + if (!node.initializer) { + var initializer = addAnnotationPropertyEnumInitalizer(propType); + if (initializer) { + links.annotationPropertyEvaluatedInitializer = initializer; + } + } + } + return links.annotationPropertyEvaluatedInitializer; }, getAnnotationPropertyInferredType: function (node) { - return getNodeLinks(node).annotationPropertyInferredType; + var links = getNodeLinks(node); + if (!links.annotationPropertyInferredType) { + var propType = getTypeOfNode(node); + if (!isAllowedAnnotationPropertyType(propType)) { + return undefined; + } + links.annotationPropertyInferredType = nodeBuilder.typeToTypeNode(propType); + } + return links.annotationPropertyInferredType; }, isReferredToAnnotation: function (node) { - return getNodeLinks(node).exportOrImportRefersToAnnotation; + var links = getNodeLinks(node); + if (!links.exportOrImportRefersToAnnotation) { + var ident = undefined; + if ((ts.isExportAssignment(node))) { + switch (node.expression.kind) { + case 79 /* SyntaxKind.Identifier */: + ident = node.expression; + break; + case 211 /* SyntaxKind.PropertyAccessExpression */: + ident = node.expression; + break; + default: + return undefined; + } + if (!ident) { + return undefined; + } + var symbol = getSymbolOfNameOrPropertyAccessExpression(ident); + if (!symbol) { + return undefined; + } + if (getAllSymbolFlags(symbol) & 268435456 /* SymbolFlags.Annotation */) { + links.exportOrImportRefersToAnnotation = true; + } + } + if ((ts.isImportSpecifier(node) || ts.isExportSpecifier(node))) { + var symbol = getSymbolOfNode(node); + if (!symbol) { + return undefined; + } + var target = resolveAlias(symbol); + var targetFlags = getAllSymbolFlags(target); + if (targetFlags & 268435456 /* SymbolFlags.Annotation */) { + links.exportOrImportRefersToAnnotation = true; + } + } + } + return links.exportOrImportRefersToAnnotation; } }; function isImportRequiredByAugmentation(node) { @@ -93781,7 +93926,7 @@ var ts; var flags = 0 /* ModifierFlags.None */; for (var _i = 0, _a = node.modifiers; _i < _a.length; _i++) { var modifier = _a[_i]; - if (ts.isDecorator(modifier)) + if (ts.isDecoratorOrAnnotation(modifier)) continue; if (modifier.kind !== 147 /* SyntaxKind.ReadonlyKeyword */) { if (node.kind === 170 /* SyntaxKind.PropertySignature */ || node.kind === 173 /* SyntaxKind.MethodSignature */) { @@ -94129,7 +94274,7 @@ var ts; function nodeHasAnyModifiersExcept(node, allowedModifier) { for (var _i = 0, _a = node.modifiers; _i < _a.length; _i++) { var modifier = _a[_i]; - if (ts.isDecorator(modifier)) + if (ts.isDecoratorOrAnnotation(modifier)) continue; return modifier.kind !== allowedModifier; } @@ -98144,7 +98289,7 @@ var ts; } } function modifierVisitor(node) { - if (ts.isDecorator(node)) + if (ts.isDecoratorOrAnnotation(node)) return undefined; if (ts.modifierToFlag(node.kind) & 117086 /* ModifierFlags.TypeScriptModifier */) { return undefined; @@ -102368,8 +102513,8 @@ var ts; function generateClassElementDecorationExpressions(node, isStatic) { var members = getDecoratedClassElements(node, isStatic); var expressions; - for (var _i = 0, members_9 = members; _i < members_9.length; _i++) { - var member = members_9[_i]; + for (var _i = 0, members_10 = members; _i < members_10.length; _i++) { + var member = members_10[_i]; expressions = ts.append(expressions, generateClassElementDecorationExpression(node, member)); } return expressions; @@ -115330,6 +115475,7 @@ var ts; case 265 /* SyntaxKind.StructDeclaration */: case 268 /* SyntaxKind.TypeAliasDeclaration */: case 269 /* SyntaxKind.EnumDeclaration */: + case 266 /* SyntaxKind.AnnotationDeclaration */: return !resolver.isDeclarationVisible(node); // The following should be doing their own visibility checks based on filtering their members case 261 /* SyntaxKind.VariableDeclaration */: @@ -115552,6 +115698,21 @@ var ts; return statement; } } + function checkAnnotationVisibilityByDecorator(input) { + ts.forEach(input, function (decorator) { + if (!ts.isAnnotation(decorator)) { + return; + } + if (ts.isCallExpression(decorator.expression)) { + // @Anno({}) + checkEntityNameVisibility((decorator.expression.expression), enclosingDeclaration); + } + else if (ts.isIdentifier(decorator.expression)) { + // @Anno + checkEntityNameVisibility((decorator.expression), enclosingDeclaration); + } + }); + } function visitDeclarationSubtree(input) { if (shouldStripInternal(input)) return; @@ -115624,7 +115785,8 @@ var ts; if (ts.isPrivateIdentifier(input.name)) { return cleanup(/*returnValue*/ undefined); } - var reservedDecorators_1 = ts.getReservedDecoratorsOfStructDeclaration(input, host); + var reservedDecorators_1 = ts.concatenate(ts.getReservedDecoratorsOfStructDeclaration(input, host), ts.getAnnotations(input)); + checkAnnotationVisibilityByDecorator(reservedDecorators_1); var sig = factory.createMethodDeclaration(ts.concatenateDecoratorsAndModifiers(reservedDecorators_1, ensureModifiers(input)), /*asteriskToken*/ undefined, input.name, input.questionToken, ts.inEtsStylesContext(input, host) ? undefined : ensureTypeParams(input, input.typeParameters), updateParamsList(input, input.parameters), ensureType(input, input.type), /*body*/ undefined); @@ -116046,13 +116208,14 @@ var ts; } return factory.updateHeritageClause(clause, ts.visitNodes(factory.createNodeArray(ts.filter(clause.types, function (t) { return ts.isEntityNameExpression(t.expression) || t.expression.kind === 105 /* SyntaxKind.NullKeyword */; })), visitDeclarationSubtree)); })); - var reservedDecorators = ts.getReservedDecoratorsOfEtsFile(input, host); + var reservedDecorators = ts.concatenate(ts.getReservedDecoratorsOfEtsFile(input, host), ts.getAnnotations(input)); + checkAnnotationVisibilityByDecorator(reservedDecorators); return [statement, cleanup(factory.updateClassDeclaration(input, ts.concatenateDecoratorsAndModifiers(reservedDecorators, modifiers), input.name, typeParameters, heritageClauses, members))]; // TODO: GH#18217 } else { var heritageClauses = transformHeritageClauses(input.heritageClauses); - var reservedDecorators = ts.getReservedDecoratorsOfEtsFile(input, host); - ; + var reservedDecorators = ts.concatenate(ts.getReservedDecoratorsOfEtsFile(input, host), ts.getAnnotations(input)); + checkAnnotationVisibilityByDecorator(reservedDecorators); return cleanup(factory.updateClassDeclaration(input, ts.concatenateDecoratorsAndModifiers(reservedDecorators, modifiers), input.name, typeParameters, heritageClauses, members)); } } @@ -120689,7 +120852,7 @@ var ts; // if all modifier-likes are `Modifier`, simply emit the array as modifiers. return emitModifiers(node, modifiers); } - if (ts.every(modifiers, ts.isDecorator)) { + if (ts.every(modifiers, ts.isDecoratorOrAnnotation)) { // if all modifier-likes are `Decorator`, simply emit the array as decorators. return emitDecorators(node, modifiers); } @@ -120702,7 +120865,7 @@ var ts; while (start < modifiers.length) { while (pos < modifiers.length) { var modifier = modifiers[pos]; - mode = ts.isDecorator(modifier) ? "decorators" : "modifiers"; + mode = ts.isDecoratorOrAnnotation(modifier) ? "decorators" : "modifiers"; if (lastMode === undefined) { lastMode = mode; } diff --git a/lib/typescript.d.ts b/lib/typescript.d.ts index 6a74eb1412..440f35c680 100644 --- a/lib/typescript.d.ts +++ b/lib/typescript.d.ts @@ -4821,6 +4821,7 @@ declare namespace ts { function getNameOfJSDocTypedef(declaration: JSDocTypedefTag): Identifier | PrivateIdentifier | undefined; function getNameOfDeclaration(declaration: Declaration | Expression | undefined): DeclarationName | undefined; function getDecorators(node: HasDecorators): readonly Decorator[] | undefined; + function getAnnotations(node: HasDecorators): readonly Decorator[] | undefined; function getModifiers(node: HasModifiers): readonly Modifier[] | undefined; function getAllDecorators(node: Node | undefined): readonly Decorator[]; function getIllegalDecorators(node: HasIllegalDecorators): readonly Decorator[] | undefined; @@ -5114,6 +5115,7 @@ declare namespace ts { function isComputedPropertyName(node: Node): node is ComputedPropertyName; function isTypeParameterDeclaration(node: Node): node is TypeParameterDeclaration; function isParameter(node: Node): node is ParameterDeclaration; + function isDecoratorOrAnnotation(node: Node): node is Decorator; function isDecorator(node: Node): node is Decorator; function isAnnotation(node: Node): node is Annotation; function isPropertySignature(node: Node): node is PropertySignature; diff --git a/lib/typescript.js b/lib/typescript.js index 66909a24d8..ec669feb94 100644 --- a/lib/typescript.js +++ b/lib/typescript.js @@ -13360,6 +13360,12 @@ var ts; } } ts.getDecorators = getDecorators; + function getAnnotations(node) { + if (ts.hasAnnotations(node)) { + return ts.filter(node.modifiers, ts.isAnnotation); + } + } + ts.getAnnotations = getAnnotations; function getModifiers(node) { if (ts.hasSyntacticModifier(node, 126975 /* ModifierFlags.Modifier */)) { return ts.filter(node.modifiers, isModifier); @@ -14113,7 +14119,7 @@ var ts; ts.isNamedClassElement = isNamedClassElement; // Type members function isModifierLike(node) { - return isModifier(node) || ts.isDecorator(node); + return isModifier(node) || ts.isDecoratorOrAnnotation(node); } ts.isModifierLike = isModifierLike; function isTypeElement(node) { @@ -29921,6 +29927,10 @@ var ts; return node.kind === 168 /* SyntaxKind.Parameter */; } ts.isParameter = isParameter; + function isDecoratorOrAnnotation(node) { + return node.kind === 169 /* SyntaxKind.Decorator */; + } + ts.isDecoratorOrAnnotation = isDecoratorOrAnnotation; function isDecorator(node) { return node.kind === 169 /* SyntaxKind.Decorator */ && node.annotationDeclaration === undefined; } @@ -47418,7 +47428,7 @@ var ts; } // Firstly, visit declarations var updatedSource = ts.factory.updateSourceFile(node, ts.visitLexicalEnvironment(node.statements, visitAnnotationsDeclarations, context)); - // Secondly, visit usage of annotations + // Secondly, visit import and usage of annotations return ts.factory.updateSourceFile(node, ts.visitLexicalEnvironment(updatedSource.statements, visitAnnotations, context)); } function visitAnnotationsDeclarations(node) { @@ -47431,13 +47441,30 @@ var ts; } function visitAnnotations(node) { switch (node.kind) { + case 279 /* SyntaxKind.ImportSpecifier */: + return visitImportSpecifier(node); case 169 /* SyntaxKind.Decorator */: return visitAnnotation(node); default: return ts.visitEachChild(node, visitAnnotations, context); } } + function visitImportSpecifier(node) { + // Return if the import has type or not refered to Annotation + if (node.isTypeOnly || !resolver.isReferredToAnnotation(node)) { + return node; + } + var magicPrefixName = addMagicPrefixToAnnotationNameIdentifier(node.name); + ts.Debug.assert(ts.isIdentifier(magicPrefixName)); + // Add magic prefix for import Annotation. For example, + // import {Anno} from "xxx" ---> import {__$$ETS_ANNOTATION$$__Anno} from "xxx" + return ts.factory.updateImportSpecifier(node, node.isTypeOnly, node.propertyName, magicPrefixName); + } function visitAnnotationDeclaration(node) { + // Add magic prefix for AnnotationDeclaration. For example, + // @interface Anno {} ---> @interface __$$ETS_ANNOTATION$$__Anno {} + var magicPrefixName = addMagicPrefixToAnnotationNameIdentifier(node.name); + ts.Debug.assert(ts.isIdentifier(magicPrefixName)); // Add explicit type annotation and initializer. For example, // @interface Anno { // a = 10 + 5 @@ -47445,7 +47472,7 @@ var ts; // // will be transformed to // - // @interface Anno { + // @interface __$$ETS_ANNOTATION$$__Anno { // a: number = 15 // } var members = node.members.map(function (node) { @@ -47453,7 +47480,7 @@ var ts; var initializer = resolver.getAnnotationPropertyEvaluatedInitializer(node); return ts.factory.updateAnnotationPropertyDeclaration(node, node.name, type, initializer); }); - return ts.factory.updateAnnotationDeclaration(node, node.modifiers, node.name, members); + return ts.factory.updateAnnotationDeclaration(node, node.modifiers, magicPrefixName, members); } function visitAnnotation(node) { if (!node.annotationDeclaration) { @@ -47471,7 +47498,7 @@ var ts; // and // // Add the magic prefix for annotation name. For example, - // @myModule.Anno({a: 10, b: "abc"}) --- > @#myModule.Anno({a: 10, b: "abc"}) + // @myModule.Anno({a: 10, b: "abc"}) --- > @myModule.__$$ETS_ANNOTATION$$__Anno({a: 10, b: "abc"}) return ts.factory.updateDecorator(node, addMagicPrefixToAnnotationNameIdentifier(addDefaultValuesIntoAnnotationObjectLiteral(node))); } function addMagicPrefixToAnnotationNameIdentifier(expr) { @@ -47480,7 +47507,7 @@ var ts; return ts.factory.createIdentifier(ts.annotationMagicNamePrefix + expr.escapedText); case 211 /* SyntaxKind.PropertyAccessExpression */: var propAccessExpr = expr; - return ts.factory.updatePropertyAccessExpression(propAccessExpr, addMagicPrefixToAnnotationNameIdentifier(propAccessExpr.expression), propAccessExpr.name); + return ts.factory.updatePropertyAccessExpression(propAccessExpr, propAccessExpr.expression, addMagicPrefixToAnnotationNameIdentifier(propAccessExpr.name)); case 213 /* SyntaxKind.CallExpression */: var callExpr = expr; return ts.factory.updateCallExpression(callExpr, addMagicPrefixToAnnotationNameIdentifier(callExpr.expression), callExpr.typeArguments, callExpr.arguments); @@ -47496,6 +47523,7 @@ var ts; for (var i = 0; i < members.length; ++i) { var member = members[i]; var initializer = resolver.getAnnotationPropertyEvaluatedInitializer(member); + ts.Debug.assert(initializer !== undefined); defaultValues[i] = ts.factory.createPropertyAssignment(member.name, initializer); } var newCallExpr = ts.factory.createCallExpression(annotation.expression, @@ -59586,6 +59614,7 @@ var ts; case 263 /* SyntaxKind.FunctionDeclaration */: case 269 /* SyntaxKind.EnumDeclaration */: case 274 /* SyntaxKind.ImportEqualsDeclaration */: + case 266 /* SyntaxKind.AnnotationDeclaration */: // external module augmentation is always visible if (ts.isExternalModuleAugmentation(node)) { return true; @@ -93370,16 +93399,132 @@ var ts; }, isImportRequiredByAugmentation: isImportRequiredByAugmentation, getAnnotationObjectLiteralEvaluatedProps: function (node) { - return getNodeLinks(node).annotationObjectLiteralEvaluatedProps; + var links = getNodeLinks(node); + if (!links.annotationObjectLiteralEvaluatedProps) { + if (!ts.isCallExpression(node.expression)) { + return undefined; + } + // let d = {} + // @Anno(d) + // class C {} + if (!node.expression.arguments || + node.expression.arguments.length !== 1 || + !ts.isObjectLiteralExpression(node.expression.arguments[0])) { + return undefined; + } + // let bar = goo() + // @Anno({foo: bar}) + // class C {} + var funcType = checkExpression(node.expression); + var apparentType = getApparentType(funcType); + if (isErrorType(apparentType)) { + return undefined; + } + var arg = node.expression.arguments[0]; + var evaluatedProps = new ts.Map(); + for (var _i = 0, _a = arg.properties; _i < _a.length; _i++) { + var prop = _a[_i]; + if (!ts.isPropertyAssignment(prop)) { + return undefined; + } + var evaluated = evaluateAnnotationPropertyConstantExpression(prop.initializer); + if (evaluated === undefined) { + return undefined; + } + evaluatedProps.set(ts.tryGetTextOfPropertyName(prop.name), evaluated); + } + var members = node.annotationDeclaration.members; + for (var _b = 0, members_9 = members; _b < members_9.length; _b++) { + var m = members_9[_b]; + var memberName = ts.tryGetTextOfPropertyName(m.name); + if (evaluatedProps.has(memberName)) { + var propValue = annotationEvaluatedValueToExpr(evaluatedProps.get(memberName), getTypeOfNode(m)); + if (links.annotationObjectLiteralEvaluatedProps === undefined) { + links.annotationObjectLiteralEvaluatedProps = new ts.Map(); + } + links.annotationObjectLiteralEvaluatedProps.set(memberName, propValue); + } + } + } + return links.annotationObjectLiteralEvaluatedProps; }, getAnnotationPropertyEvaluatedInitializer: function (node) { - return getNodeLinks(node).annotationPropertyEvaluatedInitializer; + var links = getNodeLinks(node); + if (!links.annotationPropertyEvaluatedInitializer) { + var propType = getTypeOfNode(node); + if (!isAllowedAnnotationPropertyType(propType)) { + return undefined; + } + if (node.initializer) { + var evaluated = evaluateAnnotationPropertyConstantExpression(node.initializer); + if (evaluated === undefined) { + return undefined; + } + else { + var evaluatedExpr = annotationEvaluatedValueToExpr(evaluated, getTypeOfNode(node)); + links.annotationPropertyEvaluatedInitializer = evaluatedExpr; + } + } + // Special cases for enums + if (!node.initializer) { + var initializer = addAnnotationPropertyEnumInitalizer(propType); + if (initializer) { + links.annotationPropertyEvaluatedInitializer = initializer; + } + } + } + return links.annotationPropertyEvaluatedInitializer; }, getAnnotationPropertyInferredType: function (node) { - return getNodeLinks(node).annotationPropertyInferredType; + var links = getNodeLinks(node); + if (!links.annotationPropertyInferredType) { + var propType = getTypeOfNode(node); + if (!isAllowedAnnotationPropertyType(propType)) { + return undefined; + } + links.annotationPropertyInferredType = nodeBuilder.typeToTypeNode(propType); + } + return links.annotationPropertyInferredType; }, isReferredToAnnotation: function (node) { - return getNodeLinks(node).exportOrImportRefersToAnnotation; + var links = getNodeLinks(node); + if (!links.exportOrImportRefersToAnnotation) { + var ident = undefined; + if ((ts.isExportAssignment(node))) { + switch (node.expression.kind) { + case 79 /* SyntaxKind.Identifier */: + ident = node.expression; + break; + case 211 /* SyntaxKind.PropertyAccessExpression */: + ident = node.expression; + break; + default: + return undefined; + } + if (!ident) { + return undefined; + } + var symbol = getSymbolOfNameOrPropertyAccessExpression(ident); + if (!symbol) { + return undefined; + } + if (getAllSymbolFlags(symbol) & 268435456 /* SymbolFlags.Annotation */) { + links.exportOrImportRefersToAnnotation = true; + } + } + if ((ts.isImportSpecifier(node) || ts.isExportSpecifier(node))) { + var symbol = getSymbolOfNode(node); + if (!symbol) { + return undefined; + } + var target = resolveAlias(symbol); + var targetFlags = getAllSymbolFlags(target); + if (targetFlags & 268435456 /* SymbolFlags.Annotation */) { + links.exportOrImportRefersToAnnotation = true; + } + } + } + return links.exportOrImportRefersToAnnotation; } }; function isImportRequiredByAugmentation(node) { @@ -93772,7 +93917,7 @@ var ts; var flags = 0 /* ModifierFlags.None */; for (var _i = 0, _a = node.modifiers; _i < _a.length; _i++) { var modifier = _a[_i]; - if (ts.isDecorator(modifier)) + if (ts.isDecoratorOrAnnotation(modifier)) continue; if (modifier.kind !== 147 /* SyntaxKind.ReadonlyKeyword */) { if (node.kind === 170 /* SyntaxKind.PropertySignature */ || node.kind === 173 /* SyntaxKind.MethodSignature */) { @@ -94120,7 +94265,7 @@ var ts; function nodeHasAnyModifiersExcept(node, allowedModifier) { for (var _i = 0, _a = node.modifiers; _i < _a.length; _i++) { var modifier = _a[_i]; - if (ts.isDecorator(modifier)) + if (ts.isDecoratorOrAnnotation(modifier)) continue; return modifier.kind !== allowedModifier; } @@ -98135,7 +98280,7 @@ var ts; } } function modifierVisitor(node) { - if (ts.isDecorator(node)) + if (ts.isDecoratorOrAnnotation(node)) return undefined; if (ts.modifierToFlag(node.kind) & 117086 /* ModifierFlags.TypeScriptModifier */) { return undefined; @@ -102359,8 +102504,8 @@ var ts; function generateClassElementDecorationExpressions(node, isStatic) { var members = getDecoratedClassElements(node, isStatic); var expressions; - for (var _i = 0, members_9 = members; _i < members_9.length; _i++) { - var member = members_9[_i]; + for (var _i = 0, members_10 = members; _i < members_10.length; _i++) { + var member = members_10[_i]; expressions = ts.append(expressions, generateClassElementDecorationExpression(node, member)); } return expressions; @@ -115321,6 +115466,7 @@ var ts; case 265 /* SyntaxKind.StructDeclaration */: case 268 /* SyntaxKind.TypeAliasDeclaration */: case 269 /* SyntaxKind.EnumDeclaration */: + case 266 /* SyntaxKind.AnnotationDeclaration */: return !resolver.isDeclarationVisible(node); // The following should be doing their own visibility checks based on filtering their members case 261 /* SyntaxKind.VariableDeclaration */: @@ -115543,6 +115689,21 @@ var ts; return statement; } } + function checkAnnotationVisibilityByDecorator(input) { + ts.forEach(input, function (decorator) { + if (!ts.isAnnotation(decorator)) { + return; + } + if (ts.isCallExpression(decorator.expression)) { + // @Anno({}) + checkEntityNameVisibility((decorator.expression.expression), enclosingDeclaration); + } + else if (ts.isIdentifier(decorator.expression)) { + // @Anno + checkEntityNameVisibility((decorator.expression), enclosingDeclaration); + } + }); + } function visitDeclarationSubtree(input) { if (shouldStripInternal(input)) return; @@ -115615,7 +115776,8 @@ var ts; if (ts.isPrivateIdentifier(input.name)) { return cleanup(/*returnValue*/ undefined); } - var reservedDecorators_1 = ts.getReservedDecoratorsOfStructDeclaration(input, host); + var reservedDecorators_1 = ts.concatenate(ts.getReservedDecoratorsOfStructDeclaration(input, host), ts.getAnnotations(input)); + checkAnnotationVisibilityByDecorator(reservedDecorators_1); var sig = factory.createMethodDeclaration(ts.concatenateDecoratorsAndModifiers(reservedDecorators_1, ensureModifiers(input)), /*asteriskToken*/ undefined, input.name, input.questionToken, ts.inEtsStylesContext(input, host) ? undefined : ensureTypeParams(input, input.typeParameters), updateParamsList(input, input.parameters), ensureType(input, input.type), /*body*/ undefined); @@ -116037,13 +116199,14 @@ var ts; } return factory.updateHeritageClause(clause, ts.visitNodes(factory.createNodeArray(ts.filter(clause.types, function (t) { return ts.isEntityNameExpression(t.expression) || t.expression.kind === 105 /* SyntaxKind.NullKeyword */; })), visitDeclarationSubtree)); })); - var reservedDecorators = ts.getReservedDecoratorsOfEtsFile(input, host); + var reservedDecorators = ts.concatenate(ts.getReservedDecoratorsOfEtsFile(input, host), ts.getAnnotations(input)); + checkAnnotationVisibilityByDecorator(reservedDecorators); return [statement, cleanup(factory.updateClassDeclaration(input, ts.concatenateDecoratorsAndModifiers(reservedDecorators, modifiers), input.name, typeParameters, heritageClauses, members))]; // TODO: GH#18217 } else { var heritageClauses = transformHeritageClauses(input.heritageClauses); - var reservedDecorators = ts.getReservedDecoratorsOfEtsFile(input, host); - ; + var reservedDecorators = ts.concatenate(ts.getReservedDecoratorsOfEtsFile(input, host), ts.getAnnotations(input)); + checkAnnotationVisibilityByDecorator(reservedDecorators); return cleanup(factory.updateClassDeclaration(input, ts.concatenateDecoratorsAndModifiers(reservedDecorators, modifiers), input.name, typeParameters, heritageClauses, members)); } } @@ -120680,7 +120843,7 @@ var ts; // if all modifier-likes are `Modifier`, simply emit the array as modifiers. return emitModifiers(node, modifiers); } - if (ts.every(modifiers, ts.isDecorator)) { + if (ts.every(modifiers, ts.isDecoratorOrAnnotation)) { // if all modifier-likes are `Decorator`, simply emit the array as decorators. return emitDecorators(node, modifiers); } @@ -120693,7 +120856,7 @@ var ts; while (start < modifiers.length) { while (pos < modifiers.length) { var modifier = modifiers[pos]; - mode = ts.isDecorator(modifier) ? "decorators" : "modifiers"; + mode = ts.isDecoratorOrAnnotation(modifier) ? "decorators" : "modifiers"; if (lastMode === undefined) { lastMode = mode; } diff --git a/lib/typescriptServices.d.ts b/lib/typescriptServices.d.ts index a273ee24d7..0818b95377 100644 --- a/lib/typescriptServices.d.ts +++ b/lib/typescriptServices.d.ts @@ -4821,6 +4821,7 @@ declare namespace ts { function getNameOfJSDocTypedef(declaration: JSDocTypedefTag): Identifier | PrivateIdentifier | undefined; function getNameOfDeclaration(declaration: Declaration | Expression | undefined): DeclarationName | undefined; function getDecorators(node: HasDecorators): readonly Decorator[] | undefined; + function getAnnotations(node: HasDecorators): readonly Decorator[] | undefined; function getModifiers(node: HasModifiers): readonly Modifier[] | undefined; function getAllDecorators(node: Node | undefined): readonly Decorator[]; function getIllegalDecorators(node: HasIllegalDecorators): readonly Decorator[] | undefined; @@ -5114,6 +5115,7 @@ declare namespace ts { function isComputedPropertyName(node: Node): node is ComputedPropertyName; function isTypeParameterDeclaration(node: Node): node is TypeParameterDeclaration; function isParameter(node: Node): node is ParameterDeclaration; + function isDecoratorOrAnnotation(node: Node): node is Decorator; function isDecorator(node: Node): node is Decorator; function isAnnotation(node: Node): node is Annotation; function isPropertySignature(node: Node): node is PropertySignature; diff --git a/lib/typescriptServices.js b/lib/typescriptServices.js index ed6f3541fa..d80f8ed38e 100644 --- a/lib/typescriptServices.js +++ b/lib/typescriptServices.js @@ -13360,6 +13360,12 @@ var ts; } } ts.getDecorators = getDecorators; + function getAnnotations(node) { + if (ts.hasAnnotations(node)) { + return ts.filter(node.modifiers, ts.isAnnotation); + } + } + ts.getAnnotations = getAnnotations; function getModifiers(node) { if (ts.hasSyntacticModifier(node, 126975 /* ModifierFlags.Modifier */)) { return ts.filter(node.modifiers, isModifier); @@ -14113,7 +14119,7 @@ var ts; ts.isNamedClassElement = isNamedClassElement; // Type members function isModifierLike(node) { - return isModifier(node) || ts.isDecorator(node); + return isModifier(node) || ts.isDecoratorOrAnnotation(node); } ts.isModifierLike = isModifierLike; function isTypeElement(node) { @@ -29921,6 +29927,10 @@ var ts; return node.kind === 168 /* SyntaxKind.Parameter */; } ts.isParameter = isParameter; + function isDecoratorOrAnnotation(node) { + return node.kind === 169 /* SyntaxKind.Decorator */; + } + ts.isDecoratorOrAnnotation = isDecoratorOrAnnotation; function isDecorator(node) { return node.kind === 169 /* SyntaxKind.Decorator */ && node.annotationDeclaration === undefined; } @@ -47418,7 +47428,7 @@ var ts; } // Firstly, visit declarations var updatedSource = ts.factory.updateSourceFile(node, ts.visitLexicalEnvironment(node.statements, visitAnnotationsDeclarations, context)); - // Secondly, visit usage of annotations + // Secondly, visit import and usage of annotations return ts.factory.updateSourceFile(node, ts.visitLexicalEnvironment(updatedSource.statements, visitAnnotations, context)); } function visitAnnotationsDeclarations(node) { @@ -47431,13 +47441,30 @@ var ts; } function visitAnnotations(node) { switch (node.kind) { + case 279 /* SyntaxKind.ImportSpecifier */: + return visitImportSpecifier(node); case 169 /* SyntaxKind.Decorator */: return visitAnnotation(node); default: return ts.visitEachChild(node, visitAnnotations, context); } } + function visitImportSpecifier(node) { + // Return if the import has type or not refered to Annotation + if (node.isTypeOnly || !resolver.isReferredToAnnotation(node)) { + return node; + } + var magicPrefixName = addMagicPrefixToAnnotationNameIdentifier(node.name); + ts.Debug.assert(ts.isIdentifier(magicPrefixName)); + // Add magic prefix for import Annotation. For example, + // import {Anno} from "xxx" ---> import {__$$ETS_ANNOTATION$$__Anno} from "xxx" + return ts.factory.updateImportSpecifier(node, node.isTypeOnly, node.propertyName, magicPrefixName); + } function visitAnnotationDeclaration(node) { + // Add magic prefix for AnnotationDeclaration. For example, + // @interface Anno {} ---> @interface __$$ETS_ANNOTATION$$__Anno {} + var magicPrefixName = addMagicPrefixToAnnotationNameIdentifier(node.name); + ts.Debug.assert(ts.isIdentifier(magicPrefixName)); // Add explicit type annotation and initializer. For example, // @interface Anno { // a = 10 + 5 @@ -47445,7 +47472,7 @@ var ts; // // will be transformed to // - // @interface Anno { + // @interface __$$ETS_ANNOTATION$$__Anno { // a: number = 15 // } var members = node.members.map(function (node) { @@ -47453,7 +47480,7 @@ var ts; var initializer = resolver.getAnnotationPropertyEvaluatedInitializer(node); return ts.factory.updateAnnotationPropertyDeclaration(node, node.name, type, initializer); }); - return ts.factory.updateAnnotationDeclaration(node, node.modifiers, node.name, members); + return ts.factory.updateAnnotationDeclaration(node, node.modifiers, magicPrefixName, members); } function visitAnnotation(node) { if (!node.annotationDeclaration) { @@ -47471,7 +47498,7 @@ var ts; // and // // Add the magic prefix for annotation name. For example, - // @myModule.Anno({a: 10, b: "abc"}) --- > @#myModule.Anno({a: 10, b: "abc"}) + // @myModule.Anno({a: 10, b: "abc"}) --- > @myModule.__$$ETS_ANNOTATION$$__Anno({a: 10, b: "abc"}) return ts.factory.updateDecorator(node, addMagicPrefixToAnnotationNameIdentifier(addDefaultValuesIntoAnnotationObjectLiteral(node))); } function addMagicPrefixToAnnotationNameIdentifier(expr) { @@ -47480,7 +47507,7 @@ var ts; return ts.factory.createIdentifier(ts.annotationMagicNamePrefix + expr.escapedText); case 211 /* SyntaxKind.PropertyAccessExpression */: var propAccessExpr = expr; - return ts.factory.updatePropertyAccessExpression(propAccessExpr, addMagicPrefixToAnnotationNameIdentifier(propAccessExpr.expression), propAccessExpr.name); + return ts.factory.updatePropertyAccessExpression(propAccessExpr, propAccessExpr.expression, addMagicPrefixToAnnotationNameIdentifier(propAccessExpr.name)); case 213 /* SyntaxKind.CallExpression */: var callExpr = expr; return ts.factory.updateCallExpression(callExpr, addMagicPrefixToAnnotationNameIdentifier(callExpr.expression), callExpr.typeArguments, callExpr.arguments); @@ -47496,6 +47523,7 @@ var ts; for (var i = 0; i < members.length; ++i) { var member = members[i]; var initializer = resolver.getAnnotationPropertyEvaluatedInitializer(member); + ts.Debug.assert(initializer !== undefined); defaultValues[i] = ts.factory.createPropertyAssignment(member.name, initializer); } var newCallExpr = ts.factory.createCallExpression(annotation.expression, @@ -59586,6 +59614,7 @@ var ts; case 263 /* SyntaxKind.FunctionDeclaration */: case 269 /* SyntaxKind.EnumDeclaration */: case 274 /* SyntaxKind.ImportEqualsDeclaration */: + case 266 /* SyntaxKind.AnnotationDeclaration */: // external module augmentation is always visible if (ts.isExternalModuleAugmentation(node)) { return true; @@ -93370,16 +93399,132 @@ var ts; }, isImportRequiredByAugmentation: isImportRequiredByAugmentation, getAnnotationObjectLiteralEvaluatedProps: function (node) { - return getNodeLinks(node).annotationObjectLiteralEvaluatedProps; + var links = getNodeLinks(node); + if (!links.annotationObjectLiteralEvaluatedProps) { + if (!ts.isCallExpression(node.expression)) { + return undefined; + } + // let d = {} + // @Anno(d) + // class C {} + if (!node.expression.arguments || + node.expression.arguments.length !== 1 || + !ts.isObjectLiteralExpression(node.expression.arguments[0])) { + return undefined; + } + // let bar = goo() + // @Anno({foo: bar}) + // class C {} + var funcType = checkExpression(node.expression); + var apparentType = getApparentType(funcType); + if (isErrorType(apparentType)) { + return undefined; + } + var arg = node.expression.arguments[0]; + var evaluatedProps = new ts.Map(); + for (var _i = 0, _a = arg.properties; _i < _a.length; _i++) { + var prop = _a[_i]; + if (!ts.isPropertyAssignment(prop)) { + return undefined; + } + var evaluated = evaluateAnnotationPropertyConstantExpression(prop.initializer); + if (evaluated === undefined) { + return undefined; + } + evaluatedProps.set(ts.tryGetTextOfPropertyName(prop.name), evaluated); + } + var members = node.annotationDeclaration.members; + for (var _b = 0, members_9 = members; _b < members_9.length; _b++) { + var m = members_9[_b]; + var memberName = ts.tryGetTextOfPropertyName(m.name); + if (evaluatedProps.has(memberName)) { + var propValue = annotationEvaluatedValueToExpr(evaluatedProps.get(memberName), getTypeOfNode(m)); + if (links.annotationObjectLiteralEvaluatedProps === undefined) { + links.annotationObjectLiteralEvaluatedProps = new ts.Map(); + } + links.annotationObjectLiteralEvaluatedProps.set(memberName, propValue); + } + } + } + return links.annotationObjectLiteralEvaluatedProps; }, getAnnotationPropertyEvaluatedInitializer: function (node) { - return getNodeLinks(node).annotationPropertyEvaluatedInitializer; + var links = getNodeLinks(node); + if (!links.annotationPropertyEvaluatedInitializer) { + var propType = getTypeOfNode(node); + if (!isAllowedAnnotationPropertyType(propType)) { + return undefined; + } + if (node.initializer) { + var evaluated = evaluateAnnotationPropertyConstantExpression(node.initializer); + if (evaluated === undefined) { + return undefined; + } + else { + var evaluatedExpr = annotationEvaluatedValueToExpr(evaluated, getTypeOfNode(node)); + links.annotationPropertyEvaluatedInitializer = evaluatedExpr; + } + } + // Special cases for enums + if (!node.initializer) { + var initializer = addAnnotationPropertyEnumInitalizer(propType); + if (initializer) { + links.annotationPropertyEvaluatedInitializer = initializer; + } + } + } + return links.annotationPropertyEvaluatedInitializer; }, getAnnotationPropertyInferredType: function (node) { - return getNodeLinks(node).annotationPropertyInferredType; + var links = getNodeLinks(node); + if (!links.annotationPropertyInferredType) { + var propType = getTypeOfNode(node); + if (!isAllowedAnnotationPropertyType(propType)) { + return undefined; + } + links.annotationPropertyInferredType = nodeBuilder.typeToTypeNode(propType); + } + return links.annotationPropertyInferredType; }, isReferredToAnnotation: function (node) { - return getNodeLinks(node).exportOrImportRefersToAnnotation; + var links = getNodeLinks(node); + if (!links.exportOrImportRefersToAnnotation) { + var ident = undefined; + if ((ts.isExportAssignment(node))) { + switch (node.expression.kind) { + case 79 /* SyntaxKind.Identifier */: + ident = node.expression; + break; + case 211 /* SyntaxKind.PropertyAccessExpression */: + ident = node.expression; + break; + default: + return undefined; + } + if (!ident) { + return undefined; + } + var symbol = getSymbolOfNameOrPropertyAccessExpression(ident); + if (!symbol) { + return undefined; + } + if (getAllSymbolFlags(symbol) & 268435456 /* SymbolFlags.Annotation */) { + links.exportOrImportRefersToAnnotation = true; + } + } + if ((ts.isImportSpecifier(node) || ts.isExportSpecifier(node))) { + var symbol = getSymbolOfNode(node); + if (!symbol) { + return undefined; + } + var target = resolveAlias(symbol); + var targetFlags = getAllSymbolFlags(target); + if (targetFlags & 268435456 /* SymbolFlags.Annotation */) { + links.exportOrImportRefersToAnnotation = true; + } + } + } + return links.exportOrImportRefersToAnnotation; } }; function isImportRequiredByAugmentation(node) { @@ -93772,7 +93917,7 @@ var ts; var flags = 0 /* ModifierFlags.None */; for (var _i = 0, _a = node.modifiers; _i < _a.length; _i++) { var modifier = _a[_i]; - if (ts.isDecorator(modifier)) + if (ts.isDecoratorOrAnnotation(modifier)) continue; if (modifier.kind !== 147 /* SyntaxKind.ReadonlyKeyword */) { if (node.kind === 170 /* SyntaxKind.PropertySignature */ || node.kind === 173 /* SyntaxKind.MethodSignature */) { @@ -94120,7 +94265,7 @@ var ts; function nodeHasAnyModifiersExcept(node, allowedModifier) { for (var _i = 0, _a = node.modifiers; _i < _a.length; _i++) { var modifier = _a[_i]; - if (ts.isDecorator(modifier)) + if (ts.isDecoratorOrAnnotation(modifier)) continue; return modifier.kind !== allowedModifier; } @@ -98135,7 +98280,7 @@ var ts; } } function modifierVisitor(node) { - if (ts.isDecorator(node)) + if (ts.isDecoratorOrAnnotation(node)) return undefined; if (ts.modifierToFlag(node.kind) & 117086 /* ModifierFlags.TypeScriptModifier */) { return undefined; @@ -102359,8 +102504,8 @@ var ts; function generateClassElementDecorationExpressions(node, isStatic) { var members = getDecoratedClassElements(node, isStatic); var expressions; - for (var _i = 0, members_9 = members; _i < members_9.length; _i++) { - var member = members_9[_i]; + for (var _i = 0, members_10 = members; _i < members_10.length; _i++) { + var member = members_10[_i]; expressions = ts.append(expressions, generateClassElementDecorationExpression(node, member)); } return expressions; @@ -115321,6 +115466,7 @@ var ts; case 265 /* SyntaxKind.StructDeclaration */: case 268 /* SyntaxKind.TypeAliasDeclaration */: case 269 /* SyntaxKind.EnumDeclaration */: + case 266 /* SyntaxKind.AnnotationDeclaration */: return !resolver.isDeclarationVisible(node); // The following should be doing their own visibility checks based on filtering their members case 261 /* SyntaxKind.VariableDeclaration */: @@ -115543,6 +115689,21 @@ var ts; return statement; } } + function checkAnnotationVisibilityByDecorator(input) { + ts.forEach(input, function (decorator) { + if (!ts.isAnnotation(decorator)) { + return; + } + if (ts.isCallExpression(decorator.expression)) { + // @Anno({}) + checkEntityNameVisibility((decorator.expression.expression), enclosingDeclaration); + } + else if (ts.isIdentifier(decorator.expression)) { + // @Anno + checkEntityNameVisibility((decorator.expression), enclosingDeclaration); + } + }); + } function visitDeclarationSubtree(input) { if (shouldStripInternal(input)) return; @@ -115615,7 +115776,8 @@ var ts; if (ts.isPrivateIdentifier(input.name)) { return cleanup(/*returnValue*/ undefined); } - var reservedDecorators_1 = ts.getReservedDecoratorsOfStructDeclaration(input, host); + var reservedDecorators_1 = ts.concatenate(ts.getReservedDecoratorsOfStructDeclaration(input, host), ts.getAnnotations(input)); + checkAnnotationVisibilityByDecorator(reservedDecorators_1); var sig = factory.createMethodDeclaration(ts.concatenateDecoratorsAndModifiers(reservedDecorators_1, ensureModifiers(input)), /*asteriskToken*/ undefined, input.name, input.questionToken, ts.inEtsStylesContext(input, host) ? undefined : ensureTypeParams(input, input.typeParameters), updateParamsList(input, input.parameters), ensureType(input, input.type), /*body*/ undefined); @@ -116037,13 +116199,14 @@ var ts; } return factory.updateHeritageClause(clause, ts.visitNodes(factory.createNodeArray(ts.filter(clause.types, function (t) { return ts.isEntityNameExpression(t.expression) || t.expression.kind === 105 /* SyntaxKind.NullKeyword */; })), visitDeclarationSubtree)); })); - var reservedDecorators = ts.getReservedDecoratorsOfEtsFile(input, host); + var reservedDecorators = ts.concatenate(ts.getReservedDecoratorsOfEtsFile(input, host), ts.getAnnotations(input)); + checkAnnotationVisibilityByDecorator(reservedDecorators); return [statement, cleanup(factory.updateClassDeclaration(input, ts.concatenateDecoratorsAndModifiers(reservedDecorators, modifiers), input.name, typeParameters, heritageClauses, members))]; // TODO: GH#18217 } else { var heritageClauses = transformHeritageClauses(input.heritageClauses); - var reservedDecorators = ts.getReservedDecoratorsOfEtsFile(input, host); - ; + var reservedDecorators = ts.concatenate(ts.getReservedDecoratorsOfEtsFile(input, host), ts.getAnnotations(input)); + checkAnnotationVisibilityByDecorator(reservedDecorators); return cleanup(factory.updateClassDeclaration(input, ts.concatenateDecoratorsAndModifiers(reservedDecorators, modifiers), input.name, typeParameters, heritageClauses, members)); } } @@ -120680,7 +120843,7 @@ var ts; // if all modifier-likes are `Modifier`, simply emit the array as modifiers. return emitModifiers(node, modifiers); } - if (ts.every(modifiers, ts.isDecorator)) { + if (ts.every(modifiers, ts.isDecoratorOrAnnotation)) { // if all modifier-likes are `Decorator`, simply emit the array as decorators. return emitDecorators(node, modifiers); } @@ -120693,7 +120856,7 @@ var ts; while (start < modifiers.length) { while (pos < modifiers.length) { var modifier = modifiers[pos]; - mode = ts.isDecorator(modifier) ? "decorators" : "modifiers"; + mode = ts.isDecoratorOrAnnotation(modifier) ? "decorators" : "modifiers"; if (lastMode === undefined) { lastMode = mode; } diff --git a/lib/typingsInstaller.js b/lib/typingsInstaller.js index 0f22525e48..55d1ade84d 100644 --- a/lib/typingsInstaller.js +++ b/lib/typingsInstaller.js @@ -13350,6 +13350,12 @@ var ts; } } ts.getDecorators = getDecorators; + function getAnnotations(node) { + if (ts.hasAnnotations(node)) { + return ts.filter(node.modifiers, ts.isAnnotation); + } + } + ts.getAnnotations = getAnnotations; function getModifiers(node) { if (ts.hasSyntacticModifier(node, 126975 /* ModifierFlags.Modifier */)) { return ts.filter(node.modifiers, isModifier); @@ -14103,7 +14109,7 @@ var ts; ts.isNamedClassElement = isNamedClassElement; // Type members function isModifierLike(node) { - return isModifier(node) || ts.isDecorator(node); + return isModifier(node) || ts.isDecoratorOrAnnotation(node); } ts.isModifierLike = isModifierLike; function isTypeElement(node) { @@ -29911,6 +29917,10 @@ var ts; return node.kind === 168 /* SyntaxKind.Parameter */; } ts.isParameter = isParameter; + function isDecoratorOrAnnotation(node) { + return node.kind === 169 /* SyntaxKind.Decorator */; + } + ts.isDecoratorOrAnnotation = isDecoratorOrAnnotation; function isDecorator(node) { return node.kind === 169 /* SyntaxKind.Decorator */ && node.annotationDeclaration === undefined; } @@ -47408,7 +47418,7 @@ var ts; } // Firstly, visit declarations var updatedSource = ts.factory.updateSourceFile(node, ts.visitLexicalEnvironment(node.statements, visitAnnotationsDeclarations, context)); - // Secondly, visit usage of annotations + // Secondly, visit import and usage of annotations return ts.factory.updateSourceFile(node, ts.visitLexicalEnvironment(updatedSource.statements, visitAnnotations, context)); } function visitAnnotationsDeclarations(node) { @@ -47421,13 +47431,30 @@ var ts; } function visitAnnotations(node) { switch (node.kind) { + case 279 /* SyntaxKind.ImportSpecifier */: + return visitImportSpecifier(node); case 169 /* SyntaxKind.Decorator */: return visitAnnotation(node); default: return ts.visitEachChild(node, visitAnnotations, context); } } + function visitImportSpecifier(node) { + // Return if the import has type or not refered to Annotation + if (node.isTypeOnly || !resolver.isReferredToAnnotation(node)) { + return node; + } + var magicPrefixName = addMagicPrefixToAnnotationNameIdentifier(node.name); + ts.Debug.assert(ts.isIdentifier(magicPrefixName)); + // Add magic prefix for import Annotation. For example, + // import {Anno} from "xxx" ---> import {__$$ETS_ANNOTATION$$__Anno} from "xxx" + return ts.factory.updateImportSpecifier(node, node.isTypeOnly, node.propertyName, magicPrefixName); + } function visitAnnotationDeclaration(node) { + // Add magic prefix for AnnotationDeclaration. For example, + // @interface Anno {} ---> @interface __$$ETS_ANNOTATION$$__Anno {} + var magicPrefixName = addMagicPrefixToAnnotationNameIdentifier(node.name); + ts.Debug.assert(ts.isIdentifier(magicPrefixName)); // Add explicit type annotation and initializer. For example, // @interface Anno { // a = 10 + 5 @@ -47435,7 +47462,7 @@ var ts; // // will be transformed to // - // @interface Anno { + // @interface __$$ETS_ANNOTATION$$__Anno { // a: number = 15 // } var members = node.members.map(function (node) { @@ -47443,7 +47470,7 @@ var ts; var initializer = resolver.getAnnotationPropertyEvaluatedInitializer(node); return ts.factory.updateAnnotationPropertyDeclaration(node, node.name, type, initializer); }); - return ts.factory.updateAnnotationDeclaration(node, node.modifiers, node.name, members); + return ts.factory.updateAnnotationDeclaration(node, node.modifiers, magicPrefixName, members); } function visitAnnotation(node) { if (!node.annotationDeclaration) { @@ -47461,7 +47488,7 @@ var ts; // and // // Add the magic prefix for annotation name. For example, - // @myModule.Anno({a: 10, b: "abc"}) --- > @#myModule.Anno({a: 10, b: "abc"}) + // @myModule.Anno({a: 10, b: "abc"}) --- > @myModule.__$$ETS_ANNOTATION$$__Anno({a: 10, b: "abc"}) return ts.factory.updateDecorator(node, addMagicPrefixToAnnotationNameIdentifier(addDefaultValuesIntoAnnotationObjectLiteral(node))); } function addMagicPrefixToAnnotationNameIdentifier(expr) { @@ -47470,7 +47497,7 @@ var ts; return ts.factory.createIdentifier(ts.annotationMagicNamePrefix + expr.escapedText); case 211 /* SyntaxKind.PropertyAccessExpression */: var propAccessExpr = expr; - return ts.factory.updatePropertyAccessExpression(propAccessExpr, addMagicPrefixToAnnotationNameIdentifier(propAccessExpr.expression), propAccessExpr.name); + return ts.factory.updatePropertyAccessExpression(propAccessExpr, propAccessExpr.expression, addMagicPrefixToAnnotationNameIdentifier(propAccessExpr.name)); case 213 /* SyntaxKind.CallExpression */: var callExpr = expr; return ts.factory.updateCallExpression(callExpr, addMagicPrefixToAnnotationNameIdentifier(callExpr.expression), callExpr.typeArguments, callExpr.arguments); @@ -47486,6 +47513,7 @@ var ts; for (var i = 0; i < members.length; ++i) { var member = members[i]; var initializer = resolver.getAnnotationPropertyEvaluatedInitializer(member); + ts.Debug.assert(initializer !== undefined); defaultValues[i] = ts.factory.createPropertyAssignment(member.name, initializer); } var newCallExpr = ts.factory.createCallExpression(annotation.expression, @@ -59576,6 +59604,7 @@ var ts; case 263 /* SyntaxKind.FunctionDeclaration */: case 269 /* SyntaxKind.EnumDeclaration */: case 274 /* SyntaxKind.ImportEqualsDeclaration */: + case 266 /* SyntaxKind.AnnotationDeclaration */: // external module augmentation is always visible if (ts.isExternalModuleAugmentation(node)) { return true; @@ -93360,16 +93389,132 @@ var ts; }, isImportRequiredByAugmentation: isImportRequiredByAugmentation, getAnnotationObjectLiteralEvaluatedProps: function (node) { - return getNodeLinks(node).annotationObjectLiteralEvaluatedProps; + var links = getNodeLinks(node); + if (!links.annotationObjectLiteralEvaluatedProps) { + if (!ts.isCallExpression(node.expression)) { + return undefined; + } + // let d = {} + // @Anno(d) + // class C {} + if (!node.expression.arguments || + node.expression.arguments.length !== 1 || + !ts.isObjectLiteralExpression(node.expression.arguments[0])) { + return undefined; + } + // let bar = goo() + // @Anno({foo: bar}) + // class C {} + var funcType = checkExpression(node.expression); + var apparentType = getApparentType(funcType); + if (isErrorType(apparentType)) { + return undefined; + } + var arg = node.expression.arguments[0]; + var evaluatedProps = new ts.Map(); + for (var _i = 0, _a = arg.properties; _i < _a.length; _i++) { + var prop = _a[_i]; + if (!ts.isPropertyAssignment(prop)) { + return undefined; + } + var evaluated = evaluateAnnotationPropertyConstantExpression(prop.initializer); + if (evaluated === undefined) { + return undefined; + } + evaluatedProps.set(ts.tryGetTextOfPropertyName(prop.name), evaluated); + } + var members = node.annotationDeclaration.members; + for (var _b = 0, members_9 = members; _b < members_9.length; _b++) { + var m = members_9[_b]; + var memberName = ts.tryGetTextOfPropertyName(m.name); + if (evaluatedProps.has(memberName)) { + var propValue = annotationEvaluatedValueToExpr(evaluatedProps.get(memberName), getTypeOfNode(m)); + if (links.annotationObjectLiteralEvaluatedProps === undefined) { + links.annotationObjectLiteralEvaluatedProps = new ts.Map(); + } + links.annotationObjectLiteralEvaluatedProps.set(memberName, propValue); + } + } + } + return links.annotationObjectLiteralEvaluatedProps; }, getAnnotationPropertyEvaluatedInitializer: function (node) { - return getNodeLinks(node).annotationPropertyEvaluatedInitializer; + var links = getNodeLinks(node); + if (!links.annotationPropertyEvaluatedInitializer) { + var propType = getTypeOfNode(node); + if (!isAllowedAnnotationPropertyType(propType)) { + return undefined; + } + if (node.initializer) { + var evaluated = evaluateAnnotationPropertyConstantExpression(node.initializer); + if (evaluated === undefined) { + return undefined; + } + else { + var evaluatedExpr = annotationEvaluatedValueToExpr(evaluated, getTypeOfNode(node)); + links.annotationPropertyEvaluatedInitializer = evaluatedExpr; + } + } + // Special cases for enums + if (!node.initializer) { + var initializer = addAnnotationPropertyEnumInitalizer(propType); + if (initializer) { + links.annotationPropertyEvaluatedInitializer = initializer; + } + } + } + return links.annotationPropertyEvaluatedInitializer; }, getAnnotationPropertyInferredType: function (node) { - return getNodeLinks(node).annotationPropertyInferredType; + var links = getNodeLinks(node); + if (!links.annotationPropertyInferredType) { + var propType = getTypeOfNode(node); + if (!isAllowedAnnotationPropertyType(propType)) { + return undefined; + } + links.annotationPropertyInferredType = nodeBuilder.typeToTypeNode(propType); + } + return links.annotationPropertyInferredType; }, isReferredToAnnotation: function (node) { - return getNodeLinks(node).exportOrImportRefersToAnnotation; + var links = getNodeLinks(node); + if (!links.exportOrImportRefersToAnnotation) { + var ident = undefined; + if ((ts.isExportAssignment(node))) { + switch (node.expression.kind) { + case 79 /* SyntaxKind.Identifier */: + ident = node.expression; + break; + case 211 /* SyntaxKind.PropertyAccessExpression */: + ident = node.expression; + break; + default: + return undefined; + } + if (!ident) { + return undefined; + } + var symbol = getSymbolOfNameOrPropertyAccessExpression(ident); + if (!symbol) { + return undefined; + } + if (getAllSymbolFlags(symbol) & 268435456 /* SymbolFlags.Annotation */) { + links.exportOrImportRefersToAnnotation = true; + } + } + if ((ts.isImportSpecifier(node) || ts.isExportSpecifier(node))) { + var symbol = getSymbolOfNode(node); + if (!symbol) { + return undefined; + } + var target = resolveAlias(symbol); + var targetFlags = getAllSymbolFlags(target); + if (targetFlags & 268435456 /* SymbolFlags.Annotation */) { + links.exportOrImportRefersToAnnotation = true; + } + } + } + return links.exportOrImportRefersToAnnotation; } }; function isImportRequiredByAugmentation(node) { @@ -93762,7 +93907,7 @@ var ts; var flags = 0 /* ModifierFlags.None */; for (var _i = 0, _a = node.modifiers; _i < _a.length; _i++) { var modifier = _a[_i]; - if (ts.isDecorator(modifier)) + if (ts.isDecoratorOrAnnotation(modifier)) continue; if (modifier.kind !== 147 /* SyntaxKind.ReadonlyKeyword */) { if (node.kind === 170 /* SyntaxKind.PropertySignature */ || node.kind === 173 /* SyntaxKind.MethodSignature */) { @@ -94110,7 +94255,7 @@ var ts; function nodeHasAnyModifiersExcept(node, allowedModifier) { for (var _i = 0, _a = node.modifiers; _i < _a.length; _i++) { var modifier = _a[_i]; - if (ts.isDecorator(modifier)) + if (ts.isDecoratorOrAnnotation(modifier)) continue; return modifier.kind !== allowedModifier; } @@ -98125,7 +98270,7 @@ var ts; } } function modifierVisitor(node) { - if (ts.isDecorator(node)) + if (ts.isDecoratorOrAnnotation(node)) return undefined; if (ts.modifierToFlag(node.kind) & 117086 /* ModifierFlags.TypeScriptModifier */) { return undefined; @@ -102349,8 +102494,8 @@ var ts; function generateClassElementDecorationExpressions(node, isStatic) { var members = getDecoratedClassElements(node, isStatic); var expressions; - for (var _i = 0, members_9 = members; _i < members_9.length; _i++) { - var member = members_9[_i]; + for (var _i = 0, members_10 = members; _i < members_10.length; _i++) { + var member = members_10[_i]; expressions = ts.append(expressions, generateClassElementDecorationExpression(node, member)); } return expressions; @@ -115311,6 +115456,7 @@ var ts; case 265 /* SyntaxKind.StructDeclaration */: case 268 /* SyntaxKind.TypeAliasDeclaration */: case 269 /* SyntaxKind.EnumDeclaration */: + case 266 /* SyntaxKind.AnnotationDeclaration */: return !resolver.isDeclarationVisible(node); // The following should be doing their own visibility checks based on filtering their members case 261 /* SyntaxKind.VariableDeclaration */: @@ -115533,6 +115679,21 @@ var ts; return statement; } } + function checkAnnotationVisibilityByDecorator(input) { + ts.forEach(input, function (decorator) { + if (!ts.isAnnotation(decorator)) { + return; + } + if (ts.isCallExpression(decorator.expression)) { + // @Anno({}) + checkEntityNameVisibility((decorator.expression.expression), enclosingDeclaration); + } + else if (ts.isIdentifier(decorator.expression)) { + // @Anno + checkEntityNameVisibility((decorator.expression), enclosingDeclaration); + } + }); + } function visitDeclarationSubtree(input) { if (shouldStripInternal(input)) return; @@ -115605,7 +115766,8 @@ var ts; if (ts.isPrivateIdentifier(input.name)) { return cleanup(/*returnValue*/ undefined); } - var reservedDecorators_1 = ts.getReservedDecoratorsOfStructDeclaration(input, host); + var reservedDecorators_1 = ts.concatenate(ts.getReservedDecoratorsOfStructDeclaration(input, host), ts.getAnnotations(input)); + checkAnnotationVisibilityByDecorator(reservedDecorators_1); var sig = factory.createMethodDeclaration(ts.concatenateDecoratorsAndModifiers(reservedDecorators_1, ensureModifiers(input)), /*asteriskToken*/ undefined, input.name, input.questionToken, ts.inEtsStylesContext(input, host) ? undefined : ensureTypeParams(input, input.typeParameters), updateParamsList(input, input.parameters), ensureType(input, input.type), /*body*/ undefined); @@ -116027,13 +116189,14 @@ var ts; } return factory.updateHeritageClause(clause, ts.visitNodes(factory.createNodeArray(ts.filter(clause.types, function (t) { return ts.isEntityNameExpression(t.expression) || t.expression.kind === 105 /* SyntaxKind.NullKeyword */; })), visitDeclarationSubtree)); })); - var reservedDecorators = ts.getReservedDecoratorsOfEtsFile(input, host); + var reservedDecorators = ts.concatenate(ts.getReservedDecoratorsOfEtsFile(input, host), ts.getAnnotations(input)); + checkAnnotationVisibilityByDecorator(reservedDecorators); return [statement, cleanup(factory.updateClassDeclaration(input, ts.concatenateDecoratorsAndModifiers(reservedDecorators, modifiers), input.name, typeParameters, heritageClauses, members))]; // TODO: GH#18217 } else { var heritageClauses = transformHeritageClauses(input.heritageClauses); - var reservedDecorators = ts.getReservedDecoratorsOfEtsFile(input, host); - ; + var reservedDecorators = ts.concatenate(ts.getReservedDecoratorsOfEtsFile(input, host), ts.getAnnotations(input)); + checkAnnotationVisibilityByDecorator(reservedDecorators); return cleanup(factory.updateClassDeclaration(input, ts.concatenateDecoratorsAndModifiers(reservedDecorators, modifiers), input.name, typeParameters, heritageClauses, members)); } } @@ -120670,7 +120833,7 @@ var ts; // if all modifier-likes are `Modifier`, simply emit the array as modifiers. return emitModifiers(node, modifiers); } - if (ts.every(modifiers, ts.isDecorator)) { + if (ts.every(modifiers, ts.isDecoratorOrAnnotation)) { // if all modifier-likes are `Decorator`, simply emit the array as decorators. return emitDecorators(node, modifiers); } @@ -120683,7 +120846,7 @@ var ts; while (start < modifiers.length) { while (pos < modifiers.length) { var modifier = modifiers[pos]; - mode = ts.isDecorator(modifier) ? "decorators" : "modifiers"; + mode = ts.isDecoratorOrAnnotation(modifier) ? "decorators" : "modifiers"; if (lastMode === undefined) { lastMode = mode; } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0338d9ef18..3aeb6c2d77 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8805,6 +8805,7 @@ namespace ts { case SyntaxKind.FunctionDeclaration: case SyntaxKind.EnumDeclaration: case SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.AnnotationDeclaration: // external module augmentation is always visible if (isExternalModuleAugmentation(node)) { return true; @@ -45474,16 +45475,134 @@ namespace ts { }, isImportRequiredByAugmentation, getAnnotationObjectLiteralEvaluatedProps: (node: Annotation): ESMap<__String, Expression> | undefined => { - return getNodeLinks(node).annotationObjectLiteralEvaluatedProps; + let links: NodeLinks = getNodeLinks(node); + if (!links.annotationObjectLiteralEvaluatedProps) { + if (!isCallExpression(node.expression)) { + return undefined; + } + // let d = {} + // @Anno(d) + // class C {} + if (!node.expression.arguments || + node.expression.arguments.length !== 1 || + !isObjectLiteralExpression(node.expression.arguments[0])) { + return undefined; + } + + // let bar = goo() + // @Anno({foo: bar}) + // class C {} + const funcType = checkExpression(node.expression); + const apparentType = getApparentType(funcType); + if (isErrorType(apparentType)) { + return undefined; + } + + const arg: ObjectLiteralExpression = node.expression.arguments[0]; + const evaluatedProps: ESMap<__String, AnnotationConstantExpressionType> = new Map<__String, AnnotationConstantExpressionType>(); + for (const prop of arg.properties) { + if (!isPropertyAssignment(prop)) { + return undefined; + } + const evaluated: AnnotationConstantExpressionType | undefined = evaluateAnnotationPropertyConstantExpression(prop.initializer); + if (evaluated === undefined) { + return undefined; + } + evaluatedProps.set(tryGetTextOfPropertyName(prop.name)!, evaluated); + } + + const members: NodeArray = node.annotationDeclaration!.members; + for (const m of members) { + const memberName: __String | undefined = tryGetTextOfPropertyName(m.name)!; + if (evaluatedProps.has(memberName)) { + const propValue: Expression = annotationEvaluatedValueToExpr(evaluatedProps.get(memberName)!, getTypeOfNode(m))!; + if (links.annotationObjectLiteralEvaluatedProps === undefined) { + links.annotationObjectLiteralEvaluatedProps = new Map<__String, Expression>(); + } + links.annotationObjectLiteralEvaluatedProps!.set(memberName, propValue); + } + } + } + return links.annotationObjectLiteralEvaluatedProps; }, getAnnotationPropertyEvaluatedInitializer: (node: AnnotationPropertyDeclaration): Expression | undefined => { - return getNodeLinks(node).annotationPropertyEvaluatedInitializer; + let links: NodeLinks = getNodeLinks(node); + if (!links.annotationPropertyEvaluatedInitializer) { + const propType: Type = getTypeOfNode(node); + if (!isAllowedAnnotationPropertyType(propType)) { + return undefined; + } + if (node.initializer) { + const evaluated: AnnotationConstantExpressionType | undefined = evaluateAnnotationPropertyConstantExpression(node.initializer); + if (evaluated === undefined) { + return undefined; + } else { + const evaluatedExpr: Expression | undefined = annotationEvaluatedValueToExpr(evaluated, getTypeOfNode(node)); + links.annotationPropertyEvaluatedInitializer = evaluatedExpr; + } + } + + // Special cases for enums + if (!node.initializer) { + const initializer: Expression | undefined = addAnnotationPropertyEnumInitalizer(propType); + if (initializer) { + links.annotationPropertyEvaluatedInitializer = initializer; + } + } + } + return links.annotationPropertyEvaluatedInitializer; }, getAnnotationPropertyInferredType: (node: AnnotationPropertyDeclaration): TypeNode | undefined => { - return getNodeLinks(node).annotationPropertyInferredType; + let links: NodeLinks = getNodeLinks(node); + if (!links.annotationPropertyInferredType) { + const propType: Type = getTypeOfNode(node); + if (!isAllowedAnnotationPropertyType(propType)) { + return undefined; + } + links.annotationPropertyInferredType = nodeBuilder.typeToTypeNode(propType); + } + return links.annotationPropertyInferredType; }, isReferredToAnnotation: (node: ImportSpecifier | ExportSpecifier | ExportAssignment): boolean | undefined => { - return getNodeLinks(node).exportOrImportRefersToAnnotation; + let links: NodeLinks = getNodeLinks(node); + if (!links.exportOrImportRefersToAnnotation) { + let ident: Identifier | PropertyAccessExpression | undefined = undefined; + if ((isExportAssignment(node))) { + switch (node.expression.kind) { + case SyntaxKind.Identifier: + ident = node.expression as Identifier; + break; + case SyntaxKind.PropertyAccessExpression: + ident = node.expression as PropertyAccessExpression; + break; + default: + return undefined; + } + if (!ident) { + return undefined; + } + const symbol: Symbol | undefined = getSymbolOfNameOrPropertyAccessExpression(ident); + if (!symbol) { + return undefined; + } + if (getAllSymbolFlags(symbol) & SymbolFlags.Annotation) { + links.exportOrImportRefersToAnnotation = true; + } + } + + if ((isImportSpecifier(node) || isExportSpecifier(node))) { + let symbol: Symbol | undefined = getSymbolOfNode(node); + if (!symbol) { + return undefined; + } + const target: Symbol = resolveAlias(symbol); + const targetFlags: SymbolFlags = getAllSymbolFlags(target); + if (targetFlags & SymbolFlags.Annotation) { + links.exportOrImportRefersToAnnotation = true; + } + } + } + return links.exportOrImportRefersToAnnotation; } }; @@ -45888,7 +46007,7 @@ namespace ts { let lastStatic: Node | undefined, lastDeclare: Node | undefined, lastAsync: Node | undefined, lastOverride: Node | undefined; let flags = ModifierFlags.None; for (const modifier of node.modifiers!) { - if (isDecorator(modifier)) continue; + if (isDecoratorOrAnnotation(modifier)) continue; if (modifier.kind !== SyntaxKind.ReadonlyKeyword) { if (node.kind === SyntaxKind.PropertySignature || node.kind === SyntaxKind.MethodSignature) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_type_member, tokenToString(modifier.kind)); @@ -46250,7 +46369,7 @@ namespace ts { function nodeHasAnyModifiersExcept(node: HasModifiers, allowedModifier: SyntaxKind): boolean { for (const modifier of node.modifiers!) { - if (isDecorator(modifier)) continue; + if (isDecoratorOrAnnotation(modifier)) continue; return modifier.kind !== allowedModifier; } return false; diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 0580988630..a0533983c5 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -4341,7 +4341,7 @@ namespace ts { return emitModifiers(node, modifiers as NodeArray); } - if (every(modifiers, isDecorator)) { + if (every(modifiers, isDecoratorOrAnnotation)) { // if all modifier-likes are `Decorator`, simply emit the array as decorators. return emitDecorators(node, modifiers as NodeArray); } @@ -4356,7 +4356,7 @@ namespace ts { while (start < modifiers.length) { while (pos < modifiers.length) { const modifier = modifiers[pos]; - mode = isDecorator(modifier) ? "decorators" : "modifiers"; + mode = isDecoratorOrAnnotation(modifier) ? "decorators" : "modifiers"; if (lastMode === undefined) { lastMode = mode; } diff --git a/src/compiler/factory/nodeTests.ts b/src/compiler/factory/nodeTests.ts index d1cdf297d4..5747108f2f 100644 --- a/src/compiler/factory/nodeTests.ts +++ b/src/compiler/factory/nodeTests.ts @@ -175,6 +175,10 @@ namespace ts { return node.kind === SyntaxKind.Parameter; } + export function isDecoratorOrAnnotation(node: Node): node is Decorator { + return node.kind === SyntaxKind.Decorator; + } + export function isDecorator(node: Node): node is Decorator { return node.kind === SyntaxKind.Decorator && (node as Decorator).annotationDeclaration === undefined; } diff --git a/src/compiler/ohApi.ts b/src/compiler/ohApi.ts index 82c6809c37..ce12ce60f7 100644 --- a/src/compiler/ohApi.ts +++ b/src/compiler/ohApi.ts @@ -415,7 +415,7 @@ namespace ts { // Firstly, visit declarations const updatedSource = factory.updateSourceFile(node, visitLexicalEnvironment(node.statements, visitAnnotationsDeclarations, context)); - // Secondly, visit usage of annotations + // Secondly, visit import and usage of annotations return factory.updateSourceFile( node, visitLexicalEnvironment(updatedSource.statements, visitAnnotations, context)); @@ -432,6 +432,8 @@ namespace ts { function visitAnnotations(node: Node): VisitResult { switch (node.kind) { + case SyntaxKind.ImportSpecifier: + return visitImportSpecifier(node); case SyntaxKind.Decorator: return visitAnnotation(node); default: @@ -439,7 +441,23 @@ namespace ts { } } + function visitImportSpecifier(node: ImportSpecifier): VisitResult { + // Return if the import has type or not refered to Annotation + if (node.isTypeOnly || !resolver.isReferredToAnnotation(node)) { + return node; + } + const magicPrefixName = addMagicPrefixToAnnotationNameIdentifier(node.name); + Debug.assert(isIdentifier(magicPrefixName)); + // Add magic prefix for import Annotation. For example, + // import {Anno} from "xxx" ---> import {__$$ETS_ANNOTATION$$__Anno} from "xxx" + return factory.updateImportSpecifier(node, node.isTypeOnly, node.propertyName, magicPrefixName); + } + function visitAnnotationDeclaration(node: AnnotationDeclaration): VisitResult { + // Add magic prefix for AnnotationDeclaration. For example, + // @interface Anno {} ---> @interface __$$ETS_ANNOTATION$$__Anno {} + const magicPrefixName = addMagicPrefixToAnnotationNameIdentifier(node.name); + Debug.assert(isIdentifier(magicPrefixName)); // Add explicit type annotation and initializer. For example, // @interface Anno { // a = 10 + 5 @@ -447,7 +465,7 @@ namespace ts { // // will be transformed to // - // @interface Anno { + // @interface __$$ETS_ANNOTATION$$__Anno { // a: number = 15 // } const members = node.members.map((node: AnnotationPropertyDeclaration) => { @@ -456,7 +474,7 @@ namespace ts { return factory.updateAnnotationPropertyDeclaration(node, node.name, type, initializer); }); - return factory.updateAnnotationDeclaration(node, node.modifiers, node.name, members); + return factory.updateAnnotationDeclaration(node, node.modifiers, magicPrefixName , members); } function visitAnnotation(node: Annotation): VisitResult { @@ -475,7 +493,7 @@ namespace ts { // and // // Add the magic prefix for annotation name. For example, - // @myModule.Anno({a: 10, b: "abc"}) --- > @#myModule.Anno({a: 10, b: "abc"}) + // @myModule.Anno({a: 10, b: "abc"}) --- > @myModule.__$$ETS_ANNOTATION$$__Anno({a: 10, b: "abc"}) return factory.updateDecorator( node, addMagicPrefixToAnnotationNameIdentifier( @@ -493,9 +511,8 @@ namespace ts { const propAccessExpr = expr as PropertyAccessExpression; return factory.updatePropertyAccessExpression( propAccessExpr, - addMagicPrefixToAnnotationNameIdentifier(propAccessExpr.expression), - propAccessExpr.name - + propAccessExpr.expression, + addMagicPrefixToAnnotationNameIdentifier(propAccessExpr.name) as Identifier ); case SyntaxKind.CallExpression: const callExpr = expr as CallExpression; @@ -518,6 +535,7 @@ namespace ts { for (let i = 0; i < members.length; ++i) { const member = members[i] as AnnotationPropertyDeclaration; const initializer = resolver.getAnnotationPropertyEvaluatedInitializer(member); + Debug.assert(initializer !== undefined); defaultValues[i] = factory.createPropertyAssignment(member.name, initializer!); } const newCallExpr = factory.createCallExpression( diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index c6534d90f5..a321b6dcae 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -606,6 +606,7 @@ namespace ts { case SyntaxKind.StructDeclaration: case SyntaxKind.TypeAliasDeclaration: case SyntaxKind.EnumDeclaration: + case SyntaxKind.AnnotationDeclaration: return !resolver.isDeclarationVisible(node); // The following should be doing their own visibility checks based on filtering their members case SyntaxKind.VariableDeclaration: @@ -881,6 +882,21 @@ namespace ts { } } + function checkAnnotationVisibilityByDecorator(input: readonly Decorator[]): void { + forEach(input, (decorator) => { + if (!isAnnotation(decorator)) { + return; + } + if (isCallExpression(decorator.expression)) { + // @Anno({}) + checkEntityNameVisibility((decorator.expression.expression) as Identifier, enclosingDeclaration); + } else if (isIdentifier(decorator.expression)) { + // @Anno + checkEntityNameVisibility((decorator.expression) as Identifier, enclosingDeclaration); + } + }); + } + function visitDeclarationSubtree(input: Node): VisitResult { if (shouldStripInternal(input)) return; if (isDeclaration(input)) { @@ -964,8 +980,8 @@ namespace ts { if (isPrivateIdentifier(input.name)) { return cleanup(/*returnValue*/ undefined); } - let reservedDecorators = getReservedDecoratorsOfStructDeclaration(input, host); - + let reservedDecorators = concatenate(getReservedDecoratorsOfStructDeclaration(input, host), getAnnotations(input)); + checkAnnotationVisibilityByDecorator(reservedDecorators); const sig = factory.createMethodDeclaration( concatenateDecoratorsAndModifiers(reservedDecorators, ensureModifiers(input)), /*asteriskToken*/ undefined, @@ -1540,7 +1556,8 @@ namespace ts { } return factory.updateHeritageClause(clause, visitNodes(factory.createNodeArray(filter(clause.types, t => isEntityNameExpression(t.expression) || t.expression.kind === SyntaxKind.NullKeyword)), visitDeclarationSubtree)); })); - let reservedDecorators = getReservedDecoratorsOfEtsFile(input, host); + let reservedDecorators = concatenate(getReservedDecoratorsOfEtsFile(input, host), getAnnotations(input)); + checkAnnotationVisibilityByDecorator(reservedDecorators); return [statement, cleanup(factory.updateClassDeclaration( input, @@ -1553,8 +1570,8 @@ namespace ts { } else { const heritageClauses = transformHeritageClauses(input.heritageClauses); - let reservedDecorators = getReservedDecoratorsOfEtsFile(input, host);; - + let reservedDecorators = concatenate(getReservedDecoratorsOfEtsFile(input, host), getAnnotations(input)); + checkAnnotationVisibilityByDecorator(reservedDecorators); return cleanup(factory.updateClassDeclaration( input, concatenateDecoratorsAndModifiers(reservedDecorators, modifiers), diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 5f70a357c8..00e461e3e8 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -363,7 +363,7 @@ namespace ts { } function modifierVisitor(node: Node): VisitResult { - if (isDecorator(node)) return undefined; + if (isDecoratorOrAnnotation(node)) return undefined; if (modifierToFlag(node.kind) & ModifierFlags.TypeScriptModifier) { return undefined; } diff --git a/src/compiler/utilitiesPublic.ts b/src/compiler/utilitiesPublic.ts index 7ac4421775..5ebf86e127 100644 --- a/src/compiler/utilitiesPublic.ts +++ b/src/compiler/utilitiesPublic.ts @@ -651,6 +651,12 @@ namespace ts { } } + export function getAnnotations(node: HasDecorators): readonly Decorator[] | undefined { + if (hasAnnotations(node)) { + return filter(node.modifiers, isAnnotation); + } + } + export function getModifiers(node: HasModifiers): readonly Modifier[] | undefined { if (hasSyntacticModifier(node, ModifierFlags.Modifier)) { return filter(node.modifiers, isModifier); @@ -1421,7 +1427,7 @@ namespace ts { // Type members export function isModifierLike(node: Node): node is ModifierLike { - return isModifier(node) || isDecorator(node); + return isModifier(node) || isDecoratorOrAnnotation(node); } export function isTypeElement(node: Node): node is TypeElement { diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index b86d15474f..463b30f132 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -4821,6 +4821,7 @@ declare namespace ts { function getNameOfJSDocTypedef(declaration: JSDocTypedefTag): Identifier | PrivateIdentifier | undefined; function getNameOfDeclaration(declaration: Declaration | Expression | undefined): DeclarationName | undefined; function getDecorators(node: HasDecorators): readonly Decorator[] | undefined; + function getAnnotations(node: HasDecorators): readonly Decorator[] | undefined; function getModifiers(node: HasModifiers): readonly Modifier[] | undefined; function getAllDecorators(node: Node | undefined): readonly Decorator[]; function getIllegalDecorators(node: HasIllegalDecorators): readonly Decorator[] | undefined; @@ -5114,6 +5115,7 @@ declare namespace ts { function isComputedPropertyName(node: Node): node is ComputedPropertyName; function isTypeParameterDeclaration(node: Node): node is TypeParameterDeclaration; function isParameter(node: Node): node is ParameterDeclaration; + function isDecoratorOrAnnotation(node: Node): node is Decorator; function isDecorator(node: Node): node is Decorator; function isAnnotation(node: Node): node is Annotation; function isPropertySignature(node: Node): node is PropertySignature; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 6a74eb1412..440f35c680 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -4821,6 +4821,7 @@ declare namespace ts { function getNameOfJSDocTypedef(declaration: JSDocTypedefTag): Identifier | PrivateIdentifier | undefined; function getNameOfDeclaration(declaration: Declaration | Expression | undefined): DeclarationName | undefined; function getDecorators(node: HasDecorators): readonly Decorator[] | undefined; + function getAnnotations(node: HasDecorators): readonly Decorator[] | undefined; function getModifiers(node: HasModifiers): readonly Modifier[] | undefined; function getAllDecorators(node: Node | undefined): readonly Decorator[]; function getIllegalDecorators(node: HasIllegalDecorators): readonly Decorator[] | undefined; @@ -5114,6 +5115,7 @@ declare namespace ts { function isComputedPropertyName(node: Node): node is ComputedPropertyName; function isTypeParameterDeclaration(node: Node): node is TypeParameterDeclaration; function isParameter(node: Node): node is ParameterDeclaration; + function isDecoratorOrAnnotation(node: Node): node is Decorator; function isDecorator(node: Node): node is Decorator; function isAnnotation(node: Node): node is Annotation; function isPropertySignature(node: Node): node is PropertySignature; -- Gitee