diff --git a/.gitignore b/.gitignore index f1ea04e3efb..a6c8c2940d8 100644 --- a/.gitignore +++ b/.gitignore @@ -57,3 +57,4 @@ internal/ !tests/cases/projects/NodeModulesSearch/**/* !tests/baselines/reference/project/nodeModules*/**/* .idea +yarn.lock \ No newline at end of file diff --git a/Gulpfile.ts b/Gulpfile.ts index 7e7f05fd9c4..3d4bae39a32 100644 --- a/Gulpfile.ts +++ b/Gulpfile.ts @@ -21,10 +21,6 @@ declare module "gulp-typescript" { import * as insert from "gulp-insert"; import * as sourcemaps from "gulp-sourcemaps"; import Q = require("q"); -declare global { - // `del` further depends on `Promise` (and is also not included), so we just, patch the global scope's Promise to Q's (which we already include in our deps because gulp depends on it) - type Promise = Q.Promise; -} import del = require("del"); import mkdirP = require("mkdirp"); import minimist = require("minimist"); @@ -394,7 +390,7 @@ gulp.task(builtLocalCompiler, false, [servicesFile], () => { .pipe(localCompilerProject()) .pipe(prependCopyright()) .pipe(sourcemaps.write(".")) - .pipe(gulp.dest(".")); + .pipe(gulp.dest("src/compiler")); }); gulp.task(servicesFile, false, ["lib", "generate-diagnostics"], () => { @@ -426,7 +422,7 @@ gulp.task(servicesFile, false, ["lib", "generate-diagnostics"], () => { file.path = nodeStandaloneDefinitionsFile; return content.replace(/declare (namespace|module) ts/g, 'declare module "typescript"'); })) - ]).pipe(gulp.dest(".")); + ]).pipe(gulp.dest("src/services")); }); // cancellationToken.js @@ -452,7 +448,7 @@ gulp.task(typingsInstallerJs, false, [servicesFile], () => { .pipe(cancellationTokenProject()) .pipe(prependCopyright()) .pipe(sourcemaps.write(".")) - .pipe(gulp.dest(".")); + .pipe(gulp.dest("src/server/typingsInstaller")); }); const serverFile = path.join(builtLocalDirectory, "tsserver.js"); @@ -465,7 +461,7 @@ gulp.task(serverFile, false, [servicesFile, typingsInstallerJs, cancellationToke .pipe(serverProject()) .pipe(prependCopyright()) .pipe(sourcemaps.write(".")) - .pipe(gulp.dest(".")); + .pipe(gulp.dest("src/server")); }); const tsserverLibraryFile = path.join(builtLocalDirectory, "tsserverlibrary.js"); @@ -560,7 +556,7 @@ gulp.task(run, false, [servicesFile], () => { .pipe(sourcemaps.init()) .pipe(testProject()) .pipe(sourcemaps.write(".", { includeContent: false, sourceRoot: "../../" })) - .pipe(gulp.dest(".")); + .pipe(gulp.dest("src/harness")); }); const internalTests = "internal/"; @@ -782,7 +778,7 @@ gulp.task("browserify", "Runs browserify on run.js to produce a file suitable fo }); })) .pipe(sourcemaps.write(".", { includeContent: false })) - .pipe(gulp.dest(".")); + .pipe(gulp.dest("src/harness")); }); diff --git a/Jakefile.js b/Jakefile.js index 78516f60731..f8be7c2b671 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -587,7 +587,7 @@ var watchGuardFile = path.join(builtLocalDirectory, "watchGuard.js"); compileFile(watchGuardFile, watchGuardSources, [builtLocalDirectory].concat(watchGuardSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { outDir: builtLocalDirectory, noOutFile: false }); var serverFile = path.join(builtLocalDirectory, "tsserver.js"); -compileFile(serverFile, serverSources, [builtLocalDirectory, copyright, cancellationTokenFile, typingsInstallerFile, watchGuardFile].concat(serverSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { types: ["node"], preserveConstEnums: true }); +compileFile(serverFile, serverSources, [builtLocalDirectory, copyright, cancellationTokenFile, typingsInstallerFile, watchGuardFile].concat(serverSources).concat(servicesSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { types: ["node"], preserveConstEnums: true }); var tsserverLibraryFile = path.join(builtLocalDirectory, "tsserverlibrary.js"); var tsserverLibraryDefinitionFile = path.join(builtLocalDirectory, "tsserverlibrary.d.ts"); compileFile( diff --git a/lib/protocol.d.ts b/lib/protocol.d.ts index 2fc15c3a256..e675ba87417 100644 --- a/lib/protocol.d.ts +++ b/lib/protocol.d.ts @@ -1742,6 +1742,7 @@ declare namespace ts.server.protocol { insertSpaceAfterFunctionKeywordForAnonymousFunctions?: boolean; insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis?: boolean; insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets?: boolean; + insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces?: boolean; insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces?: boolean; insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces?: boolean; insertSpaceBeforeFunctionParenthesis?: boolean; diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 51830c50bfe..7e8a99343bd 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -670,6 +670,12 @@ namespace ts { case SyntaxKind.CallExpression: bindCallExpressionFlow(node); break; + case SyntaxKind.JSDocComment: + bindJSDocComment(node); + break; + case SyntaxKind.JSDocTypedefTag: + bindJSDocTypedefTag(node); + break; default: bindEachChild(node); break; @@ -1335,6 +1341,26 @@ namespace ts { } } + function bindJSDocComment(node: JSDoc) { + forEachChild(node, n => { + if (n.kind !== SyntaxKind.JSDocTypedefTag) { + bind(n); + } + }); + } + + function bindJSDocTypedefTag(node: JSDocTypedefTag) { + forEachChild(node, n => { + // if the node has a fullName "A.B.C", that means symbol "C" was already bound + // when we visit "fullName"; so when we visit the name "C" as the next child of + // the jsDocTypedefTag, we should skip binding it. + if (node.fullName && n === node.name && node.fullName.kind !== SyntaxKind.Identifier) { + return; + } + bind(n); + }); + } + function bindCallExpressionFlow(node: CallExpression) { // If the target of the call expression is a function expression or arrow function we have // an immediately invoked function expression (IIFE). Initialize the flowNode property to @@ -1874,6 +1900,18 @@ namespace ts { } node.parent = parent; const saveInStrictMode = inStrictMode; + + // Even though in the AST the jsdoc @typedef node belongs to the current node, + // its symbol might be in the same scope with the current node's symbol. Consider: + // + // /** @typedef {string | number} MyType */ + // function foo(); + // + // Here the current node is "foo", which is a container, but the scope of "MyType" should + // not be inside "foo". Therefore we always bind @typedef before bind the parent node, + // and skip binding this tag later when binding all the other jsdoc tags. + bindJSDocTypedefTagIfAny(node); + // First we bind declaration nodes to a symbol if possible. We'll both create a symbol // and then potentially add the symbol to an appropriate symbol table. Possible // destination symbol tables are: @@ -1908,6 +1946,27 @@ namespace ts { inStrictMode = saveInStrictMode; } + function bindJSDocTypedefTagIfAny(node: Node) { + if (!node.jsDoc) { + return; + } + + for (const jsDoc of node.jsDoc) { + if (!jsDoc.tags) { + continue; + } + + for (const tag of jsDoc.tags) { + if (tag.kind === SyntaxKind.JSDocTypedefTag) { + const savedParent = parent; + parent = jsDoc; + bind(tag); + parent = savedParent; + } + } + } + } + function updateStrictModeStatementList(statements: NodeArray) { if (!inStrictMode) { for (const statement of statements) { diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 83fea11c993..9cd5b7a31d2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -197,6 +197,8 @@ namespace ts { const evolvingArrayTypes: EvolvingArrayType[] = []; const unknownSymbol = createSymbol(SymbolFlags.Property, "unknown"); + const untypedModuleSymbol = createSymbol(SymbolFlags.ValueModule, ""); + untypedModuleSymbol.exports = createMap(); const resolvingSymbol = createSymbol(0, "__resolving__"); const anyType = createIntrinsicType(TypeFlags.Any, "any"); @@ -1227,7 +1229,7 @@ namespace ts { if (moduleSymbol) { let exportDefaultSymbol: Symbol; - if (isShorthandAmbientModuleSymbol(moduleSymbol)) { + if (isUntypedOrShorthandAmbientModuleSymbol(moduleSymbol)) { exportDefaultSymbol = moduleSymbol; } else { @@ -1307,7 +1309,7 @@ namespace ts { if (targetSymbol) { const name = specifier.propertyName || specifier.name; if (name.text) { - if (isShorthandAmbientModuleSymbol(moduleSymbol)) { + if (isUntypedOrShorthandAmbientModuleSymbol(moduleSymbol)) { return moduleSymbol; } @@ -1560,15 +1562,19 @@ namespace ts { if (isForAugmentation) { const diag = Diagnostics.Invalid_module_name_in_augmentation_Module_0_resolves_to_an_untyped_module_at_1_which_cannot_be_augmented; error(errorNode, diag, moduleReference, resolvedModule.resolvedFileName); + return undefined; } else if (compilerOptions.noImplicitAny && moduleNotFoundError) { error(errorNode, Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type, moduleReference, resolvedModule.resolvedFileName); + return undefined; } - // Failed imports and untyped modules are both treated in an untyped manner; only difference is whether we give a diagnostic first. - return undefined; + // Unlike a failed import, an untyped module produces a dummy symbol. + // This is checked for by `isUntypedOrShorthandAmbientModuleSymbol`. + // This must be different than `unknownSymbol` because `getBaseConstructorTypeOfClass` won't fail for `unknownSymbol`. + return untypedModuleSymbol; } if (moduleNotFoundError) { @@ -3753,7 +3759,7 @@ namespace ts { function getTypeOfFuncClassEnumModule(symbol: Symbol): Type { const links = getSymbolLinks(symbol); if (!links.type) { - if (symbol.flags & SymbolFlags.Module && isShorthandAmbientModuleSymbol(symbol)) { + if (symbol.flags & SymbolFlags.Module && isUntypedOrShorthandAmbientModuleSymbol(symbol)) { links.type = anyType; } else { @@ -5897,15 +5903,52 @@ namespace ts { return getTypeFromNonGenericTypeReference(node, symbol); } + function getPrimitiveTypeFromJSDocTypeReference(node: JSDocTypeReference): Type { + if (isIdentifier(node.name)) { + switch (node.name.text) { + case "String": + return stringType; + case "Number": + return numberType; + case "Boolean": + return booleanType; + case "Void": + return voidType; + case "Undefined": + return undefinedType; + case "Null": + return nullType; + case "Object": + return anyType; + case "Function": + return anyFunctionType; + case "Array": + case "array": + return !node.typeArguments || !node.typeArguments.length ? createArrayType(anyType) : undefined; + case "Promise": + case "promise": + return !node.typeArguments || !node.typeArguments.length ? createPromiseType(anyType) : undefined; + } + } + } + + function getTypeFromJSDocNullableTypeNode(node: JSDocNullableType) { + const type = getTypeFromTypeNode(node.type); + return strictNullChecks ? getUnionType([type, nullType]) : type; + } + function getTypeFromTypeReference(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference): Type { const links = getNodeLinks(node); if (!links.resolvedType) { let symbol: Symbol; let type: Type; if (node.kind === SyntaxKind.JSDocTypeReference) { - const typeReferenceName = getTypeReferenceName(node); - symbol = resolveTypeReferenceName(typeReferenceName); - type = getTypeReferenceType(node, symbol); + type = getPrimitiveTypeFromJSDocTypeReference(node); + if (!type) { + const typeReferenceName = getTypeReferenceName(node); + symbol = resolveTypeReferenceName(typeReferenceName); + type = getTypeReferenceType(node, symbol); + } } else { // We only support expressions that are simple qualified names. For other expressions this produces undefined. @@ -6812,12 +6855,6 @@ namespace ts { return neverType; case SyntaxKind.ObjectKeyword: return nonPrimitiveType; - case SyntaxKind.JSDocNullKeyword: - return nullType; - case SyntaxKind.JSDocUndefinedKeyword: - return undefinedType; - case SyntaxKind.JSDocNeverKeyword: - return neverType; case SyntaxKind.ThisType: case SyntaxKind.ThisKeyword: return getTypeFromThisTypeNode(node); @@ -6844,8 +6881,9 @@ namespace ts { return getTypeFromUnionTypeNode(node); case SyntaxKind.IntersectionType: return getTypeFromIntersectionTypeNode(node); - case SyntaxKind.ParenthesizedType: case SyntaxKind.JSDocNullableType: + return getTypeFromJSDocNullableTypeNode(node); + case SyntaxKind.ParenthesizedType: case SyntaxKind.JSDocNonNullableType: case SyntaxKind.JSDocConstructorType: case SyntaxKind.JSDocThisType: @@ -11546,7 +11584,7 @@ namespace ts { if (isBindingPattern(declaration.parent)) { const parentDeclaration = declaration.parent.parent; const name = declaration.propertyName || declaration.name; - if (isVariableLike(parentDeclaration) && + if (parentDeclaration.kind !== SyntaxKind.BindingElement && parentDeclaration.type && !isBindingPattern(name)) { const text = getTextOfPropertyName(name); @@ -14772,7 +14810,6 @@ namespace ts { function checkMetaProperty(node: MetaProperty) { checkGrammarMetaProperty(node); - Debug.assert(node.keywordToken === SyntaxKind.NewKeyword && node.name.text === "target", "Unrecognized meta-property."); const container = getNewTargetContainer(node); if (!container) { error(node, Diagnostics.Meta_property_0_is_only_allowed_in_the_body_of_a_function_declaration_function_expression_or_constructor, "new.target"); @@ -15897,12 +15934,16 @@ namespace ts { checkAssignmentOperator(rightType); return getRegularTypeOfObjectLiteral(rightType); case SyntaxKind.CommaToken: - if (!compilerOptions.allowUnreachableCode && isSideEffectFree(left)) { + if (!compilerOptions.allowUnreachableCode && isSideEffectFree(left) && !isEvalNode(right)) { error(left, Diagnostics.Left_side_of_comma_operator_is_unused_and_has_no_side_effects); } return rightType; } + function isEvalNode(node: Expression) { + return node.kind === SyntaxKind.Identifier && (node as Identifier).text === "eval"; + } + // Return true if there was no error, false if there was an error. function checkForDisallowedESSymbolOperand(operator: SyntaxKind): boolean { const offendingSymbolOperand = @@ -20898,7 +20939,9 @@ namespace ts { return getSymbolOfNode(entityName.parent); } - if (isInJavaScriptFile(entityName) && entityName.parent.kind === SyntaxKind.PropertyAccessExpression) { + if (isInJavaScriptFile(entityName) && + entityName.parent.kind === SyntaxKind.PropertyAccessExpression && + entityName.parent === (entityName.parent.parent as BinaryExpression).left) { // Check if this is a special property assignment const specialPropertyAssignmentSymbol = getSpecialPropertyAssignmentSymbolFromEntityName(entityName); if (specialPropertyAssignmentSymbol) { @@ -21101,7 +21144,15 @@ namespace ts { } if (isPartOfTypeNode(node)) { - return getTypeFromTypeNode(node); + let typeFromTypeNode = getTypeFromTypeNode(node); + + if (typeFromTypeNode && isExpressionWithTypeArgumentsInClassImplementsClause(node)) { + const containingClass = getContainingClass(node); + const classType = getTypeOfNode(containingClass) as InterfaceType; + typeFromTypeNode = getTypeWithThisArgument(typeFromTypeNode, classType.thisType); + } + + return typeFromTypeNode; } if (isPartOfExpression(node)) { @@ -21111,7 +21162,10 @@ namespace ts { if (isExpressionWithTypeArgumentsInClassExtendsClause(node)) { // A SyntaxKind.ExpressionWithTypeArguments is considered a type node, except when it occurs in the // extends clause of a class. We handle that case here. - return getBaseTypes(getDeclaredTypeOfSymbol(getSymbolOfNode(node.parent.parent)))[0]; + const classNode = getContainingClass(node); + const classType = getDeclaredTypeOfSymbol(getSymbolOfNode(classNode)) as InterfaceType; + const baseType = getBaseTypes(classType)[0]; + return baseType && getTypeWithThisArgument(baseType, classType.thisType); } if (isTypeDeclaration(node)) { @@ -21279,7 +21333,7 @@ namespace ts { function moduleExportsSomeValue(moduleReferenceExpression: Expression): boolean { let moduleSymbol = resolveExternalModuleName(moduleReferenceExpression.parent, moduleReferenceExpression); - if (!moduleSymbol || isShorthandAmbientModuleSymbol(moduleSymbol)) { + if (!moduleSymbol || isUntypedOrShorthandAmbientModuleSymbol(moduleSymbol)) { // If the module is not found or is shorthand, assume that it may export a value. return true; } @@ -22983,7 +23037,7 @@ namespace ts { function checkGrammarMetaProperty(node: MetaProperty) { if (node.keywordToken === SyntaxKind.NewKeyword) { if (node.name.text !== "target") { - return grammarErrorOnNode(node.name, Diagnostics._0_is_not_a_valid_meta_property_for_keyword_1_Did_you_mean_0, node.name.text, tokenToString(node.keywordToken), "target"); + return grammarErrorOnNode(node.name, Diagnostics._0_is_not_a_valid_meta_property_for_keyword_1_Did_you_mean_2, node.name.text, tokenToString(node.keywordToken), "target"); } } } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index b9572b2b0f4..75aa5d25f72 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3269,7 +3269,7 @@ "category": "Error", "code": 17011 }, - "'{0}' is not a valid meta-property for keyword '{1}'. Did you mean '{0}'?": { + "'{0}' is not a valid meta-property for keyword '{1}'. Did you mean '{2}'?": { "category": "Error", "code": 17012 }, diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts index ff832188b5b..57e85f50f39 100644 --- a/src/compiler/transformers/generators.ts +++ b/src/compiler/transformers/generators.ts @@ -1942,7 +1942,7 @@ namespace ts { } function substituteExpressionIdentifier(node: Identifier) { - if (renamedCatchVariables && renamedCatchVariables.has(node.text)) { + if (!isGeneratedIdentifier(node) && renamedCatchVariables && renamedCatchVariables.has(node.text)) { const original = getOriginalNode(node); if (isIdentifier(original) && original.parent) { const declaration = resolver.getReferencedValueDeclaration(original); @@ -2108,17 +2108,24 @@ namespace ts { function beginCatchBlock(variable: VariableDeclaration): void { Debug.assert(peekBlockKind() === CodeBlockKind.Exception); - const text = (variable.name).text; - const name = declareLocal(text); - - if (!renamedCatchVariables) { - renamedCatchVariables = createMap(); - renamedCatchVariableDeclarations = []; - context.enableSubstitution(SyntaxKind.Identifier); + // generated identifiers should already be unique within a file + let name: Identifier; + if (isGeneratedIdentifier(variable.name)) { + name = variable.name; + hoistVariableDeclaration(variable.name); } + else { + const text = (variable.name).text; + name = declareLocal(text); + if (!renamedCatchVariables) { + renamedCatchVariables = createMap(); + renamedCatchVariableDeclarations = []; + context.enableSubstitution(SyntaxKind.Identifier); + } - renamedCatchVariables.set(text, true); - renamedCatchVariableDeclarations[getOriginalNodeId(variable)] = name; + renamedCatchVariables.set(text, true); + renamedCatchVariableDeclarations[getOriginalNodeId(variable)] = name; + } const exception = peekBlock(); Debug.assert(exception.state < ExceptionBlockState.Catch); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index de42d5d9745..4ffd44e6aa1 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -381,9 +381,6 @@ JSDocPropertyTag, JSDocTypeLiteral, JSDocLiteralType, - JSDocNullKeyword, - JSDocUndefinedKeyword, - JSDocNeverKeyword, // Synthesized list SyntaxList, @@ -423,9 +420,9 @@ LastBinaryOperator = CaretEqualsToken, FirstNode = QualifiedName, FirstJSDocNode = JSDocTypeExpression, - LastJSDocNode = JSDocNeverKeyword, + LastJSDocNode = JSDocLiteralType, FirstJSDocTagNode = JSDocComment, - LastJSDocTagNode = JSDocNeverKeyword + LastJSDocTagNode = JSDocLiteralType } export const enum NodeFlags { @@ -624,6 +621,7 @@ export interface TypeParameterDeclaration extends Declaration { kind: SyntaxKind.TypeParameter; + parent?: DeclarationWithTypeParameters; name: Identifier; constraint?: TypeNode; default?: TypeNode; @@ -651,7 +649,7 @@ export interface VariableDeclaration extends Declaration { kind: SyntaxKind.VariableDeclaration; - parent?: VariableDeclarationList; + parent?: VariableDeclarationList | CatchClause; name: BindingName; // Declared variable name type?: TypeNode; // Optional type annotation initializer?: Expression; // Optional initializer @@ -659,11 +657,13 @@ export interface VariableDeclarationList extends Node { kind: SyntaxKind.VariableDeclarationList; + parent?: VariableStatement | ForStatement | ForOfStatement | ForInStatement; declarations: NodeArray; } export interface ParameterDeclaration extends Declaration { kind: SyntaxKind.Parameter; + parent?: SignatureDeclaration; dotDotDotToken?: DotDotDotToken; // Present on rest parameter name: BindingName; // Declared parameter name questionToken?: QuestionToken; // Present on optional parameter @@ -673,6 +673,7 @@ export interface BindingElement extends Declaration { kind: SyntaxKind.BindingElement; + parent?: BindingPattern; propertyName?: PropertyName; // Binding property name (in object binding pattern) dotDotDotToken?: DotDotDotToken; // Present on rest element (in object binding pattern) name: BindingName; // Declared binding element name @@ -754,11 +755,13 @@ export interface ObjectBindingPattern extends Node { kind: SyntaxKind.ObjectBindingPattern; + parent?: VariableDeclaration | ParameterDeclaration | BindingElement; elements: NodeArray; } export interface ArrayBindingPattern extends Node { kind: SyntaxKind.ArrayBindingPattern; + parent?: VariableDeclaration | ParameterDeclaration | BindingElement; elements: NodeArray; } @@ -1327,14 +1330,17 @@ export interface TemplateHead extends LiteralLikeNode { kind: SyntaxKind.TemplateHead; + parent?: TemplateExpression; } export interface TemplateMiddle extends LiteralLikeNode { kind: SyntaxKind.TemplateMiddle; + parent?: TemplateSpan; } export interface TemplateTail extends LiteralLikeNode { kind: SyntaxKind.TemplateTail; + parent?: TemplateSpan; } export type TemplateLiteral = TemplateExpression | NoSubstitutionTemplateLiteral; @@ -1349,6 +1355,7 @@ // The template literal must have kind TemplateMiddleLiteral or TemplateTailLiteral. export interface TemplateSpan extends Node { kind: SyntaxKind.TemplateSpan; + parent?: TemplateExpression; expression: Expression; literal: TemplateMiddle | TemplateTail; } @@ -1436,6 +1443,7 @@ export interface ExpressionWithTypeArguments extends TypeNode { kind: SyntaxKind.ExpressionWithTypeArguments; + parent?: HeritageClause; expression: LeftHandSideExpression; typeArguments?: NodeArray; } @@ -1503,6 +1511,7 @@ /// The opening element of a ... JsxElement export interface JsxOpeningElement extends Expression { kind: SyntaxKind.JsxOpeningElement; + parent?: JsxElement; tagName: JsxTagNameExpression; attributes: JsxAttributes; } @@ -1516,6 +1525,7 @@ export interface JsxAttribute extends ObjectLiteralElement { kind: SyntaxKind.JsxAttribute; + parent?: JsxOpeningLikeElement; name: Identifier; /// JSX attribute initializers are optional; is sugar for initializer?: StringLiteral | JsxExpression; @@ -1523,22 +1533,26 @@ export interface JsxSpreadAttribute extends ObjectLiteralElement { kind: SyntaxKind.JsxSpreadAttribute; + parent?: JsxOpeningLikeElement; expression: Expression; } export interface JsxClosingElement extends Node { kind: SyntaxKind.JsxClosingElement; + parent?: JsxElement; tagName: JsxTagNameExpression; } export interface JsxExpression extends Expression { kind: SyntaxKind.JsxExpression; + parent?: JsxElement | JsxAttributeLike; dotDotDotToken?: Token; expression?: Expression; } export interface JsxText extends Node { kind: SyntaxKind.JsxText; + parent?: JsxElement; } export type JsxChild = JsxText | JsxExpression | JsxElement | JsxSelfClosingElement; @@ -1680,17 +1694,20 @@ export interface CaseBlock extends Node { kind: SyntaxKind.CaseBlock; + parent?: SwitchStatement; clauses: NodeArray; } export interface CaseClause extends Node { kind: SyntaxKind.CaseClause; + parent?: CaseBlock; expression: Expression; statements: NodeArray; } export interface DefaultClause extends Node { kind: SyntaxKind.DefaultClause; + parent?: CaseBlock; statements: NodeArray; } @@ -1716,6 +1733,7 @@ export interface CatchClause extends Node { kind: SyntaxKind.CatchClause; + parent?: TryStatement; variableDeclaration: VariableDeclaration; block: Block; } @@ -1759,6 +1777,7 @@ export interface HeritageClause extends Node { kind: SyntaxKind.HeritageClause; + parent?: InterfaceDeclaration | ClassDeclaration | ClassExpression; token: SyntaxKind; types?: NodeArray; } @@ -1772,6 +1791,7 @@ export interface EnumMember extends Declaration { kind: SyntaxKind.EnumMember; + parent?: EnumDeclaration; // This does include ComputedPropertyName, but the parser will give an error // if it parses a ComputedPropertyName in an EnumMember name: PropertyName; @@ -1790,7 +1810,8 @@ export interface ModuleDeclaration extends DeclarationStatement { kind: SyntaxKind.ModuleDeclaration; - name: Identifier | StringLiteral; + parent?: ModuleBody | SourceFile; + name: ModuleName; body?: ModuleBody | JSDocNamespaceDeclaration | Identifier; } @@ -1810,6 +1831,7 @@ export interface ModuleBlock extends Node, Statement { kind: SyntaxKind.ModuleBlock; + parent?: ModuleDeclaration; statements: NodeArray; } @@ -1817,6 +1839,7 @@ export interface ImportEqualsDeclaration extends DeclarationStatement { kind: SyntaxKind.ImportEqualsDeclaration; + parent?: SourceFile | ModuleBlock; name: Identifier; // 'EntityName' for an internal module reference, 'ExternalModuleReference' for an external @@ -1826,6 +1849,7 @@ export interface ExternalModuleReference extends Node { kind: SyntaxKind.ExternalModuleReference; + parent?: ImportEqualsDeclaration; expression?: Expression; } @@ -1835,6 +1859,7 @@ // ImportClause information is shown at its declaration below. export interface ImportDeclaration extends Statement { kind: SyntaxKind.ImportDeclaration; + parent?: SourceFile | ModuleBlock; importClause?: ImportClause; moduleSpecifier: Expression; } @@ -1849,12 +1874,14 @@ // import d, { a, b as x } from "mod" => name = d, namedBinding: NamedImports = { elements: [{ name: a }, { name: x, propertyName: b}]} export interface ImportClause extends Declaration { kind: SyntaxKind.ImportClause; + parent?: ImportDeclaration; name?: Identifier; // Default binding namedBindings?: NamedImportBindings; } export interface NamespaceImport extends Declaration { kind: SyntaxKind.NamespaceImport; + parent?: ImportClause; name: Identifier; } @@ -1866,17 +1893,20 @@ export interface ExportDeclaration extends DeclarationStatement { kind: SyntaxKind.ExportDeclaration; + parent?: SourceFile | ModuleBlock; exportClause?: NamedExports; moduleSpecifier?: Expression; } export interface NamedImports extends Node { kind: SyntaxKind.NamedImports; + parent?: ImportClause; elements: NodeArray; } export interface NamedExports extends Node { kind: SyntaxKind.NamedExports; + parent?: ExportDeclaration; elements: NodeArray; } @@ -1884,12 +1914,14 @@ export interface ImportSpecifier extends Declaration { kind: SyntaxKind.ImportSpecifier; + parent?: NamedImports; propertyName?: Identifier; // Name preceding "as" keyword (or undefined when "as" is absent) name: Identifier; // Declared name } export interface ExportSpecifier extends Declaration { kind: SyntaxKind.ExportSpecifier; + parent?: NamedExports; propertyName?: Identifier; // Name preceding "as" keyword (or undefined when "as" is absent) name: Identifier; // Declared name } @@ -1898,6 +1930,7 @@ export interface ExportAssignment extends DeclarationStatement { kind: SyntaxKind.ExportAssignment; + parent?: SourceFile; isExportEquals?: boolean; expression: Expression; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 66bf693d831..e107c4b669b 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -435,8 +435,8 @@ namespace ts { } /** Given a symbol for a module, checks that it is either an untyped import or a shorthand ambient module. */ - export function isShorthandAmbientModuleSymbol(moduleSymbol: Symbol): boolean { - return isShorthandAmbientModule(moduleSymbol.valueDeclaration); + export function isUntypedOrShorthandAmbientModuleSymbol(moduleSymbol: Symbol): boolean { + return !moduleSymbol.declarations || isShorthandAmbientModule(moduleSymbol.valueDeclaration); } function isShorthandAmbientModule(node: Node): boolean { @@ -1554,7 +1554,10 @@ namespace ts { } } else { - result.push(...filter((doc as JSDoc).tags, tag => tag.kind === kind)); + const tags = (doc as JSDoc).tags; + if (tags) { + result.push(...filter(tags, tag => tag.kind === kind)); + } } } return result; @@ -3126,6 +3129,15 @@ namespace ts { return tryGetClassExtendingExpressionWithTypeArguments(node) !== undefined; } + export function isExpressionWithTypeArgumentsInClassImplementsClause(node: Node): node is ExpressionWithTypeArguments { + return node.kind === SyntaxKind.ExpressionWithTypeArguments + && isEntityNameExpression((node as ExpressionWithTypeArguments).expression) + && node.parent + && (node.parent).token === SyntaxKind.ImplementsKeyword + && node.parent.parent + && isClassLike(node.parent.parent); + } + export function isEntityNameExpression(node: Expression): node is EntityNameExpression { return node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.PropertyAccessExpression && isEntityNameExpression((node).expression); diff --git a/src/server/protocol.ts b/src/server/protocol.ts index c7d27d80d25..d054867cd1c 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -2218,6 +2218,7 @@ namespace ts.server.protocol { insertSpaceAfterFunctionKeywordForAnonymousFunctions?: boolean; insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis?: boolean; insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets?: boolean; + insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces?: boolean; insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces?: boolean; insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces?: boolean; insertSpaceBeforeFunctionParenthesis?: boolean; diff --git a/src/services/breakpoints.ts b/src/services/breakpoints.ts index c751cf3871b..1f6bec41109 100644 --- a/src/services/breakpoints.ts +++ b/src/services/breakpoints.ts @@ -370,8 +370,8 @@ namespace ts.BreakpointResolver { } function textSpanFromVariableDeclaration(variableDeclaration: VariableDeclaration): TextSpan { - const declarations = variableDeclaration.parent.declarations; - if (declarations && declarations[0] === variableDeclaration) { + if (variableDeclaration.parent.kind === SyntaxKind.VariableDeclarationList && + variableDeclaration.parent.declarations[0] === variableDeclaration) { // First declaration - include let keyword return textSpan(findPrecedingToken(variableDeclaration.pos, sourceFile, variableDeclaration.parent), variableDeclaration); } @@ -400,8 +400,8 @@ namespace ts.BreakpointResolver { return textSpanFromVariableDeclaration(variableDeclaration); } - const declarations = variableDeclaration.parent.declarations; - if (declarations && declarations[0] !== variableDeclaration) { + if (variableDeclaration.parent.kind === SyntaxKind.VariableDeclarationList && + variableDeclaration.parent.declarations[0] !== variableDeclaration) { // If we cannot set breakpoint on this declaration, set it on previous one // Because the variable declaration may be binding pattern and // we would like to set breakpoint in last binding element if that's the case, diff --git a/src/services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts b/src/services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts index 22546e55ecc..16edce0a516 100644 --- a/src/services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts +++ b/src/services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts @@ -22,8 +22,8 @@ namespace ts.codefix { const classDecl = token.parent as ClassLikeDeclaration; const startPos = classDecl.members.pos; - const classType = checker.getTypeAtLocation(classDecl) as InterfaceType; - const instantiatedExtendsType = checker.getBaseTypes(classType)[0]; + const extendsNode = getClassExtendsHeritageClauseElement(classDecl); + const instantiatedExtendsType = checker.getTypeAtLocation(extendsNode); // Note that this is ultimately derived from a map indexed by symbol names, // so duplicates cannot occur. diff --git a/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts b/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts index 42488dc2aed..67b2242c8d9 100644 --- a/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts +++ b/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts @@ -17,7 +17,7 @@ namespace ts.codefix { } const startPos: number = classDecl.members.pos; - const classType = checker.getTypeAtLocation(classDecl); + const classType = checker.getTypeAtLocation(classDecl) as InterfaceType; const implementedTypeNodes = getClassImplementsHeritageClauseElements(classDecl); const hasNumericIndexSignature = !!checker.getIndexTypeOfType(classType, IndexKind.Number); @@ -25,9 +25,9 @@ namespace ts.codefix { const result: CodeAction[] = []; for (const implementedTypeNode of implementedTypeNodes) { - const implementedType = checker.getTypeFromTypeNode(implementedTypeNode) as InterfaceType; // Note that this is ultimately derived from a map indexed by symbol names, // so duplicates cannot occur. + const implementedType = checker.getTypeAtLocation(implementedTypeNode) as InterfaceType; const implementedTypeSymbols = checker.getPropertiesOfType(implementedType); const nonPrivateMembers = implementedTypeSymbols.filter(symbol => !(getModifierFlags(symbol.valueDeclaration) & ModifierFlags.Private)); diff --git a/src/services/codefixes/helpers.ts b/src/services/codefixes/helpers.ts index 3eab994f84c..d20fc0129cd 100644 --- a/src/services/codefixes/helpers.ts +++ b/src/services/codefixes/helpers.ts @@ -23,8 +23,6 @@ namespace ts.codefix { * @returns Empty string iff there we can't figure out a representation for `symbol` in `enclosingDeclaration`. */ function getInsertionForMemberSymbol(symbol: Symbol, enclosingDeclaration: ClassLikeDeclaration, checker: TypeChecker, newlineChar: string): string { - // const name = symbol.getName(); - const type = checker.getTypeOfSymbolAtLocation(symbol, enclosingDeclaration); const declarations = symbol.getDeclarations(); if (!(declarations && declarations.length)) { return ""; @@ -34,6 +32,8 @@ namespace ts.codefix { const name = declaration.name ? declaration.name.getText() : undefined; const visibility = getVisibilityPrefixWithSpace(getModifierFlags(declaration)); + const type = checker.getTypeOfSymbolAtLocation(symbol, enclosingDeclaration); + switch (declaration.kind) { case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: diff --git a/src/services/completions.ts b/src/services/completions.ts index 1bf57d33fdc..6a4ee3485de 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -16,11 +16,16 @@ namespace ts.Completions { return undefined; } - const { symbols, isGlobalCompletion, isMemberCompletion, isNewIdentifierLocation, location, isJsDocTagName } = completionData; + const { symbols, isGlobalCompletion, isMemberCompletion, isNewIdentifierLocation, location, requestJsDocTagName, requestJsDocTag } = completionData; - if (isJsDocTagName) { + if (requestJsDocTagName) { // If the current position is a jsDoc tag name, only tag names should be provided for completion - return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, entries: JsDoc.getAllJsDocCompletionEntries() }; + return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, entries: JsDoc.getJSDocTagNameCompletions() }; + } + + if (requestJsDocTag) { + // If the current position is a jsDoc tag, only tags should be provided for completion + return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, entries: JsDoc.getJSDocTagCompletions() }; } const entries: CompletionEntry[] = []; @@ -54,7 +59,7 @@ namespace ts.Completions { } // Add keywords if this is not a member completion list - if (!isMemberCompletion && !isJsDocTagName) { + if (!isMemberCompletion && !requestJsDocTag && !requestJsDocTagName) { addRange(entries, keywordCompletions); } @@ -814,7 +819,10 @@ namespace ts.Completions { function getCompletionData(typeChecker: TypeChecker, log: (message: string) => void, sourceFile: SourceFile, position: number) { const isJavaScriptFile = isSourceFileJavaScript(sourceFile); - let isJsDocTagName = false; + // JsDoc tag-name is just the name of the JSDoc tagname (exclude "@") + let requestJsDocTagName = false; + // JsDoc tag includes both "@" and tag-name + let requestJsDocTag = false; let start = timestamp(); const currentToken = getTokenAtPosition(sourceFile, position); @@ -826,10 +834,32 @@ namespace ts.Completions { log("getCompletionData: Is inside comment: " + (timestamp() - start)); if (insideComment) { - // The current position is next to the '@' sign, when no tag name being provided yet. - // Provide a full list of tag names - if (hasDocComment(sourceFile, position) && sourceFile.text.charCodeAt(position - 1) === CharacterCodes.at) { - isJsDocTagName = true; + if (hasDocComment(sourceFile, position)) { + // The current position is next to the '@' sign, when no tag name being provided yet. + // Provide a full list of tag names + if (sourceFile.text.charCodeAt(position - 1) === CharacterCodes.at) { + requestJsDocTagName = true; + } + else { + // When completion is requested without "@", we will have check to make sure that + // there are no comments prefix the request position. We will only allow "*" and space. + // e.g + // /** |c| /* + // + // /** + // |c| + // */ + // + // /** + // * |c| + // */ + // + // /** + // * |c| + // */ + const lineStart = getLineStartPositionForPosition(position, sourceFile); + requestJsDocTag = !(sourceFile.text.substring(lineStart, position).match(/[^\*|\s|(/\*\*)]/)); + } } // Completion should work inside certain JsDoc tags. For example: @@ -839,7 +869,7 @@ namespace ts.Completions { const tag = getJsDocTagAtPosition(sourceFile, position); if (tag) { if (tag.tagName.pos <= position && position <= tag.tagName.end) { - isJsDocTagName = true; + requestJsDocTagName = true; } switch (tag.kind) { @@ -854,8 +884,8 @@ namespace ts.Completions { } } - if (isJsDocTagName) { - return { symbols: undefined, isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, location: undefined, isRightOfDot: false, isJsDocTagName }; + if (requestJsDocTagName || requestJsDocTag) { + return { symbols: undefined, isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, location: undefined, isRightOfDot: false, requestJsDocTagName, requestJsDocTag }; } if (!insideJsDocTagExpression) { @@ -983,7 +1013,7 @@ namespace ts.Completions { log("getCompletionData: Semantic work: " + (timestamp() - semanticStart)); - return { symbols, isGlobalCompletion, isMemberCompletion, isNewIdentifierLocation, location, isRightOfDot: (isRightOfDot || isRightOfOpenTag), isJsDocTagName }; + return { symbols, isGlobalCompletion, isMemberCompletion, isNewIdentifierLocation, location, isRightOfDot: (isRightOfDot || isRightOfOpenTag), requestJsDocTagName, requestJsDocTag }; function getTypeScriptMemberSymbols(): void { // Right of dot member completion list diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 24d7d648272..3dd55eb3590 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -133,7 +133,7 @@ namespace ts.FindAllReferences { return { symbol }; } - if (ts.isShorthandAmbientModuleSymbol(aliasedSymbol)) { + if (ts.isUntypedOrShorthandAmbientModuleSymbol(aliasedSymbol)) { return { symbol, shorthandModuleSymbol: aliasedSymbol }; } diff --git a/src/services/goToDefinition.ts b/src/services/goToDefinition.ts index 0ac6c9f7812..b732d8a1193 100644 --- a/src/services/goToDefinition.ts +++ b/src/services/goToDefinition.ts @@ -198,7 +198,11 @@ namespace ts.GoToDefinition { return false; } - function tryAddSignature(signatureDeclarations: Declaration[], selectConstructors: boolean, symbolKind: string, symbolName: string, containerName: string, result: DefinitionInfo[]) { + function tryAddSignature(signatureDeclarations: Declaration[] | undefined, selectConstructors: boolean, symbolKind: string, symbolName: string, containerName: string, result: DefinitionInfo[]) { + if (!signatureDeclarations) { + return false; + } + const declarations: Declaration[] = []; let definition: Declaration | undefined; diff --git a/src/services/jsDoc.ts b/src/services/jsDoc.ts index 08a51a63e63..59c6ad4b03b 100644 --- a/src/services/jsDoc.ts +++ b/src/services/jsDoc.ts @@ -42,7 +42,8 @@ namespace ts.JsDoc { "prop", "version" ]; - let jsDocCompletionEntries: CompletionEntry[]; + let jsDocTagNameCompletionEntries: CompletionEntry[]; + let jsDocTagCompletionEntries: CompletionEntry[]; export function getJsDocCommentsFromDeclarations(declarations: Declaration[]) { // Only collect doc comments from duplicate declarations once: @@ -88,8 +89,8 @@ namespace ts.JsDoc { return undefined; } - export function getAllJsDocCompletionEntries(): CompletionEntry[] { - return jsDocCompletionEntries || (jsDocCompletionEntries = ts.map(jsDocTagNames, tagName => { + export function getJSDocTagNameCompletions(): CompletionEntry[] { + return jsDocTagNameCompletionEntries || (jsDocTagNameCompletionEntries = ts.map(jsDocTagNames, tagName => { return { name: tagName, kind: ScriptElementKind.keyword, @@ -99,6 +100,17 @@ namespace ts.JsDoc { })); } + export function getJSDocTagCompletions(): CompletionEntry[] { + return jsDocTagCompletionEntries || (jsDocTagCompletionEntries = ts.map(jsDocTagNames, tagName => { + return { + name: `@${tagName}`, + kind: ScriptElementKind.keyword, + kindModifiers: "", + sortText: "0" + } + })); + } + /** * Checks if position points to a valid position to add JSDoc comments, and if so, * returns the appropriate template. Otherwise returns an empty string. diff --git a/src/services/services.ts b/src/services/services.ts index 0c7b5d97d26..f122e39bcc6 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -412,7 +412,7 @@ namespace ts { getDeclaration(): SignatureDeclaration { return this.declaration; } - getTypeParameters(): Type[] { + getTypeParameters(): TypeParameter[] { return this.typeParameters; } getParameters(): Symbol[] { diff --git a/src/services/types.ts b/src/services/types.ts index a577fb20aac..9253153c004 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -39,7 +39,7 @@ namespace ts { export interface Signature { getDeclaration(): SignatureDeclaration; - getTypeParameters(): Type[]; + getTypeParameters(): TypeParameter[]; getParameters(): Symbol[]; getReturnType(): Type; getDocumentationComment(): SymbolDisplayPart[]; diff --git a/tests/baselines/reference/emitter.forAwait.es5.js b/tests/baselines/reference/emitter.forAwait.es5.js index efbbe872b3f..14b70e933bb 100644 --- a/tests/baselines/reference/emitter.forAwait.es5.js +++ b/tests/baselines/reference/emitter.forAwait.es5.js @@ -68,36 +68,36 @@ var __asyncValues = (this && this.__asyncIterator) || function (o) { }; function f1() { return __awaiter(this, void 0, void 0, function () { - var y, y_1, y_1_1, x, _a, e_1, _b; - return __generator(this, function (_c) { - switch (_c.label) { + var y, y_1, y_1_1, x, e_1_1, e_1, _a; + return __generator(this, function (_b) { + switch (_b.label) { case 0: - _c.trys.push([0, 6, 7, 12]); + _b.trys.push([0, 6, 7, 12]); y_1 = __asyncValues(y); return [4 /*yield*/, y_1.next()]; case 1: - y_1_1 = _c.sent(); - _c.label = 2; + y_1_1 = _b.sent(); + _b.label = 2; case 2: if (!!y_1_1.done) return [3 /*break*/, 5]; x = y_1_1.value; - _c.label = 3; + _b.label = 3; case 3: return [4 /*yield*/, y_1.next()]; case 4: - y_1_1 = _c.sent(); + y_1_1 = _b.sent(); return [3 /*break*/, 2]; case 5: return [3 /*break*/, 12]; case 6: - _a = _c.sent(); + e_1_1 = _b.sent(); e_1 = { error: e_1_1 }; return [3 /*break*/, 12]; case 7: - _c.trys.push([7, , 10, 11]); - if (!(y_1_1 && !y_1_1.done && (_b = y_1.return))) return [3 /*break*/, 9]; - return [4 /*yield*/, _b.call(y_1)]; + _b.trys.push([7, , 10, 11]); + if (!(y_1_1 && !y_1_1.done && (_a = y_1.return))) return [3 /*break*/, 9]; + return [4 /*yield*/, _a.call(y_1)]; case 8: - _c.sent(); - _c.label = 9; + _b.sent(); + _b.label = 9; case 9: return [3 /*break*/, 11]; case 10: if (e_1) throw e_1.error; @@ -151,36 +151,36 @@ var __asyncValues = (this && this.__asyncIterator) || function (o) { }; function f2() { return __awaiter(this, void 0, void 0, function () { - var x, y, y_1, y_1_1, _a, e_1, _b; - return __generator(this, function (_c) { - switch (_c.label) { + var x, y, y_1, y_1_1, e_1_1, e_1, _a; + return __generator(this, function (_b) { + switch (_b.label) { case 0: - _c.trys.push([0, 6, 7, 12]); + _b.trys.push([0, 6, 7, 12]); y_1 = __asyncValues(y); return [4 /*yield*/, y_1.next()]; case 1: - y_1_1 = _c.sent(); - _c.label = 2; + y_1_1 = _b.sent(); + _b.label = 2; case 2: if (!!y_1_1.done) return [3 /*break*/, 5]; x = y_1_1.value; - _c.label = 3; + _b.label = 3; case 3: return [4 /*yield*/, y_1.next()]; case 4: - y_1_1 = _c.sent(); + y_1_1 = _b.sent(); return [3 /*break*/, 2]; case 5: return [3 /*break*/, 12]; case 6: - _a = _c.sent(); + e_1_1 = _b.sent(); e_1 = { error: e_1_1 }; return [3 /*break*/, 12]; case 7: - _c.trys.push([7, , 10, 11]); - if (!(y_1_1 && !y_1_1.done && (_b = y_1.return))) return [3 /*break*/, 9]; - return [4 /*yield*/, _b.call(y_1)]; + _b.trys.push([7, , 10, 11]); + if (!(y_1_1 && !y_1_1.done && (_a = y_1.return))) return [3 /*break*/, 9]; + return [4 /*yield*/, _a.call(y_1)]; case 8: - _c.sent(); - _c.label = 9; + _b.sent(); + _b.label = 9; case 9: return [3 /*break*/, 11]; case 10: if (e_1) throw e_1.error; @@ -239,36 +239,36 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar }; function f3() { return __asyncGenerator(this, arguments, function f3_1() { - var y, y_1, y_1_1, x, _a, e_1, _b; - return __generator(this, function (_c) { - switch (_c.label) { + var y, y_1, y_1_1, x, e_1_1, e_1, _a; + return __generator(this, function (_b) { + switch (_b.label) { case 0: - _c.trys.push([0, 6, 7, 12]); + _b.trys.push([0, 6, 7, 12]); y_1 = __asyncValues(y); return [4 /*yield*/, ["await", y_1.next()]]; case 1: - y_1_1 = _c.sent(); - _c.label = 2; + y_1_1 = _b.sent(); + _b.label = 2; case 2: if (!!y_1_1.done) return [3 /*break*/, 5]; x = y_1_1.value; - _c.label = 3; + _b.label = 3; case 3: return [4 /*yield*/, ["await", y_1.next()]]; case 4: - y_1_1 = _c.sent(); + y_1_1 = _b.sent(); return [3 /*break*/, 2]; case 5: return [3 /*break*/, 12]; case 6: - _a = _c.sent(); + e_1_1 = _b.sent(); e_1 = { error: e_1_1 }; return [3 /*break*/, 12]; case 7: - _c.trys.push([7, , 10, 11]); - if (!(y_1_1 && !y_1_1.done && (_b = y_1.return))) return [3 /*break*/, 9]; - return [4 /*yield*/, ["await", _b.call(y_1)]]; + _b.trys.push([7, , 10, 11]); + if (!(y_1_1 && !y_1_1.done && (_a = y_1.return))) return [3 /*break*/, 9]; + return [4 /*yield*/, ["await", _a.call(y_1)]]; case 8: - _c.sent(); - _c.label = 9; + _b.sent(); + _b.label = 9; case 9: return [3 /*break*/, 11]; case 10: if (e_1) throw e_1.error; @@ -327,36 +327,36 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar }; function f4() { return __asyncGenerator(this, arguments, function f4_1() { - var x, y, y_1, y_1_1, _a, e_1, _b; - return __generator(this, function (_c) { - switch (_c.label) { + var x, y, y_1, y_1_1, e_1_1, e_1, _a; + return __generator(this, function (_b) { + switch (_b.label) { case 0: - _c.trys.push([0, 6, 7, 12]); + _b.trys.push([0, 6, 7, 12]); y_1 = __asyncValues(y); return [4 /*yield*/, ["await", y_1.next()]]; case 1: - y_1_1 = _c.sent(); - _c.label = 2; + y_1_1 = _b.sent(); + _b.label = 2; case 2: if (!!y_1_1.done) return [3 /*break*/, 5]; x = y_1_1.value; - _c.label = 3; + _b.label = 3; case 3: return [4 /*yield*/, ["await", y_1.next()]]; case 4: - y_1_1 = _c.sent(); + y_1_1 = _b.sent(); return [3 /*break*/, 2]; case 5: return [3 /*break*/, 12]; case 6: - _a = _c.sent(); + e_1_1 = _b.sent(); e_1 = { error: e_1_1 }; return [3 /*break*/, 12]; case 7: - _c.trys.push([7, , 10, 11]); - if (!(y_1_1 && !y_1_1.done && (_b = y_1.return))) return [3 /*break*/, 9]; - return [4 /*yield*/, ["await", _b.call(y_1)]]; + _b.trys.push([7, , 10, 11]); + if (!(y_1_1 && !y_1_1.done && (_a = y_1.return))) return [3 /*break*/, 9]; + return [4 /*yield*/, ["await", _a.call(y_1)]]; case 8: - _c.sent(); - _c.label = 9; + _b.sent(); + _b.label = 9; case 9: return [3 /*break*/, 11]; case 10: if (e_1) throw e_1.error; diff --git a/tests/baselines/reference/evalAfter0.errors.txt b/tests/baselines/reference/evalAfter0.errors.txt new file mode 100644 index 00000000000..448772eda08 --- /dev/null +++ b/tests/baselines/reference/evalAfter0.errors.txt @@ -0,0 +1,10 @@ +tests/cases/compiler/evalAfter0.ts(4,2): error TS2695: Left side of comma operator is unused and has no side effects. + + +==== tests/cases/compiler/evalAfter0.ts (1 errors) ==== + (0,eval)("10"); // fine: special case for eval + + declare var eva; + (0,eva)("10"); // error: no side effect left of comma (suspect of missing method name or something) + ~ +!!! error TS2695: Left side of comma operator is unused and has no side effects. \ No newline at end of file diff --git a/tests/baselines/reference/evalAfter0.js b/tests/baselines/reference/evalAfter0.js new file mode 100644 index 00000000000..aeaa8f6476c --- /dev/null +++ b/tests/baselines/reference/evalAfter0.js @@ -0,0 +1,9 @@ +//// [evalAfter0.ts] +(0,eval)("10"); // fine: special case for eval + +declare var eva; +(0,eva)("10"); // error: no side effect left of comma (suspect of missing method name or something) + +//// [evalAfter0.js] +(0, eval)("10"); // fine: special case for eval +(0, eva)("10"); // error: no side effect left of comma (suspect of missing method name or something) diff --git a/tests/baselines/reference/extendsUntypedModule.errors.txt b/tests/baselines/reference/extendsUntypedModule.errors.txt new file mode 100644 index 00000000000..9a1c4235352 --- /dev/null +++ b/tests/baselines/reference/extendsUntypedModule.errors.txt @@ -0,0 +1,14 @@ +/a.ts(2,17): error TS2507: Type 'any' is not a constructor function type. + + +==== /a.ts (1 errors) ==== + import Foo from "foo"; + class A extends Foo { } + ~~~ +!!! error TS2507: Type 'any' is not a constructor function type. + +==== /node_modules/foo/index.js (0 errors) ==== + // Test that extending an untyped module is an error, unlike extending unknownSymbol. + + This file is not read. + \ No newline at end of file diff --git a/tests/baselines/reference/extendsUntypedModule.js b/tests/baselines/reference/extendsUntypedModule.js new file mode 100644 index 00000000000..f86ded7e6cb --- /dev/null +++ b/tests/baselines/reference/extendsUntypedModule.js @@ -0,0 +1,33 @@ +//// [tests/cases/compiler/extendsUntypedModule.ts] //// + +//// [index.js] +// Test that extending an untyped module is an error, unlike extending unknownSymbol. + +This file is not read. + +//// [a.ts] +import Foo from "foo"; +class A extends Foo { } + + +//// [a.js] +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +exports.__esModule = true; +var foo_1 = require("foo"); +var A = (function (_super) { + __extends(A, _super); + function A() { + return _super !== null && _super.apply(this, arguments) || this; + } + return A; +}(foo_1["default"])); diff --git a/tests/baselines/reference/jsDocTypes.js b/tests/baselines/reference/jsDocTypes.js new file mode 100644 index 00000000000..a6df2f361c6 --- /dev/null +++ b/tests/baselines/reference/jsDocTypes.js @@ -0,0 +1,137 @@ +//// [tests/cases/conformance/salsa/jsDocTypes.ts] //// + +//// [a.js] + +/** @type {String} */ +var S; + +/** @type {string} */ +var s; + +/** @type {Number} */ +var N; + +/** @type {number} */ +var n; + +/** @type {Boolean} */ +var B; + +/** @type {boolean} */ +var b; + +/** @type {Void} */ +var V; + +/** @type {void} */ +var v; + +/** @type {Undefined} */ +var U; + +/** @type {undefined} */ +var u; + +/** @type {Null} */ +var Nl; + +/** @type {null} */ +var nl; + +/** @type {Array} */ +var A; + +/** @type {array} */ +var a; + +/** @type {Promise} */ +var P; + +/** @type {promise} */ +var p; + +/** @type {?number} */ +var nullable; + +/** @type {Object} */ +var Obj; + + + +//// [b.ts] +var S: string; +var s: string; +var N: number; +var n: number +var B: boolean; +var b: boolean; +var V :void; +var v: void; +var U: undefined; +var u: undefined; +var Nl: null; +var nl: null; +var A: any[]; +var a: any[]; +var P: Promise; +var p: Promise; +var nullable: number | null; +var Obj: any; + + +//// [a.js] +/** @type {String} */ +var S; +/** @type {string} */ +var s; +/** @type {Number} */ +var N; +/** @type {number} */ +var n; +/** @type {Boolean} */ +var B; +/** @type {boolean} */ +var b; +/** @type {Void} */ +var V; +/** @type {void} */ +var v; +/** @type {Undefined} */ +var U; +/** @type {undefined} */ +var u; +/** @type {Null} */ +var Nl; +/** @type {null} */ +var nl; +/** @type {Array} */ +var A; +/** @type {array} */ +var a; +/** @type {Promise} */ +var P; +/** @type {promise} */ +var p; +/** @type {?number} */ +var nullable; +/** @type {Object} */ +var Obj; +//// [b.js] +var S; +var s; +var N; +var n; +var B; +var b; +var V; +var v; +var U; +var u; +var Nl; +var nl; +var A; +var a; +var P; +var p; +var nullable; +var Obj; diff --git a/tests/baselines/reference/jsDocTypes.symbols b/tests/baselines/reference/jsDocTypes.symbols new file mode 100644 index 00000000000..9bde032cb44 --- /dev/null +++ b/tests/baselines/reference/jsDocTypes.symbols @@ -0,0 +1,133 @@ +=== tests/cases/conformance/salsa/a.js === + +/** @type {String} */ +var S; +>S : Symbol(S, Decl(a.js, 2, 3), Decl(b.ts, 0, 3)) + +/** @type {string} */ +var s; +>s : Symbol(s, Decl(a.js, 5, 3), Decl(b.ts, 1, 3)) + +/** @type {Number} */ +var N; +>N : Symbol(N, Decl(a.js, 8, 3), Decl(b.ts, 2, 3)) + +/** @type {number} */ +var n; +>n : Symbol(n, Decl(a.js, 11, 3), Decl(b.ts, 3, 3)) + +/** @type {Boolean} */ +var B; +>B : Symbol(B, Decl(a.js, 14, 3), Decl(b.ts, 4, 3)) + +/** @type {boolean} */ +var b; +>b : Symbol(b, Decl(a.js, 17, 3), Decl(b.ts, 5, 3)) + +/** @type {Void} */ +var V; +>V : Symbol(V, Decl(a.js, 20, 3), Decl(b.ts, 6, 3)) + +/** @type {void} */ +var v; +>v : Symbol(v, Decl(a.js, 23, 3), Decl(b.ts, 7, 3)) + +/** @type {Undefined} */ +var U; +>U : Symbol(U, Decl(a.js, 26, 3), Decl(b.ts, 8, 3)) + +/** @type {undefined} */ +var u; +>u : Symbol(u, Decl(a.js, 29, 3), Decl(b.ts, 9, 3)) + +/** @type {Null} */ +var Nl; +>Nl : Symbol(Nl, Decl(a.js, 32, 3), Decl(b.ts, 10, 3)) + +/** @type {null} */ +var nl; +>nl : Symbol(nl, Decl(a.js, 35, 3), Decl(b.ts, 11, 3)) + +/** @type {Array} */ +var A; +>A : Symbol(A, Decl(a.js, 38, 3), Decl(b.ts, 12, 3)) + +/** @type {array} */ +var a; +>a : Symbol(a, Decl(a.js, 41, 3), Decl(b.ts, 13, 3)) + +/** @type {Promise} */ +var P; +>P : Symbol(P, Decl(a.js, 44, 3), Decl(b.ts, 14, 3)) + +/** @type {promise} */ +var p; +>p : Symbol(p, Decl(a.js, 47, 3), Decl(b.ts, 15, 3)) + +/** @type {?number} */ +var nullable; +>nullable : Symbol(nullable, Decl(a.js, 50, 3), Decl(b.ts, 16, 3)) + +/** @type {Object} */ +var Obj; +>Obj : Symbol(Obj, Decl(a.js, 53, 3), Decl(b.ts, 17, 3)) + + + +=== tests/cases/conformance/salsa/b.ts === +var S: string; +>S : Symbol(S, Decl(a.js, 2, 3), Decl(b.ts, 0, 3)) + +var s: string; +>s : Symbol(s, Decl(a.js, 5, 3), Decl(b.ts, 1, 3)) + +var N: number; +>N : Symbol(N, Decl(a.js, 8, 3), Decl(b.ts, 2, 3)) + +var n: number +>n : Symbol(n, Decl(a.js, 11, 3), Decl(b.ts, 3, 3)) + +var B: boolean; +>B : Symbol(B, Decl(a.js, 14, 3), Decl(b.ts, 4, 3)) + +var b: boolean; +>b : Symbol(b, Decl(a.js, 17, 3), Decl(b.ts, 5, 3)) + +var V :void; +>V : Symbol(V, Decl(a.js, 20, 3), Decl(b.ts, 6, 3)) + +var v: void; +>v : Symbol(v, Decl(a.js, 23, 3), Decl(b.ts, 7, 3)) + +var U: undefined; +>U : Symbol(U, Decl(a.js, 26, 3), Decl(b.ts, 8, 3)) + +var u: undefined; +>u : Symbol(u, Decl(a.js, 29, 3), Decl(b.ts, 9, 3)) + +var Nl: null; +>Nl : Symbol(Nl, Decl(a.js, 32, 3), Decl(b.ts, 10, 3)) + +var nl: null; +>nl : Symbol(nl, Decl(a.js, 35, 3), Decl(b.ts, 11, 3)) + +var A: any[]; +>A : Symbol(A, Decl(a.js, 38, 3), Decl(b.ts, 12, 3)) + +var a: any[]; +>a : Symbol(a, Decl(a.js, 41, 3), Decl(b.ts, 13, 3)) + +var P: Promise; +>P : Symbol(P, Decl(a.js, 44, 3), Decl(b.ts, 14, 3)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --)) + +var p: Promise; +>p : Symbol(p, Decl(a.js, 47, 3), Decl(b.ts, 15, 3)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --)) + +var nullable: number | null; +>nullable : Symbol(nullable, Decl(a.js, 50, 3), Decl(b.ts, 16, 3)) + +var Obj: any; +>Obj : Symbol(Obj, Decl(a.js, 53, 3), Decl(b.ts, 17, 3)) + diff --git a/tests/baselines/reference/jsDocTypes.types b/tests/baselines/reference/jsDocTypes.types new file mode 100644 index 00000000000..c0214edf627 --- /dev/null +++ b/tests/baselines/reference/jsDocTypes.types @@ -0,0 +1,136 @@ +=== tests/cases/conformance/salsa/a.js === + +/** @type {String} */ +var S; +>S : string + +/** @type {string} */ +var s; +>s : string + +/** @type {Number} */ +var N; +>N : number + +/** @type {number} */ +var n; +>n : number + +/** @type {Boolean} */ +var B; +>B : boolean + +/** @type {boolean} */ +var b; +>b : boolean + +/** @type {Void} */ +var V; +>V : void + +/** @type {void} */ +var v; +>v : void + +/** @type {Undefined} */ +var U; +>U : undefined + +/** @type {undefined} */ +var u; +>u : undefined + +/** @type {Null} */ +var Nl; +>Nl : null + +/** @type {null} */ +var nl; +>nl : null + +/** @type {Array} */ +var A; +>A : any[] + +/** @type {array} */ +var a; +>a : any[] + +/** @type {Promise} */ +var P; +>P : Promise + +/** @type {promise} */ +var p; +>p : Promise + +/** @type {?number} */ +var nullable; +>nullable : number | null + +/** @type {Object} */ +var Obj; +>Obj : any + + + +=== tests/cases/conformance/salsa/b.ts === +var S: string; +>S : string + +var s: string; +>s : string + +var N: number; +>N : number + +var n: number +>n : number + +var B: boolean; +>B : boolean + +var b: boolean; +>b : boolean + +var V :void; +>V : void + +var v: void; +>v : void + +var U: undefined; +>U : undefined + +var u: undefined; +>u : undefined + +var Nl: null; +>Nl : null +>null : null + +var nl: null; +>nl : null +>null : null + +var A: any[]; +>A : any[] + +var a: any[]; +>a : any[] + +var P: Promise; +>P : Promise +>Promise : Promise + +var p: Promise; +>p : Promise +>Promise : Promise + +var nullable: number | null; +>nullable : number | null +>null : null + +var Obj: any; +>Obj : any + diff --git a/tests/baselines/reference/jsFileCompilationRestParamJsDocFunction.types b/tests/baselines/reference/jsFileCompilationRestParamJsDocFunction.types index 54bc7938689..66e3da3e67f 100644 --- a/tests/baselines/reference/jsFileCompilationRestParamJsDocFunction.types +++ b/tests/baselines/reference/jsFileCompilationRestParamJsDocFunction.types @@ -10,8 +10,8 @@ * @returns {*} Returns the result of `func`. */ function apply(func, thisArg, args) { ->apply : (func: Function, thisArg: any, ...args: any[]) => any ->func : Function +>apply : (func: {}, thisArg: any, ...args: any[]) => any +>func : {} >thisArg : any >args : any[] @@ -28,7 +28,7 @@ function apply(func, thisArg, args) { >0 : 0 >func.call(thisArg) : any >func.call : (this: Function, thisArg: any, ...argArray: any[]) => any ->func : Function +>func : {} >call : (this: Function, thisArg: any, ...argArray: any[]) => any >thisArg : any @@ -36,7 +36,7 @@ function apply(func, thisArg, args) { >1 : 1 >func.call(thisArg, args[0]) : any >func.call : (this: Function, thisArg: any, ...argArray: any[]) => any ->func : Function +>func : {} >call : (this: Function, thisArg: any, ...argArray: any[]) => any >thisArg : any >args[0] : any @@ -47,7 +47,7 @@ function apply(func, thisArg, args) { >2 : 2 >func.call(thisArg, args[0], args[1]) : any >func.call : (this: Function, thisArg: any, ...argArray: any[]) => any ->func : Function +>func : {} >call : (this: Function, thisArg: any, ...argArray: any[]) => any >thisArg : any >args[0] : any @@ -61,7 +61,7 @@ function apply(func, thisArg, args) { >3 : 3 >func.call(thisArg, args[0], args[1], args[2]) : any >func.call : (this: Function, thisArg: any, ...argArray: any[]) => any ->func : Function +>func : {} >call : (this: Function, thisArg: any, ...argArray: any[]) => any >thisArg : any >args[0] : any @@ -77,12 +77,12 @@ function apply(func, thisArg, args) { return func.apply(thisArg, args); >func.apply(thisArg, args) : any >func.apply : (this: Function, thisArg: any, argArray?: any) => any ->func : Function +>func : {} >apply : (this: Function, thisArg: any, argArray?: any) => any >thisArg : any >args : any[] } export default apply; ->apply : (func: Function, thisArg: any, ...args: any[]) => any +>apply : (func: {}, thisArg: any, ...args: any[]) => any diff --git a/tests/baselines/reference/misspelledNewMetaProperty.errors.txt b/tests/baselines/reference/misspelledNewMetaProperty.errors.txt new file mode 100644 index 00000000000..429a40a5b80 --- /dev/null +++ b/tests/baselines/reference/misspelledNewMetaProperty.errors.txt @@ -0,0 +1,7 @@ +tests/cases/compiler/misspelledNewMetaProperty.ts(1,20): error TS17012: 'targ' is not a valid meta-property for keyword 'new'. Did you mean 'target'? + + +==== tests/cases/compiler/misspelledNewMetaProperty.ts (1 errors) ==== + function foo(){new.targ} + ~~~~ +!!! error TS17012: 'targ' is not a valid meta-property for keyword 'new'. Did you mean 'target'? \ No newline at end of file diff --git a/tests/baselines/reference/misspelledNewMetaProperty.js b/tests/baselines/reference/misspelledNewMetaProperty.js new file mode 100644 index 00000000000..964cf91d52c --- /dev/null +++ b/tests/baselines/reference/misspelledNewMetaProperty.js @@ -0,0 +1,5 @@ +//// [misspelledNewMetaProperty.ts] +function foo(){new.targ} + +//// [misspelledNewMetaProperty.js] +function foo() { new.targ; } diff --git a/tests/cases/compiler/evalAfter0.ts b/tests/cases/compiler/evalAfter0.ts new file mode 100644 index 00000000000..2245150ce6a --- /dev/null +++ b/tests/cases/compiler/evalAfter0.ts @@ -0,0 +1,4 @@ +(0,eval)("10"); // fine: special case for eval + +declare var eva; +(0,eva)("10"); // error: no side effect left of comma (suspect of missing method name or something) \ No newline at end of file diff --git a/tests/cases/compiler/extendsUntypedModule.ts b/tests/cases/compiler/extendsUntypedModule.ts new file mode 100644 index 00000000000..8eaf6b3833a --- /dev/null +++ b/tests/cases/compiler/extendsUntypedModule.ts @@ -0,0 +1,9 @@ +// Test that extending an untyped module is an error, unlike extending unknownSymbol. +// @noImplicitReferences: true + +// @Filename: /node_modules/foo/index.js +This file is not read. + +// @Filename: /a.ts +import Foo from "foo"; +class A extends Foo { } diff --git a/tests/cases/compiler/misspelledNewMetaProperty.ts b/tests/cases/compiler/misspelledNewMetaProperty.ts new file mode 100644 index 00000000000..8882264478c --- /dev/null +++ b/tests/cases/compiler/misspelledNewMetaProperty.ts @@ -0,0 +1 @@ +function foo(){new.targ} \ No newline at end of file diff --git a/tests/cases/conformance/salsa/jsDocTypes.ts b/tests/cases/conformance/salsa/jsDocTypes.ts new file mode 100644 index 00000000000..9a13c533d0a --- /dev/null +++ b/tests/cases/conformance/salsa/jsDocTypes.ts @@ -0,0 +1,80 @@ +// @allowJS: true +// @suppressOutputPathCheck: true +// @strictNullChecks: true + +// @filename: a.js +/** @type {String} */ +var S; + +/** @type {string} */ +var s; + +/** @type {Number} */ +var N; + +/** @type {number} */ +var n; + +/** @type {Boolean} */ +var B; + +/** @type {boolean} */ +var b; + +/** @type {Void} */ +var V; + +/** @type {void} */ +var v; + +/** @type {Undefined} */ +var U; + +/** @type {undefined} */ +var u; + +/** @type {Null} */ +var Nl; + +/** @type {null} */ +var nl; + +/** @type {Array} */ +var A; + +/** @type {array} */ +var a; + +/** @type {Promise} */ +var P; + +/** @type {promise} */ +var p; + +/** @type {?number} */ +var nullable; + +/** @type {Object} */ +var Obj; + + + +// @filename: b.ts +var S: string; +var s: string; +var N: number; +var n: number +var B: boolean; +var b: boolean; +var V :void; +var v: void; +var U: undefined; +var u: undefined; +var Nl: null; +var nl: null; +var A: any[]; +var a: any[]; +var P: Promise; +var p: Promise; +var nullable: number | null; +var Obj: any; diff --git a/tests/cases/fourslash/codeFixClassExtendAbstractGetterSetter.ts b/tests/cases/fourslash/codeFixClassExtendAbstractGetterSetter.ts index fc0ac400623..4bddfb799f2 100644 --- a/tests/cases/fourslash/codeFixClassExtendAbstractGetterSetter.ts +++ b/tests/cases/fourslash/codeFixClassExtendAbstractGetterSetter.ts @@ -2,9 +2,17 @@ //// abstract class A { //// private _a: string; -//// -//// abstract get a(): string; -//// abstract set a(newName: string); +//// +//// abstract get a(): number | string; +//// abstract get b(): this; +//// abstract get c(): A; +//// +//// abstract set d(arg: number | string); +//// abstract set e(arg: this); +//// abstract set f(arg: A); +//// +//// abstract get g(): string; +//// abstract set g(newName: string); //// } //// //// // Don't need to add anything in this case. @@ -13,5 +21,11 @@ //// class C extends A {[| |]} verify.rangeAfterCodeFix(` - a: string; + a: string | number; + b: this; + c: A; + d: string | number; + e: this; + f: A; + g: string; `); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixClassExtendAbstractMethod.ts b/tests/cases/fourslash/codeFixClassExtendAbstractMethod.ts index a657dfeb718..344a7ee3f2b 100644 --- a/tests/cases/fourslash/codeFixClassExtendAbstractMethod.ts +++ b/tests/cases/fourslash/codeFixClassExtendAbstractMethod.ts @@ -2,6 +2,7 @@ //// abstract class A { //// abstract f(a: number, b: string): boolean; +//// abstract f(a: number, b: string): this; //// abstract f(a: string, b: number): Function; //// abstract f(a: string): Function; //// } @@ -10,6 +11,7 @@ verify.rangeAfterCodeFix(` f(a: number, b: string): boolean; + f(a: number, b: string): this; f(a: string, b: number): Function; f(a: string): Function; f(a: any, b?: any) { diff --git a/tests/cases/fourslash/codeFixClassExtendAbstractSetter.ts b/tests/cases/fourslash/codeFixClassExtendAbstractMethodThis.ts similarity index 50% rename from tests/cases/fourslash/codeFixClassExtendAbstractSetter.ts rename to tests/cases/fourslash/codeFixClassExtendAbstractMethodThis.ts index e8cb55fa660..55b3ad4b77e 100644 --- a/tests/cases/fourslash/codeFixClassExtendAbstractSetter.ts +++ b/tests/cases/fourslash/codeFixClassExtendAbstractMethodThis.ts @@ -1,11 +1,13 @@ -/// - -//// abstract class A { -//// abstract set c(arg: number | string); -//// } -//// -//// class C extends A {[| |]} - -verify.rangeAfterCodeFix(` - c: string | number; -`); \ No newline at end of file +/// + +//// abstract class A { +//// abstract f(): this; +//// } +//// +//// class C extends A {[| |]} + +verify.rangeAfterCodeFix(` + f(): this { + throw new Error('Method not implemented.'); + } +`); diff --git a/tests/cases/fourslash/codeFixClassExtendAbstractProperty.ts b/tests/cases/fourslash/codeFixClassExtendAbstractProperty.ts index 3160a3b9a08..b7300acf5ae 100644 --- a/tests/cases/fourslash/codeFixClassExtendAbstractProperty.ts +++ b/tests/cases/fourslash/codeFixClassExtendAbstractProperty.ts @@ -2,6 +2,8 @@ //// abstract class A { //// abstract x: number; +//// abstract y: this; +//// abstract z: A; //// abstract foo(): number; //// } //// @@ -10,6 +12,8 @@ verify.rangeAfterCodeFix(` x: number; + y: this; + z: A; foo(): number { throw new Error('Method not implemented.'); } diff --git a/tests/cases/fourslash/codeFixClassExtendAbstractGetter.ts b/tests/cases/fourslash/codeFixClassExtendAbstractPropertyThis.ts similarity index 68% rename from tests/cases/fourslash/codeFixClassExtendAbstractGetter.ts rename to tests/cases/fourslash/codeFixClassExtendAbstractPropertyThis.ts index 8d79cce710e..de128ca1b79 100644 --- a/tests/cases/fourslash/codeFixClassExtendAbstractGetter.ts +++ b/tests/cases/fourslash/codeFixClassExtendAbstractPropertyThis.ts @@ -1,11 +1,11 @@ -/// - -//// abstract class A { -//// abstract get b(): number; -//// } -//// -//// class C extends A {[| |]} - -verify.rangeAfterCodeFix(` - b: number; -`); \ No newline at end of file +/// + +//// abstract class A { +//// abstract x: this; +//// } +//// +//// class C extends A {[| |]} + +verify.rangeAfterCodeFix(` + x: this; +`); diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceMethodWithParams.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceMethodThisAndSelfReference.ts similarity index 71% rename from tests/cases/fourslash/codeFixClassImplementInterfaceMethodWithParams.ts rename to tests/cases/fourslash/codeFixClassImplementInterfaceMethodThisAndSelfReference.ts index 0ee842975e0..95cc3476bf1 100644 --- a/tests/cases/fourslash/codeFixClassImplementInterfaceMethodWithParams.ts +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceMethodThisAndSelfReference.ts @@ -1,14 +1,14 @@ /// //// interface I { -//// f(x: number, y: string): I +//// f(x: number, y: this): I //// } //// //// class C implements I {[| //// |]} verify.rangeAfterCodeFix(` -f(x: number,y: string): I { +f(x: number,y: this): I { throw new Error('Method not implemented.'); } `); diff --git a/tests/cases/fourslash/completionInJsDoc.ts b/tests/cases/fourslash/completionInJsDoc.ts index 8ab9dbd0131..60707905956 100644 --- a/tests/cases/fourslash/completionInJsDoc.ts +++ b/tests/cases/fourslash/completionInJsDoc.ts @@ -2,29 +2,57 @@ // @allowJs: true // @Filename: Foo.js -/////** @/*1*/ */ -////var v1; +//// /** @/*1*/ */ +//// var v1; //// -/////** @p/*2*/ */ -////var v2; +//// /** @p/*2*/ */ +//// var v2; //// -/////** @param /*3*/ */ -////var v3; +//// /** @param /*3*/ */ +//// var v3; //// -/////** @param { n/*4*/ } bar */ -////var v4; +//// /** @param { n/*4*/ } bar */ +//// var v4; //// -/////** @type { n/*5*/ } */ -////var v5; +//// /** @type { n/*5*/ } */ +//// var v5; //// -////// @/*6*/ -////var v6; +//// // @/*6*/ +//// var v6; //// -////// @pa/*7*/ -////var v7; +//// // @pa/*7*/ +//// var v7; //// -/////** @return { n/*8*/ } */ -////var v8; +//// /** @return { n/*8*/ } */ +//// var v8; +//// +//// /** /*9*/ */ +//// +//// /** +//// /*10*/ +//// */ +//// +//// /** +//// * /*11*/ +//// */ +//// +//// /** +//// /*12*/ +//// */ +//// +//// /** +//// * /*13*/ +//// */ +//// +//// /** +//// * some comment /*14*/ +//// */ +//// +//// /** +//// * @param /*15*/ +//// */ +//// +//// /** @param /*16*/ */ goTo.marker('1'); verify.completionListContains("constructor"); @@ -55,3 +83,31 @@ verify.completionListIsEmpty(); goTo.marker('8'); verify.completionListContains('number'); +goTo.marker('9'); +verify.completionListCount(40); +verify.completionListContains("@argument"); + +goTo.marker('10'); +verify.completionListCount(40); +verify.completionListContains("@returns"); + +goTo.marker('11'); +verify.completionListCount(40); +verify.completionListContains("@argument"); + +goTo.marker('12'); +verify.completionListCount(40); +verify.completionListContains("@constructor"); + +goTo.marker('13'); +verify.completionListCount(40); +verify.completionListContains("@param"); + +goTo.marker('14'); +verify.completionListIsEmpty(); + +goTo.marker('15'); +verify.completionListIsEmpty(); + +goTo.marker('16'); +verify.completionListIsEmpty(); \ No newline at end of file diff --git a/tests/cases/fourslash/completionListAtInvalidLocations.ts b/tests/cases/fourslash/completionListAtInvalidLocations.ts index 0660f0e183b..171f63825f2 100644 --- a/tests/cases/fourslash/completionListAtInvalidLocations.ts +++ b/tests/cases/fourslash/completionListAtInvalidLocations.ts @@ -1,28 +1,24 @@ /// -////var v1 = ''; -////" /*openString1*/ -////var v2 = ''; -////"/*openString2*/ -////var v3 = ''; -////" bar./*openString3*/ -////var v4 = ''; -////// bar./*inComment1*/ -////var v6 = ''; -////// /*inComment2*/ -////var v7 = ''; -/////** /*inComment3*/ -////var v8 = ''; -/////** /*inComment4*/ **/ -////var v9 = ''; -/////* /*inComment5*/ -////var v11 = ''; -//// // /*inComment6*/ -////var v12 = ''; -////type htm/*inTypeAlias*/ -/// -////// /*inComment7*/ -////foo; -////var v10 = /reg/*inRegExp1*/ex/; +//// var v1 = ''; +//// " /*openString1*/ +//// var v2 = ''; +//// "/*openString2*/ +//// var v3 = ''; +//// " bar./*openString3*/ +//// var v4 = ''; +//// // bar./*inComment1*/ +//// var v6 = ''; +//// // /*inComment2*/ +//// var v7 = ''; +//// /* /*inComment3*/ +//// var v11 = ''; +//// // /*inComment4*/ +//// var v12 = ''; +//// type htm/*inTypeAlias*/ +//// +//// // /*inComment5*/ +//// foo; +//// var v10 = /reg/*inRegExp1*/ex/; goTo.eachMarker(() => verify.completionListIsEmpty()); diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 34afb71ec85..ab83752d93b 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -92,6 +92,7 @@ declare namespace FourSlashInterface { InsertSpaceAfterFunctionKeywordForAnonymousFunctions: boolean; InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: boolean; InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: boolean; + InsertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: boolean; InsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: boolean; InsertSpaceAfterTypeAssertion: boolean; PlaceOpenBraceOnNewLineForFunctions: boolean; diff --git a/tests/cases/fourslash/goToDefinition_untypedModule.ts b/tests/cases/fourslash/goToDefinition_untypedModule.ts new file mode 100644 index 00000000000..b4571438434 --- /dev/null +++ b/tests/cases/fourslash/goToDefinition_untypedModule.ts @@ -0,0 +1,10 @@ +/// + +// @Filename: /node_modules/foo/index.js +////not read + +// @Filename: /a.ts +////import { f } from "foo"; +/////**/f(); + +verify.goToDefinition("", []); diff --git a/tests/cases/fourslash/renameJsSpecialAssignmentRhs1.ts b/tests/cases/fourslash/renameJsSpecialAssignmentRhs1.ts new file mode 100644 index 00000000000..b4b9fb80528 --- /dev/null +++ b/tests/cases/fourslash/renameJsSpecialAssignmentRhs1.ts @@ -0,0 +1,13 @@ +/// +// @allowJs: true +// @Filename: a.js +////const foo = { +//// set: function (x) { +//// this._x = x; +//// }, +//// copy: function ([|x|]) { +//// this._x = /**/[|x|].prop; +//// } +////}; +goTo.marker(); +verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false); diff --git a/tests/cases/fourslash/renameJsSpecialAssignmentRhs2.ts b/tests/cases/fourslash/renameJsSpecialAssignmentRhs2.ts new file mode 100644 index 00000000000..5b4b6e851cf --- /dev/null +++ b/tests/cases/fourslash/renameJsSpecialAssignmentRhs2.ts @@ -0,0 +1,13 @@ +/// +// @allowJs: true +// @Filename: a.js +////const foo = { +//// set: function (x) { +//// this._x = x; +//// }, +//// copy: function (/**/[|x|]) { +//// this._x = [|x|].prop; +//// } +////}; +goTo.marker(); +verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false); diff --git a/tests/cases/fourslash/server/jsdocTypedefTag1.ts b/tests/cases/fourslash/server/jsdocTypedefTag1.ts new file mode 100644 index 00000000000..273dc1002af --- /dev/null +++ b/tests/cases/fourslash/server/jsdocTypedefTag1.ts @@ -0,0 +1,20 @@ +/// + +// @allowNonTsExtensions: true +// @Filename: jsdocCompletion_typedef.js + +//// /** +//// * @typedef {Object} MyType +//// * @property {string} yes +//// */ +//// function foo() { } + +//// /** +//// * @param {MyType} my +//// */ +//// function a(my) { +//// my.yes./*1*/ +//// } + +goTo.marker('1'); +verify.completionListContains('charAt'); \ No newline at end of file diff --git a/tests/cases/fourslash/server/jsdocTypedefTag2.ts b/tests/cases/fourslash/server/jsdocTypedefTag2.ts new file mode 100644 index 00000000000..60210935210 --- /dev/null +++ b/tests/cases/fourslash/server/jsdocTypedefTag2.ts @@ -0,0 +1,30 @@ +/// + +// @allowNonTsExtensions: true +// @Filename: jsdocCompletion_typedef.js + +//// /** +//// * @typedef {Object} A.B.MyType +//// * @property {string} yes +//// */ +//// function foo() {} + +//// /** +//// * @param {A.B.MyType} my2 +//// */ +//// function a(my2) { +//// my2.yes./*1*/ +//// } + +//// /** +//// * @param {MyType} my2 +//// */ +//// function b(my2) { +//// my2.yes./*2*/ +//// } + + +goTo.marker('1'); +verify.completionListContains('charAt'); +goTo.marker('2'); +verify.not.completionListContains('charAt'); \ No newline at end of file diff --git a/tests/cases/fourslash/untypedModuleImport.ts b/tests/cases/fourslash/untypedModuleImport.ts index 1854010d5b6..433c584e3cf 100644 --- a/tests/cases/fourslash/untypedModuleImport.ts +++ b/tests/cases/fourslash/untypedModuleImport.ts @@ -12,7 +12,7 @@ verify.numberOfErrorsInCurrentFile(0); goTo.marker("fooModule"); verify.goToDefinitionIs([]); -verify.quickInfoIs(""); +verify.quickInfoIs("module "); verify.noReferences(); goTo.marker("foo");