From 711c2dd2f212319c9edf4d3e98c94b7bfa4ee4da Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Tue, 15 Aug 2017 09:14:53 -0700 Subject: [PATCH 1/5] Use NodeFlags to detect nodes in ambient contexts instead of climbing ancestors --- src/compiler/binder.ts | 14 ++-- src/compiler/checker.ts | 82 +++++++++---------- src/compiler/parser.ts | 57 +++++++++---- src/compiler/types.ts | 3 +- src/compiler/utilities.ts | 10 --- src/harness/unittests/incrementalParser.ts | 6 +- src/services/breakpoints.ts | 3 +- src/services/refactors/extractMethod.ts | 2 +- src/services/utilities.ts | 2 +- .../parserConstructorDeclaration4.errors.txt | 5 +- ...rserMemberAccessorDeclaration11.errors.txt | 5 +- ...arserMemberFunctionDeclaration5.errors.txt | 5 +- 12 files changed, 104 insertions(+), 90 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index a7e94da09d995..0bd921e5fce4d 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1551,7 +1551,7 @@ namespace ts { function setExportContextFlag(node: ModuleDeclaration | SourceFile) { // A declaration source file or ambient module declaration that contains no export declarations (but possibly regular // declarations with export modifiers) is an export context in which declarations are implicitly exported. - if (isInAmbientContext(node) && !hasExportDeclarations(node)) { + if (node.flags & NodeFlags.Ambient && !hasExportDeclarations(node)) { node.flags |= NodeFlags.ExportContext; } else { @@ -1724,7 +1724,7 @@ namespace ts { node.originalKeywordKind >= SyntaxKind.FirstFutureReservedWord && node.originalKeywordKind <= SyntaxKind.LastFutureReservedWord && !isIdentifierName(node) && - !isInAmbientContext(node)) { + !(node.flags & NodeFlags.Ambient)) { // Report error only if there are no parse errors in file if (!file.parseDiagnostics.length) { @@ -2480,7 +2480,7 @@ namespace ts { } function bindParameter(node: ParameterDeclaration) { - if (inStrictMode && !isInAmbientContext(node)) { + if (inStrictMode && !(node.flags & NodeFlags.Ambient)) { // It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a // strict mode FunctionLikeDeclaration or FunctionExpression(13.1) checkStrictModeEvalOrArguments(node, node.name); @@ -2502,7 +2502,7 @@ namespace ts { } function bindFunctionDeclaration(node: FunctionDeclaration) { - if (!file.isDeclarationFile && !isInAmbientContext(node)) { + if (!file.isDeclarationFile && !(node.flags & NodeFlags.Ambient)) { if (isAsyncFunction(node)) { emitFlags |= NodeFlags.HasAsyncFunctions; } @@ -2519,7 +2519,7 @@ namespace ts { } function bindFunctionExpression(node: FunctionExpression) { - if (!file.isDeclarationFile && !isInAmbientContext(node)) { + if (!file.isDeclarationFile && !(node.flags & NodeFlags.Ambient)) { if (isAsyncFunction(node)) { emitFlags |= NodeFlags.HasAsyncFunctions; } @@ -2533,7 +2533,7 @@ namespace ts { } function bindPropertyOrMethodOrAccessor(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) { - if (!file.isDeclarationFile && !isInAmbientContext(node) && isAsyncFunction(node)) { + if (!file.isDeclarationFile && !(node.flags & NodeFlags.Ambient) && isAsyncFunction(node)) { emitFlags |= NodeFlags.HasAsyncFunctions; } @@ -2582,7 +2582,7 @@ namespace ts { // On the other side we do want to report errors on non-initialized 'lets' because of TDZ const reportUnreachableCode = !options.allowUnreachableCode && - !isInAmbientContext(node) && + !(node.flags & NodeFlags.Ambient) && ( node.kind !== SyntaxKind.VariableStatement || getCombinedNodeFlags((node).declarationList) & NodeFlags.BlockScoped || diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4481531b5982d..5fb86e12dabba 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -652,7 +652,7 @@ namespace ts { else { // find a module that about to be augmented // do not validate names of augmentations that are defined in ambient context - const moduleNotFoundError = !isInAmbientContext(moduleName.parent.parent) + const moduleNotFoundError = !(moduleName.parent.parent.flags & NodeFlags.Ambient) ? Diagnostics.Invalid_module_name_in_augmentation_module_0_cannot_be_found : undefined; let mainModule = resolveExternalModuleNameWorker(moduleName, moduleName, moduleNotFoundError, /*isForAugmentation*/ true); @@ -756,7 +756,7 @@ namespace ts { if ((modulekind && (declarationFile.externalModuleIndicator || useFile.externalModuleIndicator)) || (!compilerOptions.outFile && !compilerOptions.out) || isInTypeQuery(usage) || - isInAmbientContext(declaration)) { + declaration.flags & NodeFlags.Ambient) { // nodes are in different files and order cannot be determined return true; } @@ -1309,7 +1309,7 @@ namespace ts { Debug.assert(declaration !== undefined, "Declaration to checkResolvedBlockScopedVariable is undefined"); - if (!isInAmbientContext(declaration) && !isBlockScopedNameDeclaredBeforeUse(declaration, errorLocation)) { + if (!(declaration.flags & NodeFlags.Ambient) && !isBlockScopedNameDeclaredBeforeUse(declaration, errorLocation)) { if (result.flags & SymbolFlags.BlockScopedVariable) { error(errorLocation, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, declarationNameToString(getNameOfDeclaration(declaration))); } @@ -3886,7 +3886,7 @@ namespace ts { const parent = getDeclarationContainer(node); // If the node is not exported or it is not ambient module element (except import declaration) if (!(getCombinedModifierFlags(node) & ModifierFlags.Export) && - !(node.kind !== SyntaxKind.ImportEqualsDeclaration && parent.kind !== SyntaxKind.SourceFile && isInAmbientContext(parent))) { + !(node.kind !== SyntaxKind.ImportEqualsDeclaration && parent.kind !== SyntaxKind.SourceFile && parent.flags & NodeFlags.Ambient)) { return isGlobalSourceFile(parent); } // Exported members/ambient module elements (exception import declaration) are visible if parent is visible @@ -4269,7 +4269,7 @@ namespace ts { if ((noImplicitAny || isInJavaScriptFile(declaration)) && declaration.kind === SyntaxKind.VariableDeclaration && !isBindingPattern(declaration.name) && - !(getCombinedModifierFlags(declaration) & ModifierFlags.Export) && !isInAmbientContext(declaration)) { + !(getCombinedModifierFlags(declaration) & ModifierFlags.Export) && !(declaration.flags & NodeFlags.Ambient)) { // If --noImplicitAny is on or the declaration is in a Javascript file, // use control flow tracked 'any' type for non-ambient, non-exported var or let variables with no // initializer or a 'null' or 'undefined' initializer. @@ -5128,7 +5128,7 @@ namespace ts { function isLiteralEnumMember(member: EnumMember) { const expr = member.initializer; if (!expr) { - return !isInAmbientContext(member); + return !(member.flags & NodeFlags.Ambient); } switch (expr.kind) { case SyntaxKind.StringLiteral: @@ -12269,7 +12269,7 @@ namespace ts { const assumeInitialized = isParameter || isAlias || isOuterVariable || type !== autoType && type !== autoArrayType && (!strictNullChecks || (type.flags & TypeFlags.Any) !== 0 || isInTypeQuery(node) || node.parent.kind === SyntaxKind.ExportSpecifier) || node.parent.kind === SyntaxKind.NonNullExpression || - isInAmbientContext(declaration); + declaration.flags & NodeFlags.Ambient; const initialType = assumeInitialized ? (isParameter ? removeOptionalityFromDeclaredType(type, getRootDeclaration(declaration) as VariableLikeDeclaration) : type) : type === autoType || type === autoArrayType ? undefinedType : getNullableType(type, TypeFlags.Undefined); @@ -14631,7 +14631,7 @@ namespace ts { } if (prop.valueDeclaration.kind === SyntaxKind.ClassDeclaration && node.parent && node.parent.kind !== SyntaxKind.TypeReference && - !isInAmbientContext(prop.valueDeclaration) && + !(prop.valueDeclaration.flags & NodeFlags.Ambient) && !isBlockScopedNameDeclaredBeforeUse(prop.valueDeclaration, right)) { error(right, Diagnostics.Class_0_used_before_its_declaration, unescapeLeadingUnderscores(right.escapedText)); } @@ -16484,7 +16484,7 @@ namespace ts { if (targetDeclarationKind !== SyntaxKind.Unknown) { const decl = getDeclarationOfKind(resolvedRequire, targetDeclarationKind); // function/variable declaration should be ambient - return isInAmbientContext(decl); + return decl.flags & NodeFlags.Ambient; } return false; } @@ -18617,7 +18617,7 @@ namespace ts { checkDecorators(node); checkSignatureDeclaration(node); if (node.kind === SyntaxKind.GetAccessor) { - if (!isInAmbientContext(node) && nodeIsPresent(node.body) && (node.flags & NodeFlags.HasImplicitReturn)) { + if (!(node.flags & NodeFlags.Ambient) && nodeIsPresent(node.body) && (node.flags & NodeFlags.HasImplicitReturn)) { if (!(node.flags & NodeFlags.HasExplicitReturn)) { error(node.name, Diagnostics.A_get_accessor_must_return_a_value); } @@ -18793,7 +18793,7 @@ namespace ts { } function isPrivateWithinAmbient(node: Node): boolean { - return hasModifier(node, ModifierFlags.Private) && isInAmbientContext(node); + return hasModifier(node, ModifierFlags.Private) && !!(node.flags & NodeFlags.Ambient); } function getEffectiveDeclarationFlags(n: Node, flagsToCheck: ModifierFlags): ModifierFlags { @@ -18804,7 +18804,7 @@ namespace ts { if (n.parent.kind !== SyntaxKind.InterfaceDeclaration && n.parent.kind !== SyntaxKind.ClassDeclaration && n.parent.kind !== SyntaxKind.ClassExpression && - isInAmbientContext(n)) { + n.flags & NodeFlags.Ambient) { if (!(flags & ModifierFlags.Ambient)) { // It is nested in an ambient context, which means it is automatically exported flags |= ModifierFlags.Export; @@ -18943,7 +18943,7 @@ namespace ts { let multipleConstructorImplementation = false; for (const current of declarations) { const node = current; - const inAmbientContext = isInAmbientContext(node); + const inAmbientContext = node.flags & NodeFlags.Ambient; const inAmbientContextOrInterface = node.parent.kind === SyntaxKind.InterfaceDeclaration || node.parent.kind === SyntaxKind.TypeLiteral || inAmbientContext; if (inAmbientContextOrInterface) { // check if declarations are consecutive only if they are non-ambient @@ -19754,7 +19754,7 @@ namespace ts { } function checkUnusedLocalsAndParameters(node: Node): void { - if (node.parent.kind !== SyntaxKind.InterfaceDeclaration && noUnusedIdentifiers && !isInAmbientContext(node)) { + if (node.parent.kind !== SyntaxKind.InterfaceDeclaration && noUnusedIdentifiers && !(node.flags & NodeFlags.Ambient)) { node.locals.forEach(local => { if (!local.isReferenced) { if (local.valueDeclaration && getRootDeclaration(local.valueDeclaration).kind === SyntaxKind.Parameter) { @@ -19805,7 +19805,7 @@ namespace ts { } function checkUnusedClassMembers(node: ClassDeclaration | ClassExpression): void { - if (compilerOptions.noUnusedLocals && !isInAmbientContext(node)) { + if (compilerOptions.noUnusedLocals && !(node.flags & NodeFlags.Ambient)) { if (node.members) { for (const member of node.members) { if (member.kind === SyntaxKind.MethodDeclaration || member.kind === SyntaxKind.PropertyDeclaration) { @@ -19826,7 +19826,7 @@ namespace ts { } function checkUnusedTypeParameters(node: ClassDeclaration | ClassExpression | FunctionDeclaration | MethodDeclaration | FunctionExpression | ArrowFunction | ConstructorDeclaration | SignatureDeclaration | InterfaceDeclaration | TypeAliasDeclaration) { - if (compilerOptions.noUnusedLocals && !isInAmbientContext(node)) { + if (compilerOptions.noUnusedLocals && !(node.flags & NodeFlags.Ambient)) { if (node.typeParameters) { // Only report errors on the last declaration for the type parameter container; // this ensures that all uses have been accounted for. @@ -19845,7 +19845,7 @@ namespace ts { } function checkUnusedModuleMembers(node: ModuleDeclaration | SourceFile): void { - if (compilerOptions.noUnusedLocals && !isInAmbientContext(node)) { + if (compilerOptions.noUnusedLocals && !(node.flags & NodeFlags.Ambient)) { node.locals.forEach(local => { if (!local.isReferenced && !local.exportSymbol) { for (const declaration of local.declarations) { @@ -19871,7 +19871,7 @@ namespace ts { function checkCollisionWithArgumentsInGeneratedCode(node: SignatureDeclaration) { // no rest parameters \ declaration context \ overload - no codegen impact - if (!hasDeclaredRestParameter(node) || isInAmbientContext(node) || nodeIsMissing((node).body)) { + if (!hasDeclaredRestParameter(node) || node.flags & NodeFlags.Ambient || nodeIsMissing((node).body)) { return; } @@ -19897,7 +19897,7 @@ namespace ts { return false; } - if (isInAmbientContext(node)) { + if (node.flags & NodeFlags.Ambient) { // ambient context - no codegen impact return false; } @@ -19962,7 +19962,7 @@ namespace ts { // bubble up and find containing type const enclosingClass = getContainingClass(node); // if containing type was not found or it is ambient - exit (no codegen) - if (!enclosingClass || isInAmbientContext(enclosingClass)) { + if (!enclosingClass || enclosingClass.flags & NodeFlags.Ambient) { return; } @@ -21262,7 +21262,7 @@ namespace ts { checkClassForDuplicateDeclarations(node); // Only check for reserved static identifiers on non-ambient context. - if (!isInAmbientContext(node)) { + if (!(node.flags & NodeFlags.Ambient)) { checkClassForStaticPropertyNameConflicts(node); } @@ -21568,7 +21568,7 @@ namespace ts { } // In ambient enum declarations that specify no const modifier, enum member declarations that omit // a value are considered computed members (as opposed to having auto-incremented values). - if (isInAmbientContext(member.parent) && !isConst(member.parent)) { + if (member.parent.flags & NodeFlags.Ambient && !isConst(member.parent)) { return undefined; } // If the member declaration specifies no value, the member is considered a constant enum member. @@ -21601,7 +21601,7 @@ namespace ts { else if (isConstEnum) { error(initializer, Diagnostics.In_const_enum_declarations_member_initializer_must_be_constant_expression); } - else if (isInAmbientContext(member.parent)) { + else if (member.parent.flags & NodeFlags.Ambient) { error(initializer, Diagnostics.In_ambient_enum_declarations_member_initializer_must_be_constant_expression); } else { @@ -21714,7 +21714,7 @@ namespace ts { computeEnumMemberValues(node); const enumIsConst = isConst(node); - if (compilerOptions.isolatedModules && enumIsConst && isInAmbientContext(node)) { + if (compilerOptions.isolatedModules && enumIsConst && node.flags & NodeFlags.Ambient) { error(node.name, Diagnostics.Ambient_const_enums_are_not_allowed_when_the_isolatedModules_flag_is_provided); } @@ -21766,7 +21766,7 @@ namespace ts { for (const declaration of declarations) { if ((declaration.kind === SyntaxKind.ClassDeclaration || (declaration.kind === SyntaxKind.FunctionDeclaration && nodeIsPresent((declaration).body))) && - !isInAmbientContext(declaration)) { + !(declaration.flags & NodeFlags.Ambient)) { return declaration; } } @@ -21791,7 +21791,7 @@ namespace ts { if (produceDiagnostics) { // Grammar checking const isGlobalAugmentation = isGlobalScopeAugmentation(node); - const inAmbientContext = isInAmbientContext(node); + const inAmbientContext = node.flags & NodeFlags.Ambient; if (isGlobalAugmentation && !inAmbientContext) { error(node.name, Diagnostics.Augmentations_for_the_global_scope_should_have_declare_modifier_unless_they_appear_in_already_ambient_context); } @@ -22010,7 +22010,7 @@ namespace ts { if (compilerOptions.isolatedModules && node.kind === SyntaxKind.ExportSpecifier && !(target.flags & SymbolFlags.Value) - && !isInAmbientContext(node)) { + && !(node.flags & NodeFlags.Ambient)) { error(node, Diagnostics.Cannot_re_export_a_type_when_the_isolatedModules_flag_is_provided); } } @@ -22077,7 +22077,7 @@ namespace ts { } } else { - if (modulekind === ModuleKind.ES2015 && !isInAmbientContext(node)) { + if (modulekind === ModuleKind.ES2015 && !((node as ImportEqualsDeclaration).flags & NodeFlags.Ambient)) { // Import equals declaration is deprecated in es6 or above grammarErrorOnNode(node, Diagnostics.Import_assignment_cannot_be_used_when_targeting_ECMAScript_2015_modules_Consider_using_import_Asterisk_as_ns_from_mod_import_a_from_mod_import_d_from_mod_or_another_module_format_instead); } @@ -22103,7 +22103,7 @@ namespace ts { const inAmbientExternalModule = node.parent.kind === SyntaxKind.ModuleBlock && isAmbientModule(node.parent.parent); const inAmbientNamespaceDeclaration = !inAmbientExternalModule && node.parent.kind === SyntaxKind.ModuleBlock && - !node.moduleSpecifier && isInAmbientContext(node); + !node.moduleSpecifier && node.flags & NodeFlags.Ambient; if (node.parent.kind !== SyntaxKind.SourceFile && !inAmbientExternalModule && !inAmbientNamespaceDeclaration) { error(node, Diagnostics.Export_declarations_are_not_permitted_in_a_namespace); } @@ -22176,7 +22176,7 @@ namespace ts { checkExternalModuleExports(container); - if (node.isExportEquals && !isInAmbientContext(node)) { + if (node.isExportEquals && !(node.flags & NodeFlags.Ambient)) { if (modulekind === ModuleKind.ES2015) { // export assignment is not supported in es6 modules grammarErrorOnNode(node, Diagnostics.Export_assignment_cannot_be_used_when_targeting_ECMAScript_2015_modules_Consider_using_export_default_or_another_module_format_instead); @@ -23780,7 +23780,7 @@ namespace ts { function checkExternalEmitHelpers(location: Node, helpers: ExternalEmitHelpers) { if ((requestedExternalEmitHelpers & helpers) !== helpers && compilerOptions.importHelpers) { const sourceFile = getSourceFileOfNode(location); - if (isEffectiveExternalModule(sourceFile, compilerOptions) && !isInAmbientContext(location)) { + if (isEffectiveExternalModule(sourceFile, compilerOptions) && !(location.flags & NodeFlags.Ambient)) { const helpersModule = resolveHelpersModule(sourceFile, location); if (helpersModule !== unknownSymbol) { const uncheckedHelpers = helpers & ~requestedExternalEmitHelpers; @@ -23988,7 +23988,7 @@ namespace ts { else if (node.kind === SyntaxKind.Parameter) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_parameter, "declare"); } - else if (isInAmbientContext(node.parent) && node.parent.kind === SyntaxKind.ModuleBlock) { + else if ((node.parent.flags & NodeFlags.Ambient) && node.parent.kind === SyntaxKind.ModuleBlock) { return grammarErrorOnNode(modifier, Diagnostics.A_declare_modifier_cannot_be_used_in_an_already_ambient_context); } flags |= ModifierFlags.Ambient; @@ -24024,7 +24024,7 @@ namespace ts { if (flags & ModifierFlags.Async) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "async"); } - else if (flags & ModifierFlags.Ambient || isInAmbientContext(node.parent)) { + else if (flags & ModifierFlags.Ambient || node.parent.flags & NodeFlags.Ambient) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_in_an_ambient_context, "async"); } else if (node.kind === SyntaxKind.Parameter) { @@ -24375,7 +24375,7 @@ namespace ts { node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.FunctionExpression || node.kind === SyntaxKind.MethodDeclaration); - if (isInAmbientContext(node)) { + if (node.flags & NodeFlags.Ambient) { return grammarErrorOnNode(node.asteriskToken, Diagnostics.Generators_are_not_allowed_in_an_ambient_context); } if (!node.body) { @@ -24562,7 +24562,7 @@ namespace ts { if (languageVersion < ScriptTarget.ES5) { return grammarErrorOnNode(accessor.name, Diagnostics.Accessors_are_only_available_when_targeting_ECMAScript_5_and_higher); } - else if (isInAmbientContext(accessor)) { + else if (accessor.flags & NodeFlags.Ambient) { return grammarErrorOnNode(accessor.name, Diagnostics.An_accessor_cannot_be_declared_in_an_ambient_context); } else if (accessor.body === undefined && !hasModifier(accessor, ModifierFlags.Abstract)) { @@ -24641,7 +24641,7 @@ namespace ts { // However, property declarations disallow computed names in general, // and accessors are not allowed in ambient contexts in general, // so this error only really matters for methods. - if (isInAmbientContext(node)) { + if (node.flags & NodeFlags.Ambient) { return checkGrammarForNonSymbolComputedProperty(node.name, Diagnostics.A_computed_property_name_in_an_ambient_context_must_directly_refer_to_a_built_in_symbol); } else if (!node.body) { @@ -24736,7 +24736,7 @@ namespace ts { function checkGrammarVariableDeclaration(node: VariableDeclaration) { if (node.parent.parent.kind !== SyntaxKind.ForInStatement && node.parent.parent.kind !== SyntaxKind.ForOfStatement) { - if (isInAmbientContext(node)) { + if (node.flags & NodeFlags.Ambient) { if (node.initializer) { if (isConst(node) && !node.type) { if (!isStringOrNumberLiteralExpression(node.initializer)) { @@ -24768,7 +24768,7 @@ namespace ts { } if (compilerOptions.module !== ModuleKind.ES2015 && compilerOptions.module !== ModuleKind.System && !compilerOptions.noEmit && - !isInAmbientContext(node.parent.parent) && hasModifier(node.parent.parent, ModifierFlags.Export)) { + !(node.parent.parent.flags & NodeFlags.Ambient) && hasModifier(node.parent.parent, ModifierFlags.Export)) { checkESModuleMarker(node.name); } @@ -24926,7 +24926,7 @@ namespace ts { } } - if (isInAmbientContext(node) && node.initializer) { + if (node.flags & NodeFlags.Ambient && node.initializer) { return grammarErrorOnFirstToken(node.initializer, Diagnostics.Initializers_are_not_allowed_in_ambient_contexts); } } @@ -24969,11 +24969,11 @@ namespace ts { } function checkGrammarSourceFile(node: SourceFile): boolean { - return isInAmbientContext(node) && checkGrammarTopLevelElementsForRequiredDeclareModifier(node); + return !!(node.flags & NodeFlags.Ambient) && checkGrammarTopLevelElementsForRequiredDeclareModifier(node); } function checkGrammarStatementInAmbientContext(node: Node): boolean { - if (isInAmbientContext(node)) { + if (node.flags & NodeFlags.Ambient) { // An accessors is already reported about the ambient context if (isAccessor(node.parent)) { return getNodeLinks(node).hasReportedStatementInAmbientContext = true; diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index a2fe752ad18e9..c8d9e56dca965 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -613,11 +613,12 @@ namespace ts { let parseErrorBeforeNextFinishedNode = false; export function parseSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, syntaxCursor: IncrementalParser.SyntaxCursor, setParentNodes?: boolean, scriptKind?: ScriptKind): SourceFile { + const isDeclarationFile = isDeclarationFileName(fileName); scriptKind = ensureScriptKind(fileName, scriptKind); - initializeState(sourceText, languageVersion, syntaxCursor, scriptKind); + initializeState(sourceText, languageVersion, syntaxCursor, scriptKind, isDeclarationFile); - const result = parseSourceFileWorker(fileName, languageVersion, setParentNodes, scriptKind); + const result = parseSourceFileWorker(fileName, languageVersion, setParentNodes, scriptKind, isDeclarationFile); clearState(); @@ -625,7 +626,8 @@ namespace ts { } export function parseIsolatedEntityName(content: string, languageVersion: ScriptTarget): EntityName { - initializeState(content, languageVersion, /*syntaxCursor*/ undefined, ScriptKind.JS); + // Choice of `isDeclarationFile` should be arbitrary + initializeState(content, languageVersion, /*syntaxCursor*/ undefined, ScriptKind.JS, /*isDeclarationFile*/ false); // Prime the scanner. nextToken(); const entityName = parseEntityName(/*allowReservedWords*/ true); @@ -635,9 +637,10 @@ namespace ts { } export function parseJsonText(fileName: string, sourceText: string): JsonSourceFile { - initializeState(sourceText, ScriptTarget.ES2015, /*syntaxCursor*/ undefined, ScriptKind.JSON); + const isDeclaration = isDeclarationFileName(fileName); + initializeState(sourceText, ScriptTarget.ES2015, /*syntaxCursor*/ undefined, ScriptKind.JSON, isDeclaration); // Set source file so that errors will be reported with this file name - sourceFile = createSourceFile(fileName, ScriptTarget.ES2015, ScriptKind.JSON); + sourceFile = createSourceFile(fileName, ScriptTarget.ES2015, ScriptKind.JSON, isDeclaration); const result = sourceFile; // Prime the scanner. @@ -664,7 +667,7 @@ namespace ts { return scriptKind === ScriptKind.TSX || scriptKind === ScriptKind.JSX || scriptKind === ScriptKind.JS || scriptKind === ScriptKind.JSON ? LanguageVariant.JSX : LanguageVariant.Standard; } - function initializeState(_sourceText: string, languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor, scriptKind: ScriptKind) { + function initializeState(_sourceText: string, languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor, scriptKind: ScriptKind, isDeclarationFile: boolean) { NodeConstructor = objectAllocator.getNodeConstructor(); TokenConstructor = objectAllocator.getTokenConstructor(); IdentifierConstructor = objectAllocator.getIdentifierConstructor(); @@ -679,7 +682,16 @@ namespace ts { identifierCount = 0; nodeCount = 0; - contextFlags = scriptKind === ScriptKind.JS || scriptKind === ScriptKind.JSX || scriptKind === ScriptKind.JSON ? NodeFlags.JavaScriptFile : NodeFlags.None; + switch (scriptKind) { + case ScriptKind.JS: + case ScriptKind.JSX: + case ScriptKind.JSON: + contextFlags = NodeFlags.JavaScriptFile; + break; + default: + contextFlags = isDeclarationFile ? NodeFlags.Ambient : NodeFlags.None; + break; + } parseErrorBeforeNextFinishedNode = false; // Initialize and prime the scanner before parsing the source elements. @@ -702,8 +714,8 @@ namespace ts { sourceText = undefined; } - function parseSourceFileWorker(fileName: string, languageVersion: ScriptTarget, setParentNodes: boolean, scriptKind: ScriptKind): SourceFile { - sourceFile = createSourceFile(fileName, languageVersion, scriptKind); + function parseSourceFileWorker(fileName: string, languageVersion: ScriptTarget, setParentNodes: boolean, scriptKind: ScriptKind, isDeclarationFile: boolean): SourceFile { + sourceFile = createSourceFile(fileName, languageVersion, scriptKind, isDeclarationFile); sourceFile.flags = contextFlags; // Prime the scanner. @@ -780,7 +792,7 @@ namespace ts { } } - function createSourceFile(fileName: string, languageVersion: ScriptTarget, scriptKind: ScriptKind): SourceFile { + function createSourceFile(fileName: string, languageVersion: ScriptTarget, scriptKind: ScriptKind, isDeclarationFile: boolean): SourceFile { // code from createNode is inlined here so createNode won't have to deal with special case of creating source files // this is quite rare comparing to other nodes and createNode should be as fast as possible const sourceFile = new SourceFileConstructor(SyntaxKind.SourceFile, /*pos*/ 0, /* end */ sourceText.length); @@ -791,7 +803,7 @@ namespace ts { sourceFile.languageVersion = languageVersion; sourceFile.fileName = normalizePath(fileName); sourceFile.languageVariant = getLanguageVariant(scriptKind); - sourceFile.isDeclarationFile = fileExtensionIs(sourceFile.fileName, Extension.Dts); + sourceFile.isDeclarationFile = isDeclarationFile; sourceFile.scriptKind = scriptKind; return sourceFile; @@ -5088,6 +5100,15 @@ namespace ts { const fullStart = getNodePos(); const decorators = parseDecorators(); const modifiers = parseModifiers(); + if (modifiers && modifiers.some(m => m.kind === SyntaxKind.DeclareKeyword)) { + return doInsideOfContext(NodeFlags.Ambient, () => parseDeclarationWorker(fullStart, decorators, modifiers)); + } + else { + return parseDeclarationWorker(fullStart, decorators, modifiers); + } + } + + function parseDeclarationWorker(fullStart: number, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): Statement { switch (token()) { case SyntaxKind.VarKeyword: case SyntaxKind.LetKeyword: @@ -5445,8 +5466,8 @@ namespace ts { return false; } - function parseDecorators(): NodeArray { - let decorators: NodeArray & Decorator[]; + function parseDecorators(): NodeArray | undefined { + let decorators: NodeArray & Decorator[] | undefined; while (true) { const decoratorStart = getNodePos(); if (!parseOptional(SyntaxKind.AtToken)) { @@ -6143,8 +6164,8 @@ namespace ts { export namespace JSDocParser { export function parseJSDocTypeExpressionForTests(content: string, start: number, length: number): { jsDocTypeExpression: JSDocTypeExpression, diagnostics: Diagnostic[] } | undefined { - initializeState(content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS); - sourceFile = createSourceFile("file.js", ScriptTarget.Latest, ScriptKind.JS); + initializeState(content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS, /*isDeclarationFile*/ false); + sourceFile = createSourceFile("file.js", ScriptTarget.Latest, ScriptKind.JS, /*isDeclarationFile*/ false); scanner.setText(content, start, length); currentToken = scanner.scan(); const jsDocTypeExpression = parseJSDocTypeExpression(); @@ -6168,7 +6189,7 @@ namespace ts { } export function parseIsolatedJSDocComment(content: string, start: number, length: number): { jsDoc: JSDoc, diagnostics: Diagnostic[] } | undefined { - initializeState(content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS); + initializeState(content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS, /*isDeclarationFile*/ false); sourceFile = { languageVariant: LanguageVariant.Standard, text: content }; // tslint:disable-line no-object-literal-type-assertion const jsDoc = parseJSDocCommentWorker(start, length); const diagnostics = parseDiagnostics; @@ -7451,4 +7472,8 @@ namespace ts { Value = -1 } } + + function isDeclarationFileName(fileName: string): boolean { + return fileExtensionIs(fileName, Extension.Dts); + } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index faaed7799558a..c0186c91cc5e4 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -451,6 +451,7 @@ namespace ts { /* @internal */ PossiblyContainsDynamicImport = 1 << 19, JSDoc = 1 << 20, // If node was parsed inside jsdoc + Ambient = 1 << 21, // If node was inside an ambient context -- a declaration file, or inside something with the `declare` modifier. BlockScoped = Let | Const, @@ -458,7 +459,7 @@ namespace ts { ReachabilityAndEmitFlags = ReachabilityCheckFlags | HasAsyncFunctions, // Parsing context flags - ContextFlags = DisallowInContext | YieldContext | DecoratorContext | AwaitContext | JavaScriptFile, + ContextFlags = DisallowInContext | YieldContext | DecoratorContext | AwaitContext | JavaScriptFile | Ambient, // Exclude these flags when parsing a Type TypeExcludesFlags = YieldContext | AwaitContext, diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index c77d267471a06..f4d41c31c92fd 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1706,16 +1706,6 @@ namespace ts { return false; } - export function isInAmbientContext(node: Node): boolean { - while (node) { - if (hasModifier(node, ModifierFlags.Ambient) || (node.kind === SyntaxKind.SourceFile && (node as SourceFile).isDeclarationFile)) { - return true; - } - node = node.parent; - } - return false; - } - // True if the given identifier, string literal, or number literal is the name of a declaration node export function isDeclarationName(name: Node): boolean { switch (name.kind) { diff --git a/src/harness/unittests/incrementalParser.ts b/src/harness/unittests/incrementalParser.ts index fbd8a60da9233..c71b89d3da68d 100644 --- a/src/harness/unittests/incrementalParser.ts +++ b/src/harness/unittests/incrementalParser.ts @@ -591,7 +591,7 @@ module m3 { }\ const index = 0; const newTextAndChange = withInsert(oldText, index, "declare "); - compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 3); + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); }); it("Insert function above arrow function with comment", () => { @@ -674,7 +674,7 @@ module m3 { }\ const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withInsert(oldText, 0, "{"); - compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 9); + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 4); }); it("Removing block around function declarations", () => { @@ -683,7 +683,7 @@ module m3 { }\ const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withDelete(oldText, 0, "{".length); - compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 9); + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 4); }); it("Moving methods from class to object literal", () => { diff --git a/src/services/breakpoints.ts b/src/services/breakpoints.ts index 37aa8df0ca175..d18a69ae6b834 100644 --- a/src/services/breakpoints.ts +++ b/src/services/breakpoints.ts @@ -31,7 +31,8 @@ namespace ts.BreakpointResolver { } // Cannot set breakpoint in ambient declarations - if (isInAmbientContext(tokenAtLocation)) { + // (Tokens do not have flags set, but their parents do.) + if (tokenAtLocation.parent.flags & NodeFlags.Ambient) { return undefined; } diff --git a/src/services/refactors/extractMethod.ts b/src/services/refactors/extractMethod.ts index de163d0771772..7ca6d38ecbd5e 100644 --- a/src/services/refactors/extractMethod.ts +++ b/src/services/refactors/extractMethod.ts @@ -293,7 +293,7 @@ namespace ts.refactor.extractMethod { return [createDiagnosticForNode(nodeToCheck, Messages.StatementOrExpressionExpected)]; } - if (isInAmbientContext(nodeToCheck)) { + if (nodeToCheck.flags & NodeFlags.Ambient) { return [createDiagnosticForNode(nodeToCheck, Messages.CannotExtractAmbientBlock)]; } diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 27215190db3fd..7712aabe4e9fe 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -930,7 +930,7 @@ namespace ts { if (flags & ModifierFlags.Static) result.push(ScriptElementKindModifier.staticModifier); if (flags & ModifierFlags.Abstract) result.push(ScriptElementKindModifier.abstractModifier); if (flags & ModifierFlags.Export) result.push(ScriptElementKindModifier.exportedModifier); - if (isInAmbientContext(node)) result.push(ScriptElementKindModifier.ambientModifier); + if (node.flags & NodeFlags.Ambient) result.push(ScriptElementKindModifier.ambientModifier); return result.length > 0 ? result.join(",") : ScriptElementKindModifier.none; } diff --git a/tests/baselines/reference/parserConstructorDeclaration4.errors.txt b/tests/baselines/reference/parserConstructorDeclaration4.errors.txt index b5329a1cb47ad..bd27ccbb255ee 100644 --- a/tests/baselines/reference/parserConstructorDeclaration4.errors.txt +++ b/tests/baselines/reference/parserConstructorDeclaration4.errors.txt @@ -1,12 +1,9 @@ tests/cases/conformance/parser/ecmascript5/ConstructorDeclarations/parserConstructorDeclaration4.ts(2,3): error TS1031: 'declare' modifier cannot appear on a class element. -tests/cases/conformance/parser/ecmascript5/ConstructorDeclarations/parserConstructorDeclaration4.ts(2,25): error TS1183: An implementation cannot be declared in ambient contexts. -==== tests/cases/conformance/parser/ecmascript5/ConstructorDeclarations/parserConstructorDeclaration4.ts (2 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/ConstructorDeclarations/parserConstructorDeclaration4.ts (1 errors) ==== class C { declare constructor() { } ~~~~~~~ !!! error TS1031: 'declare' modifier cannot appear on a class element. - ~ -!!! error TS1183: An implementation cannot be declared in ambient contexts. } \ No newline at end of file diff --git a/tests/baselines/reference/parserMemberAccessorDeclaration11.errors.txt b/tests/baselines/reference/parserMemberAccessorDeclaration11.errors.txt index 5da5e536e067a..3a04bfbbd0296 100644 --- a/tests/baselines/reference/parserMemberAccessorDeclaration11.errors.txt +++ b/tests/baselines/reference/parserMemberAccessorDeclaration11.errors.txt @@ -1,9 +1,12 @@ tests/cases/conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration11.ts(2,5): error TS1031: 'declare' modifier cannot appear on a class element. +tests/cases/conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration11.ts(2,17): error TS2378: A 'get' accessor must return a value. -==== tests/cases/conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration11.ts (1 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration11.ts (2 errors) ==== class C { declare get Foo() { } ~~~~~~~ !!! error TS1031: 'declare' modifier cannot appear on a class element. + ~~~ +!!! error TS2378: A 'get' accessor must return a value. } \ No newline at end of file diff --git a/tests/baselines/reference/parserMemberFunctionDeclaration5.errors.txt b/tests/baselines/reference/parserMemberFunctionDeclaration5.errors.txt index 402355919a031..dc19cb0f8550a 100644 --- a/tests/baselines/reference/parserMemberFunctionDeclaration5.errors.txt +++ b/tests/baselines/reference/parserMemberFunctionDeclaration5.errors.txt @@ -1,12 +1,9 @@ tests/cases/conformance/parser/ecmascript5/MemberFunctionDeclarations/parserMemberFunctionDeclaration5.ts(2,5): error TS1031: 'declare' modifier cannot appear on a class element. -tests/cases/conformance/parser/ecmascript5/MemberFunctionDeclarations/parserMemberFunctionDeclaration5.ts(2,19): error TS1183: An implementation cannot be declared in ambient contexts. -==== tests/cases/conformance/parser/ecmascript5/MemberFunctionDeclarations/parserMemberFunctionDeclaration5.ts (2 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/MemberFunctionDeclarations/parserMemberFunctionDeclaration5.ts (1 errors) ==== class C { declare Foo() { } ~~~~~~~ !!! error TS1031: 'declare' modifier cannot appear on a class element. - ~ -!!! error TS1183: An implementation cannot be declared in ambient contexts. } \ No newline at end of file From 98a31d9667d446cb0694936905b64d0cd5883fca Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Thu, 14 Sep 2017 13:21:19 -0700 Subject: [PATCH 2/5] Set context flags on tokens --- src/compiler/parser.ts | 3 +++ src/services/breakpoints.ts | 3 +-- src/services/services.ts | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 0e2a87f03c30a..67feac504397c 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5097,6 +5097,9 @@ namespace ts { const decorators = parseDecorators(); const modifiers = parseModifiers(); if (modifiers && modifiers.some(m => m.kind === SyntaxKind.DeclareKeyword)) { + for (const m of modifiers) { + m.flags |= NodeFlags.Ambient; + } return doInsideOfContext(NodeFlags.Ambient, () => parseDeclarationWorker(fullStart, decorators, modifiers)); } else { diff --git a/src/services/breakpoints.ts b/src/services/breakpoints.ts index d18a69ae6b834..3421404a30f35 100644 --- a/src/services/breakpoints.ts +++ b/src/services/breakpoints.ts @@ -31,8 +31,7 @@ namespace ts.BreakpointResolver { } // Cannot set breakpoint in ambient declarations - // (Tokens do not have flags set, but their parents do.) - if (tokenAtLocation.parent.flags & NodeFlags.Ambient) { + if (tokenAtLocation.flags & NodeFlags.Ambient) { return undefined; } diff --git a/src/services/services.ts b/src/services/services.ts index bdd0eb41e4fd8..eedb546996417 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -41,6 +41,7 @@ namespace ts { kind === SyntaxKind.Identifier ? new IdentifierObject(SyntaxKind.Identifier, pos, end) : new TokenObject(kind, pos, end); node.parent = parent; + node.flags = parent.flags & NodeFlags.ContextFlags; return node; } From 6fcd0033c2d405dba044a56bbfd33278d079a0aa Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Thu, 14 Sep 2017 13:37:16 -0700 Subject: [PATCH 3/5] Remove 'isDeclarationFile' parameter to 'initializeState' and move to 'parseSourceFileWorker' --- src/compiler/parser.ts | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 67feac504397c..8011f252112ea 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -615,12 +615,11 @@ namespace ts { let parseErrorBeforeNextFinishedNode = false; export function parseSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, syntaxCursor: IncrementalParser.SyntaxCursor, setParentNodes?: boolean, scriptKind?: ScriptKind): SourceFile { - const isDeclarationFile = isDeclarationFileName(fileName); scriptKind = ensureScriptKind(fileName, scriptKind); - initializeState(sourceText, languageVersion, syntaxCursor, scriptKind, isDeclarationFile); + initializeState(sourceText, languageVersion, syntaxCursor, scriptKind); - const result = parseSourceFileWorker(fileName, languageVersion, setParentNodes, scriptKind, isDeclarationFile); + const result = parseSourceFileWorker(fileName, languageVersion, setParentNodes, scriptKind); clearState(); @@ -629,7 +628,7 @@ namespace ts { export function parseIsolatedEntityName(content: string, languageVersion: ScriptTarget): EntityName { // Choice of `isDeclarationFile` should be arbitrary - initializeState(content, languageVersion, /*syntaxCursor*/ undefined, ScriptKind.JS, /*isDeclarationFile*/ false); + initializeState(content, languageVersion, /*syntaxCursor*/ undefined, ScriptKind.JS); // Prime the scanner. nextToken(); const entityName = parseEntityName(/*allowReservedWords*/ true); @@ -639,10 +638,9 @@ namespace ts { } export function parseJsonText(fileName: string, sourceText: string): JsonSourceFile { - const isDeclaration = isDeclarationFileName(fileName); - initializeState(sourceText, ScriptTarget.ES2015, /*syntaxCursor*/ undefined, ScriptKind.JSON, isDeclaration); + initializeState(sourceText, ScriptTarget.ES2015, /*syntaxCursor*/ undefined, ScriptKind.JSON); // Set source file so that errors will be reported with this file name - sourceFile = createSourceFile(fileName, ScriptTarget.ES2015, ScriptKind.JSON, isDeclaration); + sourceFile = createSourceFile(fileName, ScriptTarget.ES2015, ScriptKind.JSON, /*isDeclaration*/ false); const result = sourceFile; // Prime the scanner. @@ -669,7 +667,7 @@ namespace ts { return scriptKind === ScriptKind.TSX || scriptKind === ScriptKind.JSX || scriptKind === ScriptKind.JS || scriptKind === ScriptKind.JSON ? LanguageVariant.JSX : LanguageVariant.Standard; } - function initializeState(_sourceText: string, languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor, scriptKind: ScriptKind, isDeclarationFile: boolean) { + function initializeState(_sourceText: string, languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor, scriptKind: ScriptKind) { NodeConstructor = objectAllocator.getNodeConstructor(); TokenConstructor = objectAllocator.getTokenConstructor(); IdentifierConstructor = objectAllocator.getIdentifierConstructor(); @@ -691,7 +689,7 @@ namespace ts { contextFlags = NodeFlags.JavaScriptFile; break; default: - contextFlags = isDeclarationFile ? NodeFlags.Ambient : NodeFlags.None; + contextFlags = NodeFlags.None; break; } parseErrorBeforeNextFinishedNode = false; @@ -716,7 +714,12 @@ namespace ts { sourceText = undefined; } - function parseSourceFileWorker(fileName: string, languageVersion: ScriptTarget, setParentNodes: boolean, scriptKind: ScriptKind, isDeclarationFile: boolean): SourceFile { + function parseSourceFileWorker(fileName: string, languageVersion: ScriptTarget, setParentNodes: boolean, scriptKind: ScriptKind): SourceFile { + const isDeclarationFile = isDeclarationFileName(fileName); + if (isDeclarationFile) { + contextFlags |= NodeFlags.Ambient; + } + sourceFile = createSourceFile(fileName, languageVersion, scriptKind, isDeclarationFile); sourceFile.flags = contextFlags; @@ -6146,7 +6149,7 @@ namespace ts { export namespace JSDocParser { export function parseJSDocTypeExpressionForTests(content: string, start: number, length: number): { jsDocTypeExpression: JSDocTypeExpression, diagnostics: Diagnostic[] } | undefined { - initializeState(content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS, /*isDeclarationFile*/ false); + initializeState(content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS); sourceFile = createSourceFile("file.js", ScriptTarget.Latest, ScriptKind.JS, /*isDeclarationFile*/ false); scanner.setText(content, start, length); currentToken = scanner.scan(); @@ -6171,7 +6174,7 @@ namespace ts { } export function parseIsolatedJSDocComment(content: string, start: number, length: number): { jsDoc: JSDoc, diagnostics: Diagnostic[] } | undefined { - initializeState(content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS, /*isDeclarationFile*/ false); + initializeState(content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS); sourceFile = { languageVariant: LanguageVariant.Standard, text: content }; // tslint:disable-line no-object-literal-type-assertion const jsDoc = parseJSDocCommentWorker(start, length); const diagnostics = parseDiagnostics; From f3f11a0eec1a199564d828568303fe0a9ae9ba00 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Mon, 30 Oct 2017 12:51:34 -0700 Subject: [PATCH 4/5] Changes based on code review --- src/compiler/checker.ts | 8 ++++---- src/compiler/parser.ts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 19af2cf40c64d..5e56fe6295f9b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17057,7 +17057,7 @@ namespace ts { return type; } - function isCommonJsRequire(node: Node) { + function isCommonJsRequire(node: Node): boolean { if (!isRequireCall(node, /*checkArgumentIsStringLiteral*/ true)) { return false; } @@ -17081,7 +17081,7 @@ namespace ts { if (targetDeclarationKind !== SyntaxKind.Unknown) { const decl = getDeclarationOfKind(resolvedRequire, targetDeclarationKind); // function/variable declaration should be ambient - return decl.flags & NodeFlags.Ambient; + return !!(decl.flags & NodeFlags.Ambient); } return false; } @@ -22724,7 +22724,7 @@ namespace ts { if (hasModifier(node, ModifierFlags.Export)) { markExportAsReferenced(node); } - if (isInternalModuleImportEqualsDeclaration(node)) { + if (node.moduleReference.kind !== SyntaxKind.ExternalModuleReference) { const target = resolveAlias(getSymbolOfNode(node)); if (target !== unknownSymbol) { if (target.flags & SymbolFlags.Value) { @@ -22740,7 +22740,7 @@ namespace ts { } } else { - if (modulekind >= ModuleKind.ES2015 && !((node as ImportEqualsDeclaration).flags & NodeFlags.Ambient)) { + if (modulekind >= ModuleKind.ES2015 && !(node.flags & NodeFlags.Ambient)) { // Import equals declaration is deprecated in es6 or above grammarErrorOnNode(node, Diagnostics.Import_assignment_cannot_be_used_when_targeting_ECMAScript_modules_Consider_using_import_Asterisk_as_ns_from_mod_import_a_from_mod_import_d_from_mod_or_another_module_format_instead); } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index e8eb2c49f9466..ebaa89541db5f 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5104,7 +5104,7 @@ namespace ts { const fullStart = getNodePos(); const decorators = parseDecorators(); const modifiers = parseModifiers(); - if (modifiers && modifiers.some(m => m.kind === SyntaxKind.DeclareKeyword)) { + if (some(modifiers, m => m.kind === SyntaxKind.DeclareKeyword)) { for (const m of modifiers) { m.flags |= NodeFlags.Ambient; } From 5dda7e59c21d32bf0afdba5d2156cefc870ef982 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Mon, 30 Oct 2017 13:44:12 -0700 Subject: [PATCH 5/5] Update API baselines --- tests/baselines/reference/api/tsserverlibrary.d.ts | 2 +- tests/baselines/reference/api/typescript.d.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 26c03954b4544..fc5d6790b6484 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -408,7 +408,7 @@ declare namespace ts { BlockScoped = 3, ReachabilityCheckFlags = 384, ReachabilityAndEmitFlags = 1408, - ContextFlags = 2193408, + ContextFlags = 6387712, TypeExcludesFlags = 20480, } enum ModifierFlags { diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 6abf9d0cb6e16..94bdeb93339f3 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -408,7 +408,7 @@ declare namespace ts { BlockScoped = 3, ReachabilityCheckFlags = 384, ReachabilityAndEmitFlags = 1408, - ContextFlags = 2193408, + ContextFlags = 6387712, TypeExcludesFlags = 20480, } enum ModifierFlags {