diff --git a/.mailmap b/.mailmap index 73ebed0cc7c..97941bcdf5a 100644 --- a/.mailmap +++ b/.mailmap @@ -248,4 +248,23 @@ rdosanjh # Raj Dosanjh gdh1995 # Dahan Gong cedvdb # @cedvdb kpreisser # K. Preißer -e-cloud # @e-cloud \ No newline at end of file +e-cloud # @e-cloud +Andrew Casey Andrew Casey +Andrew Stegmaier +Benny Neugebauer +Blaine Bublitz +Charles Pierce +Daniel Król +Diogo Franco (Kovensky) +Donald Pipowitch +Halasi Tamás +Ika +Joe Chung +Kate Miháliková +Mohsen Azimi +Noel Varanda +Reiner Dolp +t_ # @t_ +TravCav # @TravCav +Vladimir Kurchatkin +William Orr \ No newline at end of file diff --git a/AUTHORS.md b/AUTHORS.md index 4772d5371fa..824c696ce4f 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -15,7 +15,9 @@ TypeScript is authored by: * Anders Hejlsberg * Andreas Martin * Andrej Baran +* Andrew Casey * Andrew Ochsner +* Andrew Stegmaier * Andrew Z Allen * András Parditka * Andy Hanson @@ -31,7 +33,9 @@ TypeScript is authored by: * Ben Duffield * Ben Mosher * Benjamin Bock +* Benny Neugebauer * Bill Ticehurst +* Blaine Bublitz * Blake Embrey * @bootstraponline * Bowden Kelly @@ -39,6 +43,7 @@ TypeScript is authored by: * Bryan Forbes * Caitlin Potter * @cedvdb +* Charles Pierce * Charly POLY * Chris Bubernak * Christophe Vidal @@ -52,6 +57,7 @@ TypeScript is authored by: * Dan Corder * Dan Quirk * Daniel Hollocher +* Daniel Król * Daniel Lehenbauer * Daniel Rosenwasser * David Kmenta @@ -60,9 +66,11 @@ TypeScript is authored by: * David Souther * Denis Nedelyaev * Dick van den Brink +* Diogo Franco (Kovensky) * Dirk Bäumer * Dirk Holtwick * Dom Chen +* Donald Pipowitch * Doug Ilijev * @e-cloud * Elisée Maurer @@ -89,12 +97,14 @@ TypeScript is authored by: * Guilherme Oenning * Guillaume Salles * Guy Bedford +* Halasi Tamás * Harald Niesche * Hendrik Liebau * Herrington Darkholme * Homa Wong * Iain Monro * Igor Novozhilov +* Ika * Ingvar Stepanyan * Isiah Meadows * Ivo Gabe de Wolff @@ -111,6 +121,7 @@ TypeScript is authored by: * Jeffrey Morlan * Jesse Schalken * Jiri Tobisek +* Joe Chung * Joel Day * Joey Wilson * Johannes Rieken @@ -131,6 +142,7 @@ TypeScript is authored by: * K. Preißer * Kagami Sascha Rosylight * Kanchalai Tanglertsampan +* Kate Miháliková * Keith Mashinter * Ken Howard * Kenji Imamula @@ -159,6 +171,7 @@ TypeScript is authored by: * Mike Busyrev * Mine Starks * Mohamed Hegazy +* Mohsen Azimi * Myles Megyesi * Natalie Coley * Nathan Shively-Sanders @@ -166,6 +179,7 @@ TypeScript is authored by: * Nicolas Henry * Nima Zahedi * Noah Chen +* Noel Varanda * Noj Vek * Oleg Mihailik * Oleksandr Chekhovskyi @@ -186,6 +200,7 @@ TypeScript is authored by: * Punya Biswal * Rado Kirov * Raj Dosanjh +* Reiner Dolp * Richard Karmazín * Richard Knoll * Richard Sentino @@ -213,6 +228,7 @@ TypeScript is authored by: * Sudheesh Singanamalla * Sébastien Arod * @T18970237136 +* @t_ * Tarik Ozket * Tetsuharu Ohzeki * Thomas Loubiou @@ -225,13 +241,16 @@ TypeScript is authored by: * togru * Tomas Grubliauskas * Torben Fitschen +* @TravCav * TruongSinh Tran-Nguyen * Vadi Taslim * Vidar Tonaas Fauske * Viktor Zozulyak * Vilic Vane +* Vladimir Kurchatkin * Vladimir Matveev * Wesley Wigham +* William Orr * York Yao * @yortus * Yuichi Nukiyama diff --git a/Gulpfile.ts b/Gulpfile.ts index c2724b5fb10..63faf992599 100644 --- a/Gulpfile.ts +++ b/Gulpfile.ts @@ -39,25 +39,25 @@ Error.stackTraceLimit = 1000; const cmdLineOptions = minimist(process.argv.slice(2), { boolean: ["debug", "inspect", "light", "colors", "lint", "soft"], - string: ["browser", "tests", "host", "reporter", "stackTraceLimit"], + string: ["browser", "tests", "host", "reporter", "stackTraceLimit", "timeout"], alias: { b: "browser", - d: "debug", - t: "tests", - test: "tests", + d: "debug", "debug-brk": "debug", + i: "inspect", "inspect-brk": "inspect", + t: "tests", test: "tests", r: "reporter", - color: "colors", - f: "files", - file: "files", + c: "colors", color: "colors", + f: "files", file: "files", w: "workers", }, default: { soft: false, colors: process.env.colors || process.env.color || true, - debug: process.env.debug || process.env.d, - inspect: process.env.inspect, + debug: process.env.debug || process.env["debug-brk"] || process.env.d, + inspect: process.env.inspect || process.env["inspect-brk"] || process.env.i, host: process.env.TYPESCRIPT_HOST || process.env.host || "node", browser: process.env.browser || process.env.b || "IE", + timeout: process.env.timeout || 40000, tests: process.env.test || process.env.tests || process.env.t, light: process.env.light || false, reporter: process.env.reporter || process.env.r, @@ -594,11 +594,11 @@ function restoreSavedNodeEnv() { process.env.NODE_ENV = savedNodeEnv; } -let testTimeout = 40000; function runConsoleTests(defaultReporter: string, runInParallel: boolean, done: (e?: any) => void) { const lintFlag = cmdLineOptions["lint"]; cleanTestDirs((err) => { if (err) { console.error(err); failWithStatus(err, 1); } + let testTimeout = cmdLineOptions["timeout"]; const debug = cmdLineOptions["debug"]; const inspect = cmdLineOptions["inspect"]; const tests = cmdLineOptions["tests"]; @@ -637,12 +637,6 @@ function runConsoleTests(defaultReporter: string, runInParallel: boolean, done: // default timeout is 2sec which really should be enough, but maybe we just need a small amount longer if (!runInParallel) { const args = []; - if (inspect) { - args.push("--inspect"); - } - if (inspect || debug) { - args.push("--debug-brk"); - } args.push("-R", reporter); if (tests) { args.push("-g", `"${tests}"`); @@ -653,7 +647,15 @@ function runConsoleTests(defaultReporter: string, runInParallel: boolean, done: else { args.push("--no-colors"); } - args.push("-t", testTimeout); + if (inspect) { + args.unshift("--inspect-brk"); + } + else if (debug) { + args.unshift("--debug-brk"); + } + else { + args.push("-t", testTimeout); + } args.push(run); setNodeEnvToDevelopment(); exec(mocha, args, lintThenFinish, function(e, status) { @@ -838,6 +840,7 @@ gulp.task("runtests-browser", "Runs the tests using the built run.js file like ' }); gulp.task("generate-code-coverage", "Generates code coverage data via istanbul", ["tests"], (done) => { + const testTimeout = cmdLineOptions["timeout"]; exec("istanbul", ["cover", "node_modules/mocha/bin/_mocha", "--", "-R", "min", "-t", testTimeout.toString(), run], done, done); }); diff --git a/Jakefile.js b/Jakefile.js index fe0d5f7352e..730754f4256 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -25,6 +25,8 @@ var LKGDirectory = "lib/"; var copyright = "CopyrightNotice.txt"; var thirdParty = "ThirdPartyNoticeText.txt"; +var defaultTestTimeout = 40000; + // add node_modules to path so we don't need global modules, prefer the modules by adding them first var nodeModulesPathPrefix = path.resolve("./node_modules/.bin/") + path.delimiter; if (process.env.path !== undefined) { @@ -74,6 +76,10 @@ function measure(marker) { console.log("travis_time:end:" + marker.id + ":start=" + toNs(marker.stamp) + ",finish=" + toNs(total) + ",duration=" + toNs(diff) + "\r"); } +function removeConstModifierFromEnumDeclarations(text) { + return text.replace(/^(\s*)(export )?const enum (\S+) {(\s*)$/gm, '$1$2enum $3 {$4'); +} + var compilerSources = filesFromConfig("./src/compiler/tsconfig.json"); var servicesSources = filesFromConfig("./src/services/tsconfig.json"); var cancellationTokenSources = filesFromConfig(path.join(serverDirectory, "cancellationToken/tsconfig.json")); @@ -268,7 +274,6 @@ var builtLocalCompiler = path.join(builtLocalDirectory, compilerFilename); * @param {boolean} opts.preserveConstEnums: true if compiler should keep const enums in code * @param {boolean} opts.noResolve: true if compiler should not include non-rooted files in compilation * @param {boolean} opts.stripInternal: true if compiler should remove declarations marked as @internal - * @param {boolean} opts.noMapRoot: true if compiler omit mapRoot option * @param {boolean} opts.inlineSourceMap: true if compiler should inline sourceMap * @param {Array} opts.types: array of types to include in compilation * @param callback: a function to execute after the compilation process ends @@ -321,9 +326,6 @@ function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, opts } else { options += " -sourcemap"; - if (!opts.noMapRoot) { - options += " -mapRoot file:///" + path.resolve(path.dirname(outFile)); - } } } else { @@ -527,7 +529,7 @@ task("importDefinitelyTypedTests", [importDefinitelyTypedTestsJs], function () { // Local target to build the compiler and services var tscFile = path.join(builtLocalDirectory, compilerFilename); -compileFile(tscFile, compilerSources, [builtLocalDirectory, copyright].concat(compilerSources), [copyright], /*useBuiltCompiler:*/ false, { noMapRoot: true }); +compileFile(tscFile, compilerSources, [builtLocalDirectory, copyright].concat(compilerSources), [copyright], /*useBuiltCompiler:*/ false); var servicesFile = path.join(builtLocalDirectory, "typescriptServices.js"); var servicesFileInBrowserTest = path.join(builtLocalDirectory, "typescriptServicesInBrowserTest.js"); @@ -555,7 +557,7 @@ compileFile(servicesFile, servicesSources, [builtLocalDirectory, copyright].conc // Stanalone/web definition file using global 'ts' namespace jake.cpR(standaloneDefinitionsFile, nodeDefinitionsFile, { silent: true }); var definitionFileContents = fs.readFileSync(nodeDefinitionsFile).toString(); - definitionFileContents = definitionFileContents.replace(/^(\s*)(export )?const enum (\S+) {(\s*)$/gm, '$1$2enum $3 {$4'); + definitionFileContents = removeConstModifierFromEnumDeclarations(definitionFileContents) fs.writeFileSync(standaloneDefinitionsFile, definitionFileContents); // Official node package definition file, pointed to by 'typings' in package.json @@ -582,7 +584,6 @@ compileFile( keepComments: true, noResolve: false, stripInternal: true, - noMapRoot: true, inlineSourceMap: true }); @@ -616,6 +617,7 @@ compileFile( fs.readFileSync(tsserverLibraryDefinitionFile).toString() + "\r\nexport = ts;" + "\r\nexport as namespace ts;"; + tsserverLibraryDefinitionFileContents = removeConstModifierFromEnumDeclarations(tsserverLibraryDefinitionFileContents); fs.writeFileSync(tsserverLibraryDefinitionFile, tsserverLibraryDefinitionFileContents); }); @@ -805,9 +807,10 @@ function runConsoleTests(defaultReporter, runInParallel) { cleanTestDirs(); } - var debug = process.env.debug || process.env.d; - var inspect = process.env.inspect; - tests = process.env.test || process.env.tests || process.env.t; + var debug = process.env.debug || process.env["debug-brk"] || process.env.d; + var inspect = process.env.inspect || process.env["inspect-brk"] || process.env.i; + var testTimeout = process.env.timeout || defaultTestTimeout; + var tests = process.env.test || process.env.tests || process.env.t; var light = process.env.light || false; var stackTraceLimit = process.env.stackTraceLimit; var testConfigFile = 'test.config'; @@ -825,7 +828,7 @@ function runConsoleTests(defaultReporter, runInParallel) { } while (fs.existsSync(taskConfigsFolder)); fs.mkdirSync(taskConfigsFolder); - workerCount = process.env.workerCount || os.cpus().length; + workerCount = process.env.workerCount || process.env.p || os.cpus().length; } if (tests || light || taskConfigsFolder) { @@ -846,12 +849,6 @@ function runConsoleTests(defaultReporter, runInParallel) { if (!runInParallel) { var startTime = mark(); var args = []; - if (inspect) { - args.push("--inspect"); - } - if (inspect || debug) { - args.push("--debug-brk"); - } args.push("-R", reporter); if (tests) { args.push("-g", `"${tests}"`); @@ -865,7 +862,15 @@ function runConsoleTests(defaultReporter, runInParallel) { if (bail) { args.push("--bail"); } - args.push("-t", testTimeout); + if (inspect) { + args.unshift("--inspect-brk"); + } + else if (debug) { + args.unshift("--debug-brk"); + } + else { + args.push("-t", testTimeout); + } args.push(run); var cmd = "mocha " + args.join(" "); @@ -930,7 +935,6 @@ function runConsoleTests(defaultReporter, runInParallel) { } } -var testTimeout = 20000; desc("Runs all the tests in parallel using the built run.js file. Optional arguments are: t[ests]=category1|category2|... d[ebug]=true."); task("runtests-parallel", ["build-rules", "tests", builtLocalDirectory], function () { runConsoleTests('min', /*runInParallel*/ true); @@ -943,6 +947,7 @@ task("runtests", ["build-rules", "tests", builtLocalDirectory], function() { desc("Generates code coverage data via instanbul"); task("generate-code-coverage", ["tests", builtLocalDirectory], function () { + var testTimeout = process.env.timeout || defaultTestTimeout; var cmd = 'istanbul cover node_modules/mocha/bin/_mocha -- -R min -t ' + testTimeout + ' ' + run; console.log(cmd); exec(cmd); diff --git a/scripts/buildProtocol.ts b/scripts/buildProtocol.ts index 37ebd0105ae..e03338bf60d 100644 --- a/scripts/buildProtocol.ts +++ b/scripts/buildProtocol.ts @@ -113,7 +113,7 @@ class DeclarationsWalker { } } -function generateProtocolFile(protocolTs: string, typeScriptServicesDts: string): string { +function writeProtocolFile(outputFile: string, protocolTs: string, typeScriptServicesDts: string) { const options = { target: ts.ScriptTarget.ES5, declaration: true, noResolve: true, types: [], stripInternal: true }; /** @@ -163,14 +163,17 @@ function generateProtocolFile(protocolTs: string, typeScriptServicesDts: string) protocolDts += "\nimport protocol = ts.server.protocol;"; protocolDts += "\nexport = protocol;"; protocolDts += "\nexport as namespace protocol;"; + // do sanity check and try to compile generated text as standalone program const sanityCheckProgram = getProgramWithProtocolText(protocolDts, /*includeTypeScriptServices*/ false); const diagnostics = [...sanityCheckProgram.getSyntacticDiagnostics(), ...sanityCheckProgram.getSemanticDiagnostics(), ...sanityCheckProgram.getGlobalDiagnostics()]; + + ts.sys.writeFile(outputFile, protocolDts); + if (diagnostics.length) { const flattenedDiagnostics = diagnostics.map(d => `${ts.flattenDiagnosticMessageText(d.messageText, "\n")} at ${d.file.fileName} line ${d.start}`).join("\n"); throw new Error(`Unexpected errors during sanity check: ${flattenedDiagnostics}`); } - return protocolDts; } if (process.argv.length < 5) { @@ -181,5 +184,4 @@ if (process.argv.length < 5) { const protocolTs = process.argv[2]; const typeScriptServicesDts = process.argv[3]; const outputFile = process.argv[4]; -const generatedProtocolDts = generateProtocolFile(protocolTs, typeScriptServicesDts); -ts.sys.writeFile(outputFile, generatedProtocolDts); +writeProtocolFile(outputFile, protocolTs, typeScriptServicesDts); diff --git a/scripts/tslint/nextLineRule.ts b/scripts/tslint/nextLineRule.ts index b149d09eb38..fa03746afc6 100644 --- a/scripts/tslint/nextLineRule.ts +++ b/scripts/tslint/nextLineRule.ts @@ -18,7 +18,7 @@ export class Rule extends Lint.Rules.AbstractRule { function walk(ctx: Lint.WalkContext, checkCatch: boolean, checkElse: boolean): void { const { sourceFile } = ctx; - function recur(node: ts.Node): void { + ts.forEachChild(sourceFile, function recur(node) { switch (node.kind) { case ts.SyntaxKind.IfStatement: checkIf(node as ts.IfStatement); @@ -28,7 +28,7 @@ function walk(ctx: Lint.WalkContext, checkCatch: boolean, checkElse: boole break; } ts.forEachChild(node, recur); - } + }); function checkIf(node: ts.IfStatement): void { const { thenStatement, elseStatement } = node; diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index d55f3650c10..ba5022a7b3c 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -612,7 +612,7 @@ namespace ts { break; case SyntaxKind.ForInStatement: case SyntaxKind.ForOfStatement: - bindForInOrForOfStatement(node); + bindForInOrForOfStatement(node); break; case SyntaxKind.IfStatement: bindIfStatement(node); @@ -950,7 +950,7 @@ namespace ts { currentFlow = finishFlowLabel(postLoopLabel); } - function bindForInOrForOfStatement(node: ForInStatement | ForOfStatement): void { + function bindForInOrForOfStatement(node: ForInOrOfStatement): void { const preLoopLabel = createLoopLabel(); const postLoopLabel = createBranchLabel(); addAntecedent(preLoopLabel, currentFlow); @@ -1328,7 +1328,7 @@ namespace ts { function bindVariableDeclarationFlow(node: VariableDeclaration) { bindEachChild(node); - if (node.initializer || node.parent.parent.kind === SyntaxKind.ForInStatement || node.parent.parent.kind === SyntaxKind.ForOfStatement) { + if (node.initializer || isForInOrOfStatement(node.parent.parent)) { bindInitializedVariableFlow(node); } } @@ -1521,7 +1521,7 @@ namespace ts { // All the children of these container types are never visible through another // symbol (i.e. through another symbol's 'exports' or 'members'). Instead, // they're only accessed 'lexically' (i.e. from code that exists underneath - // their container in the tree. To accomplish this, we simply add their declared + // their container in the tree). To accomplish this, we simply add their declared // symbol to the 'locals' of the container. These symbols can then be found as // the type checker walks up the containers, checking them for matching names. return declareSymbol(container.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes); @@ -2053,7 +2053,10 @@ namespace ts { case SyntaxKind.TypePredicate: return checkTypePredicate(node as TypePredicateNode); case SyntaxKind.TypeParameter: - return declareSymbolAndAddToSymbolTable(node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes); + if (node.parent.kind !== ts.SyntaxKind.JSDocTemplateTag || isInJavaScriptFile(node)) { + return declareSymbolAndAddToSymbolTable(node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes); + } + return; case SyntaxKind.Parameter: return bindParameter(node); case SyntaxKind.VariableDeclaration: @@ -2135,8 +2138,10 @@ namespace ts { case SyntaxKind.EnumDeclaration: return bindEnumDeclaration(node); case SyntaxKind.ModuleDeclaration: - return bindModuleDeclaration(node); - + if (node.parent.kind !== ts.SyntaxKind.JSDocTypedefTag || isInJavaScriptFile(node)) { + return bindModuleDeclaration(node); + } + return undefined; // Jsx-attributes case SyntaxKind.JsxAttributes: return bindJsxAttributes(node); @@ -2333,7 +2338,7 @@ namespace ts { // A common practice in node modules is to set 'export = module.exports = {}', this ensures that 'exports' // is still pointing to 'module.exports'. // We do not want to consider this as 'export=' since a module can have only one of these. - // Similarlly we do not want to treat 'module.exports = exports' as an 'export='. + // Similarly we do not want to treat 'module.exports = exports' as an 'export='. const assignedExpression = getRightMostAssignedExpression(node.right); if (isEmptyObjectLiteral(assignedExpression) || isExportsOrModuleExportsOrAlias(assignedExpression)) { // Mark it as a module in case there are no other exports in the file @@ -2741,6 +2746,10 @@ namespace ts { transformFlags |= TransformFlags.AssertES2015; } + if (expression.kind === SyntaxKind.ImportKeyword) { + transformFlags |= TransformFlags.ContainsDynamicImport; + } + node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; return transformFlags & ~TransformFlags.ArrayLiteralOrCallOrNewExcludes; } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 58ffc78f889..7d57825bf44 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -210,6 +210,11 @@ namespace ts { getSuggestionForNonexistentProperty, getSuggestionForNonexistentSymbol, getBaseConstraintOfType, + getJsxNamespace, + resolveNameAtLocation(location: Node, name: string, meaning: SymbolFlags): Symbol | undefined { + location = getParseTreeNode(location); + return resolveName(location, name, meaning, /*nameNotFoundMessage*/ undefined, name); + }, }; const tupleTypes: GenericType[] = []; @@ -735,6 +740,7 @@ namespace ts { if (declarationFile !== useFile) { if ((modulekind && (declarationFile.externalModuleIndicator || useFile.externalModuleIndicator)) || (!compilerOptions.outFile && !compilerOptions.out) || + isInTypeQuery(usage) || isInAmbientContext(declaration)) { // nodes are in different files and order cannot be determined return true; @@ -798,16 +804,8 @@ namespace ts { break; } - switch (declaration.parent.parent.kind) { - case SyntaxKind.ForInStatement: - case SyntaxKind.ForOfStatement: - // ForIn/ForOf case - use site should not be used in expression part - if (isSameScopeDescendentOf(usage, (declaration.parent.parent).expression, container)) { - return true; - } - } - - return false; + // ForIn/ForOf case - use site should not be used in expression part + return isForInOrOfStatement(declaration.parent.parent) && isSameScopeDescendentOf(usage, declaration.parent.parent.expression, container); } function isUsedInFunctionOrInstanceProperty(usage: Node, declaration: Node, container?: Node): boolean { @@ -847,7 +845,7 @@ namespace ts { location: Node | undefined, name: string, meaning: SymbolFlags, - nameNotFoundMessage: DiagnosticMessage, + nameNotFoundMessage: DiagnosticMessage | undefined, nameArg: string | Identifier, suggestedNameNotFoundMessage?: DiagnosticMessage): Symbol { return resolveNameHelper(location, name, meaning, nameNotFoundMessage, nameArg, getSymbol, suggestedNameNotFoundMessage); @@ -1364,6 +1362,9 @@ namespace ts { // An 'import { Point } from "graphics"' needs to create a symbol that combines the value side 'Point' // property with the type/namespace side interface 'Point'. function combineValueAndTypeSymbols(valueSymbol: Symbol, typeSymbol: Symbol): Symbol { + if (valueSymbol === unknownSymbol && typeSymbol === unknownSymbol) { + return unknownSymbol; + } if (valueSymbol.flags & (SymbolFlags.Type | SymbolFlags.Namespace)) { return valueSymbol; } @@ -1464,8 +1465,15 @@ namespace ts { } } + /** + * Indicates that a symbol is an alias that does not merge with a local declaration. + */ + function isNonLocalAlias(symbol: Symbol, excludes = SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace) { + return symbol && (symbol.flags & (SymbolFlags.Alias | excludes)) === SymbolFlags.Alias; + } + function resolveSymbol(symbol: Symbol, dontResolveAlias?: boolean): Symbol { - const shouldResolve = !dontResolveAlias && symbol && symbol.flags & SymbolFlags.Alias && !(symbol.flags & (SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace)); + const shouldResolve = !dontResolveAlias && isNonLocalAlias(symbol); return shouldResolve ? resolveAlias(symbol) : symbol; } @@ -2282,10 +2290,10 @@ namespace ts { function typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string { const typeNode = nodeBuilder.typeToTypeNode(type, enclosingDeclaration, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors | NodeBuilderFlags.WriteTypeParametersInQualifiedName); - Debug.assert(typeNode !== undefined, "should always get typenode?"); + Debug.assert(typeNode !== undefined, "should always get typenode"); const options = { removeComments: true }; const writer = createTextWriter(""); - const printer = createPrinter(options, writer); + const printer = createPrinter(options); const sourceFile = enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration); printer.writeNode(EmitHint.Unspecified, typeNode, /*sourceFile*/ sourceFile, writer); const result = writer.getText(); @@ -2816,6 +2824,17 @@ namespace ts { function symbolToParameterDeclaration(parameterSymbol: Symbol, context: NodeBuilderContext): ParameterDeclaration { const parameterDeclaration = getDeclarationOfKind(parameterSymbol, SyntaxKind.Parameter); + if (isTransientSymbol(parameterSymbol) && parameterSymbol.isRestParameter) { + // special-case synthetic rest parameters in JS files + return createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + parameterSymbol.isRestParameter ? createToken(SyntaxKind.DotDotDotToken) : undefined, + "args", + /*questionToken*/ undefined, + typeToTypeNodeHelper(anyArrayType, context), + /*initializer*/ undefined); + } const modifiers = parameterDeclaration.modifiers && parameterDeclaration.modifiers.map(getSynthesizedClone); const dotDotDotToken = isRestParameter(parameterDeclaration) ? createToken(SyntaxKind.DotDotDotToken) : undefined; const name = parameterDeclaration.name ? @@ -4173,16 +4192,6 @@ namespace ts { // Return the inferred type for a variable, parameter, or property declaration function getTypeForVariableLikeDeclaration(declaration: VariableLikeDeclaration, includeOptionality: boolean): Type { - if (declaration.flags & NodeFlags.JavaScriptFile) { - // If this is a variable in a JavaScript file, then use the JSDoc type (if it has - // one as its type), otherwise fallback to the below standard TS codepaths to - // try to figure it out. - const type = getTypeForDeclarationFromJSDocComment(declaration); - if (type && type !== unknownType) { - return type; - } - } - // A variable declared in a for..in statement is of type string, or of type keyof T when the // right hand expression is of a type parameter type. if (declaration.parent.parent.kind === SyntaxKind.ForInStatement) { @@ -4204,8 +4213,9 @@ namespace ts { } // Use type from type annotation if one is present - if (declaration.type) { - const declaredType = getTypeFromTypeNode(declaration.type); + const typeNode = getEffectiveTypeAnnotationNode(declaration); + if (typeNode) { + const declaredType = getTypeFromTypeNode(typeNode); return addOptionality(declaredType, /*optional*/ declaration.questionToken && includeOptionality); } @@ -4496,10 +4506,11 @@ namespace ts { function getAnnotatedAccessorType(accessor: AccessorDeclaration): Type { if (accessor) { if (accessor.kind === SyntaxKind.GetAccessor) { - return accessor.type && getTypeFromTypeNode(accessor.type); + const getterTypeAnnotation = getEffectiveReturnTypeNode(accessor); + return getterTypeAnnotation && getTypeFromTypeNode(getterTypeAnnotation); } else { - const setterTypeAnnotation = getSetAccessorTypeAnnotationNode(accessor); + const setterTypeAnnotation = getEffectiveSetAccessorTypeAnnotationNode(accessor); return setterTypeAnnotation && getTypeFromTypeNode(setterTypeAnnotation); } } @@ -4652,7 +4663,7 @@ namespace ts { function reportCircularityError(symbol: Symbol) { // Check if variable has type annotation that circularly references the variable itself - if ((symbol.valueDeclaration).type) { + if (getEffectiveTypeAnnotationNode(symbol.valueDeclaration)) { error(symbol.valueDeclaration, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol)); return unknownType; @@ -5238,14 +5249,18 @@ namespace ts { // A variable-like declaration is considered independent (free of this references) if it has a type annotation // that specifies an independent type, or if it has no type annotation and no initializer (and thus of type any). function isIndependentVariableLikeDeclaration(node: VariableLikeDeclaration): boolean { - return node.type && isIndependentType(node.type) || !node.type && !node.initializer; + const typeNode = getEffectiveTypeAnnotationNode(node); + return typeNode ? isIndependentType(typeNode) : !node.initializer; } // A function-like declaration is considered independent (free of this references) if it has a return type // annotation that is considered independent and if each parameter is considered independent. function isIndependentFunctionLikeDeclaration(node: FunctionLikeDeclaration): boolean { - if (node.kind !== SyntaxKind.Constructor && (!node.type || !isIndependentType(node.type))) { - return false; + if (node.kind !== SyntaxKind.Constructor) { + const typeNode = getEffectiveReturnTypeNode(node); + if (!typeNode || !isIndependentType(typeNode)) { + return false; + } } for (const parameter of node.parameters) { if (!isIndependentVariableLikeDeclaration(parameter)) { @@ -5841,7 +5856,8 @@ namespace ts { } } return arrayFrom(props.values()); - } else { + } + else { return getPropertiesOfType(type); } } @@ -5957,7 +5973,7 @@ namespace ts { typeParameter.default = targetDefault ? instantiateType(targetDefault, typeParameter.mapper) : noConstraintType; } else { - const defaultDeclaration = typeParameter.symbol && forEach(typeParameter.symbol.declarations, decl => isTypeParameter(decl) && decl.default); + const defaultDeclaration = typeParameter.symbol && forEach(typeParameter.symbol.declarations, decl => isTypeParameterDeclaration(decl) && decl.default); typeParameter.default = defaultDeclaration ? getTypeFromTypeNode(defaultDeclaration) : noConstraintType; } } @@ -6154,24 +6170,16 @@ namespace ts { return undefined; } - function getTypeParametersFromJSDocTemplate(declaration: SignatureDeclaration): TypeParameter[] { - if (declaration.flags & NodeFlags.JavaScriptFile) { - const templateTag = getJSDocTemplateTag(declaration); - if (templateTag) { - return getTypeParametersFromDeclaration(templateTag.typeParameters); - } - } - - return undefined; - } - // Return list of type parameters with duplicates removed (duplicate identifier errors are generated in the actual // type checking functions). - function getTypeParametersFromDeclaration(typeParameterDeclarations: TypeParameterDeclaration[]): TypeParameter[] { - const result: TypeParameter[] = []; - forEach(typeParameterDeclarations, node => { + function getTypeParametersFromDeclaration(declaration: DeclarationWithTypeParameters): TypeParameter[] { + let result: TypeParameter[]; + forEach(getEffectiveTypeParameterDeclarations(declaration), node => { const tp = getDeclaredTypeOfTypeParameter(node.symbol); if (!contains(result, tp)) { + if (!result) { + result = []; + } result.push(tp); } }); @@ -6367,15 +6375,22 @@ namespace ts { const classType = declaration.kind === SyntaxKind.Constructor ? getDeclaredTypeOfClassOrInterface(getMergedSymbol((declaration.parent).symbol)) : undefined; - const typeParameters = classType ? classType.localTypeParameters : - declaration.typeParameters ? getTypeParametersFromDeclaration(declaration.typeParameters) : - getTypeParametersFromJSDocTemplate(declaration); + const typeParameters = classType ? classType.localTypeParameters : getTypeParametersFromDeclaration(declaration); const returnType = getSignatureReturnTypeFromDeclaration(declaration, isJSConstructSignature, classType); const typePredicate = declaration.type && declaration.type.kind === SyntaxKind.TypePredicate ? createTypePredicateFromTypePredicateNode(declaration.type as TypePredicateNode) : undefined; + // JS functions get a free rest parameter if they reference `arguments` + let hasRestLikeParameter = hasRestParameter(declaration); + if (!hasRestLikeParameter && isInJavaScriptFile(declaration) && !hasJSDocParameterTags(declaration) && containsArgumentsReference(declaration)) { + hasRestLikeParameter = true; + const syntheticArgsSymbol = createSymbol(SymbolFlags.Variable, "args"); + syntheticArgsSymbol.type = anyArrayType; + syntheticArgsSymbol.isRestParameter = true; + parameters.push(syntheticArgsSymbol); + } - links.resolvedSignature = createSignature(declaration, typeParameters, thisParameter, parameters, returnType, typePredicate, minArgumentCount, hasRestParameter(declaration), hasLiteralTypes); + links.resolvedSignature = createSignature(declaration, typeParameters, thisParameter, parameters, returnType, typePredicate, minArgumentCount, hasRestLikeParameter, hasLiteralTypes); } return links.resolvedSignature; } @@ -6387,15 +6402,10 @@ namespace ts { else if (classType) { return classType; } - else if (declaration.type) { - return getTypeFromTypeNode(declaration.type); - } - if (declaration.flags & NodeFlags.JavaScriptFile) { - const type = getReturnTypeFromJSDocComment(declaration); - if (type && type !== unknownType) { - return type; - } + const typeNode = getEffectiveReturnTypeNode(declaration); + if (typeNode) { + return getTypeFromTypeNode(typeNode); } // TypeScript 1.0 spec (April 2014): @@ -6410,14 +6420,14 @@ namespace ts { } } - function containsArgumentsReference(declaration: FunctionLikeDeclaration): boolean { + function containsArgumentsReference(declaration: SignatureDeclaration): boolean { const links = getNodeLinks(declaration); if (links.containsArgumentsReference === undefined) { if (links.flags & NodeCheckFlags.CaptureArguments) { links.containsArgumentsReference = true; } else { - links.containsArgumentsReference = traverse(declaration.body); + links.containsArgumentsReference = traverse((declaration as FunctionLikeDeclaration).body); } } return links.containsArgumentsReference; @@ -6804,21 +6814,46 @@ namespace ts { return undefined; } - function resolveTypeReferenceName(typeReferenceName: EntityNameExpression | EntityName) { + function resolveTypeReferenceName(typeReferenceName: EntityNameExpression | EntityName, meaning: SymbolFlags) { if (!typeReferenceName) { return unknownSymbol; } - return resolveEntityName(typeReferenceName, SymbolFlags.Type) || unknownSymbol; + return resolveEntityName(typeReferenceName, meaning) || unknownSymbol; } function getTypeReferenceType(node: TypeReferenceType, symbol: Symbol) { const typeArguments = typeArgumentsFromTypeReferenceNode(node); // Do unconditionally so we mark type arguments as referenced. - if (symbol === unknownSymbol) { return unknownType; } + const type = getTypeReferenceTypeWorker(node, symbol, typeArguments); + if (type) { + return type; + } + + if (symbol.flags & SymbolFlags.Value && node.kind === SyntaxKind.JSDocTypeReference) { + // A JSDocTypeReference may have resolved to a value (as opposed to a type). If + // the symbol is a constructor function, return the inferred class type; otherwise, + // the type of this reference is just the type of the value we resolved to. + const valueType = getTypeOfSymbol(symbol); + if (valueType.symbol && !isInferredClassType(valueType)) { + const referenceType = getTypeReferenceTypeWorker(node, valueType.symbol, typeArguments); + if (referenceType) { + return referenceType; + } + } + + // Resolve the type reference as a Type for the purpose of reporting errors. + resolveTypeReferenceName(getTypeReferenceName(node), SymbolFlags.Type); + return valueType; + } + + return getTypeFromNonGenericTypeReference(node, symbol); + } + + function getTypeReferenceTypeWorker(node: TypeReferenceType, symbol: Symbol, typeArguments: Type[]): Type | undefined { if (symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { return getTypeFromClassOrInterfaceReference(node, symbol, typeArguments); } @@ -6827,14 +6862,9 @@ namespace ts { return getTypeFromTypeAliasReference(node, symbol, typeArguments); } - if (symbol.flags & SymbolFlags.Value && node.kind === SyntaxKind.JSDocTypeReference) { - // A JSDocTypeReference may have resolved to a value (as opposed to a type). In - // that case, the type of this reference is just the type of the value we resolved - // to. - return getTypeOfSymbol(symbol); + if (symbol.flags & SymbolFlags.Function && node.kind === SyntaxKind.JSDocTypeReference && (symbol.members || getJSDocClassTag(symbol.valueDeclaration))) { + return getInferredClassType(symbol); } - - return getTypeFromNonGenericTypeReference(node, symbol); } function getPrimitiveTypeFromJSDocTypeReference(node: JSDocTypeReference): Type { @@ -6877,22 +6907,13 @@ namespace ts { if (!links.resolvedType) { let symbol: Symbol; let type: Type; + let meaning = SymbolFlags.Type; if (node.kind === SyntaxKind.JSDocTypeReference) { - type = getPrimitiveTypeFromJSDocTypeReference(node); - if (!type) { - const typeReferenceName = getTypeReferenceName(node); - symbol = resolveTypeReferenceName(typeReferenceName); - type = getTypeReferenceType(node, symbol); - } + type = getPrimitiveTypeFromJSDocTypeReference(node); + meaning |= SymbolFlags.Value; } - else { - // We only support expressions that are simple qualified names. For other expressions this produces undefined. - const typeNameOrExpression: EntityNameOrEntityNameExpression = node.kind === SyntaxKind.TypeReference - ? (node).typeName - : isEntityNameExpression((node).expression) - ? (node).expression - : undefined; - symbol = typeNameOrExpression && resolveEntityName(typeNameOrExpression, SymbolFlags.Type) || unknownSymbol; + if (!type) { + symbol = resolveTypeReferenceName(getTypeReferenceName(node), meaning); type = getTypeReferenceType(node, symbol); } // Cache both the resolved symbol and the resolved type. The resolved symbol is needed in when we check the @@ -7129,6 +7150,7 @@ namespace ts { containsAny?: boolean; containsUndefined?: boolean; containsNull?: boolean; + containsNever?: boolean; containsNonWideningType?: boolean; containsString?: boolean; containsNumber?: boolean; @@ -7330,10 +7352,13 @@ namespace ts { else if (type.flags & TypeFlags.Any) { typeSet.containsAny = true; } + else if (type.flags & TypeFlags.Never) { + typeSet.containsNever = true; + } else if (getObjectFlags(type) & ObjectFlags.Anonymous && isEmptyObjectType(type)) { typeSet.containsEmptyObject = true; } - else if (!(type.flags & TypeFlags.Never) && (strictNullChecks || !(type.flags & TypeFlags.Nullable)) && !contains(typeSet, type)) { + else if ((strictNullChecks || !(type.flags & TypeFlags.Nullable)) && !contains(typeSet, type)) { if (type.flags & TypeFlags.Object) { typeSet.containsObjectType = true; } @@ -7371,6 +7396,9 @@ namespace ts { } const typeSet = [] as TypeSet; addTypesToIntersection(typeSet, types); + if (typeSet.containsNever) { + return neverType; + } if (typeSet.containsAny) { return anyType; } @@ -7632,11 +7660,9 @@ namespace ts { if (left.flags & TypeFlags.Any || right.flags & TypeFlags.Any) { return anyType; } - left = filterType(left, t => !(t.flags & TypeFlags.Nullable)); if (left.flags & TypeFlags.Never) { return right; } - right = filterType(right, t => !(t.flags & TypeFlags.Nullable)); if (right.flags & TypeFlags.Never) { return left; } @@ -8023,7 +8049,7 @@ namespace ts { const result = createSignature(signature.declaration, freshTypeParameters, signature.thisParameter && instantiateSymbol(signature.thisParameter, mapper), instantiateList(signature.parameters, mapper, instantiateSymbol), - instantiateType(signature.resolvedReturnType, mapper), + /*resolvedReturnType*/ undefined, freshTypePredicate, signature.minArgumentCount, signature.hasRestParameter, signature.hasLiteralTypes); result.target = signature; @@ -8130,9 +8156,9 @@ namespace ts { case SyntaxKind.ClassExpression: case SyntaxKind.InterfaceDeclaration: case SyntaxKind.TypeAliasDeclaration: - const declaration = node as DeclarationWithTypeParameters; - if (declaration.typeParameters) { - for (const d of declaration.typeParameters) { + const typeParameters = getEffectiveTypeParameterDeclarations(node as DeclarationWithTypeParameters); + if (typeParameters) { + for (const d of typeParameters) { if (contains(mappedTypes, getDeclaredTypeOfTypeParameter(getSymbolOfNode(d)))) { return true; } @@ -8287,7 +8313,7 @@ namespace ts { return false; } // Functions with any parameters that lack type annotations are context sensitive. - if (forEach(node.parameters, p => !p.type)) { + if (forEach(node.parameters, p => !getEffectiveTypeAnnotationNode(p))) { return true; } // For arrow functions we now know we're not context sensitive. @@ -8356,6 +8382,12 @@ namespace ts { /** * This is *not* a bi-directional relationship. * If one needs to check both directions for comparability, use a second call to this function or 'checkTypeComparableTo'. + * + * A type S is comparable to a type T if some (but not necessarily all) of the possible values of S are also possible values of T. + * It is used to check following cases: + * - the types of the left and right sides of equality/inequality operators (`===`, `!==`, `==`, `!=`). + * - the types of `case` clause expressions and their respective `switch` expressions. + * - the type of an expression in a type assertion with the type being asserted. */ function isTypeComparableTo(source: Type, target: Type): boolean { return isTypeRelatedTo(source, target, comparableRelation); @@ -8408,10 +8440,9 @@ namespace ts { return Ternary.False; } - // Spec 1.0 Section 3.8.3 & 3.8.4: - // M and N (the signatures) are instantiated using type Any as the type argument for all type parameters declared by M and N - source = getErasedSignature(source); - target = getErasedSignature(target); + if (source.typeParameters) { + source = instantiateSignatureInContextOf(source, target); + } let result = Ternary.True; @@ -8583,6 +8614,7 @@ namespace ts { function isEmptyObjectType(type: Type): boolean { return type.flags & TypeFlags.Object ? isEmptyResolvedType(resolveStructuredTypeMembers(type)) : + type.flags & TypeFlags.NonPrimitive ? true : type.flags & TypeFlags.Union ? forEach((type).types, isEmptyObjectType) : type.flags & TypeFlags.Intersection ? !forEach((type).types, t => !isEmptyObjectType(t)) : false; @@ -8702,6 +8734,7 @@ namespace ts { let expandingFlags: number; let depth = 0; let overflow = false; + let isIntersectionConstituent = false; Debug.assert(relation !== identityRelation || !errorNode, "no error reporting in identity checking"); @@ -8784,7 +8817,6 @@ namespace ts { * * Ternary.False if they are not related. */ function isRelatedTo(source: Type, target: Type, reportErrors?: boolean, headMessage?: DiagnosticMessage): Ternary { - let result: Ternary; if (source.flags & TypeFlags.StringOrNumberLiteral && source.flags & TypeFlags.FreshLiteral) { source = (source).regularType; } @@ -8816,32 +8848,40 @@ namespace ts { } } + if (relation !== comparableRelation && + !(source.flags & TypeFlags.UnionOrIntersection) && + !(target.flags & TypeFlags.Union) && + !isIntersectionConstituent && + source !== globalObjectType && + getPropertiesOfType(source).length > 0 && + isWeakType(target) && + !hasCommonProperties(source, target)) { + if (reportErrors) { + reportError(Diagnostics.Type_0_has_no_properties_in_common_with_type_1, typeToString(source), typeToString(target)); + } + return Ternary.False; + } + + let result = Ternary.False; const saveErrorInfo = errorInfo; + const saveIsIntersectionConstituent = isIntersectionConstituent; + isIntersectionConstituent = false; // Note that these checks are specifically ordered to produce correct results. In particular, // we need to deconstruct unions before intersections (because unions are always at the top), // and we need to handle "each" relations before "some" relations for the same kind of type. if (source.flags & TypeFlags.Union) { - if (relation === comparableRelation) { - result = someTypeRelatedToType(source as UnionType, target, reportErrors && !(source.flags & TypeFlags.Primitive)); - } - else { - result = eachTypeRelatedToType(source as UnionType, target, reportErrors && !(source.flags & TypeFlags.Primitive)); - } - if (result) { - return result; - } + result = relation === comparableRelation ? + someTypeRelatedToType(source as UnionType, target, reportErrors && !(source.flags & TypeFlags.Primitive)) : + eachTypeRelatedToType(source as UnionType, target, reportErrors && !(source.flags & TypeFlags.Primitive)); } else { if (target.flags & TypeFlags.Union) { - if (result = typeRelatedToSomeType(source, target, reportErrors && !(source.flags & TypeFlags.Primitive) && !(target.flags & TypeFlags.Primitive))) { - return result; - } + result = typeRelatedToSomeType(source, target, reportErrors && !(source.flags & TypeFlags.Primitive) && !(target.flags & TypeFlags.Primitive)); } else if (target.flags & TypeFlags.Intersection) { - if (result = typeRelatedToEachType(source, target as IntersectionType, reportErrors)) { - return result; - } + isIntersectionConstituent = true; + result = typeRelatedToEachType(source, target as IntersectionType, reportErrors); } else if (source.flags & TypeFlags.Intersection) { // Check to see if any constituents of the intersection are immediately related to the target. @@ -8857,20 +8897,18 @@ namespace ts { // // - For a primitive type or type parameter (such as 'number = A & B') there is no point in // breaking the intersection apart. - if (result = someTypeRelatedToType(source, target, /*reportErrors*/ false)) { - return result; - } + result = someTypeRelatedToType(source, target, /*reportErrors*/ false); } - - if (source.flags & TypeFlags.StructuredOrTypeVariable || target.flags & TypeFlags.StructuredOrTypeVariable) { + if (!result && (source.flags & TypeFlags.StructuredOrTypeVariable || target.flags & TypeFlags.StructuredOrTypeVariable)) { if (result = recursiveTypeRelatedTo(source, target, reportErrors)) { errorInfo = saveErrorInfo; - return result; } } } - if (reportErrors) { + isIntersectionConstituent = saveIsIntersectionConstituent; + + if (!result && reportErrors) { if (source.flags & TypeFlags.Object && target.flags & TypeFlags.Primitive) { tryElaborateErrorsForPrimitivesAndObjects(source, target); } @@ -8879,7 +8917,7 @@ namespace ts { } reportRelationError(headMessage, source, target); } - return Ternary.False; + return result; } function isIdenticalTo(source: Type, target: Type): Ternary { @@ -8918,7 +8956,9 @@ namespace ts { reportError(Diagnostics.Property_0_does_not_exist_on_type_1, symbolToString(prop), typeToString(target)); } else { - errorNode = prop.valueDeclaration; + if (prop.valueDeclaration) { + errorNode = prop.valueDeclaration; + } reportError(Diagnostics.Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1, symbolToString(prop), typeToString(target)); } @@ -8978,7 +9018,7 @@ namespace ts { } } - function typeRelatedToEachType(source: Type, target: UnionOrIntersectionType, reportErrors: boolean): Ternary { + function typeRelatedToEachType(source: Type, target: IntersectionType, reportErrors: boolean): Ternary { let result = Ternary.True; const targetTypes = target.types; for (const targetType of targetTypes) { @@ -9280,7 +9320,6 @@ namespace ts { const requireOptionalProperties = relation === subtypeRelation && !(getObjectFlags(source) & ObjectFlags.ObjectLiteral); for (const targetProp of properties) { const sourceProp = getPropertyOfType(source, targetProp.name); - if (sourceProp !== targetProp) { if (!sourceProp) { if (!(targetProp.flags & SymbolFlags.Optional) || requireOptionalProperties) { @@ -9359,6 +9398,34 @@ namespace ts { return result; } + /** + * A type is 'weak' if it is an object type with at least one optional property + * and no required properties, call/construct signatures or index signatures + */ + function isWeakType(type: Type): boolean { + if (type.flags & TypeFlags.Object) { + const resolved = resolveStructuredTypeMembers(type); + return resolved.callSignatures.length === 0 && resolved.constructSignatures.length === 0 && + !resolved.stringIndexInfo && !resolved.numberIndexInfo && + resolved.properties.length > 0 && + every(resolved.properties, p => !!(p.flags & SymbolFlags.Optional)); + } + if (type.flags & TypeFlags.Intersection) { + return every((type).types, isWeakType); + } + return false; + } + + function hasCommonProperties(source: Type, target: Type) { + const isComparingJsxAttributes = !!(source.flags & TypeFlags.JsxAttributes); + for (const prop of getPropertiesOfType(source)) { + if (isKnownProperty(target, prop.name, isComparingJsxAttributes)) { + return true; + } + } + return false; + } + function propertiesIdenticalTo(source: Type, target: Type): Ternary { if (!(source.flags & TypeFlags.Object && target.flags & TypeFlags.Object)) { return Ternary.False; @@ -9413,23 +9480,33 @@ namespace ts { const saveErrorInfo = errorInfo; if (getObjectFlags(source) & ObjectFlags.Instantiated && getObjectFlags(target) & ObjectFlags.Instantiated && source.symbol === target.symbol) { - // We instantiations of the same anonymous type (which typically will be the type of a method). - // Simply do a pairwise comparison of the signatures in the two signature lists instead of the - // much more expensive N * M comparison matrix we explore below. + // We have instantiations of the same anonymous type (which typically will be the type of a + // method). Simply do a pairwise comparison of the signatures in the two signature lists instead + // of the much more expensive N * M comparison matrix we explore below. We erase type parameters + // as they are known to always be the same. for (let i = 0; i < targetSignatures.length; i++) { - const related = signatureRelatedTo(sourceSignatures[i], targetSignatures[i], reportErrors); + const related = signatureRelatedTo(sourceSignatures[i], targetSignatures[i], /*erase*/ true, reportErrors); if (!related) { return Ternary.False; } result &= related; } } + else if (sourceSignatures.length === 1 && targetSignatures.length === 1) { + // For simple functions (functions with a single signature) we only erase type parameters for + // the comparable relation. Otherwise, if the source signature is generic, we instantiate it + // in the context of the target signature before checking the relationship. Ideally we'd do + // this regardless of the number of signatures, but the potential costs are prohibitive due + // to the quadratic nature of the logic below. + const eraseGenerics = relation === comparableRelation || compilerOptions.noStrictGenericChecks; + result = signatureRelatedTo(sourceSignatures[0], targetSignatures[0], eraseGenerics, reportErrors); + } else { outer: for (const t of targetSignatures) { // Only elaborate errors from the first failure let shouldElaborateErrors = reportErrors; for (const s of sourceSignatures) { - const related = signatureRelatedTo(s, t, shouldElaborateErrors); + const related = signatureRelatedTo(s, t, /*erase*/ true, shouldElaborateErrors); if (related) { result &= related; errorInfo = saveErrorInfo; @@ -9452,8 +9529,9 @@ namespace ts { /** * See signatureAssignableTo, compareSignaturesIdentical */ - function signatureRelatedTo(source: Signature, target: Signature, reportErrors: boolean): Ternary { - return compareSignaturesRelated(source, target, /*checkAsCallback*/ false, /*ignoreReturnTypes*/ false, reportErrors, reportError, isRelatedTo); + function signatureRelatedTo(source: Signature, target: Signature, erase: boolean, reportErrors: boolean): Ternary { + return compareSignaturesRelated(erase ? getErasedSignature(source) : source, erase ? getErasedSignature(target) : target, + /*checkAsCallback*/ false, /*ignoreReturnTypes*/ false, reportErrors, reportError, isRelatedTo); } function signaturesIdenticalTo(source: Type, target: Type, kind: SignatureKind): Ternary { @@ -10206,7 +10284,7 @@ namespace ts { const objectFlags = getObjectFlags(type); return !!(type.flags & TypeFlags.TypeVariable || objectFlags & ObjectFlags.Reference && forEach((type).typeArguments, couldContainTypeVariables) || - objectFlags & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class) || + objectFlags & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class) || objectFlags & ObjectFlags.Mapped || type.flags & TypeFlags.UnionOrIntersection && couldUnionOrIntersectionContainTypeVariables(type)); } @@ -11972,7 +12050,9 @@ namespace ts { return getTypeOfSymbol(symbol); } - if (symbol.flags & SymbolFlags.Alias && !isInTypeQuery(node) && !isConstEnumOrConstEnumOnlyModule(resolveAlias(symbol))) { + // We should only mark aliases as referenced if there isn't a local value declaration + // for the symbol. + if (isNonLocalAlias(symbol, /*excludes*/ SymbolFlags.Value) && !isInTypeQuery(node) && !isConstEnumOrConstEnumOnlyModule(resolveAlias(symbol))) { markAliasSymbolAsReferenced(symbol); } @@ -12664,8 +12744,15 @@ namespace ts { function getContextualTypeForInitializerExpression(node: Expression): Type { const declaration = node.parent; if (node === declaration.initializer) { - if (declaration.type) { - return getTypeFromTypeNode(declaration.type); + const typeNode = getEffectiveTypeAnnotationNode(declaration); + if (typeNode) { + return getTypeFromTypeNode(typeNode); + } + if (isInJavaScriptFile(declaration)) { + const jsDocType = getTypeForDeclarationFromJSDocComment(declaration); + if (jsDocType) { + return jsDocType; + } } if (declaration.kind === SyntaxKind.Parameter) { const type = getContextuallyTypedParameterType(declaration); @@ -12679,12 +12766,13 @@ namespace ts { if (isBindingPattern(declaration.parent)) { const parentDeclaration = declaration.parent.parent; const name = declaration.propertyName || declaration.name; - if (parentDeclaration.kind !== SyntaxKind.BindingElement && - parentDeclaration.type && - !isBindingPattern(name)) { - const text = getTextOfPropertyName(name); - if (text) { - return getTypeOfPropertyOfType(getTypeFromTypeNode(parentDeclaration.type), text); + if (parentDeclaration.kind !== SyntaxKind.BindingElement) { + const parentTypeNode = getEffectiveTypeAnnotationNode(parentDeclaration); + if (parentTypeNode && !isBindingPattern(name)) { + const text = getTextOfPropertyName(name); + if (text) { + return getTypeOfPropertyOfType(getTypeFromTypeNode(parentTypeNode), text); + } } } } @@ -12738,9 +12826,9 @@ namespace ts { function getContextualReturnType(functionDecl: FunctionLikeDeclaration): Type { // If the containing function has a return type annotation, is a constructor, or is a get accessor whose // corresponding set accessor has a type annotation, return statements in the function are contextually typed - if (functionDecl.type || - functionDecl.kind === SyntaxKind.Constructor || - functionDecl.kind === SyntaxKind.GetAccessor && getSetAccessorTypeAnnotationNode(getDeclarationOfKind(functionDecl.symbol, SyntaxKind.SetAccessor))) { + if (functionDecl.kind === SyntaxKind.Constructor || + getEffectiveReturnTypeNode(functionDecl) || + isGetAccessorWithAnnotatedSetAccessor(functionDecl)) { return getReturnTypeOfSignature(getSignatureFromDeclaration(functionDecl)); } @@ -13009,13 +13097,13 @@ namespace ts { return node ? node.contextualMapper : identityMapper; } - // If the given type is an object or union type, if that type has a single signature, and if - // that signature is non-generic, return the signature. Otherwise return undefined. - function getNonGenericSignature(type: Type, node: FunctionExpression | ArrowFunction | MethodDeclaration): Signature { + // If the given type is an object or union type with a single signature, and if that signature has at + // least as many parameters as the given function, return the signature. Otherwise return undefined. + function getContextualCallSignature(type: Type, node: FunctionExpression | ArrowFunction | MethodDeclaration): Signature { const signatures = getSignaturesOfStructuredType(type, SignatureKind.Call); if (signatures.length === 1) { const signature = signatures[0]; - if (!signature.typeParameters && !isAritySmaller(signature, node)) { + if (!isAritySmaller(signature, node)) { return signature; } } @@ -13066,12 +13154,12 @@ namespace ts { return undefined; } if (!(type.flags & TypeFlags.Union)) { - return getNonGenericSignature(type, node); + return getContextualCallSignature(type, node); } let signatureList: Signature[]; const types = (type).types; for (const current of types) { - const signature = getNonGenericSignature(current, node); + const signature = getContextualCallSignature(current, node); if (signature) { if (!signatureList) { // This signature will contribute to contextual union signature @@ -14118,7 +14206,7 @@ namespace ts { checkJsxPreconditions(node); // The reactNamespace/jsxFactory's root symbol should be marked as 'used' so we don't incorrectly elide its import. // And if there is no reactNamespace/jsxFactory's symbol in scope when targeting React emit, we should issue an error. - const reactRefErr = compilerOptions.jsx === JsxEmit.React ? Diagnostics.Cannot_find_name_0 : undefined; + const reactRefErr = diagnostics && compilerOptions.jsx === JsxEmit.React ? Diagnostics.Cannot_find_name_0 : undefined; const reactNamespace = getJsxNamespace(); const reactSym = resolveName(node.tagName, reactNamespace, SymbolFlags.Value, reactRefErr, reactNamespace); if (reactSym) { @@ -14137,9 +14225,13 @@ namespace ts { /** * Check if a property with the given name is known anywhere in the given type. In an object type, a property - * is considered known if the object type is empty and the check is for assignability, if the object type has - * index signatures, or if the property is actually declared in the object type. In a union or intersection - * type, a property is considered known if it is known in any constituent type. + * is considered known if + * 1. the object type is empty and the check is for assignability, or + * 2. if the object type has index signatures, or + * 3. if the property is actually declared in the object type + * (this means that 'toString', for example, is not usually a known property). + * 4. In a union or intersection type, + * a property is considered known if it is known in any constituent type. * @param targetType a type to search a given name in * @param name a property name to search * @param isComparingJsxAttributes a boolean flag indicating whether we are searching in JsxAttributesType @@ -14147,8 +14239,10 @@ namespace ts { function isKnownProperty(targetType: Type, name: string, isComparingJsxAttributes: boolean): boolean { if (targetType.flags & TypeFlags.Object) { const resolved = resolveStructuredTypeMembers(targetType); - if (resolved.stringIndexInfo || resolved.numberIndexInfo && isNumericLiteralName(name) || - getPropertyOfType(targetType, name) || isComparingJsxAttributes && !isUnhyphenatedJsxName(name)) { + if (resolved.stringIndexInfo || + resolved.numberIndexInfo && isNumericLiteralName(name) || + getPropertyOfObjectType(targetType, name) || + isComparingJsxAttributes && !isUnhyphenatedJsxName(name)) { // For JSXAttributes, if the attribute has a hyphenated name, consider that the attribute to be known. return true; } @@ -14487,6 +14581,7 @@ namespace ts { const maximumLengthDifference = Math.min(3, name.length * 0.34); let bestDistance = Number.MAX_VALUE; let bestCandidate = undefined; + let justCheckExactMatches = false; if (name.length > 30) { return undefined; } @@ -14499,6 +14594,9 @@ namespace ts { if (candidateName === name) { return candidate; } + if (justCheckExactMatches) { + continue; + } if (candidateName.length < 3 || name.length < 3 || candidateName === "eval" || @@ -14514,7 +14612,8 @@ namespace ts { continue; } if (distance < 3) { - return candidate; + justCheckExactMatches = true; + bestCandidate = candidate; } else if (distance < bestDistance) { bestDistance = distance; @@ -14899,12 +14998,15 @@ namespace ts { } // Instantiate a generic signature in the context of a non-generic signature (section 3.8.5 in TypeScript spec) - function instantiateSignatureInContextOf(signature: Signature, contextualSignature: Signature, contextualMapper: TypeMapper): Signature { + function instantiateSignatureInContextOf(signature: Signature, contextualSignature: Signature, contextualMapper?: TypeMapper): Signature { const context = createInferenceContext(signature, InferenceFlags.InferUnionTypes); forEachMatchingParameterType(contextualSignature, signature, (source, target) => { // Type parameters from outer context referenced by source type are fixed by instantiation of the source type - inferTypes(context.inferences, instantiateType(source, contextualMapper), target); + inferTypes(context.inferences, instantiateType(source, contextualMapper || identityMapper), target); }); + if (!contextualMapper) { + inferTypes(context.inferences, getReturnTypeOfSignature(contextualSignature), getReturnTypeOfSignature(signature), InferencePriority.ReturnType); + } return getSignatureInstantiation(signature, getInferredTypes(context)); } @@ -14943,11 +15045,21 @@ namespace ts { // We clone the contextual mapper to avoid disturbing a resolution in progress for an // outer call expression. Effectively we just want a snapshot of whatever has been // inferred for any outer call expression so far. - const mapper = cloneTypeMapper(getContextualMapper(node)); - const instantiatedType = instantiateType(contextualType, mapper); - const returnType = getReturnTypeOfSignature(signature); - // Inferences made from return types have lower priority than all other inferences. - inferTypes(context.inferences, instantiatedType, returnType, InferencePriority.ReturnType); + const instantiatedType = instantiateType(contextualType, cloneTypeMapper(getContextualMapper(node))); + // If the contextual type is a generic function type with a single call signature, we + // instantiate the type with its own type parameters and type arguments. This ensures that + // the type parameters are not erased to type any during type inference such that they can + // be inferred as actual types from the contextual type. For example: + // declare function arrayMap(f: (x: T) => U): (a: T[]) => U[]; + // const boxElements: (a: A[]) => { value: A }[] = arrayMap(value => ({ value })); + // Above, the type of the 'value' parameter is inferred to be 'A'. + const contextualSignature = getSingleCallSignature(instantiatedType); + const inferenceSourceType = contextualSignature && contextualSignature.typeParameters ? + getOrCreateTypeFromSignature(getSignatureInstantiation(contextualSignature, contextualSignature.typeParameters)) : + instantiatedType; + const inferenceTargetType = getReturnTypeOfSignature(signature); + // Inferences made from return types have lower priority than all other inferences. + inferTypes(context.inferences, inferenceSourceType, inferenceTargetType, InferencePriority.ReturnType); } } @@ -15446,21 +15558,6 @@ namespace ts { } } - if (signatures.length === 1) { - const declaration = signatures[0].declaration; - if (declaration && isInJavaScriptFile(declaration) && !hasJSDocParameterTags(declaration)) { - if (containsArgumentsReference(declaration)) { - const signatureWithRest = cloneSignature(signatures[0]); - const syntheticArgsSymbol = createSymbol(SymbolFlags.Variable, "args"); - syntheticArgsSymbol.type = anyArrayType; - syntheticArgsSymbol.isRestParameter = true; - signatureWithRest.parameters = concatenate(signatureWithRest.parameters, [syntheticArgsSymbol]); - signatureWithRest.hasRestParameter = true; - signatures = [signatureWithRest]; - } - } - } - const candidates = candidatesOutArray || []; // reorderCandidates fills up the candidates array directly reorderCandidates(signatures, candidates); @@ -15854,7 +15951,7 @@ namespace ts { const callSignatures = getSignaturesOfType(expressionType, SignatureKind.Call); if (callSignatures.length) { const signature = resolveCall(node, callSignatures, candidatesOutArray); - if (getReturnTypeOfSignature(signature) !== voidType) { + if (!isJavaScriptConstructor(signature.declaration) && getReturnTypeOfSignature(signature) !== voidType) { error(node, Diagnostics.Only_a_void_function_can_be_called_with_the_new_keyword); } if (getThisTypeOfSignature(signature) === voidType) { @@ -16081,14 +16178,40 @@ namespace ts { return getNodeLinks(node).resolvedSignature === resolvingSignature ? resolvingSignature : getResolvedSignature(node); } + /** + * Indicates whether a declaration can be treated as a constructor in a JavaScript + * file. + */ + function isJavaScriptConstructor(node: Declaration): boolean { + if (isInJavaScriptFile(node)) { + // If the node has a @class tag, treat it like a constructor. + if (getJSDocClassTag(node)) return true; + + // If the symbol of the node has members, treat it like a constructor. + const symbol = isFunctionDeclaration(node) || isFunctionExpression(node) ? getSymbolOfNode(node) : + isVariableDeclaration(node) && isFunctionExpression(node.initializer) ? getSymbolOfNode(node.initializer) : + undefined; + + return symbol && symbol.members !== undefined; + } + + return false; + } + function getInferredClassType(symbol: Symbol) { const links = getSymbolLinks(symbol); if (!links.inferredClassType) { - links.inferredClassType = createAnonymousType(symbol, symbol.members, emptyArray, emptyArray, /*stringIndexType*/ undefined, /*numberIndexType*/ undefined); + links.inferredClassType = createAnonymousType(symbol, symbol.members || emptySymbols, emptyArray, emptyArray, /*stringIndexType*/ undefined, /*numberIndexType*/ undefined); } return links.inferredClassType; } + function isInferredClassType(type: Type) { + return type.symbol + && getObjectFlags(type) & ObjectFlags.Anonymous + && getSymbolLinks(type.symbol).inferredClassType === type; + } + /** * Syntactically and semantically checks a call or new expression. * @param node The call/new expression to be checked. @@ -16124,7 +16247,7 @@ namespace ts { if (funcSymbol && isDeclarationOfFunctionOrClassExpression(funcSymbol)) { funcSymbol = getSymbolOfNode((funcSymbol.valueDeclaration).initializer); } - if (funcSymbol && funcSymbol.members && funcSymbol.flags & SymbolFlags.Function) { + if (funcSymbol && funcSymbol.flags & SymbolFlags.Function && (funcSymbol.members || getJSDocClassTag(funcSymbol.valueDeclaration))) { return getInferredClassType(funcSymbol); } else if (noImplicitAny) { @@ -16142,6 +16265,35 @@ namespace ts { return getReturnTypeOfSignature(signature); } + function checkImportCallExpression(node: ImportCall): Type { + // Check grammar of dynamic import + checkGrammarArguments(node, node.arguments) || checkGrammarImportCallExpression(node); + + if (node.arguments.length === 0) { + return createPromiseReturnType(node, anyType); + } + const specifier = node.arguments[0]; + const specifierType = checkExpressionCached(specifier); + // Even though multiple arugments is grammatically incorrect, type-check extra arguments for completion + for (let i = 1; i < node.arguments.length; ++i) { + checkExpressionCached(node.arguments[i]); + } + + if (specifierType.flags & TypeFlags.Undefined || specifierType.flags & TypeFlags.Null || !isTypeAssignableTo(specifierType, stringType)) { + error(specifier, Diagnostics.Dynamic_import_s_specifier_must_be_of_type_string_but_here_has_type_0, typeToString(specifierType)); + } + + // resolveExternalModuleName will return undefined if the moduleReferenceExpression is not a string literal + const moduleSymbol = resolveExternalModuleName(node, specifier); + if (moduleSymbol) { + const esModuleSymbol = resolveESModuleSymbol(moduleSymbol, specifier, /*dontRecursivelyResolve*/ true); + if (esModuleSymbol) { + return createPromiseReturnType(node, getTypeOfSymbol(esModuleSymbol)); + } + } + return createPromiseReturnType(node, anyType); + } + function isCommonJsRequire(node: Node) { if (!isRequireCall(node, /*checkArgumentIsStringLiteral*/ true)) { return false; @@ -16231,37 +16383,43 @@ namespace ts { return signature.parameters.length > 0 ? getTypeAtPosition(signature, 0) : neverType; } - function assignContextualParameterTypes(signature: Signature, context: Signature, mapper: TypeMapper, checkMode: CheckMode) { + function inferFromAnnotatedParameters(signature: Signature, context: Signature, mapper: TypeMapper) { const len = signature.parameters.length - (signature.hasRestParameter ? 1 : 0); - if (checkMode === CheckMode.Inferential) { - for (let i = 0; i < len; i++) { - const declaration = signature.parameters[i].valueDeclaration; - if (declaration.type) { - inferTypes((mapper).inferences, getTypeFromTypeNode(declaration.type), getTypeAtPosition(context, i)); + for (let i = 0; i < len; i++) { + const declaration = signature.parameters[i].valueDeclaration; + if (declaration.type) { + const typeNode = getEffectiveTypeAnnotationNode(declaration); + if (typeNode) { + inferTypes((mapper).inferences, getTypeFromTypeNode(typeNode), getTypeAtPosition(context, i)); } } } + } + + function assignContextualParameterTypes(signature: Signature, context: Signature) { + signature.typeParameters = context.typeParameters; if (context.thisParameter) { const parameter = signature.thisParameter; if (!parameter || parameter.valueDeclaration && !(parameter.valueDeclaration).type) { if (!parameter) { signature.thisParameter = createSymbolWithType(context.thisParameter, /*type*/ undefined); } - assignTypeToParameterAndFixTypeParameters(signature.thisParameter, getTypeOfSymbol(context.thisParameter), mapper, checkMode); + assignTypeToParameterAndFixTypeParameters(signature.thisParameter, getTypeOfSymbol(context.thisParameter)); } } + const len = signature.parameters.length - (signature.hasRestParameter ? 1 : 0); for (let i = 0; i < len; i++) { const parameter = signature.parameters[i]; - if (!(parameter.valueDeclaration).type) { + if (!getEffectiveTypeAnnotationNode(parameter.valueDeclaration)) { const contextualParameterType = getTypeAtPosition(context, i); - assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper, checkMode); + assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType); } } if (signature.hasRestParameter && isRestParameterIndex(context, signature.parameters.length - 1)) { const parameter = lastOrUndefined(signature.parameters); - if (!(parameter.valueDeclaration).type) { + if (!getEffectiveTypeAnnotationNode(parameter.valueDeclaration)) { const contextualParameterType = getTypeOfSymbol(lastOrUndefined(context.parameters)); - assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper, checkMode); + assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType); } } } @@ -16281,10 +16439,10 @@ namespace ts { } } - function assignTypeToParameterAndFixTypeParameters(parameter: Symbol, contextualType: Type, mapper: TypeMapper, checkMode: CheckMode) { + function assignTypeToParameterAndFixTypeParameters(parameter: Symbol, contextualType: Type) { const links = getSymbolLinks(parameter); if (!links.type) { - links.type = instantiateType(contextualType, mapper); + links.type = contextualType; const name = getNameOfDeclaration(parameter.valueDeclaration); // if inference didn't come up with anything but {}, fall back to the binding pattern if present. if (links.type === emptyObjectType && @@ -16293,47 +16451,6 @@ namespace ts { } assignBindingElementTypes(parameter.valueDeclaration); } - else if (checkMode === CheckMode.Inferential) { - // Even if the parameter already has a type, it might be because it was given a type while - // processing the function as an argument to a prior signature during overload resolution. - // If this was the case, it may have caused some type parameters to be fixed. So here, - // we need to ensure that type parameters at the same positions get fixed again. This is - // done by calling instantiateType to attach the mapper to the contextualType, and then - // calling inferTypes to force a walk of contextualType so that all the correct fixing - // happens. The choice to pass in links.type may seem kind of arbitrary, but it serves - // to make sure that all the correct positions in contextualType are reached by the walk. - // Here is an example: - // - // interface Base { - // baseProp; - // } - // interface Derived extends Base { - // toBase(): Base; - // } - // - // var derived: Derived; - // - // declare function foo(x: T, func: (p: T) => T): T; - // declare function foo(x: T, func: (p: T) => T): T; - // - // var result = foo(derived, d => d.toBase()); - // - // We are typing d while checking the second overload. But we've already given d - // a type (Derived) from the first overload. However, we still want to fix the - // T in the second overload so that we do not infer Base as a candidate for T - // (inferring Base would make type argument inference inconsistent between the two - // overloads). - inferTypes((mapper).inferences, links.type, instantiateType(contextualType, mapper)); - } - } - - function getReturnTypeFromJSDocComment(func: SignatureDeclaration | FunctionDeclaration): Type { - const returnTag = getJSDocReturnTag(func); - if (returnTag && returnTag.typeExpression) { - return getTypeFromTypeNode(returnTag.typeExpression.type); - } - - return undefined; } function createPromiseType(promisedType: Type): Type { @@ -16348,14 +16465,18 @@ namespace ts { return emptyObjectType; } - function createPromiseReturnType(func: FunctionLikeDeclaration, promisedType: Type) { + function createPromiseReturnType(func: FunctionLikeDeclaration | ImportCall, promisedType: Type) { const promiseType = createPromiseType(promisedType); if (promiseType === emptyObjectType) { - error(func, Diagnostics.An_async_function_or_method_must_return_a_Promise_Make_sure_you_have_a_declaration_for_Promise_or_include_ES2015_in_your_lib_option); + error(func, isImportCall(func) ? + Diagnostics.A_dynamic_import_call_returns_a_Promise_Make_sure_you_have_a_declaration_for_Promise_or_include_ES2015_in_your_lib_option : + Diagnostics.An_async_function_or_method_must_return_a_Promise_Make_sure_you_have_a_declaration_for_Promise_or_include_ES2015_in_your_lib_option); return unknownType; } else if (!getGlobalPromiseConstructorSymbol(/*reportErrors*/ true)) { - error(func, Diagnostics.An_async_function_or_method_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option); + error(func, isImportCall(func) ? + Diagnostics.A_dynamic_import_call_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option : + Diagnostics.An_async_function_or_method_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option); } return promiseType; @@ -16557,16 +16678,16 @@ namespace ts { const hasExplicitReturn = func.flags & NodeFlags.HasExplicitReturn; if (returnType && returnType.flags & TypeFlags.Never) { - error(func.type, Diagnostics.A_function_returning_never_cannot_have_a_reachable_end_point); + error(getEffectiveReturnTypeNode(func), Diagnostics.A_function_returning_never_cannot_have_a_reachable_end_point); } else if (returnType && !hasExplicitReturn) { // minimal check: function has syntactic return type annotation and no explicit return statements in the body // this function does not conform to the specification. // NOTE: having returnType !== undefined is a precondition for entering this branch so func.type will always be present - error(func.type, Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value); + error(getEffectiveReturnTypeNode(func), Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value); } else if (returnType && strictNullChecks && !isTypeAssignableTo(undefinedType, returnType)) { - error(func.type, Diagnostics.Function_lacks_ending_return_statement_and_return_type_does_not_include_undefined); + error(getEffectiveReturnTypeNode(func), Diagnostics.Function_lacks_ending_return_statement_and_return_type_does_not_include_undefined); } else if (compilerOptions.noImplicitReturns) { if (!returnType) { @@ -16581,7 +16702,7 @@ namespace ts { return; } } - error(func.type || func, Diagnostics.Not_all_code_paths_return_a_value); + error(getEffectiveReturnTypeNode(func) || func, Diagnostics.Not_all_code_paths_return_a_value); } } @@ -16602,37 +16723,35 @@ namespace ts { const links = getNodeLinks(node); const type = getTypeOfSymbol(node.symbol); - const contextSensitive = isContextSensitive(node); - const mightFixTypeParameters = contextSensitive && checkMode === CheckMode.Inferential; // Check if function expression is contextually typed and assign parameter types if so. - // See the comment in assignTypeToParameterAndFixTypeParameters to understand why we need to - // check mightFixTypeParameters. - if (mightFixTypeParameters || !(links.flags & NodeCheckFlags.ContextChecked)) { + if (!(links.flags & NodeCheckFlags.ContextChecked)) { const contextualSignature = getContextualSignature(node); // If a type check is started at a function expression that is an argument of a function call, obtaining the // contextual type may recursively get back to here during overload resolution of the call. If so, we will have // already assigned contextual types. - const contextChecked = !!(links.flags & NodeCheckFlags.ContextChecked); - if (mightFixTypeParameters || !contextChecked) { + if (!(links.flags & NodeCheckFlags.ContextChecked)) { links.flags |= NodeCheckFlags.ContextChecked; if (contextualSignature) { const signature = getSignaturesOfType(type, SignatureKind.Call)[0]; - if (contextSensitive) { - assignContextualParameterTypes(signature, contextualSignature, getContextualMapper(node), checkMode); + if (isContextSensitive(node)) { + const contextualMapper = getContextualMapper(node); + if (checkMode === CheckMode.Inferential) { + inferFromAnnotatedParameters(signature, contextualSignature, contextualMapper); + } + const instantiatedContextualSignature = contextualMapper === identityMapper ? + contextualSignature : instantiateSignature(contextualSignature, contextualMapper); + assignContextualParameterTypes(signature, instantiatedContextualSignature); } - if (mightFixTypeParameters || !node.type && !signature.resolvedReturnType) { + if (!getEffectiveReturnTypeNode(node) && !signature.resolvedReturnType) { const returnType = getReturnTypeFromBody(node, checkMode); if (!signature.resolvedReturnType) { signature.resolvedReturnType = returnType; } } } - - if (!contextChecked) { - checkSignatureDeclaration(node); - checkNodeDeferred(node); - } + checkSignatureDeclaration(node); + checkNodeDeferred(node); } } @@ -16649,10 +16768,11 @@ namespace ts { Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node)); const functionFlags = getFunctionFlags(node); - const returnOrPromisedType = node.type && + const returnTypeNode = getEffectiveReturnTypeNode(node); + const returnOrPromisedType = returnTypeNode && ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.Async ? checkAsyncFunctionReturnType(node) : // Async function - getTypeFromTypeNode(node.type)); // AsyncGenerator function, Generator function, or normal function + getTypeFromTypeNode(returnTypeNode)); // AsyncGenerator function, Generator function, or normal function if ((functionFlags & FunctionFlags.Generator) === 0) { // Async function or normal function // return is not necessary in the body of generators @@ -16660,7 +16780,7 @@ namespace ts { } if (node.body) { - if (!node.type) { + if (!returnTypeNode) { // There are some checks that are only performed in getReturnTypeFromBody, that may produce errors // we need. An example is the noImplicitAny errors resulting from widening the return expression // of a function. Because checking of function expression bodies is deferred, there was never an @@ -16723,8 +16843,9 @@ namespace ts { (expr as PropertyAccessExpression | ElementAccessExpression).expression.kind === SyntaxKind.ThisKeyword) { // Look for if this is the constructor for the class that `symbol` is a property of. const func = getContainingFunction(expr); - if (!(func && func.kind === SyntaxKind.Constructor)) + if (!(func && func.kind === SyntaxKind.Constructor)) { return true; + } // If func.parent is a class and symbol is a (readonly) property of that class, or // if func is a constructor and symbol is a (readonly) parameter property declared in it, // then symbol is writeable here. @@ -16751,7 +16872,7 @@ namespace ts { function checkReferenceExpression(expr: Expression, invalidReferenceMessage: DiagnosticMessage): boolean { // References are combinations of identifiers, parentheses, and property accesses. - const node = skipParentheses(expr); + const node = skipOuterExpressions(expr, OuterExpressionKinds.Assertions | OuterExpressionKinds.Parentheses); if (node.kind !== SyntaxKind.Identifier && node.kind !== SyntaxKind.PropertyAccessExpression && node.kind !== SyntaxKind.ElementAccessExpression) { error(expr, invalidReferenceMessage); return false; @@ -17445,8 +17566,9 @@ namespace ts { // There is no point in doing an assignability check if the function // has no explicit return type because the return type is directly computed // from the yield expressions. - if (func.type) { - const signatureElementType = getIteratedTypeOfGenerator(getTypeFromTypeNode(func.type), (functionFlags & FunctionFlags.Async) !== 0) || anyType; + const returnType = getEffectiveReturnTypeNode(func); + if (returnType) { + const signatureElementType = getIteratedTypeOfGenerator(getTypeFromTypeNode(returnType), (functionFlags & FunctionFlags.Async) !== 0) || anyType; if (nodeIsYieldStar) { checkTypeAssignableTo( functionFlags & FunctionFlags.Async @@ -17602,7 +17724,7 @@ namespace ts { if (signature && signature.typeParameters) { const contextualType = getApparentTypeOfContextualType(node); if (contextualType) { - const contextualSignature = getSingleCallSignature(contextualType); + const contextualSignature = getSingleCallSignature(getNonNullableType(contextualType)); if (contextualSignature && !contextualSignature.typeParameters) { return getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, getContextualMapper(node))); } @@ -17714,6 +17836,10 @@ namespace ts { case SyntaxKind.ElementAccessExpression: return checkIndexedAccess(node); case SyntaxKind.CallExpression: + if ((node).expression.kind === SyntaxKind.ImportKeyword) { + return checkImportCallExpression(node); + } + /* falls through */ case SyntaxKind.NewExpression: return checkCallExpression(node); case SyntaxKind.TaggedTemplateExpression: @@ -17970,13 +18096,15 @@ namespace ts { forEach(node.parameters, checkParameter); + // TODO(rbuckton): Should we start checking JSDoc types? if (node.type) { checkSourceElement(node.type); } if (produceDiagnostics) { checkCollisionWithArgumentsInGeneratedCode(node); - if (noImplicitAny && !node.type) { + const returnTypeNode = getEffectiveReturnTypeNode(node); + if (noImplicitAny && !returnTypeNode) { switch (node.kind) { case SyntaxKind.ConstructSignature: error(node, Diagnostics.Construct_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type); @@ -17987,12 +18115,12 @@ namespace ts { } } - if (node.type) { + if (returnTypeNode) { const functionFlags = getFunctionFlags(node); if ((functionFlags & (FunctionFlags.Invalid | FunctionFlags.Generator)) === FunctionFlags.Generator) { - const returnType = getTypeFromTypeNode(node.type); + const returnType = getTypeFromTypeNode(returnTypeNode); if (returnType === voidType) { - error(node.type, Diagnostics.A_generator_cannot_have_a_void_type_annotation); + error(returnTypeNode, Diagnostics.A_generator_cannot_have_a_void_type_annotation); } else { const generatorElementType = getIteratedTypeOfGenerator(returnType, (functionFlags & FunctionFlags.Async) !== 0) || anyType; @@ -18006,7 +18134,7 @@ namespace ts { // interface BadGenerator extends Iterable, Iterator { } // function* g(): BadGenerator { } // Iterable and Iterator have different types! // - checkTypeAssignableTo(iterableIteratorInstantiation, returnType, node.type); + checkTypeAssignableTo(iterableIteratorInstantiation, returnType, returnTypeNode); } } else if ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.Async) { @@ -19018,7 +19146,8 @@ namespace ts { // then(...): Promise; // } // - const returnType = getTypeFromTypeNode(node.type); + const returnTypeNode = getEffectiveReturnTypeNode(node); + const returnType = getTypeFromTypeNode(returnTypeNode); if (languageVersion >= ScriptTarget.ES2015) { if (returnType === unknownType) { @@ -19028,21 +19157,21 @@ namespace ts { if (globalPromiseType !== emptyGenericType && !isReferenceToType(returnType, globalPromiseType)) { // The promise type was not a valid type reference to the global promise type, so we // report an error and return the unknown type. - error(node.type, Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type); + error(returnTypeNode, Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type); return unknownType; } } else { // Always mark the type node as referenced if it points to a value - markTypeNodeAsReferenced(node.type); + markTypeNodeAsReferenced(returnTypeNode); if (returnType === unknownType) { return unknownType; } - const promiseConstructorName = getEntityNameFromTypeNode(node.type); + const promiseConstructorName = getEntityNameFromTypeNode(returnTypeNode); if (promiseConstructorName === undefined) { - error(node.type, Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, typeToString(returnType)); + error(returnTypeNode, Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, typeToString(returnType)); return unknownType; } @@ -19050,10 +19179,10 @@ namespace ts { const promiseConstructorType = promiseConstructorSymbol ? getTypeOfSymbol(promiseConstructorSymbol) : unknownType; if (promiseConstructorType === unknownType) { if (promiseConstructorName.kind === SyntaxKind.Identifier && promiseConstructorName.text === "Promise" && getTargetType(returnType) === getGlobalPromiseType(/*reportErrors*/ false)) { - error(node.type, Diagnostics.An_async_function_or_method_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option); + error(returnTypeNode, Diagnostics.An_async_function_or_method_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option); } else { - error(node.type, Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, entityNameToString(promiseConstructorName)); + error(returnTypeNode, Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, entityNameToString(promiseConstructorName)); } return unknownType; } @@ -19062,11 +19191,11 @@ namespace ts { if (globalPromiseConstructorLikeType === emptyObjectType) { // If we couldn't resolve the global PromiseConstructorLike type we cannot verify // compatibility with __awaiter. - error(node.type, Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, entityNameToString(promiseConstructorName)); + error(returnTypeNode, Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, entityNameToString(promiseConstructorName)); return unknownType; } - if (!checkTypeAssignableTo(promiseConstructorType, globalPromiseConstructorLikeType, node.type, + if (!checkTypeAssignableTo(promiseConstructorType, globalPromiseConstructorLikeType, returnTypeNode, Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value)) { return unknownType; } @@ -19211,7 +19340,8 @@ namespace ts { } function getParameterTypeNodeForDecoratorCheck(node: ParameterDeclaration): TypeNode { - return node.dotDotDotToken ? getRestParameterElementType(node.type) : node.type; + const typeNode = getEffectiveTypeAnnotationNode(node); + return isRestParameter(node) ? getRestParameterElementType(typeNode) : typeNode; } /** Check the decorators of a node */ @@ -19257,14 +19387,15 @@ namespace ts { markDecoratorMedataDataTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(parameter)); } - markDecoratorMedataDataTypeNodeAsReferenced((node).type); + markDecoratorMedataDataTypeNodeAsReferenced(getEffectiveReturnTypeNode(node)); break; case SyntaxKind.PropertyDeclaration: - markDecoratorMedataDataTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(node)); + markDecoratorMedataDataTypeNodeAsReferenced(getEffectiveTypeAnnotationNode(node)); break; + case SyntaxKind.Parameter: - markDecoratorMedataDataTypeNodeAsReferenced((node).type); + markDecoratorMedataDataTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(node)); break; } } @@ -19274,8 +19405,8 @@ namespace ts { function checkFunctionDeclaration(node: FunctionDeclaration): void { if (produceDiagnostics) { - checkFunctionOrMethodDeclaration(node) || checkGrammarForGenerator(node); - + checkFunctionOrMethodDeclaration(node); + checkGrammarForGenerator(node); checkCollisionWithCapturedSuperVariable(node, node.name); checkCollisionWithCapturedThisVariable(node, node.name); checkCollisionWithCapturedNewTargetVariable(node, node.name); @@ -19329,14 +19460,15 @@ namespace ts { checkSourceElement(node.body); + const returnTypeNode = getEffectiveReturnTypeNode(node); if ((functionFlags & FunctionFlags.Generator) === 0) { // Async function or normal function - const returnOrPromisedType = node.type && (functionFlags & FunctionFlags.Async + const returnOrPromisedType = returnTypeNode && (functionFlags & FunctionFlags.Async ? checkAsyncFunctionReturnType(node) // Async function - : getTypeFromTypeNode(node.type)); // normal function + : getTypeFromTypeNode(returnTypeNode)); // normal function checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnOrPromisedType); } - if (produceDiagnostics && !node.type) { + if (produceDiagnostics && !returnTypeNode) { // Report an implicit any error if there is no body, no explicit return type, and node is not a private method // in an ambient context if (noImplicitAny && nodeIsMissing(node.body) && !isPrivateWithinAmbient(node)) { @@ -19441,9 +19573,7 @@ namespace ts { function errorUnusedLocal(node: Node, name: string) { if (isIdentifierThatStartsWithUnderScore(node)) { const declaration = getRootDeclaration(node.parent); - if (declaration.kind === SyntaxKind.VariableDeclaration && - (declaration.parent.parent.kind === SyntaxKind.ForInStatement || - declaration.parent.parent.kind === SyntaxKind.ForOfStatement)) { + if (declaration.kind === SyntaxKind.VariableDeclaration && isForInOrOfStatement(declaration.parent.parent)) { return; } } @@ -20136,7 +20266,7 @@ namespace ts { } } - function checkForInOrForOfVariableDeclaration(iterationStatement: ForInStatement | ForOfStatement): void { + function checkForInOrForOfVariableDeclaration(iterationStatement: ForInOrOfStatement): void { const variableDeclarationList = iterationStatement.initializer; // checkGrammarForInOrForOfStatement will check that there is exactly one declaration. if (variableDeclarationList.declarations.length >= 1) { @@ -20466,7 +20596,8 @@ namespace ts { } function isGetAccessorWithAnnotatedSetAccessor(node: FunctionLikeDeclaration) { - return !!(node.kind === SyntaxKind.GetAccessor && getSetAccessorTypeAnnotationNode(getDeclarationOfKind(node.symbol, SyntaxKind.SetAccessor))); + return node.kind === SyntaxKind.GetAccessor + && getEffectiveSetAccessorTypeAnnotationNode(getDeclarationOfKind(node.symbol, SyntaxKind.SetAccessor)) !== undefined; } function isUnwrappedReturnTypeVoidOrAny(func: FunctionLikeDeclaration, returnType: Type): boolean { @@ -20510,7 +20641,7 @@ namespace ts { error(node, Diagnostics.Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class); } } - else if (func.type || isGetAccessorWithAnnotatedSetAccessor(func)) { + else if (getEffectiveReturnTypeNode(func) || isGetAccessorWithAnnotatedSetAccessor(func)) { if (functionFlags & FunctionFlags.Async) { // Async function const promisedType = getPromisedTypeOfPromise(returnType); const awaitedType = checkAwaitedType(exprType, node, Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member); @@ -21648,7 +21779,10 @@ namespace ts { } // Don't allow to re-export something with no value side when `--isolatedModules` is set. - if (node.kind === SyntaxKind.ExportSpecifier && compilerOptions.isolatedModules && !(target.flags & SymbolFlags.Value)) { + if (compilerOptions.isolatedModules + && node.kind === SyntaxKind.ExportSpecifier + && !(target.flags & SymbolFlags.Value) + && !isInAmbientContext(node)) { error(node, Diagnostics.Cannot_re_export_a_type_when_the_isolatedModules_flag_is_provided); } } @@ -21752,6 +21886,10 @@ namespace ts { if (moduleSymbol && hasExportAssignmentSymbol(moduleSymbol)) { error(node.moduleSpecifier, Diagnostics.Module_0_uses_export_and_cannot_be_used_with_export_Asterisk, symbolToString(moduleSymbol)); } + + if (modulekind !== ModuleKind.System && modulekind !== ModuleKind.ES2015) { + checkExternalEmitHelpers(node, ExternalEmitHelpers.ExportStar); + } } } } @@ -22406,10 +22544,16 @@ namespace ts { } if (entityName.parent!.kind === SyntaxKind.JSDocParameterTag) { - const parameter = ts.getParameterFromJSDoc(entityName.parent as JSDocParameterTag); + const parameter = getParameterFromJSDoc(entityName.parent as JSDocParameterTag); return parameter && parameter.symbol; } + if (entityName.parent.kind === SyntaxKind.TypeParameter && entityName.parent.parent.kind === SyntaxKind.JSDocTemplateTag) { + Debug.assert(!isInJavaScriptFile(entityName)); // Otherwise `isDeclarationName` would have been true. + const typeParameter = getTypeParameterFromJsDoc(entityName.parent as TypeParameterDeclaration & { parent: JSDocTemplateTag }); + return typeParameter && typeParameter.symbol; + } + if (isPartOfExpression(entityName)) { if (nodeIsMissing(entityName)) { // Missing entity name. @@ -22723,12 +22867,12 @@ namespace ts { return symbols; } else if (symbol.flags & SymbolFlags.Transient) { - if ((symbol as SymbolLinks).leftSpread) { - const links = symbol as SymbolLinks; - return [...getRootSymbols(links.leftSpread), ...getRootSymbols(links.rightSpread)]; + const transient = symbol as TransientSymbol; + if (transient.leftSpread) { + return [...getRootSymbols(transient.leftSpread), ...getRootSymbols(transient.rightSpread)]; } - if ((symbol as SymbolLinks).syntheticOrigin) { - return getRootSymbols((symbol as SymbolLinks).syntheticOrigin); + if (transient.syntheticOrigin) { + return getRootSymbols(transient.syntheticOrigin); } let target: Symbol; @@ -22833,7 +22977,9 @@ namespace ts { node = getParseTreeNode(node, isIdentifier); if (node) { const symbol = getReferencedValueSymbol(node); - if (symbol && symbol.flags & SymbolFlags.Alias) { + // We should only get the declaration of an alias if there isn't a local value + // declaration for the symbol + if (isNonLocalAlias(symbol, /*excludes*/ SymbolFlags.Value)) { return getDeclarationOfAliasSymbol(symbol); } } @@ -23424,7 +23570,8 @@ namespace ts { case ExternalEmitHelpers.AsyncGenerator: return "__asyncGenerator"; case ExternalEmitHelpers.AsyncDelegator: return "__asyncDelegator"; case ExternalEmitHelpers.AsyncValues: return "__asyncValues"; - default: Debug.fail("Unrecognized helper."); + case ExternalEmitHelpers.ExportStar: return "__exportStar"; + default: Debug.fail("Unrecognized helper"); } } @@ -24099,7 +24246,7 @@ namespace ts { } } - function checkGrammarForInOrForOfStatement(forInOrOfStatement: ForInStatement | ForOfStatement): boolean { + function checkGrammarForInOrForOfStatement(forInOrOfStatement: ForInOrOfStatement): boolean { if (checkGrammarStatementInAmbientContext(forInOrOfStatement)) { return true; } @@ -24639,6 +24786,27 @@ namespace ts { }); return result; } + + function checkGrammarImportCallExpression(node: ImportCall): boolean { + if (modulekind === ModuleKind.ES2015) { + return grammarErrorOnNode(node, Diagnostics.Dynamic_import_cannot_be_used_when_targeting_ECMAScript_2015_modules); + } + + if (node.typeArguments) { + return grammarErrorOnNode(node, Diagnostics.Dynamic_import_cannot_have_type_arguments); + } + + const arguments = node.arguments; + if (arguments.length !== 1) { + return grammarErrorOnNode(node, Diagnostics.Dynamic_import_must_have_one_specifier_as_an_argument); + } + + // see: parseArgumentOrArrayLiteralElement...we use this function which parse arguments of callExpression to parse specifier for dynamic import. + // parseArgumentOrArrayLiteralElement allows spread element to be in an argument list which is not allowed as specifier in dynamic import. + if (isSpreadElement(arguments[0])) { + return grammarErrorOnNode(arguments[0], Diagnostics.Specifier_of_dynamic_import_cannot_be_spread_element); + } + } } /** Like 'isDeclarationName', but returns true for LHS of `import { x as y }` or `export { x as y }`. */ @@ -24646,13 +24814,9 @@ namespace ts { switch (name.parent.kind) { case SyntaxKind.ImportSpecifier: case SyntaxKind.ExportSpecifier: - if ((name.parent as ImportOrExportSpecifier).propertyName) { - return true; - } - // falls through + return true; default: return isDeclarationName(name); - } } } diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index e612378671d..a21c9bd5cd9 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -100,11 +100,12 @@ namespace ts { "umd": ModuleKind.UMD, "es6": ModuleKind.ES2015, "es2015": ModuleKind.ES2015, + "esnext": ModuleKind.ESNext }), paramType: Diagnostics.KIND, showInSimplifiedHelpView: true, category: Diagnostics.Basic_Options, - description: Diagnostics.Specify_module_code_generation_Colon_commonjs_amd_system_umd_or_es2015, + description: Diagnostics.Specify_module_code_generation_Colon_commonjs_amd_system_umd_es2015_or_ESNext, }, { name: "lib", @@ -619,6 +620,12 @@ namespace ts { category: Diagnostics.Advanced_Options, description: Diagnostics.The_maximum_dependency_depth_to_search_under_node_modules_and_load_JavaScript_files }, + { + name: "noStrictGenericChecks", + type: "boolean", + category: Diagnostics.Advanced_Options, + description: Diagnostics.Disable_strict_checking_of_generic_signatures_in_function_types, + }, { // A list of plugins to load in the language service name: "plugins", @@ -1042,7 +1049,7 @@ namespace ts { for (let i = 0; i < nameColumn.length; i++) { const optionName = nameColumn[i]; const description = descriptionColumn[i]; - result.push(tab + tab + optionName + makePadding(marginLength - optionName.length + 2) + description); + result.push(optionName && `${tab}${tab}${optionName}${ description && (makePadding(marginLength - optionName.length + 2) + description)}`); } if (configurations.files && configurations.files.length) { result.push(`${tab}},`); @@ -1625,10 +1632,12 @@ namespace ts { } // Remove any subpaths under an existing recursively watched directory. - for (const key in wildcardDirectories) if (hasProperty(wildcardDirectories, key)) { - for (const recursiveKey of recursiveKeys) { - if (key !== recursiveKey && containsPath(recursiveKey, key, path, !useCaseSensitiveFileNames)) { - delete wildcardDirectories[key]; + for (const key in wildcardDirectories) { + if (hasProperty(wildcardDirectories, key)) { + for (const recursiveKey of recursiveKeys) { + if (key !== recursiveKey && containsPath(recursiveKey, key, path, !useCaseSensitiveFileNames)) { + delete wildcardDirectories[key]; + } } } } @@ -1716,10 +1725,12 @@ namespace ts { /* @internal */ export function convertCompilerOptionsForTelemetry(opts: ts.CompilerOptions): ts.CompilerOptions { const out: ts.CompilerOptions = {}; - for (const key in opts) if (opts.hasOwnProperty(key)) { - const type = getOptionFromName(key); - if (type !== undefined) { // Ignore unknown options - out[key] = getOptionValueWithEmptyStrings(opts[key], type); + for (const key in opts) { + if (opts.hasOwnProperty(key)) { + const type = getOptionFromName(key); + if (type !== undefined) { // Ignore unknown options + out[key] = getOptionValueWithEmptyStrings(opts[key], type); + } } } return out; diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 5819e634ff4..d70369f4ab6 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -51,8 +51,10 @@ namespace ts { // Copies keys/values from template. Note that for..in will not throw if // template is undefined, and instead will just exit the loop. - for (const key in template) if (hasOwnProperty.call(template, key)) { - map.set(key, template[key]); + for (const key in template) { + if (hasOwnProperty.call(template, key)) { + map.set(key, template[key]); + } } return map; @@ -473,7 +475,7 @@ namespace ts { * @param array The array to map. * @param mapfn The callback used to map the result into one or more values. */ - export function flatMap(array: T[], mapfn: (x: T, i: number) => U | U[]): U[] { + export function flatMap(array: T[] | undefined, mapfn: (x: T, i: number) => U | U[] | undefined): U[] | undefined { let result: U[]; if (array) { result = []; @@ -521,8 +523,8 @@ namespace ts { return result || array; } - export function mapDefined(array: ReadonlyArray, mapFn: (x: T, i: number) => T | undefined): ReadonlyArray { - const result: T[] = []; + export function mapDefined(array: ReadonlyArray, mapFn: (x: T, i: number) => U | undefined): U[] { + const result: U[] = []; for (let i = 0; i < array.length; i++) { const item = array[i]; const mapped = mapFn(item, i); @@ -977,9 +979,12 @@ namespace ts { */ export function getOwnKeys(map: MapLike): string[] { const keys: string[] = []; - for (const key in map) if (hasOwnProperty.call(map, key)) { - keys.push(key); + for (const key in map) { + if (hasOwnProperty.call(map, key)) { + keys.push(key); + } } + return keys; } @@ -1042,8 +1047,10 @@ namespace ts { export function assign>(t: T1, ...args: any[]): any; export function assign>(t: T1, ...args: any[]) { for (const arg of args) { - for (const p in arg) if (hasProperty(arg, p)) { - t[p] = arg[p]; + for (const p in arg) { + if (hasProperty(arg, p)) { + t[p] = arg[p]; + } } } return t; @@ -1058,13 +1065,19 @@ namespace ts { export function equalOwnProperties(left: MapLike, right: MapLike, equalityComparer?: (left: T, right: T) => boolean) { if (left === right) return true; if (!left || !right) return false; - for (const key in left) if (hasOwnProperty.call(left, key)) { - if (!hasOwnProperty.call(right, key) === undefined) return false; - if (equalityComparer ? !equalityComparer(left[key], right[key]) : left[key] !== right[key]) return false; + for (const key in left) { + if (hasOwnProperty.call(left, key)) { + if (!hasOwnProperty.call(right, key) === undefined) return false; + if (equalityComparer ? !equalityComparer(left[key], right[key]) : left[key] !== right[key]) return false; + } } - for (const key in right) if (hasOwnProperty.call(right, key)) { - if (!hasOwnProperty.call(left, key)) return false; + + for (const key in right) { + if (hasOwnProperty.call(right, key)) { + if (!hasOwnProperty.call(left, key)) return false; + } } + return true; } @@ -1106,12 +1119,18 @@ namespace ts { export function extend(first: T1, second: T2): T1 & T2 { const result: T1 & T2 = {}; - for (const id in second) if (hasOwnProperty.call(second, id)) { - (result as any)[id] = (second as any)[id]; + for (const id in second) { + if (hasOwnProperty.call(second, id)) { + (result as any)[id] = (second as any)[id]; + } } - for (const id in first) if (hasOwnProperty.call(first, id)) { - (result as any)[id] = (first as any)[id]; + + for (const id in first) { + if (hasOwnProperty.call(first, id)) { + (result as any)[id] = (first as any)[id]; + } } + return result; } @@ -2112,13 +2131,13 @@ namespace ts { export function getScriptKindFromFileName(fileName: string): ScriptKind { const ext = fileName.substr(fileName.lastIndexOf(".")); switch (ext.toLowerCase()) { - case ".js": + case Extension.Js: return ScriptKind.JS; - case ".jsx": + case Extension.Jsx: return ScriptKind.JSX; - case ".ts": + case Extension.Ts: return ScriptKind.TS; - case ".tsx": + case Extension.Tsx: return ScriptKind.TSX; default: return ScriptKind.Unknown; @@ -2128,10 +2147,10 @@ namespace ts { /** * List of supported extensions in order of file resolution precedence. */ - export const supportedTypeScriptExtensions = [".ts", ".tsx", ".d.ts"]; + export const supportedTypeScriptExtensions = [Extension.Ts, Extension.Tsx, Extension.Dts]; /** Must have ".d.ts" first because if ".ts" goes first, that will be detected as the extension instead of ".d.ts". */ - export const supportedTypescriptExtensionsForExtractExtension = [".d.ts", ".ts", ".tsx"]; - export const supportedJavascriptExtensions = [".js", ".jsx"]; + export const supportedTypescriptExtensionsForExtractExtension = [Extension.Dts, Extension.Ts, Extension.Tsx]; + export const supportedJavascriptExtensions = [Extension.Js, Extension.Jsx]; const allSupportedExtensions = supportedTypeScriptExtensions.concat(supportedJavascriptExtensions); export function getSupportedExtensions(options?: CompilerOptions, extraFileExtensions?: JsFileExtensionInfo[]): string[] { @@ -2139,7 +2158,7 @@ namespace ts { if (!extraFileExtensions || extraFileExtensions.length === 0 || !needAllExtensions) { return needAllExtensions ? allSupportedExtensions : supportedTypeScriptExtensions; } - const extensions = allSupportedExtensions.slice(0); + const extensions: string[] = allSupportedExtensions.slice(0); for (const extInfo of extraFileExtensions) { if (extensions.indexOf(extInfo.extension) === -1) { extensions.push(extInfo.extension); @@ -2218,7 +2237,7 @@ namespace ts { } } - const extensionsToRemove = [".d.ts", ".ts", ".js", ".tsx", ".jsx"]; + const extensionsToRemove = [Extension.Dts, Extension.Ts, Extension.Js, Extension.Tsx, Extension.Jsx]; export function removeFileExtension(path: string): string { for (const ext of extensionsToRemove) { const extensionless = tryRemoveExtension(path, ext); @@ -2249,6 +2268,7 @@ namespace ts { getSymbolConstructor(): new (flags: SymbolFlags, name: string) => Symbol; getTypeConstructor(): new (checker: TypeChecker, flags: TypeFlags) => Type; getSignatureConstructor(): new (checker: TypeChecker) => Signature; + getSourceMapSourceConstructor(): new (fileName: string, text: string, skipTrivia?: (pos: number) => number) => SourceMapSource; } function Symbol(this: Symbol, flags: SymbolFlags, name: string) { @@ -2279,6 +2299,12 @@ namespace ts { this.original = undefined; } + function SourceMapSource(this: SourceMapSource, fileName: string, text: string, skipTrivia?: (pos: number) => number) { + this.fileName = fileName; + this.text = text; + this.skipTrivia = skipTrivia || (pos => pos); + } + export let objectAllocator: ObjectAllocator = { getNodeConstructor: () => Node, getTokenConstructor: () => Node, @@ -2286,7 +2312,8 @@ namespace ts { getSourceFileConstructor: () => Node, getSymbolConstructor: () => Symbol, getTypeConstructor: () => Type, - getSignatureConstructor: () => Signature + getSignatureConstructor: () => Signature, + getSourceMapSourceConstructor: () => SourceMapSource, }; export const enum AssertionLevel { @@ -2464,7 +2491,7 @@ namespace ts { /** True if an extension is one of the supported TypeScript extensions. */ export function extensionIsTypeScript(ext: Extension): boolean { - return ext <= Extension.LastTypeScriptExtension; + return ext === Extension.Ts || ext === Extension.Tsx || ext === Extension.Dts; } /** @@ -2479,21 +2506,7 @@ namespace ts { Debug.fail(`File ${path} has unknown extension.`); } export function tryGetExtensionFromPath(path: string): Extension | undefined { - if (fileExtensionIs(path, ".d.ts")) { - return Extension.Dts; - } - if (fileExtensionIs(path, ".ts")) { - return Extension.Ts; - } - if (fileExtensionIs(path, ".tsx")) { - return Extension.Tsx; - } - if (fileExtensionIs(path, ".js")) { - return Extension.Js; - } - if (fileExtensionIs(path, ".jsx")) { - return Extension.Jsx; - } + return find(supportedTypescriptExtensionsForExtractExtension, e => fileExtensionIs(path, e)) || find(supportedJavascriptExtensions, e => fileExtensionIs(path, e)); } export function isCheckJsEnabledForFile(sourceFile: SourceFile, compilerOptions: CompilerOptions) { diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index 987157843b6..007620ad510 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -596,7 +596,7 @@ namespace ts { currentIdentifiers = node.identifiers; isCurrentFileExternalModule = isExternalModule(node); enclosingDeclaration = node; - emitDetachedComments(currentText, currentLineMap, writer, writeCommentRange, node, newLine, /*removeComents*/ true); + emitDetachedComments(currentText, currentLineMap, writer, writeCommentRange, node, newLine, /*removeComments*/ true); emitLines(node.statements); } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index a7b6db70e5e..eda408c03e5 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -883,6 +883,23 @@ "category": "Error", "code": 1322 }, + "Dynamic import cannot be used when targeting ECMAScript 2015 modules.": { + "category": "Error", + "code": 1323 + }, + "Dynamic import must have one specifier as an argument.": { + "category": "Error", + "code": 1324 + }, + "Specifier of dynamic import cannot be spread element.": { + "category": "Error", + "code": 1325 + }, + "Dynamic import cannot have type arguments": { + "category": "Error", + "code": 1326 + }, + "Duplicate identifier '{0}'.": { "category": "Error", "code": 2300 @@ -1879,6 +1896,10 @@ "category": "Error", "code": 2558 }, + "Type '{0}' has no properties in common with type '{1}'.": { + "category": "Error", + "code": 2559 + }, "JSX element attributes type '{0}' may not be a union type.": { "category": "Error", "code": 2600 @@ -1923,10 +1944,6 @@ "category": "Error", "code": 2649 }, - "Cannot emit namespaced JSX elements in React.": { - "category": "Error", - "code": 2650 - }, "A member initializer in a enum declaration cannot reference members declared after it, including members defined in other enums.": { "category": "Error", "code": 2651 @@ -2159,6 +2176,14 @@ "category": "Error", "code": 2710 }, + "A dynamic import call returns a 'Promise'. Make sure you have a declaration for 'Promise' or include 'ES2015' in your `--lib` option.": { + "category": "Error", + "code": 2711 + }, + "A dynamic import call in ES5/ES3 requires the 'Promise' constructor. Make sure you have a declaration for the 'Promise' constructor or include 'ES2015' in your `--lib` option.": { + "category": "Error", + "code": 2712 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", @@ -2625,7 +2650,7 @@ "category": "Message", "code": 6015 }, - "Specify module code generation: 'commonjs', 'amd', 'system', 'umd' or 'es2015'.": { + "Specify module code generation: 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'.": { "category": "Message", "code": 6016 }, @@ -3253,6 +3278,10 @@ "category": "Message", "code": 6184 }, + "Disable strict checking of generic signatures in function types.": { + "category": "Message", + "code": 6185 + }, "Variable '{0}' implicitly has an '{1}' type.": { "category": "Error", "code": 7005 @@ -3361,6 +3390,11 @@ "category": "Error", "code": 7035 }, + "Dynamic import's specifier must be of type 'string', but here has type '{0}'.": { + "category": "Error", + "code": 7036 + }, + "You cannot rename this element.": { "category": "Error", "code": 8000 @@ -3555,11 +3589,11 @@ "category": "Message", "code": 90015 }, - "Add declaration for missing property '{0}'.": { + "Declare property '{0}'.": { "category": "Message", "code": 90016 }, - "Add index signature for missing property '{0}'.": { + "Add index signature for property '{0}'.": { "category": "Message", "code": 90017 }, @@ -3583,7 +3617,15 @@ "category": "Message", "code": 90022 }, - + "Declare method '{0}'.": { + "category": "Message", + "code": 90023 + }, + "Declare static method '{0}'.": { + "category": "Message", + "code": 90024 + }, + "Convert function to an ES2015 class": { "category": "Message", "code": 95001 diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 1d2f75fcd60..a788bf6a4d0 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -676,6 +676,7 @@ namespace ts { case SyntaxKind.SuperKeyword: case SyntaxKind.TrueKeyword: case SyntaxKind.ThisKeyword: + case SyntaxKind.ImportKeyword: writeTokenNode(node); return; @@ -958,7 +959,7 @@ namespace ts { function emitConstructorType(node: ConstructorTypeNode) { write("new "); emitTypeParameters(node, node.typeParameters); - emitParametersForArrow(node, node.parameters); + emitParameters(node, node.parameters); write(" => "); emit(node.type); } @@ -2282,11 +2283,25 @@ namespace ts { emitList(parentNode, parameters, ListFormat.Parameters); } - function emitParametersForArrow(parentNode: Node, parameters: NodeArray) { - if (parameters && - parameters.length === 1 && - parameters[0].type === undefined && - parameters[0].pos === parentNode.pos) { + function canEmitSimpleArrowHead(parentNode: FunctionTypeNode | ArrowFunction, parameters: NodeArray) { + const parameter = singleOrUndefined(parameters); + return parameter + && parameter.pos === parentNode.pos // may not have parsed tokens between parent and parameter + && !(isArrowFunction(parentNode) && parentNode.type) // arrow function may not have return type annotation + && !some(parentNode.decorators) // parent may not have decorators + && !some(parentNode.modifiers) // parent may not have modifiers + && !some(parentNode.typeParameters) // parent may not have type parameters + && !some(parameter.decorators) // parameter may not have decorators + && !some(parameter.modifiers) // parameter may not have modifiers + && !parameter.dotDotDotToken // parameter may not be rest + && !parameter.questionToken // parameter may not be optional + && !parameter.type // parameter may not have a type annotation + && !parameter.initializer // parameter may not have an initializer + && isIdentifier(parameter.name); // parameter name must be identifier + } + + function emitParametersForArrow(parentNode: FunctionTypeNode | ArrowFunction, parameters: NodeArray) { + if (canEmitSimpleArrowHead(parentNode, parameters)) { emit(parameters[0]); } else { diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 26c40b05239..32244a86792 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -228,7 +228,7 @@ namespace ts { // Signature elements - export function createTypeParameterDeclaration(name: string | Identifier, constraint: TypeNode | undefined, defaultType: TypeNode | undefined) { + export function createTypeParameterDeclaration(name: string | Identifier, constraint?: TypeNode, defaultType?: TypeNode) { const node = createSynthesizedNode(SyntaxKind.TypeParameter) as TypeParameterDeclaration; node.name = asName(name); node.constraint = constraint; @@ -2314,15 +2314,24 @@ namespace ts { /** * Sets a custom text range to use when emitting source maps. */ - export function setSourceMapRange(node: T, range: TextRange | undefined) { + export function setSourceMapRange(node: T, range: SourceMapRange | undefined) { getOrCreateEmitNode(node).sourceMapRange = range; return node; } + let SourceMapSource: new (fileName: string, text: string, skipTrivia?: (pos: number) => number) => SourceMapSource; + + /** + * Create an external source map source file reference + */ + export function createSourceMapSource(fileName: string, text: string, skipTrivia?: (pos: number) => number): SourceMapSource { + return new (SourceMapSource || (SourceMapSource = objectAllocator.getSourceMapSourceConstructor()))(fileName, text, skipTrivia); + } + /** * Gets the TextRange to use for source maps for a token of a node. */ - export function getTokenSourceMapRange(node: Node, token: SyntaxKind): TextRange | undefined { + export function getTokenSourceMapRange(node: Node, token: SyntaxKind): SourceMapRange | undefined { const emitNode = node.emitNode; const tokenSourceMapRanges = emitNode && emitNode.tokenSourceMapRanges; return tokenSourceMapRanges && tokenSourceMapRanges[token]; @@ -2331,7 +2340,7 @@ namespace ts { /** * Sets the TextRange to use for source maps for a token of a node. */ - export function setTokenSourceMapRange(node: T, token: SyntaxKind, range: TextRange | undefined) { + export function setTokenSourceMapRange(node: T, token: SyntaxKind, range: SourceMapRange | undefined) { const emitNode = getOrCreateEmitNode(node); const tokenSourceMapRanges = emitNode.tokenSourceMapRanges || (emitNode.tokenSourceMapRanges = []); tokenSourceMapRanges[token] = range; @@ -2503,6 +2512,7 @@ namespace ts { helpers } = sourceEmitNode; if (!destEmitNode) destEmitNode = {}; + // We are using `.slice()` here in case `destEmitNode.leadingComments` is pushed to later. if (leadingComments) destEmitNode.leadingComments = addRange(leadingComments.slice(), destEmitNode.leadingComments); if (trailingComments) destEmitNode.trailingComments = addRange(trailingComments.slice(), destEmitNode.trailingComments); if (flags) destEmitNode.flags = flags; @@ -3840,23 +3850,34 @@ namespace ts { return emitNode && emitNode.externalHelpersModuleName; } - export function getOrCreateExternalHelpersModuleNameIfNeeded(node: SourceFile, compilerOptions: CompilerOptions) { - if (compilerOptions.importHelpers && (isExternalModule(node) || compilerOptions.isolatedModules)) { + export function getOrCreateExternalHelpersModuleNameIfNeeded(node: SourceFile, compilerOptions: CompilerOptions, hasExportStarsToExportValues?: boolean) { + if (compilerOptions.importHelpers && isEffectiveExternalModule(node, compilerOptions)) { const externalHelpersModuleName = getExternalHelpersModuleName(node); if (externalHelpersModuleName) { return externalHelpersModuleName; } - const helpers = getEmitHelpers(node); - if (helpers) { - for (const helper of helpers) { - if (!helper.scoped) { - const parseNode = getOriginalNode(node, isSourceFile); - const emitNode = getOrCreateEmitNode(parseNode); - return emitNode.externalHelpersModuleName || (emitNode.externalHelpersModuleName = createUniqueName(externalHelpersModuleNameText)); + const moduleKind = getEmitModuleKind(compilerOptions); + let create = hasExportStarsToExportValues + && moduleKind !== ModuleKind.System + && moduleKind !== ModuleKind.ES2015; + if (!create) { + const helpers = getEmitHelpers(node); + if (helpers) { + for (const helper of helpers) { + if (!helper.scoped) { + create = true; + break; + } } } } + + if (create) { + const parseNode = getOriginalNode(node, isSourceFile); + const emitNode = getOrCreateEmitNode(parseNode); + return emitNode.externalHelpersModuleName || (emitNode.externalHelpersModuleName = createUniqueName(externalHelpersModuleNameText)); + } } } @@ -4239,17 +4260,6 @@ namespace ts { let exportEquals: ExportAssignment = undefined; let hasExportStarsToExportValues = false; - const externalHelpersModuleName = getOrCreateExternalHelpersModuleNameIfNeeded(sourceFile, compilerOptions); - const externalHelpersImportDeclaration = externalHelpersModuleName && createImportDeclaration( - /*decorators*/ undefined, - /*modifiers*/ undefined, - createImportClause(/*name*/ undefined, createNamespaceImport(externalHelpersModuleName)), - createLiteral(externalHelpersModuleNameText)); - - if (externalHelpersImportDeclaration) { - externalImports.push(externalHelpersImportDeclaration); - } - for (const node of sourceFile.statements) { switch (node.kind) { case SyntaxKind.ImportDeclaration: @@ -4360,6 +4370,17 @@ namespace ts { } } + const externalHelpersModuleName = getOrCreateExternalHelpersModuleNameIfNeeded(sourceFile, compilerOptions, hasExportStarsToExportValues); + const externalHelpersImportDeclaration = externalHelpersModuleName && createImportDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, + createImportClause(/*name*/ undefined, createNamespaceImport(externalHelpersModuleName)), + createLiteral(externalHelpersModuleNameText)); + + if (externalHelpersImportDeclaration) { + externalImports.unshift(externalHelpersImportDeclaration); + } + return { externalImports, exportSpecifiers, exportEquals, hasExportStarsToExportValues, exportedBindings, exportedNames, externalHelpersImportDeclaration }; } diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index 4c6616c36d4..4ea590977e1 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -815,15 +815,15 @@ namespace ts { switch (extensions) { case Extensions.DtsOnly: - return tryExtension(".d.ts", Extension.Dts); + return tryExtension(Extension.Dts); case Extensions.TypeScript: - return tryExtension(".ts", Extension.Ts) || tryExtension(".tsx", Extension.Tsx) || tryExtension(".d.ts", Extension.Dts); + return tryExtension(Extension.Ts) || tryExtension(Extension.Tsx) || tryExtension(Extension.Dts); case Extensions.JavaScript: - return tryExtension(".js", Extension.Js) || tryExtension(".jsx", Extension.Jsx); + return tryExtension(Extension.Js) || tryExtension(Extension.Jsx); } - function tryExtension(ext: string, extension: Extension): Resolved | undefined { - const path = tryFile(candidate + ext, failedLookupLocations, onlyRecordFailures, state); + function tryExtension(extension: Extension): Resolved | undefined { + const path = tryFile(candidate + extension, failedLookupLocations, onlyRecordFailures, state); return path && { path, extension }; } } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 849f97bbbaf..75186eca2c1 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -15,7 +15,7 @@ namespace ts { else if (kind === SyntaxKind.Identifier) { return new (IdentifierConstructor || (IdentifierConstructor = objectAllocator.getIdentifierConstructor()))(kind, pos, end); } - else if (kind < SyntaxKind.FirstNode) { + else if (!isNodeKind(kind)) { return new (TokenConstructor || (TokenConstructor = objectAllocator.getTokenConstructor()))(kind, pos, end); } else { @@ -46,10 +46,16 @@ namespace ts { } } - // Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes - // stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; otherwise, - // embedded arrays are flattened and the 'cbNode' callback is invoked for each element. If a callback returns - // a truthy value, iteration stops and that value is returned. Otherwise, undefined is returned. + /** + * Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes + * stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; otherwise, + * embedded arrays are flattened and the 'cbNode' callback is invoked for each element. If a callback returns + * a truthy value, iteration stops and that value is returned. Otherwise, undefined is returned. + * + * @param node a given node to visit its children + * @param cbNode a callback to be invoked for all child nodes + * @param cbNodeArray a callback to be invoked for embedded array + */ export function forEachChild(node: Node, cbNode: (node: Node) => T | undefined, cbNodeArray?: (nodes: NodeArray) => T | undefined): T | undefined { if (!node) { return; @@ -475,7 +481,11 @@ namespace ts { // becoming detached from any SourceFile). It is recommended that this SourceFile not // be used once 'update' is called on it. export function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile { - return IncrementalParser.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks); + const newSourceFile = IncrementalParser.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks); + // Because new source file node is created, it may not have the flag PossiblyContainDynamicImport. This is the case if there is no new edit to add dynamic import. + // We will manually port the flag to the new source file. + newSourceFile.flags |= (sourceFile.flags & NodeFlags.PossiblyContainsDynamicImport); + return newSourceFile; } /* @internal */ @@ -754,7 +764,7 @@ namespace ts { sourceFile.languageVersion = languageVersion; sourceFile.fileName = normalizePath(fileName); sourceFile.languageVariant = getLanguageVariant(scriptKind); - sourceFile.isDeclarationFile = fileExtensionIs(sourceFile.fileName, ".d.ts"); + sourceFile.isDeclarationFile = fileExtensionIs(sourceFile.fileName, Extension.Dts); sourceFile.scriptKind = scriptKind; return sourceFile; @@ -1093,7 +1103,7 @@ namespace ts { pos = scanner.getStartPos(); } - return kind >= SyntaxKind.FirstNode ? new NodeConstructor(kind, pos, pos) : + return isNodeKind(kind) ? new NodeConstructor(kind, pos, pos) : kind === SyntaxKind.Identifier ? new IdentifierConstructor(kind, pos, pos) : new TokenConstructor(kind, pos, pos); } @@ -2409,7 +2419,7 @@ namespace ts { if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) { return parseSignatureMember(SyntaxKind.CallSignature); } - if (token() === SyntaxKind.NewKeyword && lookAhead(isStartOfConstructSignature)) { + if (token() === SyntaxKind.NewKeyword && lookAhead(nextTokenIsOpenParenOrLessThan)) { return parseSignatureMember(SyntaxKind.ConstructSignature); } const fullStart = getNodePos(); @@ -2420,7 +2430,7 @@ namespace ts { return parsePropertyOrMethodSignature(fullStart, modifiers); } - function isStartOfConstructSignature() { + function nextTokenIsOpenParenOrLessThan() { nextToken(); return token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken; } @@ -2777,6 +2787,8 @@ namespace ts { case SyntaxKind.SlashEqualsToken: case SyntaxKind.Identifier: return true; + case SyntaxKind.ImportKeyword: + return lookAhead(nextTokenIsOpenParenOrLessThan); default: return isIdentifier(); } @@ -3509,10 +3521,10 @@ namespace ts { * 5) --UnaryExpression[?Yield] */ if (isUpdateExpression()) { - const incrementExpression = parseIncrementExpression(); + const updateExpression = parseUpdateExpression(); return token() === SyntaxKind.AsteriskAsteriskToken ? - parseBinaryExpressionRest(getBinaryOperatorPrecedence(), incrementExpression) : - incrementExpression; + parseBinaryExpressionRest(getBinaryOperatorPrecedence(), updateExpression) : + updateExpression; } /** @@ -3578,7 +3590,7 @@ namespace ts { } // falls through default: - return parseIncrementExpression(); + return parseUpdateExpression(); } } @@ -3594,7 +3606,7 @@ namespace ts { */ function isUpdateExpression(): boolean { // This function is called inside parseUnaryExpression to decide - // whether to call parseSimpleUnaryExpression or call parseIncrementExpression directly + // whether to call parseSimpleUnaryExpression or call parseUpdateExpression directly switch (token()) { case SyntaxKind.PlusToken: case SyntaxKind.MinusToken: @@ -3618,9 +3630,9 @@ namespace ts { } /** - * Parse ES7 IncrementExpression. IncrementExpression is used instead of ES6's PostFixExpression. + * Parse ES7 UpdateExpression. UpdateExpression is used instead of ES6's PostFixExpression. * - * ES7 IncrementExpression[yield]: + * ES7 UpdateExpression[yield]: * 1) LeftHandSideExpression[?yield] * 2) LeftHandSideExpression[?yield] [[no LineTerminator here]]++ * 3) LeftHandSideExpression[?yield] [[no LineTerminator here]]-- @@ -3628,7 +3640,7 @@ namespace ts { * 5) --LeftHandSideExpression[?yield] * In TypeScript (2), (3) are parsed as PostfixUnaryExpression. (4), (5) are parsed as PrefixUnaryExpression */ - function parseIncrementExpression(): IncrementExpression { + function parseUpdateExpression(): UpdateExpression { if (token() === SyntaxKind.PlusPlusToken || token() === SyntaxKind.MinusMinusToken) { const node = createNode(SyntaxKind.PrefixUnaryExpression); node.operator = token(); @@ -3678,17 +3690,27 @@ namespace ts { // CallExpression Arguments // CallExpression[Expression] // CallExpression.IdentifierName - // super ( ArgumentListopt ) + // import (AssignmentExpression) + // super Arguments // super.IdentifierName // - // Because of the recursion in these calls, we need to bottom out first. There are two - // bottom out states we can run into. Either we see 'super' which must start either of - // the last two CallExpression productions. Or we have a MemberExpression which either - // completes the LeftHandSideExpression, or starts the beginning of the first four - // CallExpression productions. - const expression = token() === SyntaxKind.SuperKeyword - ? parseSuperExpression() - : parseMemberExpressionOrHigher(); + // Because of the recursion in these calls, we need to bottom out first. There are three + // bottom out states we can run into: 1) We see 'super' which must start either of + // the last two CallExpression productions. 2) We see 'import' which must start import call. + // 3)we have a MemberExpression which either completes the LeftHandSideExpression, + // or starts the beginning of the first four CallExpression productions. + let expression: MemberExpression; + if (token() === SyntaxKind.ImportKeyword) { + // We don't want to eagerly consume all import keyword as import call expression so we look a head to find "(" + // For example: + // var foo3 = require("subfolder + // import * as foo1 from "module-from-node -> we want this import to be a statement rather than import call expression + sourceFile.flags |= NodeFlags.PossiblyContainsDynamicImport; + expression = parseTokenNode(); + } + else { + expression = token() === SyntaxKind.SuperKeyword ? parseSuperExpression() : parseMemberExpressionOrHigher(); + } // Now, we *may* be complete. However, we might have consumed the start of a // CallExpression. As such, we need to consume the rest of it here to be complete. @@ -3696,7 +3718,7 @@ namespace ts { } function parseMemberExpressionOrHigher(): MemberExpression { - // Note: to make our lives simpler, we decompose the the NewExpression productions and + // Note: to make our lives simpler, we decompose the NewExpression productions and // place ObjectCreationExpression and FunctionExpression into PrimaryExpression. // like so: // @@ -4792,9 +4814,11 @@ namespace ts { case SyntaxKind.FinallyKeyword: return true; + case SyntaxKind.ImportKeyword: + return isStartOfDeclaration() || lookAhead(nextTokenIsOpenParenOrLessThan); + case SyntaxKind.ConstKeyword: case SyntaxKind.ExportKeyword: - case SyntaxKind.ImportKeyword: return isStartOfDeclaration(); case SyntaxKind.AsyncKeyword: @@ -6513,6 +6537,10 @@ namespace ts { case "augments": tag = parseAugmentsTag(atToken, tagName); break; + case "class": + case "constructor": + tag = parseClassTag(atToken, tagName); + break; case "arg": case "argument": case "param": @@ -6639,14 +6667,12 @@ namespace ts { }); } - function parseBracketNameInPropertyAndParamTag() { - let name: Identifier; - let isBracketed: boolean; + function parseBracketNameInPropertyAndParamTag(): { name: Identifier, isBracketed: boolean } { // Looking for something like '[foo]' or 'foo' - if (parseOptionalToken(SyntaxKind.OpenBracketToken)) { - name = parseJSDocIdentifierName(); + const isBracketed = parseOptional(SyntaxKind.OpenBracketToken); + const name = parseJSDocIdentifierName(/*createIfMissing*/ true); + if (isBracketed) { skipWhitespace(); - isBracketed = true; // May have an optional default, e.g. '[foo = 42]' if (parseOptionalToken(SyntaxKind.EqualsToken)) { @@ -6655,9 +6681,7 @@ namespace ts { parseExpected(SyntaxKind.CloseBracketToken); } - else if (tokenIsIdentifierOrKeyword(token())) { - name = parseJSDocIdentifierName(); - } + return { name, isBracketed }; } @@ -6668,11 +6692,6 @@ namespace ts { const { name, isBracketed } = parseBracketNameInPropertyAndParamTag(); skipWhitespace(); - if (!name) { - parseErrorAtPosition(scanner.getStartPos(), 0, Diagnostics.Identifier_expected); - return undefined; - } - let preName: Identifier, postName: Identifier; if (typeExpression) { postName = name; @@ -6732,6 +6751,13 @@ namespace ts { return finishNode(result); } + function parseClassTag(atToken: AtToken, tagName: Identifier): JSDocClassTag { + const tag = createNode(SyntaxKind.JSDocClassTag, atToken.pos); + tag.atToken = atToken; + tag.tagName = tagName; + return finishNode(tag); + } + function parseTypedefTag(atToken: AtToken, tagName: Identifier): JSDocTypedefTag { const typeExpression = tryParseTypeExpression(); skipWhitespace(); @@ -6825,7 +6851,7 @@ namespace ts { jsDocNamespaceNode.flags |= flags; jsDocNamespaceNode.name = typeNameOrNamespaceName; jsDocNamespaceNode.body = parseJSDocTypeNameWithNamespace(NodeFlags.NestedNamespace); - return jsDocNamespaceNode; + return finishNode(jsDocNamespaceNode); } if (typeNameOrNamespaceName && flags & NodeFlags.NestedNamespace) { @@ -6916,14 +6942,19 @@ namespace ts { return currentToken = scanner.scanJSDocToken(); } - function parseJSDocIdentifierName(): Identifier { - return createJSDocIdentifier(tokenIsIdentifierOrKeyword(token())); + function parseJSDocIdentifierName(createIfMissing = false): Identifier { + return createJSDocIdentifier(tokenIsIdentifierOrKeyword(token()), createIfMissing); } - function createJSDocIdentifier(isIdentifier: boolean): Identifier { + function createJSDocIdentifier(isIdentifier: boolean, createIfMissing: boolean): Identifier { if (!isIdentifier) { - parseErrorAtCurrentToken(Diagnostics.Identifier_expected); - return undefined; + if (createIfMissing) { + return createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.Identifier_expected); + } + else { + parseErrorAtCurrentToken(Diagnostics.Identifier_expected); + return undefined; + } } const pos = scanner.getTokenPos(); diff --git a/src/compiler/program.ts b/src/compiler/program.ts index e69a89cc618..cc6ae1a5813 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -984,16 +984,12 @@ namespace ts { if (sourceFile) { return getDiagnostics(sourceFile, cancellationToken); } - - const allDiagnostics: Diagnostic[] = []; - forEach(program.getSourceFiles(), sourceFile => { + return sortAndDeduplicateDiagnostics(flatMap(program.getSourceFiles(), sourceFile => { if (cancellationToken) { cancellationToken.throwIfCancellationRequested(); } - addRange(allDiagnostics, getDiagnostics(sourceFile, cancellationToken)); - }); - - return sortAndDeduplicateDiagnostics(allDiagnostics); + return getDiagnostics(sourceFile, cancellationToken); + })); } function getSyntacticDiagnostics(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] { @@ -1069,10 +1065,10 @@ namespace ts { const typeChecker = getDiagnosticsProducingTypeChecker(); Debug.assert(!!sourceFile.bindDiagnostics); - const bindDiagnostics = sourceFile.bindDiagnostics; // For JavaScript files, we don't want to report semantic errors unless explicitly requested. - const includeCheckDiagnostics = !isSourceFileJavaScript(sourceFile) || isCheckJsEnabledForFile(sourceFile, options); - const checkDiagnostics = includeCheckDiagnostics ? typeChecker.getDiagnostics(sourceFile, cancellationToken) : []; + const includeBindAndCheckDiagnostics = !isSourceFileJavaScript(sourceFile) || isCheckJsEnabledForFile(sourceFile, options); + const bindDiagnostics = includeBindAndCheckDiagnostics ? sourceFile.bindDiagnostics : emptyArray; + const checkDiagnostics = includeBindAndCheckDiagnostics ? typeChecker.getDiagnostics(sourceFile, cancellationToken) : emptyArray; const fileProcessingDiagnosticsInFile = fileProcessingDiagnostics.getDiagnostics(sourceFile.fileName); const programDiagnosticsInFile = programDiagnostics.getDiagnostics(sourceFile.fileName); @@ -1330,16 +1326,13 @@ namespace ts { } function getOptionsDiagnostics(): Diagnostic[] { - const allDiagnostics: Diagnostic[] = []; - addRange(allDiagnostics, fileProcessingDiagnostics.getGlobalDiagnostics()); - addRange(allDiagnostics, programDiagnostics.getGlobalDiagnostics()); - return sortAndDeduplicateDiagnostics(allDiagnostics); + return sortAndDeduplicateDiagnostics(concatenate( + fileProcessingDiagnostics.getGlobalDiagnostics(), + programDiagnostics.getGlobalDiagnostics())); } function getGlobalDiagnostics(): Diagnostic[] { - const allDiagnostics: Diagnostic[] = []; - addRange(allDiagnostics, getDiagnosticsProducingTypeChecker().getGlobalDiagnostics()); - return sortAndDeduplicateDiagnostics(allDiagnostics); + return sortAndDeduplicateDiagnostics(getDiagnosticsProducingTypeChecker().getGlobalDiagnostics().slice()); } function processRootFile(fileName: string, isDefaultLib: boolean) { @@ -1366,6 +1359,7 @@ namespace ts { const isJavaScriptFile = isSourceFileJavaScript(file); const isExternalModuleFile = isExternalModule(file); + // file.imports may not be undefined if there exists dynamic import let imports: LiteralExpression[]; let moduleAugmentations: LiteralExpression[]; let ambientModules: string[]; @@ -1385,8 +1379,8 @@ namespace ts { for (const node of file.statements) { collectModuleReferences(node, /*inAmbientModule*/ false); - if (isJavaScriptFile) { - collectRequireCalls(node); + if ((file.flags & NodeFlags.PossiblyContainsDynamicImport) || isJavaScriptFile) { + collectDynamicImportOrRequireCalls(node); } } @@ -1449,12 +1443,16 @@ namespace ts { } } - function collectRequireCalls(node: Node): void { + function collectDynamicImportOrRequireCalls(node: Node): void { if (isRequireCall(node, /*checkArgumentIsStringLiteral*/ true)) { (imports || (imports = [])).push((node).arguments[0]); } + // we have to check the argument list has length of 1. We will still have to process these even though we have parsing error. + else if (isImportCall(node) && node.arguments.length === 1 && node.arguments[0].kind === SyntaxKind.StringLiteral) { + (imports || (imports = [])).push((node).arguments[0]); + } else { - forEachChild(node, collectRequireCalls); + forEachChild(node, collectDynamicImportOrRequireCalls); } } } @@ -1486,7 +1484,8 @@ namespace ts { } } return sourceFile; - } else { + } + else { const sourceFileNoExtension = options.allowNonTsExtensions && getSourceFile(fileName); if (sourceFileNoExtension) return sourceFileNoExtension; @@ -1496,7 +1495,7 @@ namespace ts { } const sourceFileWithAddedExtension = forEach(supportedExtensions, extension => getSourceFile(fileName + extension)); - if (fail && !sourceFileWithAddedExtension) fail(Diagnostics.File_0_not_found, fileName + ".ts"); + if (fail && !sourceFileWithAddedExtension) fail(Diagnostics.File_0_not_found, fileName + Extension.Ts); return sourceFileWithAddedExtension; } } diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 0a072a3b8ac..dd43b3c8263 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -286,7 +286,7 @@ namespace ts { const tokenStrings = makeReverseMap(textToToken); - export function tokenToString(t: SyntaxKind): string { + export function tokenToString(t: SyntaxKind): string | undefined { return tokenStrings[t]; } @@ -363,7 +363,7 @@ namespace ts { }; } - export function getLineAndCharacterOfPosition(sourceFile: SourceFile, position: number): LineAndCharacter { + export function getLineAndCharacterOfPosition(sourceFile: SourceFileLike, position: number): LineAndCharacter { return computeLineAndCharacterOfPosition(getLineStarts(sourceFile), position); } diff --git a/src/compiler/sourcemap.ts b/src/compiler/sourcemap.ts index d743f488e75..ffef485581b 100644 --- a/src/compiler/sourcemap.ts +++ b/src/compiler/sourcemap.ts @@ -22,7 +22,7 @@ namespace ts { * * @param sourceFile The source file. */ - setSourceFile(sourceFile: SourceFile): void; + setSourceFile(sourceFile: SourceMapSource): void; /** * Emits a mapping. @@ -81,7 +81,7 @@ namespace ts { export function createSourceMapWriter(host: EmitHost, writer: EmitTextWriter): SourceMapWriter { const compilerOptions = host.getCompilerOptions(); const extendedDiagnostics = compilerOptions.extendedDiagnostics; - let currentSourceFile: SourceFile; + let currentSource: SourceMapSource; let currentSourceText: string; let sourceMapDir: string; // The directory in which sourcemap will be @@ -109,6 +109,13 @@ namespace ts { getSourceMappingURL, }; + /** + * Skips trivia such as comments and white-space that can optionally overriden by the source map source + */ + function skipSourceTrivia(pos: number): number { + return currentSource.skipTrivia ? currentSource.skipTrivia(pos) : skipTrivia(currentSourceText, pos); + } + /** * Initialize the SourceMapWriter for a new output file. * @@ -125,7 +132,7 @@ namespace ts { reset(); } - currentSourceFile = undefined; + currentSource = undefined; currentSourceText = undefined; // Current source map file and its index in the sources list @@ -192,7 +199,7 @@ namespace ts { return; } - currentSourceFile = undefined; + currentSource = undefined; sourceMapDir = undefined; sourceMapSourceIndex = undefined; lastRecordedSourceMapSpan = undefined; @@ -263,7 +270,7 @@ namespace ts { performance.mark("beforeSourcemap"); } - const sourceLinePos = getLineAndCharacterOfPosition(currentSourceFile, pos); + const sourceLinePos = getLineAndCharacterOfPosition(currentSource, pos); // Convert the location to be one-based. sourceLinePos.line++; @@ -320,14 +327,22 @@ namespace ts { if (node) { const emitNode = node.emitNode; const emitFlags = emitNode && emitNode.flags; - const { pos, end } = emitNode && emitNode.sourceMapRange || node; + const range = emitNode && emitNode.sourceMapRange; + const { pos, end } = range || node; + let source = range && range.source; + const oldSource = currentSource; + if (source === oldSource) source = undefined; + + if (source) setSourceFile(source); if (node.kind !== SyntaxKind.NotEmittedStatement && (emitFlags & EmitFlags.NoLeadingSourceMap) === 0 && pos >= 0) { - emitPos(skipTrivia(currentSourceText, pos)); + emitPos(skipSourceTrivia(pos)); } + if (source) setSourceFile(oldSource); + if (emitFlags & EmitFlags.NoNestedSourceMaps) { disabled = true; emitCallback(hint, node); @@ -337,11 +352,15 @@ namespace ts { emitCallback(hint, node); } + if (source) setSourceFile(source); + if (node.kind !== SyntaxKind.NotEmittedStatement && (emitFlags & EmitFlags.NoTrailingSourceMap) === 0 && end >= 0) { emitPos(end); } + + if (source) setSourceFile(oldSource); } } @@ -362,7 +381,7 @@ namespace ts { const emitFlags = emitNode && emitNode.flags; const range = emitNode && emitNode.tokenSourceMapRanges && emitNode.tokenSourceMapRanges[token]; - tokenPos = skipTrivia(currentSourceText, range ? range.pos : tokenPos); + tokenPos = skipSourceTrivia(range ? range.pos : tokenPos); if ((emitFlags & EmitFlags.NoTokenLeadingSourceMaps) === 0 && tokenPos >= 0) { emitPos(tokenPos); } @@ -382,13 +401,13 @@ namespace ts { * * @param sourceFile The source file. */ - function setSourceFile(sourceFile: SourceFile) { + function setSourceFile(sourceFile: SourceMapSource) { if (disabled) { return; } - currentSourceFile = sourceFile; - currentSourceText = currentSourceFile.text; + currentSource = sourceFile; + currentSourceText = currentSource.text; // Add the file to tsFilePaths // If sourceroot option: Use the relative path corresponding to the common directory path @@ -396,7 +415,7 @@ namespace ts { const sourcesDirectoryPath = compilerOptions.sourceRoot ? host.getCommonSourceDirectory() : sourceMapDir; const source = getRelativePathToDirectoryOrUrl(sourcesDirectoryPath, - currentSourceFile.fileName, + currentSource.fileName, host.getCurrentDirectory(), host.getCanonicalFileName, /*isAbsolutePathAnUrl*/ true); @@ -407,10 +426,10 @@ namespace ts { sourceMapData.sourceMapSources.push(source); // The one that can be used from program to get the actual source file - sourceMapData.inputSourceFileNames.push(currentSourceFile.fileName); + sourceMapData.inputSourceFileNames.push(currentSource.fileName); if (compilerOptions.inlineSources) { - sourceMapData.sourceMapSourcesContent.push(currentSourceFile.text); + sourceMapData.sourceMapSourcesContent.push(currentSource.text); } } } diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 1abebe937e6..cd14f3b2801 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -35,6 +35,10 @@ namespace ts { getDirectories(path: string): string[]; readDirectory(path: string, extensions?: string[], exclude?: string[], include?: string[]): string[]; getModifiedTime?(path: string): Date; + /** + * This should be cryptographically secure. + * A good implementation is node.js' `crypto.createHash`. (https://nodejs.org/api/crypto.html#crypto_crypto_createhash_algorithm) + */ createHash?(data: string): string; getMemoryUsage?(): number; exit(exitCode?: number): void; diff --git a/src/compiler/transformer.ts b/src/compiler/transformer.ts index 75f9c43c6fe..bfd3360e885 100644 --- a/src/compiler/transformer.ts +++ b/src/compiler/transformer.ts @@ -15,6 +15,7 @@ namespace ts { function getModuleTransformer(moduleKind: ModuleKind): TransformerFactory { switch (moduleKind) { + case ModuleKind.ESNext: case ModuleKind.ES2015: return transformES2015Module; case ModuleKind.System: @@ -238,7 +239,7 @@ namespace ts { function hoistVariableDeclaration(name: Identifier): void { Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization."); Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed."); - const decl = createVariableDeclaration(name); + const decl = setEmitFlags(createVariableDeclaration(name), EmitFlags.NoNestedSourceMaps); if (!lexicalEnvironmentVariableDeclarations) { lexicalEnvironmentVariableDeclarations = [decl]; } diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index a0656476421..7acbd3126b4 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -2095,9 +2095,9 @@ namespace ts { enableSubstitutionsForBlockScopedBindings(); } - const declarations = flatten(map(node.declarations, node.flags & NodeFlags.Let + const declarations = flatMap(node.declarations, node.flags & NodeFlags.Let ? visitVariableDeclarationInLetDeclarationList - : visitVariableDeclaration)); + : visitVariableDeclaration); const declarationList = createVariableDeclarationList(declarations); setOriginalNode(declarationList, node); diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index 6e2f70b5c35..a3aa0139aa4 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -351,8 +351,10 @@ namespace ts { ); } - function awaitAsYield(expression: Expression) { - return createYield(/*asteriskToken*/ undefined, enclosingFunctionFlags & FunctionFlags.Generator ? createAwaitHelper(context, expression) : expression); + function createDownlevelAwait(expression: Expression) { + return enclosingFunctionFlags & FunctionFlags.Generator + ? createYield(/*asteriskToken*/ undefined, createAwaitHelper(context, expression)) + : createAwait(expression); } function transformForAwaitOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement) { @@ -385,11 +387,11 @@ namespace ts { EmitFlags.NoHoisting ), /*condition*/ createComma( - createAssignment(result, awaitAsYield(callNext)), + createAssignment(result, createDownlevelAwait(callNext)), createLogicalNot(getDone) ), /*incrementor*/ undefined, - /*statement*/ convertForOfStatementHead(node, awaitAsYield(getValue)) + /*statement*/ convertForOfStatementHead(node, createDownlevelAwait(getValue)) ), /*location*/ node ), @@ -434,7 +436,7 @@ namespace ts { createPropertyAccess(iterator, "return") ) ), - createStatement(awaitAsYield(callReturn)) + createStatement(createDownlevelAwait(callReturn)) ), EmitFlags.SingleLine ) diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts index 9aadd6bc686..d0049e72f0b 100644 --- a/src/compiler/transformers/generators.ts +++ b/src/compiler/transformers/generators.ts @@ -640,10 +640,13 @@ namespace ts { return undefined; } - return createStatement( - inlineExpressions( - map(variables, transformInitializedVariable) - ) + return setSourceMapRange( + createStatement( + inlineExpressions( + map(variables, transformInitializedVariable) + ) + ), + node ); } } @@ -1281,9 +1284,12 @@ namespace ts { } function transformInitializedVariable(node: VariableDeclaration) { - return createAssignment( - getSynthesizedClone(node.name), - visitNode(node.initializer, visitor, isExpression) + return setSourceMapRange( + createAssignment( + setSourceMapRange(getSynthesizedClone(node.name), node.name), + visitNode(node.initializer, visitor, isExpression) + ), + node ); } diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts index b3e544a3f8b..6141f52f5f4 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -46,6 +46,7 @@ namespace ts { let currentSourceFile: SourceFile; // The current file. let currentModuleInfo: ExternalModuleInfo; // The ExternalModuleInfo for the current file. let noSubstitution: boolean[]; // Set of nodes for which substitution rules should be ignored. + let needUMDDynamicImportHelper: boolean; return transformSourceFile; @@ -55,7 +56,7 @@ namespace ts { * @param node The SourceFile node. */ function transformSourceFile(node: SourceFile) { - if (node.isDeclarationFile || !(isExternalModule(node) || compilerOptions.isolatedModules)) { + if (node.isDeclarationFile || !(isExternalModule(node) || compilerOptions.isolatedModules || node.transformFlags & TransformFlags.ContainsDynamicImport)) { return node; } @@ -66,9 +67,9 @@ namespace ts { // Perform the transformation. const transformModule = getTransformModuleDelegate(moduleKind); const updated = transformModule(node); - currentSourceFile = undefined; currentModuleInfo = undefined; + needUMDDynamicImportHelper = false; return aggregateTransformFlags(updated); } @@ -102,11 +103,12 @@ namespace ts { addRange(statements, endLexicalEnvironment()); const updated = updateSourceFileNode(node, setTextRange(createNodeArray(statements), node.statements)); - if (currentModuleInfo.hasExportStarsToExportValues) { + if (currentModuleInfo.hasExportStarsToExportValues && !compilerOptions.importHelpers) { // If we have any `export * from ...` declarations // we need to inform the emitter to add the __export helper. addEmitHelper(updated, exportStarHelper); } + addEmitHelpers(updated, context.readEmitHelpers()); return updated; } @@ -406,11 +408,14 @@ namespace ts { addRange(statements, endLexicalEnvironment()); const body = createBlock(statements, /*multiLine*/ true); - if (currentModuleInfo.hasExportStarsToExportValues) { + if (currentModuleInfo.hasExportStarsToExportValues && !compilerOptions.importHelpers) { // If we have any `export * from ...` declarations // we need to inform the emitter to add the __export helper. addEmitHelper(body, exportStarHelper); } + if (needUMDDynamicImportHelper) { + addEmitHelper(body, dynamicImportUMDHelper); + } return body; } @@ -488,12 +493,110 @@ namespace ts { return visitEndOfDeclarationMarker(node); default: - // This visitor does not descend into the tree, as export/import statements - // are only transformed at the top level of a file. - return node; + return visitEachChild(node, importCallExpressionVisitor, context); } } + function importCallExpressionVisitor(node: Node): VisitResult { + // This visitor does not need to descend into the tree if there is no dynamic import, + // as export/import statements are only transformed at the top level of a file. + if (!(node.transformFlags & TransformFlags.ContainsDynamicImport)) { + return node; + } + + if (isImportCall(node)) { + return visitImportCallExpression(node); + } + else { + return visitEachChild(node, importCallExpressionVisitor, context); + } + } + + function visitImportCallExpression(node: ImportCall): Expression { + switch (compilerOptions.module) { + case ModuleKind.AMD: + return transformImportCallExpressionAMD(node); + case ModuleKind.UMD: + return transformImportCallExpressionUMD(node); + case ModuleKind.CommonJS: + default: + return transformImportCallExpressionCommonJS(node); + } + } + + function transformImportCallExpressionUMD(node: ImportCall): Expression { + // (function (factory) { + // ... (regular UMD) + // } + // })(function (require, exports, useSyncRequire) { + // "use strict"; + // Object.defineProperty(exports, "__esModule", { value: true }); + // var __syncRequire = typeof module === "object" && typeof module.exports === "object"; + // var __resolved = new Promise(function (resolve) { resolve(); }); + // ..... + // __syncRequire + // ? __resolved.then(function () { return require(x); }) /*CommonJs Require*/ + // : new Promise(function (_a, _b) { require([x], _a, _b); }); /*Amd Require*/ + // }); + needUMDDynamicImportHelper = true; + return createConditional( + /*condition*/ createIdentifier("__syncRequire"), + /*whenTrue*/ transformImportCallExpressionCommonJS(node), + /*whenFalse*/ transformImportCallExpressionAMD(node) + ); + } + + function transformImportCallExpressionAMD(node: ImportCall): Expression { + // improt("./blah") + // emit as + // define(["require", "exports", "blah"], function (require, exports) { + // ... + // new Promise(function (_a, _b) { require([x], _a, _b); }); /*Amd Require*/ + // }); + const resolve = createUniqueName("resolve"); + const reject = createUniqueName("reject"); + return createNew( + createIdentifier("Promise"), + /*typeArguments*/ undefined, + [createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, + [createParameter(/*decorator*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, /*name*/ resolve), + createParameter(/*decorator*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, /*name*/ reject)], + /*type*/ undefined, + createBlock([createStatement( + createCall( + createIdentifier("require"), + /*typeArguments*/ undefined, + [createArrayLiteral([firstOrUndefined(node.arguments) || createOmittedExpression()]), resolve, reject] + ))]) + )]); + } + + function transformImportCallExpressionCommonJS(node: ImportCall): Expression { + // import("./blah") + // emit as + // Promise.resolve().then(function () { return require(x); }) /*CommonJs Require*/ + // We have to wrap require in then callback so that require is done in asynchronously + // if we simply do require in resolve callback in Promise constructor. We will execute the loading immediately + return createCall( + createPropertyAccess( + createCall(createPropertyAccess(createIdentifier("Promise"), "resolve"), /*typeArguments*/ undefined, /*argumentsArray*/ []), + "then"), + /*typeArguments*/ undefined, + [createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, + /*parameters*/ undefined, + /*type*/ undefined, + createBlock([createReturn(createCall(createIdentifier("require"), /*typeArguments*/ undefined, node.arguments))]) + )]); + } + /** * Visits an ImportDeclaration node. * @@ -730,15 +833,7 @@ namespace ts { // export * from "mod"; return setTextRange( createStatement( - createCall( - createIdentifier("__export"), - /*typeArguments*/ undefined, - [ - moduleKind !== ModuleKind.AMD - ? createRequireCall(node) - : generatedName - ] - ) + createExportStarHelper(context, moduleKind !== ModuleKind.AMD ? createRequireCall(node) : generatedName) ), node ); @@ -786,9 +881,9 @@ namespace ts { node.asteriskToken, getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true), /*typeParameters*/ undefined, - node.parameters, + visitNodes(node.parameters, importCallExpressionVisitor), /*type*/ undefined, - node.body + visitEachChild(node.body, importCallExpressionVisitor, context) ), /*location*/ node ), @@ -797,7 +892,7 @@ namespace ts { ); } else { - statements = append(statements, node); + statements = append(statements, visitEachChild(node, importCallExpressionVisitor, context)); } if (hasAssociatedEndOfDeclarationMarker(node)) { @@ -828,7 +923,7 @@ namespace ts { visitNodes(node.modifiers, modifierVisitor, isModifier), getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true), /*typeParameters*/ undefined, - node.heritageClauses, + visitNodes(node.heritageClauses, importCallExpressionVisitor), node.members ), node @@ -838,7 +933,7 @@ namespace ts { ); } else { - statements = append(statements, node); + statements = append(statements, visitEachChild(node, importCallExpressionVisitor, context)); } if (hasAssociatedEndOfDeclarationMarker(node)) { @@ -890,7 +985,7 @@ namespace ts { } } else { - statements = append(statements, node); + statements = append(statements, visitEachChild(node, importCallExpressionVisitor, context)); } if (hasAssociatedEndOfDeclarationMarker(node)) { @@ -913,7 +1008,7 @@ namespace ts { function transformInitializedVariable(node: VariableDeclaration): Expression { if (isBindingPattern(node.name)) { return flattenDestructuringAssignment( - node, + visitNode(node, importCallExpressionVisitor), /*visitor*/ undefined, context, FlattenLevel.All, @@ -930,7 +1025,7 @@ namespace ts { ), /*location*/ node.name ), - node.initializer + visitNode(node.initializer, importCallExpressionVisitor) ); } } @@ -1495,6 +1590,22 @@ namespace ts { text: ` function __export(m) { for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; - }` + } + ` + }; + + function createExportStarHelper(context: TransformationContext, module: Expression) { + const compilerOptions = context.getCompilerOptions(); + return compilerOptions.importHelpers + ? createCall(getHelperName("__exportStar"), /*typeArguments*/ undefined, [module, createIdentifier("exports")]) + : createCall(createIdentifier("__export"), /*typeArguments*/ undefined, [module]); + } + + // emit helper for dynamic import + const dynamicImportUMDHelper: EmitHelper = { + name: "typescript:dynamicimport-sync-require", + scoped: true, + text: ` + var __syncRequire = typeof module === "object" && typeof module.exports === "object";` }; } diff --git a/src/compiler/transformers/module/system.ts b/src/compiler/transformers/module/system.ts index e6351c0965e..fa126d1faa7 100644 --- a/src/compiler/transformers/module/system.ts +++ b/src/compiler/transformers/module/system.ts @@ -50,7 +50,7 @@ namespace ts { * @param node The SourceFile node. */ function transformSourceFile(node: SourceFile) { - if (node.isDeclarationFile || !(isExternalModule(node) || compilerOptions.isolatedModules)) { + if (node.isDeclarationFile || !(isEffectiveExternalModule(node, compilerOptions) || node.transformFlags & TransformFlags.ContainsDynamicImport)) { return node; } @@ -646,7 +646,7 @@ namespace ts { return undefined; } - const expression = visitNode(node.expression, destructuringVisitor, isExpression); + const expression = visitNode(node.expression, destructuringAndImportCallVisitor, isExpression); const original = node.original; if (original && hasAssociatedEndOfDeclarationMarker(original)) { // Defer exports until we encounter an EndOfDeclarationMarker node @@ -673,12 +673,12 @@ namespace ts { node.asteriskToken, getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true), /*typeParameters*/ undefined, - visitNodes(node.parameters, destructuringVisitor, isParameterDeclaration), + visitNodes(node.parameters, destructuringAndImportCallVisitor, isParameterDeclaration), /*type*/ undefined, - visitNode(node.body, destructuringVisitor, isBlock))); + visitNode(node.body, destructuringAndImportCallVisitor, isBlock))); } else { - hoistedStatements = append(hoistedStatements, node); + hoistedStatements = append(hoistedStatements, visitEachChild(node, destructuringAndImportCallVisitor, context)); } if (hasAssociatedEndOfDeclarationMarker(node)) { @@ -716,8 +716,8 @@ namespace ts { /*modifiers*/ undefined, node.name, /*typeParameters*/ undefined, - visitNodes(node.heritageClauses, destructuringVisitor, isHeritageClause), - visitNodes(node.members, destructuringVisitor, isClassElement) + visitNodes(node.heritageClauses, destructuringAndImportCallVisitor, isHeritageClause), + visitNodes(node.members, destructuringAndImportCallVisitor, isClassElement) ), node ) @@ -747,7 +747,7 @@ namespace ts { */ function visitVariableStatement(node: VariableStatement): VisitResult { if (!shouldHoistVariableDeclarationList(node.declarationList)) { - return visitNode(node, destructuringVisitor, isStatement); + return visitNode(node, destructuringAndImportCallVisitor, isStatement); } let expressions: Expression[]; @@ -820,13 +820,13 @@ namespace ts { return isBindingPattern(node.name) ? flattenDestructuringAssignment( node, - destructuringVisitor, + destructuringAndImportCallVisitor, context, FlattenLevel.All, /*needsValue*/ false, createAssignment ) - : createAssignment(node.name, visitNode(node.initializer, destructuringVisitor, isExpression)); + : createAssignment(node.name, visitNode(node.initializer, destructuringAndImportCallVisitor, isExpression)); } /** @@ -1204,7 +1204,7 @@ namespace ts { return visitEndOfDeclarationMarker(node); default: - return destructuringVisitor(node); + return destructuringAndImportCallVisitor(node); } } @@ -1220,8 +1220,8 @@ namespace ts { node = updateFor( node, visitForInitializer(node.initializer), - visitNode(node.condition, destructuringVisitor, isExpression), - visitNode(node.incrementor, destructuringVisitor, isExpression), + visitNode(node.condition, destructuringAndImportCallVisitor, isExpression), + visitNode(node.incrementor, destructuringAndImportCallVisitor, isExpression), visitNode(node.statement, nestedElementVisitor, isStatement) ); @@ -1241,7 +1241,7 @@ namespace ts { node = updateForIn( node, visitForInitializer(node.initializer), - visitNode(node.expression, destructuringVisitor, isExpression), + visitNode(node.expression, destructuringAndImportCallVisitor, isExpression), visitNode(node.statement, nestedElementVisitor, isStatement, liftToBlock) ); @@ -1262,7 +1262,7 @@ namespace ts { node, node.awaitModifier, visitForInitializer(node.initializer), - visitNode(node.expression, destructuringVisitor, isExpression), + visitNode(node.expression, destructuringAndImportCallVisitor, isExpression), visitNode(node.statement, nestedElementVisitor, isStatement, liftToBlock) ); @@ -1313,7 +1313,7 @@ namespace ts { return updateDo( node, visitNode(node.statement, nestedElementVisitor, isStatement, liftToBlock), - visitNode(node.expression, destructuringVisitor, isExpression) + visitNode(node.expression, destructuringAndImportCallVisitor, isExpression) ); } @@ -1325,7 +1325,7 @@ namespace ts { function visitWhileStatement(node: WhileStatement): VisitResult { return updateWhile( node, - visitNode(node.expression, destructuringVisitor, isExpression), + visitNode(node.expression, destructuringAndImportCallVisitor, isExpression), visitNode(node.statement, nestedElementVisitor, isStatement, liftToBlock) ); } @@ -1351,7 +1351,7 @@ namespace ts { function visitWithStatement(node: WithStatement): VisitResult { return updateWith( node, - visitNode(node.expression, destructuringVisitor, isExpression), + visitNode(node.expression, destructuringAndImportCallVisitor, isExpression), visitNode(node.statement, nestedElementVisitor, isStatement, liftToBlock) ); } @@ -1364,7 +1364,7 @@ namespace ts { function visitSwitchStatement(node: SwitchStatement): VisitResult { return updateSwitch( node, - visitNode(node.expression, destructuringVisitor, isExpression), + visitNode(node.expression, destructuringAndImportCallVisitor, isExpression), visitNode(node.caseBlock, nestedElementVisitor, isCaseBlock) ); } @@ -1395,7 +1395,7 @@ namespace ts { function visitCaseClause(node: CaseClause): VisitResult { return updateCaseClause( node, - visitNode(node.expression, destructuringVisitor, isExpression), + visitNode(node.expression, destructuringAndImportCallVisitor, isExpression), visitNodes(node.statements, nestedElementVisitor, isStatement) ); } @@ -1461,19 +1461,43 @@ namespace ts { * * @param node The node to visit. */ - function destructuringVisitor(node: Node): VisitResult { + function destructuringAndImportCallVisitor(node: Node): VisitResult { if (node.transformFlags & TransformFlags.DestructuringAssignment && node.kind === SyntaxKind.BinaryExpression) { return visitDestructuringAssignment(node); } - else if (node.transformFlags & TransformFlags.ContainsDestructuringAssignment) { - return visitEachChild(node, destructuringVisitor, context); + else if (isImportCall(node)) { + return visitImportCallExpression(node); + } + else if ((node.transformFlags & TransformFlags.ContainsDestructuringAssignment) || (node.transformFlags & TransformFlags.ContainsDynamicImport)) { + return visitEachChild(node, destructuringAndImportCallVisitor, context); } else { return node; } } + function visitImportCallExpression(node: ImportCall): Expression { + // import("./blah") + // emit as + // System.register([], function (_export, _context) { + // return { + // setters: [], + // execute: () => { + // _context.import('./blah'); + // } + // }; + // }); + return createCall( + createPropertyAccess( + contextObject, + createIdentifier("import") + ), + /*typeArguments*/ undefined, + node.arguments + ); + } + /** * Visits a DestructuringAssignment to flatten destructuring to exported symbols. * @@ -1483,14 +1507,14 @@ namespace ts { if (hasExportedReferenceInDestructuringTarget(node.left)) { return flattenDestructuringAssignment( node, - destructuringVisitor, + destructuringAndImportCallVisitor, context, FlattenLevel.All, /*needsValue*/ true ); } - return visitEachChild(node, destructuringVisitor, context); + return visitEachChild(node, destructuringAndImportCallVisitor, context); } /** diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 834c7326e22..637cfd0f165 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -662,6 +662,10 @@ namespace ts { } } +if (ts.Debug.isDebugging) { + ts.Debug.enableDebugInfo(); +} + if (ts.sys.tryEnableSourceMapsForHost && /^development$/i.test(ts.sys.getEnvironmentVariable("NODE_ENV"))) { ts.sys.tryEnableSourceMapsForHost(); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index ed1d5dcbe23..439091cece0 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -374,6 +374,7 @@ namespace ts { JSDocComment, JSDocTag, JSDocAugmentsTag, + JSDocClassTag, JSDocParameterTag, JSDocReturnTag, JSDocTypeTag, @@ -395,6 +396,7 @@ namespace ts { // Enum value count Count, + // Markers FirstAssignment = EqualsToken, LastAssignment = CaretEqualsToken, @@ -423,7 +425,7 @@ namespace ts { FirstNode = QualifiedName, FirstJSDocNode = JSDocTypeExpression, LastJSDocNode = JSDocLiteralType, - FirstJSDocTagNode = JSDocComment, + FirstJSDocTagNode = JSDocTag, LastJSDocTagNode = JSDocLiteralType } @@ -449,6 +451,17 @@ namespace ts { ThisNodeOrAnySubNodesHasError = 1 << 17, // If this node or any of its children had an error HasAggregatedChildData = 1 << 18, // If we've computed data from children and cached it in this node + // This flag will be set when the parser encounters a dynamic import expression so that module resolution + // will not have to walk the tree if the flag is not set. However, this flag is just a approximation because + // once it is set, the flag never gets cleared (hence why it's named "PossiblyContainsDynamicImport"). + // During editing, if dynamic import is removed, incremental parsing will *NOT* update this flag. This means that the tree will always be traversed + // during module resolution. However, the removal operation should not occur often and in the case of the + // removal, it is likely that users will add the import anyway. + // The advantage of this approach is its simplicity. For the case of batch compilation, + // we guarantee that users won't have to pay the price of walking the tree if a dynamic import isn't used. + /* @internal */ + PossiblyContainsDynamicImport = 1 << 19, + BlockScoped = Let | Const, ReachabilityCheckFlags = HasImplicitReturn | HasExplicitReturn, @@ -1001,8 +1014,10 @@ namespace ts { _unaryExpressionBrand: any; } - export interface IncrementExpression extends UnaryExpression { - _incrementExpressionBrand: any; + /** Deprecated, please use UpdateExpression */ + export type IncrementExpression = UpdateExpression; + export interface UpdateExpression extends UnaryExpression { + _updateExpressionBrand: any; } // see: https://tc39.github.io/ecma262/#prod-UpdateExpression @@ -1013,10 +1028,9 @@ namespace ts { | SyntaxKind.PlusToken | SyntaxKind.MinusToken | SyntaxKind.TildeToken - | SyntaxKind.ExclamationToken - ; + | SyntaxKind.ExclamationToken; - export interface PrefixUnaryExpression extends IncrementExpression { + export interface PrefixUnaryExpression extends UpdateExpression { kind: SyntaxKind.PrefixUnaryExpression; operator: PrefixUnaryOperator; operand: UnaryExpression; @@ -1028,13 +1042,13 @@ namespace ts { | SyntaxKind.MinusMinusToken ; - export interface PostfixUnaryExpression extends IncrementExpression { + export interface PostfixUnaryExpression extends UpdateExpression { kind: SyntaxKind.PostfixUnaryExpression; operand: LeftHandSideExpression; operator: PostfixUnaryOperator; } - export interface LeftHandSideExpression extends IncrementExpression { + export interface LeftHandSideExpression extends UpdateExpression { _leftHandSideExpressionBrand: any; } @@ -1062,6 +1076,10 @@ namespace ts { kind: SyntaxKind.SuperKeyword; } + export interface ImportExpression extends PrimaryExpression { + kind: SyntaxKind.ImportKeyword; + } + export interface DeleteExpression extends UnaryExpression { kind: SyntaxKind.DeleteExpression; expression: UnaryExpression; @@ -1454,10 +1472,7 @@ namespace ts { } // see: https://tc39.github.io/ecma262/#prod-SuperProperty - export type SuperProperty - = SuperPropertyAccessExpression - | SuperElementAccessExpression - ; + export type SuperProperty = SuperPropertyAccessExpression | SuperElementAccessExpression; export interface CallExpression extends LeftHandSideExpression, Declaration { kind: SyntaxKind.CallExpression; @@ -1471,6 +1486,10 @@ namespace ts { expression: SuperExpression; } + export interface ImportCall extends CallExpression { + expression: ImportExpression; + } + export interface ExpressionWithTypeArguments extends TypeNode { kind: SyntaxKind.ExpressionWithTypeArguments; parent?: HeritageClause; @@ -1689,6 +1708,8 @@ namespace ts { incrementor?: Expression; } + export type ForInOrOfStatement = ForInStatement | ForOfStatement; + export interface ForInStatement extends IterationStatement { kind: SyntaxKind.ForInStatement; initializer: ForInitializer; @@ -1778,7 +1799,7 @@ namespace ts { block: Block; } - export type DeclarationWithTypeParameters = SignatureDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration; + export type DeclarationWithTypeParameters = SignatureDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | JSDocTemplateTag; export interface ClassLikeDeclaration extends NamedDeclaration { name?: Identifier; @@ -2117,6 +2138,10 @@ namespace ts { typeExpression: JSDocTypeExpression; } + export interface JSDocClassTag extends JSDocTag { + kind: SyntaxKind.JSDocClassTag; + } + export interface JSDocTemplateTag extends JSDocTag { kind: SyntaxKind.JSDocTemplateTag; typeParameters: NodeArray; @@ -2535,7 +2560,6 @@ namespace ts { getNonNullableType(type: Type): Type; /** Note that the resulting nodes cannot be checked. */ - typeToTypeNode(type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): TypeNode; /** Note that the resulting nodes cannot be checked. */ signatureToSignatureDeclaration(signature: Signature, kind: SyntaxKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): SignatureDeclaration; @@ -2605,6 +2629,9 @@ namespace ts { * Does not include properties of primitive types. */ /* @internal */ getAllPossiblePropertiesOfType(type: Type): Symbol[]; + + /* @internal */ getJsxNamespace(): string; + /* @internal */ resolveNameAtLocation(location: Node, name: string, meaning: SymbolFlags): Symbol | undefined; } export enum NodeBuilderFlags { @@ -3497,6 +3524,7 @@ namespace ts { noImplicitAny?: boolean; // Always combine with strict property noImplicitReturns?: boolean; noImplicitThis?: boolean; // Always combine with strict property + noStrictGenericChecks?: boolean; noUnusedLocals?: boolean; noUnusedParameters?: boolean; noImplicitUseStrict?: boolean; @@ -3564,6 +3592,7 @@ namespace ts { UMD = 3, System = 4, ES2015 = 5, + ESNext = 6 } export const enum JsxEmit { @@ -3855,13 +3884,12 @@ namespace ts { extension: Extension; } - export enum Extension { - Ts, - Tsx, - Dts, - Js, - Jsx, - LastTypeScriptExtension = Dts + export const enum Extension { + Ts = ".ts", + Tsx = ".tsx", + Dts = ".d.ts", + Js = ".js", + Jsx = ".jsx" } export interface ResolvedModuleWithFailedLookupLocations { @@ -3948,6 +3976,11 @@ namespace ts { ContainsYield = 1 << 24, ContainsHoistedDeclarationOrCompletion = 1 << 25, + ContainsDynamicImport = 1 << 26, + + // Please leave this as 1 << 29. + // It is the maximum bit we can set before we outgrow the size of a v8 small integer (SMI) on an x86 system. + // It is a good reminder of how much room we have left HasComputedFlags = 1 << 29, // Transform flags have been computed. // Assertions @@ -3985,18 +4018,29 @@ namespace ts { ES2015FunctionSyntaxMask = ContainsCapturedLexicalThis | ContainsDefaultValueAssignments, } + export interface SourceMapRange extends TextRange { + source?: SourceMapSource; + } + + export interface SourceMapSource { + fileName: string; + text: string; + /* @internal */ lineMap: number[]; + skipTrivia?: (pos: number) => number; + } + /* @internal */ export interface EmitNode { - annotatedNodes?: Node[]; // Tracks Parse-tree nodes with EmitNodes for eventual cleanup. - flags?: EmitFlags; // Flags that customize emit - leadingComments?: SynthesizedComment[]; // Synthesized leading comments + annotatedNodes?: Node[]; // Tracks Parse-tree nodes with EmitNodes for eventual cleanup. + flags?: EmitFlags; // Flags that customize emit + leadingComments?: SynthesizedComment[]; // Synthesized leading comments trailingComments?: SynthesizedComment[]; // Synthesized trailing comments - commentRange?: TextRange; // The text range to use when emitting leading or trailing comments - sourceMapRange?: TextRange; // The text range to use when emitting leading or trailing source mappings - tokenSourceMapRanges?: TextRange[]; // The text range to use when emitting source mappings for tokens - constantValue?: string | number; // The constant value of an expression - externalHelpersModuleName?: Identifier; // The local name for an imported helpers module - helpers?: EmitHelper[]; // Emit helpers for the node + commentRange?: TextRange; // The text range to use when emitting leading or trailing comments + sourceMapRange?: SourceMapRange; // The text range to use when emitting leading or trailing source mappings + tokenSourceMapRanges?: SourceMapRange[]; // The text range to use when emitting source mappings for tokens + constantValue?: string | number; // The constant value of an expression + externalHelpersModuleName?: Identifier; // The local name for an imported helpers module + helpers?: EmitHelper[]; // Emit helpers for the node } export const enum EmitFlags { @@ -4058,6 +4102,7 @@ namespace ts { AsyncGenerator = 1 << 12, // __asyncGenerator (used by ES2017 async generator transformation) AsyncDelegator = 1 << 13, // __asyncDelegator (used by ES2017 async generator yield* transformation) AsyncValues = 1 << 14, // __asyncValues (used by ES2017 for..await..of transformation) + ExportStar = 1 << 15, // __exportStar (used by CommonJS/AMD/UMD module transformation) // Helpers included by ES2015 for..of ForOfIncludes = Values, @@ -4075,7 +4120,7 @@ namespace ts { SpreadIncludes = Read | Spread, FirstEmitHelper = Extends, - LastEmitHelper = AsyncValues + LastEmitHelper = ExportStar } export const enum EmitHint { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index b52ace78615..3833fc30875 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -596,6 +596,10 @@ namespace ts { return n.kind === SyntaxKind.CallExpression && (n).expression.kind === SyntaxKind.SuperKeyword; } + export function isImportCall(n: Node): n is ImportCall { + return n.kind === SyntaxKind.CallExpression && (n).expression.kind === SyntaxKind.ImportKeyword; + } + export function isPrologueDirective(node: Node): node is PrologueDirective { return node.kind === SyntaxKind.ExpressionStatement && (node).expression.kind === SyntaxKind.StringLiteral; @@ -1434,31 +1438,17 @@ namespace ts { } function getJSDocTags(node: Node, kind: SyntaxKind): JSDocTag[] { - const docs = getJSDocs(node); - if (docs) { - const result: JSDocTag[] = []; - for (const doc of docs) { - if (doc.kind === SyntaxKind.JSDocParameterTag) { - if (doc.kind === kind) { - result.push(doc as JSDocTag); - } - } - else { - const tags = (doc as JSDoc).tags; - if (tags) { - result.push(...filter(tags, tag => tag.kind === kind)); - } - } - } - return result; - } + return flatMap(getJSDocs(node), doc => + doc.kind === SyntaxKind.JSDocComment + ? filter((doc as JSDoc).tags, tag => tag.kind === kind) + : doc.kind === kind && doc); } function getFirstJSDocTag(node: Node, kind: SyntaxKind): JSDocTag { return node && firstOrUndefined(getJSDocTags(node, kind)); } - export function getJSDocs(node: Node): (JSDoc | JSDocTag)[] { + export function getJSDocs(node: Node): (JSDoc | JSDocTag)[] { if (isJSDocTypedefTag(node)) { return [node.parent]; } @@ -1556,6 +1546,12 @@ namespace ts { p.name.kind === SyntaxKind.Identifier && p.name.text === name); } + export function getTypeParameterFromJsDoc(node: TypeParameterDeclaration & { parent: JSDocTemplateTag }): TypeParameterDeclaration | undefined { + const name = node.name.text; + const { typeParameters } = (node.parent.parent.parent as ts.SignatureDeclaration | ts.InterfaceDeclaration | ts.ClassDeclaration); + return find(typeParameters, p => p.name.text === name); + } + export function getJSDocType(node: Node): JSDocType { let tag: JSDocTypeTag | JSDocParameterTag = getFirstJSDocTag(node, SyntaxKind.JSDocTypeTag) as JSDocTypeTag; if (!tag && node.kind === SyntaxKind.Parameter) { @@ -1572,10 +1568,19 @@ namespace ts { return getFirstJSDocTag(node, SyntaxKind.JSDocAugmentsTag) as JSDocAugmentsTag; } + export function getJSDocClassTag(node: Node): JSDocClassTag { + return getFirstJSDocTag(node, SyntaxKind.JSDocClassTag) as JSDocClassTag; + } + export function getJSDocReturnTag(node: Node): JSDocReturnTag { return getFirstJSDocTag(node, SyntaxKind.JSDocReturnTag) as JSDocReturnTag; } + export function getJSDocReturnType(node: Node): JSDocType { + const returnTag = getJSDocReturnTag(node); + return returnTag && returnTag.typeExpression && returnTag.typeExpression.type; + } + export function getJSDocTemplateTag(node: Node): JSDocTemplateTag { return getFirstJSDocTag(node, SyntaxKind.JSDocTemplateTag) as JSDocTemplateTag; } @@ -1622,7 +1627,7 @@ namespace ts { return unaryOperator === SyntaxKind.PlusPlusToken || unaryOperator === SyntaxKind.MinusMinusToken ? AssignmentKind.Compound : AssignmentKind.None; case SyntaxKind.ForInStatement: case SyntaxKind.ForOfStatement: - return (parent).initializer === node ? AssignmentKind.Definite : AssignmentKind.None; + return (parent).initializer === node ? AssignmentKind.Definite : AssignmentKind.None; case SyntaxKind.ParenthesizedExpression: case SyntaxKind.ArrayLiteralExpression: case SyntaxKind.SpreadElement: @@ -2496,7 +2501,7 @@ namespace ts { const path = outputDir ? getSourceFilePathInNewDir(sourceFile, host, outputDir) : sourceFile.fileName; - return removeFileExtension(path) + ".d.ts"; + return removeFileExtension(path) + Extension.Dts; } export interface EmitFileNames { @@ -2555,7 +2560,7 @@ namespace ts { if (sourceFiles.length) { const jsFilePath = options.outFile || options.out; const sourceMapFilePath = getSourceMapFilePath(jsFilePath, options); - const declarationFilePath = options.declaration ? removeFileExtension(jsFilePath) + ".d.ts" : ""; + const declarationFilePath = options.declaration ? removeFileExtension(jsFilePath) + Extension.Dts : ""; action({ jsFilePath, sourceMapFilePath, declarationFilePath }, createBundle(sourceFiles), emitOnlyDtsFiles); } } @@ -2576,19 +2581,19 @@ namespace ts { // JavaScript files are always LanguageVariant.JSX, as JSX syntax is allowed in .js files also. // So for JavaScript files, '.jsx' is only emitted if the input was '.jsx', and JsxEmit.Preserve. // For TypeScript, the only time to emit with a '.jsx' extension, is on JSX input, and JsxEmit.Preserve - function getOutputExtension(sourceFile: SourceFile, options: CompilerOptions): string { + function getOutputExtension(sourceFile: SourceFile, options: CompilerOptions): Extension { if (options.jsx === JsxEmit.Preserve) { if (isSourceFileJavaScript(sourceFile)) { - if (fileExtensionIs(sourceFile.fileName, ".jsx")) { - return ".jsx"; + if (fileExtensionIs(sourceFile.fileName, Extension.Jsx)) { + return Extension.Jsx; } } else if (sourceFile.languageVariant === LanguageVariant.JSX) { // TypeScript source file preserving JSX syntax - return ".jsx"; + return Extension.Jsx; } } - return ".js"; + return Extension.Js; } export function getSourceFilePathInNewDir(sourceFile: SourceFile, host: EmitHost, newDirPath: string) { @@ -2621,14 +2626,19 @@ namespace ts { }); } - /** Get the type annotaion for the value parameter. */ - export function getSetAccessorTypeAnnotationNode(accessor: SetAccessorDeclaration): TypeNode { + function getSetAccessorValueParameter(accessor: SetAccessorDeclaration): ParameterDeclaration | undefined { if (accessor && accessor.parameters.length > 0) { const hasThis = accessor.parameters.length === 2 && parameterIsThisKeyword(accessor.parameters[0]); - return accessor.parameters[hasThis ? 1 : 0].type; + return accessor.parameters[hasThis ? 1 : 0]; } } + /** Get the type annotation for the value parameter. */ + export function getSetAccessorTypeAnnotationNode(accessor: SetAccessorDeclaration): TypeNode { + const parameter = getSetAccessorValueParameter(accessor); + return parameter && parameter.type; + } + export function getThisParameter(signature: SignatureDeclaration): ParameterDeclaration | undefined { if (signature.parameters.length) { const thisParameter = signature.parameters[0]; @@ -2707,6 +2717,55 @@ namespace ts { }; } + /** + * Gets the effective type annotation of a variable, parameter, or property. If the node was + * parsed in a JavaScript file, gets the type annotation from JSDoc. + */ + export function getEffectiveTypeAnnotationNode(node: VariableLikeDeclaration): TypeNode { + if (node.type) { + return node.type; + } + if (node.flags & NodeFlags.JavaScriptFile) { + return getJSDocType(node); + } + } + + /** + * Gets the effective return type annotation of a signature. If the node was parsed in a + * JavaScript file, gets the return type annotation from JSDoc. + */ + export function getEffectiveReturnTypeNode(node: SignatureDeclaration): TypeNode { + if (node.type) { + return node.type; + } + if (node.flags & NodeFlags.JavaScriptFile) { + return getJSDocReturnType(node); + } + } + + /** + * Gets the effective type parameters. If the node was parsed in a + * JavaScript file, gets the type parameters from the `@template` tag from JSDoc. + */ + export function getEffectiveTypeParameterDeclarations(node: DeclarationWithTypeParameters): TypeParameterDeclaration[] { + if (node.typeParameters) { + return node.typeParameters; + } + if (node.flags & NodeFlags.JavaScriptFile) { + const templateTag = getJSDocTemplateTag(node); + return templateTag && templateTag.typeParameters; + } + } + + /** + * Gets the effective type annotation of the value parameter of a set accessor. If the node + * was parsed in a JavaScript file, gets the type annotation from JSDoc. + */ + export function getEffectiveSetAccessorTypeAnnotationNode(node: SetAccessorDeclaration): TypeNode { + const parameter = getSetAccessorValueParameter(node); + return parameter && getEffectiveTypeAnnotationNode(parameter); + } + export function emitNewLineBeforeLeadingComments(lineMap: number[], writer: EmitTextWriter, node: TextRange, leadingComments: CommentRange[]) { emitNewLineBeforeLeadingCommentsOfPosition(lineMap, writer, node.pos, leadingComments); } @@ -4053,7 +4112,7 @@ namespace ts { // Signature elements - export function isTypeParameter(node: Node): node is TypeParameterDeclaration { + export function isTypeParameterDeclaration(node: Node): node is TypeParameterDeclaration { return node.kind === SyntaxKind.TypeParameter; } @@ -4676,6 +4735,16 @@ namespace ts { // All node tests in the following list should *not* reference parent pointers so that // they may be used with transformations. namespace ts { + /* @internal */ + export function isNode(node: Node) { + return isNodeKind(node.kind); + } + + /* @internal */ + export function isNodeKind(kind: SyntaxKind) { + return kind >= SyntaxKind.FirstNode; + } + /** * True if node is of some token syntax kind. * For example, this is true for an IfKeyword but not for an IfStatement. @@ -5097,6 +5166,11 @@ namespace ts { return false; } + /* @internal */ + export function isForInOrOfStatement(node: Node): node is ForInOrOfStatement { + return node.kind === SyntaxKind.ForInStatement || node.kind === SyntaxKind.ForOfStatement; + } + // Element /* @internal */ @@ -5225,6 +5299,10 @@ namespace ts { /* @internal */ export function isDeclaration(node: Node): node is NamedDeclaration { + if (node.kind === SyntaxKind.TypeParameter) { + return node.parent.kind !== SyntaxKind.JSDocTemplateTag || isInJavaScriptFile(node); + } + return isDeclarationKind(node.kind); } @@ -5314,6 +5392,11 @@ namespace ts { return node.kind >= SyntaxKind.FirstJSDocNode && node.kind <= SyntaxKind.LastJSDocNode; } + /** True if node is of a kind that may contain comment text. */ + export function isJSDocCommentContainingNode(node: Node): boolean { + return node.kind === SyntaxKind.JSDocComment || isJSDocTag(node); + } + // TODO: determine what this does before making it public. /* @internal */ export function isJSDocTag(node: Node): boolean { diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index fc3b9c784cc..391fa88c79d 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -275,7 +275,7 @@ namespace ts { case SyntaxKind.MethodSignature: return updateMethodSignature(node, - nodesVisitor((node).typeParameters, visitor, isTypeParameter), + nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), nodesVisitor((node).parameters, visitor, isParameterDeclaration), visitNode((node).type, visitor, isTypeNode), visitNode((node).name, visitor, isPropertyName), @@ -288,7 +288,7 @@ namespace ts { visitNode((node).asteriskToken, tokenVisitor, isToken), visitNode((node).name, visitor, isPropertyName), visitNode((node).questionToken, tokenVisitor, isToken), - nodesVisitor((node).typeParameters, visitor, isTypeParameter), + nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), visitParameterList((node).parameters, visitor, context, nodesVisitor), visitNode((node).type, visitor, isTypeNode), visitFunctionBody((node).body, visitor, context)); @@ -319,13 +319,13 @@ namespace ts { case SyntaxKind.CallSignature: return updateCallSignature(node, - nodesVisitor((node).typeParameters, visitor, isTypeParameter), + nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), nodesVisitor((node).parameters, visitor, isParameterDeclaration), visitNode((node).type, visitor, isTypeNode)); case SyntaxKind.ConstructSignature: return updateConstructSignature(node, - nodesVisitor((node).typeParameters, visitor, isTypeParameter), + nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), nodesVisitor((node).parameters, visitor, isParameterDeclaration), visitNode((node).type, visitor, isTypeNode)); @@ -350,13 +350,13 @@ namespace ts { case SyntaxKind.FunctionType: return updateFunctionTypeNode(node, - nodesVisitor((node).typeParameters, visitor, isTypeParameter), + nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), nodesVisitor((node).parameters, visitor, isParameterDeclaration), visitNode((node).type, visitor, isTypeNode)); case SyntaxKind.ConstructorType: return updateConstructorTypeNode(node, - nodesVisitor((node).typeParameters, visitor, isTypeParameter), + nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), nodesVisitor((node).parameters, visitor, isParameterDeclaration), visitNode((node).type, visitor, isTypeNode)); @@ -400,7 +400,7 @@ namespace ts { case SyntaxKind.MappedType: return updateMappedTypeNode((node), visitNode((node).readonlyToken, tokenVisitor, isToken), - visitNode((node).typeParameter, visitor, isTypeParameter), + visitNode((node).typeParameter, visitor, isTypeParameterDeclaration), visitNode((node).questionToken, tokenVisitor, isToken), visitNode((node).type, visitor, isTypeNode)); @@ -476,7 +476,7 @@ namespace ts { nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).asteriskToken, tokenVisitor, isToken), visitNode((node).name, visitor, isIdentifier), - nodesVisitor((node).typeParameters, visitor, isTypeParameter), + nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), visitParameterList((node).parameters, visitor, context, nodesVisitor), visitNode((node).type, visitor, isTypeNode), visitFunctionBody((node).body, visitor, context)); @@ -484,7 +484,7 @@ namespace ts { case SyntaxKind.ArrowFunction: return updateArrowFunction(node, nodesVisitor((node).modifiers, visitor, isModifier), - nodesVisitor((node).typeParameters, visitor, isTypeParameter), + nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), visitParameterList((node).parameters, visitor, context, nodesVisitor), visitNode((node).type, visitor, isTypeNode), visitFunctionBody((node).body, visitor, context)); @@ -543,7 +543,7 @@ namespace ts { return updateClassExpression(node, nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).name, visitor, isIdentifier), - nodesVisitor((node).typeParameters, visitor, isTypeParameter), + nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), nodesVisitor((node).heritageClauses, visitor, isHeritageClause), nodesVisitor((node).members, visitor, isClassElement)); @@ -676,7 +676,7 @@ namespace ts { nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).asteriskToken, tokenVisitor, isToken), visitNode((node).name, visitor, isIdentifier), - nodesVisitor((node).typeParameters, visitor, isTypeParameter), + nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), visitParameterList((node).parameters, visitor, context, nodesVisitor), visitNode((node).type, visitor, isTypeNode), visitFunctionBody((node).body, visitor, context)); @@ -686,7 +686,7 @@ namespace ts { nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).name, visitor, isIdentifier), - nodesVisitor((node).typeParameters, visitor, isTypeParameter), + nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), nodesVisitor((node).heritageClauses, visitor, isHeritageClause), nodesVisitor((node).members, visitor, isClassElement)); @@ -695,7 +695,7 @@ namespace ts { nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).name, visitor, isIdentifier), - nodesVisitor((node).typeParameters, visitor, isTypeParameter), + nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), nodesVisitor((node).heritageClauses, visitor, isHeritageClause), nodesVisitor((node).members, visitor, isTypeElement)); @@ -704,7 +704,7 @@ namespace ts { nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).name, visitor, isIdentifier), - nodesVisitor((node).typeParameters, visitor, isTypeParameter), + nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), visitNode((node).type, visitor, isTypeNode)); case SyntaxKind.EnumDeclaration: @@ -1198,9 +1198,9 @@ namespace ts { case SyntaxKind.ForInStatement: case SyntaxKind.ForOfStatement: - result = reduceNode((node).initializer, cbNode, result); - result = reduceNode((node).expression, cbNode, result); - result = reduceNode((node).statement, cbNode, result); + result = reduceNode((node).initializer, cbNode, result); + result = reduceNode((node).expression, cbNode, result); + result = reduceNode((node).statement, cbNode, result); break; case SyntaxKind.ReturnStatement: @@ -1517,35 +1517,7 @@ namespace ts { } export namespace Debug { - if (isDebugging) { - // Add additional properties in debug mode to assist with debugging. - Object.defineProperties(objectAllocator.getSymbolConstructor().prototype, { - "__debugFlags": { get(this: Symbol) { return formatSymbolFlags(this.flags); } } - }); - - Object.defineProperties(objectAllocator.getTypeConstructor().prototype, { - "__debugFlags": { get(this: Type) { return formatTypeFlags(this.flags); } }, - "__debugObjectFlags": { get(this: Type) { return this.flags & TypeFlags.Object ? formatObjectFlags((this).objectFlags) : ""; } }, - "__debugTypeToString": { value(this: Type) { return this.checker.typeToString(this); } }, - }); - - for (const ctor of [objectAllocator.getNodeConstructor(), objectAllocator.getIdentifierConstructor(), objectAllocator.getTokenConstructor(), objectAllocator.getSourceFileConstructor()]) { - if (!ctor.prototype.hasOwnProperty("__debugKind")) { - Object.defineProperties(ctor.prototype, { - "__debugKind": { get(this: Node) { return formatSyntaxKind(this.kind); } }, - "__debugModifierFlags": { get(this: Node) { return formatModifierFlags(getModifierFlagsNoCache(this)); } }, - "__debugTransformFlags": { get(this: Node) { return formatTransformFlags(this.transformFlags); } }, - "__debugEmitFlags": { get(this: Node) { return formatEmitFlags(getEmitFlags(this)); } }, - "__debugGetText": { value(this: Node, includeTrivia?: boolean) { - if (nodeIsSynthesized(this)) return ""; - const parseNode = getParseTreeNode(this); - const sourceFile = parseNode && getSourceFileOfNode(parseNode); - return sourceFile ? getSourceTextOfNodeFromSourceFile(sourceFile, parseNode, includeTrivia) : ""; - } } - }); - } - } - } + let isDebugInfoEnabled = false; export const failBadSyntaxKind = shouldAssert(AssertionLevel.Normal) ? (node: Node, message?: string): void => fail( @@ -1592,5 +1564,51 @@ namespace ts { () => `Node ${formatSyntaxKind(node.kind)} was unexpected'.`, assertMissingNode) : noop; + + /** + * Injects debug information into frequently used types. + */ + export function enableDebugInfo() { + if (isDebugInfoEnabled) return; + + // Add additional properties in debug mode to assist with debugging. + Object.defineProperties(objectAllocator.getSymbolConstructor().prototype, { + "__debugFlags": { get(this: Symbol) { return formatSymbolFlags(this.flags); } } + }); + + Object.defineProperties(objectAllocator.getTypeConstructor().prototype, { + "__debugFlags": { get(this: Type) { return formatTypeFlags(this.flags); } }, + "__debugObjectFlags": { get(this: Type) { return this.flags & TypeFlags.Object ? formatObjectFlags((this).objectFlags) : ""; } }, + "__debugTypeToString": { value(this: Type) { return this.checker.typeToString(this); } }, + }); + + const nodeConstructors = [ + objectAllocator.getNodeConstructor(), + objectAllocator.getIdentifierConstructor(), + objectAllocator.getTokenConstructor(), + objectAllocator.getSourceFileConstructor() + ]; + + for (const ctor of nodeConstructors) { + if (!ctor.prototype.hasOwnProperty("__debugKind")) { + Object.defineProperties(ctor.prototype, { + "__debugKind": { get(this: Node) { return formatSyntaxKind(this.kind); } }, + "__debugModifierFlags": { get(this: Node) { return formatModifierFlags(getModifierFlagsNoCache(this)); } }, + "__debugTransformFlags": { get(this: Node) { return formatTransformFlags(this.transformFlags); } }, + "__debugEmitFlags": { get(this: Node) { return formatEmitFlags(getEmitFlags(this)); } }, + "__debugGetText": { + value(this: Node, includeTrivia?: boolean) { + if (nodeIsSynthesized(this)) return ""; + const parseNode = getParseTreeNode(this); + const sourceFile = parseNode && getSourceFileOfNode(parseNode); + return sourceFile ? getSourceTextOfNodeFromSourceFile(sourceFile, parseNode, includeTrivia) : ""; + } + } + }); + } + } + + isDebugInfoEnabled = true; + } } } diff --git a/src/harness/compilerRunner.ts b/src/harness/compilerRunner.ts index d0eee02efd7..ff418ab34de 100644 --- a/src/harness/compilerRunner.ts +++ b/src/harness/compilerRunner.ts @@ -90,7 +90,7 @@ class CompilerBaselineRunner extends RunnerBase { } lastUnit = units[units.length - 1]; - hasNonDtsFiles = ts.forEach(units, unit => !ts.fileExtensionIs(unit.name, ".d.ts")); + hasNonDtsFiles = ts.forEach(units, unit => !ts.fileExtensionIs(unit.name, ts.Extension.Dts)); // We need to assemble the list of input files for the compiler and other related files on the 'filesystem' (ie in a multi-file test) // If the last file in a test uses require or a triple slash reference we'll assume all other files will be brought in via references, // otherwise, assume all files are just meant to be in the same compilation session without explicit references to one another. diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 0f840421b65..7fdbef74ad7 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -479,24 +479,11 @@ namespace FourSlash { } private getDiagnostics(fileName: string): ts.Diagnostic[] { - const syntacticErrors = this.languageService.getSyntacticDiagnostics(fileName); - const semanticErrors = this.languageService.getSemanticDiagnostics(fileName); - - const diagnostics: ts.Diagnostic[] = []; - diagnostics.push.apply(diagnostics, syntacticErrors); - diagnostics.push.apply(diagnostics, semanticErrors); - - return diagnostics; + return this.languageService.getSyntacticDiagnostics(fileName).concat(this.languageService.getSemanticDiagnostics(fileName)); } private getAllDiagnostics(): ts.Diagnostic[] { - const diagnostics: ts.Diagnostic[] = []; - - for (const fileName of this.languageServiceAdapterHost.getFilenames()) { - diagnostics.push.apply(this.getDiagnostics(fileName)); - } - - return diagnostics; + return ts.flatMap(this.languageServiceAdapterHost.getFilenames(), fileName => this.getDiagnostics(fileName)); } public verifyErrorExistsAfterMarker(markerName: string, negative: boolean, after: boolean) { @@ -549,11 +536,16 @@ namespace FourSlash { Harness.IO.log("Unexpected error(s) found. Error list is:"); } - for (const { start, length, messageText } of errors) { - Harness.IO.log(" minChar: " + start + - ", limChar: " + (start + length) + + for (const { start, length, messageText, file } of errors) { + Harness.IO.log(" from: " + showPosition(file, start) + + ", to: " + showPosition(file, start + length) + ", message: " + ts.flattenDiagnosticMessageText(messageText, Harness.IO.newLine()) + "\n"); } + + function showPosition(file: ts.SourceFile, pos: number) { + const { line, character } = ts.getLineAndCharacterOfPosition(file, pos); + return `${line}:${character}`; + } } public verifyNoErrors() { @@ -1052,21 +1044,27 @@ namespace FourSlash { fail(`Expected ${expected}, got ${actual}`); } - for (const key in actual) if (ts.hasProperty(actual as any, key)) { - const ak = actual[key], ek = expected[key]; - if (typeof ak === "object" && typeof ek === "object") { - recur(ak, ek, path ? path + "." + key : key); - } - else if (ak !== ek) { - fail(`Expected '${key}' to be '${ek}', got '${ak}'`); + for (const key in actual) { + if (ts.hasProperty(actual as any, key)) { + const ak = actual[key], ek = expected[key]; + if (typeof ak === "object" && typeof ek === "object") { + recur(ak, ek, path ? path + "." + key : key); + } + else if (ak !== ek) { + fail(`Expected '${key}' to be '${ek}', got '${ak}'`); + } } } - for (const key in expected) if (ts.hasProperty(expected as any, key)) { - if (!ts.hasProperty(actual as any, key)) { - fail(`${msgPrefix}Missing property '${key}'`); + + for (const key in expected) { + if (ts.hasProperty(expected as any, key)) { + if (!ts.hasProperty(actual as any, key)) { + fail(`${msgPrefix}Missing property '${key}'`); + } } } }; + if (fullActual === undefined || fullExpected === undefined) { if (fullActual === fullExpected) { return; @@ -1148,15 +1146,17 @@ namespace FourSlash { } public verifyQuickInfos(namesAndTexts: { [name: string]: string | [string, string] }) { - for (const name in namesAndTexts) if (ts.hasProperty(namesAndTexts, name)) { - const text = namesAndTexts[name]; - if (ts.isArray(text)) { - assert(text.length === 2); - const [expectedText, expectedDocumentation] = text; - this.verifyQuickInfoAt(name, expectedText, expectedDocumentation); - } - else { - this.verifyQuickInfoAt(name, text); + for (const name in namesAndTexts) { + if (ts.hasProperty(namesAndTexts, name)) { + const text = namesAndTexts[name]; + if (ts.isArray(text)) { + assert(text.length === 2); + const [expectedText, expectedDocumentation] = text; + this.verifyQuickInfoAt(name, expectedText, expectedDocumentation); + } + else { + this.verifyQuickInfoAt(name, text); + } } } } @@ -1165,7 +1165,6 @@ namespace FourSlash { if (expectedDocumentation === "") { throw new Error("Use 'undefined' instead"); } - const actualQuickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition); const actualQuickInfoText = actualQuickInfo ? ts.displayPartsToString(actualQuickInfo.displayParts) : ""; const actualQuickInfoDocumentation = actualQuickInfo ? ts.displayPartsToString(actualQuickInfo.documentation) : ""; @@ -1468,7 +1467,7 @@ namespace FourSlash { let baselineFile = this.testData.globalOptions[metadataOptionNames.baselineFile]; if (!baselineFile) { baselineFile = this.activeFile.fileName.replace(this.basePath + "/breakpointValidation", "bpSpan"); - baselineFile = baselineFile.replace(".ts", ".baseline"); + baselineFile = baselineFile.replace(ts.Extension.Ts, ".baseline"); } Harness.Baseline.runBaseline( @@ -1538,7 +1537,7 @@ namespace FourSlash { public baselineQuickInfo() { let baselineFile = this.testData.globalOptions[metadataOptionNames.baselineFile]; if (!baselineFile) { - baselineFile = ts.getBaseFileName(this.activeFile.fileName).replace(".ts", ".baseline"); + baselineFile = ts.getBaseFileName(this.activeFile.fileName).replace(ts.Extension.Ts, ".baseline"); } Harness.Baseline.runBaseline( @@ -1611,16 +1610,19 @@ namespace FourSlash { } private printMembersOrCompletions(info: ts.CompletionInfo) { + if (info === undefined) { return "No completion info."; } + const { entries } = info; + function pad(s: string, length: number) { return s + new Array(length - s.length + 1).join(" "); } function max(arr: T[], selector: (x: T) => number): number { return arr.reduce((prev, x) => Math.max(prev, selector(x)), 0); } - const longestNameLength = max(info.entries, m => m.name.length); - const longestKindLength = max(info.entries, m => m.kind.length); - info.entries.sort((m, n) => m.sortText > n.sortText ? 1 : m.sortText < n.sortText ? -1 : m.name > n.name ? 1 : m.name < n.name ? -1 : 0); - const membersString = info.entries.map(m => `${pad(m.name, longestNameLength)} ${pad(m.kind, longestKindLength)} ${m.kindModifiers}`).join("\n"); + const longestNameLength = max(entries, m => m.name.length); + const longestKindLength = max(entries, m => m.kind.length); + entries.sort((m, n) => m.sortText > n.sortText ? 1 : m.sortText < n.sortText ? -1 : m.name > n.name ? 1 : m.name < n.name ? -1 : 0); + const membersString = entries.map(m => `${pad(m.name, longestNameLength)} ${pad(m.kind, longestKindLength)} ${m.kindModifiers}`).join("\n"); Harness.IO.log(membersString); } @@ -2172,7 +2174,7 @@ namespace FourSlash { Harness.IO.log(this.spanInfoToString(this.getNameOrDottedNameSpan(pos), "**")); } - private verifyClassifications(expected: { classificationType: string; text: string; textSpan?: TextSpan }[], actual: ts.ClassifiedSpan[]) { + private verifyClassifications(expected: { classificationType: string; text: string; textSpan?: TextSpan }[], actual: ts.ClassifiedSpan[], sourceFileText: string) { if (actual.length !== expected.length) { this.raiseError("verifyClassifications failed - expected total classifications to be " + expected.length + ", but was " + actual.length + @@ -2212,9 +2214,11 @@ namespace FourSlash { }); function jsonMismatchString() { + const showActual = actual.map(({ classificationType, textSpan }) => + ({ classificationType, text: sourceFileText.slice(textSpan.start, textSpan.start + textSpan.length) })); return Harness.IO.newLine() + "expected: '" + Harness.IO.newLine() + stringify(expected) + "'" + Harness.IO.newLine() + - "actual: '" + Harness.IO.newLine() + stringify(actual) + "'"; + "actual: '" + Harness.IO.newLine() + stringify(showActual) + "'"; } } @@ -2237,14 +2241,14 @@ namespace FourSlash { const actual = this.languageService.getSemanticClassifications(this.activeFile.fileName, ts.createTextSpan(0, this.activeFile.content.length)); - this.verifyClassifications(expected, actual); + this.verifyClassifications(expected, actual, this.activeFile.content); } public verifySyntacticClassifications(expected: { classificationType: string; text: string }[]) { const actual = this.languageService.getSyntacticClassifications(this.activeFile.fileName, ts.createTextSpan(0, this.activeFile.content.length)); - this.verifyClassifications(expected, actual); + this.verifyClassifications(expected, actual, this.activeFile.content); } public verifyOutliningSpans(spans: TextSpan[]) { @@ -2279,23 +2283,22 @@ namespace FourSlash { } /** - * Compares expected text to the text that would be in the sole range - * (ie: [|...|]) in the file after applying the codefix sole codefix - * in the source file. - * - * Because codefixes are only applied on the working file, it is unsafe - * to apply this more than once (consider a refactoring across files). + * Finds and applies a code action corresponding to the supplied parameters. + * If index is undefined, applies the unique code action available. + * @param errorCode The error code that generated the code action. + * @param index The nth (0-index-based) codeaction available generated by errorCode. */ - public verifyRangeAfterCodeFix(expectedText: string, includeWhiteSpace?: boolean, errorCode?: number, index?: number) { + public getAndApplyCodeActions(errorCode?: number, index?: number) { + const fileName = this.activeFile.fileName; + this.applyCodeActions(this.getCodeFixActions(fileName, errorCode), index); + } + + public verifyRangeIs(expectedText: string, includeWhiteSpace?: boolean) { const ranges = this.getRanges(); if (ranges.length !== 1) { this.raiseError("Exactly one range should be specified in the testfile."); } - const fileName = this.activeFile.fileName; - - this.applyCodeAction(fileName, this.getCodeFixActions(fileName, errorCode), index); - const actualText = this.rangeText(ranges[0]); const result = includeWhiteSpace @@ -2307,6 +2310,16 @@ namespace FourSlash { } } + /** + * Compares expected text to the text that would be in the sole range + * (ie: [|...|]) in the file after applying the codefix sole codefix + * in the source file. + */ + public verifyRangeAfterCodeFix(expectedText: string, includeWhiteSpace?: boolean, errorCode?: number, index?: number) { + this.getAndApplyCodeActions(errorCode, index); + this.verifyRangeIs(expectedText, includeWhiteSpace); + } + /** * Applies fixes for the errors in fileName and compares the results to * expectedContents after all fixes have been applied. @@ -2319,7 +2332,7 @@ namespace FourSlash { public verifyFileAfterCodeFix(expectedContents: string, fileName?: string) { fileName = fileName ? fileName : this.activeFile.fileName; - this.applyCodeAction(fileName, this.getCodeFixActions(fileName)); + this.applyCodeActions(this.getCodeFixActions(fileName)); const actualContents: string = this.getFileContent(fileName); if (this.removeWhitespace(actualContents) !== this.removeWhitespace(expectedContents)) { @@ -2357,11 +2370,10 @@ namespace FourSlash { return actions; } - private applyCodeAction(fileName: string, actions: ts.CodeAction[], index?: number): void { + private applyCodeActions(actions: ts.CodeAction[], index?: number): void { if (index === undefined) { if (!(actions && actions.length === 1)) { - const actionText = (actions && actions.length) ? JSON.stringify(actions) : "none"; - this.raiseError(`Should find exactly one codefix, but found ${actionText}`); + this.raiseError(`Should find exactly one codefix, but ${actions ? actions.length : "none"} found.`); } index = 0; } @@ -2371,12 +2383,11 @@ namespace FourSlash { } } - const fileChanges = ts.find(actions[index].changes, change => change.fileName === fileName); - if (!fileChanges) { - this.raiseError("The CodeFix found doesn't provide any changes in this file."); - } + const changes = actions[index].changes; - this.applyEdits(fileChanges.fileName, fileChanges.textChanges, /*isFormattingEdit*/ false); + for (const change of changes) { + this.applyEdits(change.fileName, change.textChanges, /*isFormattingEdit*/ false); + } } public verifyImportFixAtPosition(expectedTextArray: string[], errorCode?: number) { @@ -2388,7 +2399,10 @@ namespace FourSlash { const codeFixes = this.getCodeFixActions(this.activeFile.fileName, errorCode); if (!codeFixes || codeFixes.length === 0) { - this.raiseError("No codefixes returned."); + if (expectedTextArray.length !== 0) { + this.raiseError("No codefixes returned."); + } + return; } const actualTextArray: string[] = []; @@ -2665,6 +2679,13 @@ namespace FourSlash { this.rangesByText().forEach(ranges => this.verifyRangesAreDocumentHighlights(ranges)); } + public verifyDocumentHighlightsOf(startRange: Range, ranges: Range[]) { + ts.Debug.assert(ts.contains(ranges, startRange)); + const fileNames = unique(ranges, range => range.fileName); + this.goToRangeStart(startRange); + this.verifyDocumentHighlights(ranges, fileNames); + } + public verifyRangesAreDocumentHighlights(ranges?: Range[]) { ranges = ranges || this.getRanges(); const fileNames = unique(ranges, range => range.fileName); @@ -2747,6 +2768,7 @@ namespace FourSlash { markerName: string, expectedContent: string, refactorNameToApply: string, + actionName: string, formattingOptions?: ts.FormatCodeSettings) { formattingOptions = formattingOptions || this.formatCodeSettings; @@ -2759,9 +2781,11 @@ namespace FourSlash { this.raiseError(`The expected refactor: ${refactorNameToApply} is not available at the marker location.`); } - const codeActions = this.languageService.getRefactorCodeActions(this.activeFile.fileName, formattingOptions, markerPos, refactorNameToApply); + const editInfo = this.languageService.getEditsForRefactor(this.activeFile.fileName, formattingOptions, markerPos, refactorNameToApply, actionName); - this.applyCodeAction(this.activeFile.fileName, codeActions); + for (const edit of editInfo.edits) { + this.applyEdits(edit.fileName, edit.textChanges); + } const actualContent = this.getFileContent(this.activeFile.fileName); if (this.normalizeNewlines(actualContent) !== this.normalizeNewlines(expectedContent)) { @@ -3804,8 +3828,16 @@ namespace FourSlashInterface { this.state.verifyRangeAfterCodeFix(expectedText, includeWhiteSpace, errorCode, index); } - public fileAfterApplyingRefactorAtMarker(markerName: string, expectedContent: string, refactorNameToApply: string, formattingOptions?: ts.FormatCodeSettings): void { - this.state.verifyFileAfterApplyingRefactorAtMarker(markerName, expectedContent, refactorNameToApply, formattingOptions); + public fileAfterApplyingRefactorAtMarker(markerName: string, expectedContent: string, refactorNameToApply: string, actionName: string, formattingOptions?: ts.FormatCodeSettings): void { + this.state.verifyFileAfterApplyingRefactorAtMarker(markerName, expectedContent, refactorNameToApply, actionName, formattingOptions); + } + + public rangeIs(expectedText: string, includeWhiteSpace?: boolean): void { + this.state.verifyRangeIs(expectedText, includeWhiteSpace); + } + + public getAndApplyCodeFix(errorCode?: number, index?: number): void { + this.state.getAndApplyCodeActions(errorCode, index); } public importFixAtPosition(expectedTextArray: string[], errorCode?: number): void { @@ -3868,6 +3900,10 @@ namespace FourSlashInterface { this.state.verifyRangesWithSameTextAreDocumentHighlights(); } + public documentHighlightsOf(startRange: FourSlash.Range, ranges: FourSlash.Range[]) { + this.state.verifyDocumentHighlightsOf(startRange, ranges); + } + public completionEntryDetailIs(entryName: string, text: string, documentation?: string, kind?: string, tags?: ts.JSDocTagInfo[]) { this.state.verifyCompletionEntryDetails(entryName, text, documentation, kind, tags); } diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 49dbdbf2102..e944e68f11e 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -259,8 +259,9 @@ namespace Utils { return true; } else if ((f & v) > 0) { - if (result.length) + if (result.length) { result += " | "; + } result += flags[v]; return false; } @@ -857,6 +858,7 @@ namespace Harness { export function getDefaultLibFileName(options: ts.CompilerOptions): string { switch (options.target) { + case ts.ScriptTarget.ESNext: case ts.ScriptTarget.ES2017: return "lib.es2017.d.ts"; case ts.ScriptTarget.ES2016: @@ -1051,7 +1053,7 @@ namespace Harness { ]; let optionsIndex: ts.Map; - function getCommandLineOption(name: string): ts.CommandLineOption { + function getCommandLineOption(name: string): ts.CommandLineOption | undefined { if (!optionsIndex) { optionsIndex = ts.createMap(); const optionDeclarations = harnessOptionDeclarations.concat(ts.optionDeclarations); @@ -1247,7 +1249,7 @@ namespace Harness { sourceFileName = outFile; } - const dTsFileName = ts.removeFileExtension(sourceFileName) + ".d.ts"; + const dTsFileName = ts.removeFileExtension(sourceFileName) + ts.Extension.Dts; return ts.forEach(result.declFilesCode, declFile => declFile.fileName === dTsFileName ? declFile : undefined); } @@ -1463,7 +1465,7 @@ namespace Harness { // When calling this function from rwc-runner, the baselinePath will have no extension. // As rwc test- file is stored in json which ".json" will get stripped off. // When calling this function from compiler-runner, the baselinePath will then has either ".ts" or ".tsx" extension - const outputFileName = ts.endsWith(baselinePath, ".ts") || ts.endsWith(baselinePath, ".tsx") ? + const outputFileName = ts.endsWith(baselinePath, ts.Extension.Ts) || ts.endsWith(baselinePath, ts.Extension.Tsx) ? baselinePath.replace(/\.tsx?/, fullExtension) : baselinePath.concat(fullExtension); Harness.Baseline.runBaseline(outputFileName, () => fullBaseLine, opts); } @@ -1561,7 +1563,7 @@ namespace Harness { } // check js output - Harness.Baseline.runBaseline(baselinePath.replace(/\.tsx?/, ".js"), () => { + Harness.Baseline.runBaseline(baselinePath.replace(/\.tsx?/, ts.Extension.Js), () => { let tsCode = ""; const tsSources = otherFiles.concat(toBeCompiled); if (tsSources.length > 1) { @@ -1649,22 +1651,22 @@ namespace Harness { } export function isTS(fileName: string) { - return ts.endsWith(fileName, ".ts"); + return ts.endsWith(fileName, ts.Extension.Ts); } export function isTSX(fileName: string) { - return ts.endsWith(fileName, ".tsx"); + return ts.endsWith(fileName, ts.Extension.Tsx); } export function isDTS(fileName: string) { - return ts.endsWith(fileName, ".d.ts"); + return ts.endsWith(fileName, ts.Extension.Dts); } export function isJS(fileName: string) { - return ts.endsWith(fileName, ".js"); + return ts.endsWith(fileName, ts.Extension.Js); } export function isJSX(fileName: string) { - return ts.endsWith(fileName, ".jsx"); + return ts.endsWith(fileName, ts.Extension.Jsx); } export function isJSMap(fileName: string) { @@ -1971,7 +1973,7 @@ namespace Harness { export function isDefaultLibraryFile(filePath: string): boolean { // We need to make sure that the filePath is prefixed with "lib." not just containing "lib." and end with ".d.ts" const fileName = ts.getBaseFileName(ts.normalizeSlashes(filePath)); - return ts.startsWith(fileName, "lib.") && ts.endsWith(fileName, ".d.ts"); + return ts.startsWith(fileName, "lib.") && ts.endsWith(fileName, ts.Extension.Dts); } export function isBuiltFile(filePath: string): boolean { diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index 7aefb0f3a1f..774c43556ca 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -492,7 +492,7 @@ namespace Harness.LanguageService { getCodeFixDiagnostics(): ts.Diagnostic[] { throw new Error("Not supported on the shim."); } - getRefactorCodeActions(): ts.CodeAction[] { + getEditsForRefactor(): ts.RefactorEditInfo { throw new Error("Not supported on the shim."); } getApplicableRefactors(): ts.ApplicableRefactorInfo[] { @@ -731,7 +731,7 @@ namespace Harness.LanguageService { } createHash(s: string) { - return s; + return mockHash(s); } require(_initialDir: string, _moduleName: string): ts.server.RequireResult { @@ -856,4 +856,8 @@ namespace Harness.LanguageService { getClassifier(): ts.Classifier { throw new Error("getClassifier is not available using the server interface."); } getPreProcessedFileInfo(): ts.PreProcessedFileInfo { throw new Error("getPreProcessedFileInfo is not available using the server interface."); } } + + export function mockHash(s: string): string { + return `hash-${s}`; + } } diff --git a/src/harness/loggedIO.ts b/src/harness/loggedIO.ts index eeb47f0cfa0..76f585b623a 100644 --- a/src/harness/loggedIO.ts +++ b/src/harness/loggedIO.ts @@ -232,14 +232,11 @@ namespace Playback { // different entry). // TODO (yuisu): We can certainly remove these once we recapture the RWC using new API const normalizedPath = ts.normalizePath(path).toLowerCase(); - const result: string[] = []; - for (const directory of replayLog.directoriesRead) { + return ts.flatMap(replayLog.directoriesRead, directory => { if (ts.normalizeSlashes(directory.path).toLowerCase() === normalizedPath) { - result.push(...directory.result); + return directory.result; } - } - - return result; + }); }); wrapper.writeFile = recordReplay(wrapper.writeFile, underlying)( diff --git a/src/harness/projectsRunner.ts b/src/harness/projectsRunner.ts index 28d59fe35bd..5d4d5a41f3a 100644 --- a/src/harness/projectsRunner.ts +++ b/src/harness/projectsRunner.ts @@ -325,8 +325,8 @@ class ProjectRunner extends RunnerBase { // we need to instead create files that can live in the project reference folder // but make sure extension of these files matches with the fileName the compiler asked to write diskRelativeName = "diskFile" + nonSubfolderDiskFiles + - (Harness.Compiler.isDTS(fileName) ? ".d.ts" : - Harness.Compiler.isJS(fileName) ? ".js" : ".js.map"); + (Harness.Compiler.isDTS(fileName) ? ts.Extension.Dts : + Harness.Compiler.isJS(fileName) ? ts.Extension.Js : ".js.map"); nonSubfolderDiskFiles++; } @@ -386,14 +386,14 @@ class ProjectRunner extends RunnerBase { emitOutputFilePathWithoutExtension = ts.removeFileExtension(sourceFile.fileName); } - const outputDtsFileName = emitOutputFilePathWithoutExtension + ".d.ts"; + const outputDtsFileName = emitOutputFilePathWithoutExtension + ts.Extension.Dts; const file = findOutputDtsFile(outputDtsFileName); if (file) { allInputFiles.unshift(file); } } else { - const outputDtsFileName = ts.removeFileExtension(compilerOptions.outFile || compilerOptions.out) + ".d.ts"; + const outputDtsFileName = ts.removeFileExtension(compilerOptions.outFile || compilerOptions.out) + ts.Extension.Dts; const outputDtsFile = findOutputDtsFile(outputDtsFileName); if (!ts.contains(allInputFiles, outputDtsFile)) { allInputFiles.unshift(outputDtsFile); diff --git a/src/harness/runner.ts b/src/harness/runner.ts index 3ad6269e52f..4653e440f11 100644 --- a/src/harness/runner.ts +++ b/src/harness/runner.ts @@ -222,6 +222,10 @@ if (taskConfigsFolder) { } } else { + if (ts.Debug.isDebugging) { + ts.Debug.enableDebugInfo(); + } + runTests(runners); } if (!runUnitTests) { diff --git a/src/harness/unittests/cachingInServerLSHost.ts b/src/harness/unittests/cachingInServerLSHost.ts index 1b87fc848b5..9bb264b2637 100644 --- a/src/harness/unittests/cachingInServerLSHost.ts +++ b/src/harness/unittests/cachingInServerLSHost.ts @@ -47,7 +47,7 @@ namespace ts { clearTimeout, setImmediate: typeof setImmediate !== "undefined" ? setImmediate : action => setTimeout(action, 0), clearImmediate: typeof clearImmediate !== "undefined" ? clearImmediate : clearTimeout, - createHash: s => s + createHash: Harness.LanguageService.mockHash, }; } diff --git a/src/harness/unittests/commandLineParsing.ts b/src/harness/unittests/commandLineParsing.ts index 19ccc919d4c..01a208aa330 100644 --- a/src/harness/unittests/commandLineParsing.ts +++ b/src/harness/unittests/commandLineParsing.ts @@ -113,7 +113,7 @@ namespace ts { start: undefined, length: undefined, }, { - messageText: "Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015'.", + messageText: "Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015', 'esnext'.", category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category, code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, diff --git a/src/harness/unittests/compileOnSave.ts b/src/harness/unittests/compileOnSave.ts index eaab86b4ebc..7e262a1b257 100644 --- a/src/harness/unittests/compileOnSave.ts +++ b/src/harness/unittests/compileOnSave.ts @@ -513,7 +513,7 @@ namespace ts.projectSystem { const lines = ["var x = 1;", "var y = 2;"]; const path = "/a/app"; const f = { - path: path + ".ts", + path: path + ts.Extension.Ts, content: lines.join(newLine) }; const host = createServerHost([f], { newLine }); @@ -530,7 +530,7 @@ namespace ts.projectSystem { command: "compileOnSaveEmitFile", arguments: { file: f.path } }); - const emitOutput = host.readFile(path + ".js"); + const emitOutput = host.readFile(path + ts.Extension.Js); assert.equal(emitOutput, f.content + newLine, "content of emit output should be identical with the input + newline"); } }); diff --git a/src/harness/unittests/convertCompilerOptionsFromJson.ts b/src/harness/unittests/convertCompilerOptionsFromJson.ts index 3aa1a4c9b8e..798f8c6a76b 100644 --- a/src/harness/unittests/convertCompilerOptionsFromJson.ts +++ b/src/harness/unittests/convertCompilerOptionsFromJson.ts @@ -122,7 +122,7 @@ namespace ts { file: undefined, start: 0, length: 0, - messageText: "Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015'.", + messageText: "Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015', 'esnext'.", code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category }] diff --git a/src/harness/unittests/moduleResolution.ts b/src/harness/unittests/moduleResolution.ts index a4220f50321..87ec4ea8149 100644 --- a/src/harness/unittests/moduleResolution.ts +++ b/src/harness/unittests/moduleResolution.ts @@ -5,7 +5,7 @@ namespace ts { if (!expected === !actual) { if (expected) { assert.isTrue(expected.resolvedFileName === actual.resolvedFileName, `'resolvedFileName': expected '${expected.resolvedFileName}' to be equal to '${actual.resolvedFileName}'`); - assert.isTrue(expected.extension === actual.extension, `'ext': expected '${Extension[expected.extension]}' to be equal to '${Extension[actual.extension]}'`); + assert.isTrue(expected.extension === actual.extension, `'ext': expected '${expected.extension}' to be equal to '${actual.extension}'`); assert.isTrue(expected.isExternalLibraryImport === actual.isExternalLibraryImport, `'isExternalLibraryImport': expected '${expected.isExternalLibraryImport}' to be equal to '${actual.isExternalLibraryImport}'`); } return true; diff --git a/src/harness/unittests/printer.ts b/src/harness/unittests/printer.ts index 4bdafe04ba1..23e301f3669 100644 --- a/src/harness/unittests/printer.ts +++ b/src/harness/unittests/printer.ts @@ -81,63 +81,136 @@ namespace ts { describe("printNode", () => { const printsCorrectly = makePrintsCorrectly("printsNodeCorrectly"); - let sourceFile: SourceFile; - before(() => sourceFile = createSourceFile("source.ts", "", ScriptTarget.ES2015)); - // tslint:disable boolean-trivia - const syntheticNode = createClassDeclaration( - undefined, - undefined, - /*name*/ createIdentifier("C"), - undefined, - undefined, - createNodeArray([ - createProperty( - undefined, + printsCorrectly("class", {}, printer => printer.printNode( + EmitHint.Unspecified, + createClassDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*name*/ createIdentifier("C"), + /*typeParameters*/ undefined, + /*heritageClauses*/ undefined, + [createProperty( + /*decorators*/ undefined, createNodeArray([createToken(SyntaxKind.PublicKeyword)]), createIdentifier("prop"), - undefined, - undefined, - undefined - ) - ]) - ); + /*questionToken*/ undefined, + /*type*/ undefined, + /*initializer*/ undefined + )] + ), + createSourceFile("source.ts", "", ScriptTarget.ES2015) + )); + + printsCorrectly("namespaceExportDeclaration", {}, printer => printer.printNode( + EmitHint.Unspecified, + createNamespaceExportDeclaration("B"), + createSourceFile("source.ts", "", ScriptTarget.ES2015) + )); // https://github.com/Microsoft/TypeScript/issues/15971 - const classWithOptionalMethodAndProperty = createClassDeclaration( - undefined, - /* modifiers */ createNodeArray([createToken(SyntaxKind.DeclareKeyword)]), - /* name */ createIdentifier("X"), - undefined, - undefined, - createNodeArray([ - createMethod( - undefined, - undefined, - undefined, - /* name */ createIdentifier("method"), - /* questionToken */ createToken(SyntaxKind.QuestionToken), - undefined, - undefined, - /* type */ createKeywordTypeNode(SyntaxKind.VoidKeyword), - undefined + printsCorrectly("classWithOptionalMethodAndProperty", {}, printer => printer.printNode( + EmitHint.Unspecified, + createClassDeclaration( + /*decorators*/ undefined, + /*modifiers*/ [createToken(SyntaxKind.DeclareKeyword)], + /*name*/ createIdentifier("X"), + /*typeParameters*/ undefined, + /*heritageClauses*/ undefined, + [ + createMethod( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ createIdentifier("method"), + /*questionToken*/ createToken(SyntaxKind.QuestionToken), + /*typeParameters*/ undefined, + [], + /*type*/ createKeywordTypeNode(SyntaxKind.VoidKeyword), + /*body*/ undefined + ), + createProperty( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*name*/ createIdentifier("property"), + /*questionToken*/ createToken(SyntaxKind.QuestionToken), + /*type*/ createKeywordTypeNode(SyntaxKind.StringKeyword), + /*initializer*/ undefined + ), + ] + ), + createSourceFile("source.ts", "", ScriptTarget.ES2015) + )); + + // https://github.com/Microsoft/TypeScript/issues/15651 + printsCorrectly("functionTypes", {}, printer => printer.printNode( + EmitHint.Unspecified, + createTupleTypeNode([ + createFunctionTypeNode( + /*typeArguments*/ undefined, + [createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, + createIdentifier("args") + )], + createKeywordTypeNode(SyntaxKind.AnyKeyword) ), - createProperty( - undefined, - undefined, - /* name */ createIdentifier("property"), - /* questionToken */ createToken(SyntaxKind.QuestionToken), - /* type */ createKeywordTypeNode(SyntaxKind.StringKeyword), - undefined + createFunctionTypeNode( + [createTypeParameterDeclaration("T")], + [createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, + createIdentifier("args") + )], + createKeywordTypeNode(SyntaxKind.AnyKeyword) ), - ]) - ); - - // tslint:enable boolean-trivia - printsCorrectly("class", {}, printer => printer.printNode(EmitHint.Unspecified, syntheticNode, sourceFile)); - - printsCorrectly("namespaceExportDeclaration", {}, printer => printer.printNode(EmitHint.Unspecified, createNamespaceExportDeclaration("B"), sourceFile)); - - printsCorrectly("classWithOptionalMethodAndProperty", {}, printer => printer.printNode(EmitHint.Unspecified, classWithOptionalMethodAndProperty, sourceFile)); + createFunctionTypeNode( + /*typeArguments*/ undefined, + [createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + createToken(SyntaxKind.DotDotDotToken), + createIdentifier("args") + )], + createKeywordTypeNode(SyntaxKind.AnyKeyword) + ), + createFunctionTypeNode( + /*typeArguments*/ undefined, + [createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, + createIdentifier("args"), + createToken(SyntaxKind.QuestionToken) + )], + createKeywordTypeNode(SyntaxKind.AnyKeyword) + ), + createFunctionTypeNode( + /*typeArguments*/ undefined, + [createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, + createIdentifier("args"), + /*questionToken*/ undefined, + createKeywordTypeNode(SyntaxKind.AnyKeyword) + )], + createKeywordTypeNode(SyntaxKind.AnyKeyword) + ), + createFunctionTypeNode( + /*typeArguments*/ undefined, + [createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, + createObjectBindingPattern([]) + )], + createKeywordTypeNode(SyntaxKind.AnyKeyword) + ), + ]), + createSourceFile("source.ts", "", ScriptTarget.ES2015) + )); }); }); } diff --git a/src/harness/unittests/session.ts b/src/harness/unittests/session.ts index db33d87f087..067cd351ec7 100644 --- a/src/harness/unittests/session.ts +++ b/src/harness/unittests/session.ts @@ -25,7 +25,7 @@ namespace ts.server { clearTimeout: noop, setImmediate: () => 0, clearImmediate: noop, - createHash: s => s + createHash: Harness.LanguageService.mockHash, }; const mockLogger: Logger = { @@ -240,8 +240,8 @@ namespace ts.server { CommandNames.GetCodeFixesFull, CommandNames.GetSupportedCodeFixes, CommandNames.GetApplicableRefactors, - CommandNames.GetRefactorCodeActions, - CommandNames.GetRefactorCodeActionsFull, + CommandNames.GetEditsForRefactor, + CommandNames.GetEditsForRefactorFull, ]; it("should not throw when commands are executed with invalid arguments", () => { diff --git a/src/harness/unittests/telemetry.ts b/src/harness/unittests/telemetry.ts index d3811edf251..02be254c6f9 100644 --- a/src/harness/unittests/telemetry.ts +++ b/src/harness/unittests/telemetry.ts @@ -9,6 +9,7 @@ namespace ts.projectSystem { et.service.openClientFile(file.path); assert.equal(et.getEvents().length, 0); }); + it("only sends an event once", () => { const file = makeFile("/a.ts"); const tsconfig = makeFile("/tsconfig.json", {}); @@ -46,12 +47,13 @@ namespace ts.projectSystem { const et = new EventTracker([file1]); const compilerOptions: ts.CompilerOptions = { strict: true }; - const projectFileName = "foo.csproj"; + const projectFileName = "/hunter2/foo.csproj"; open(); // TODO: Apparently compilerOptions is mutated, so have to repeat it here! et.assertProjectInfoTelemetryEvent({ + projectId: Harness.LanguageService.mockHash("/hunter2/foo.csproj"), compilerOptions: { strict: true }, compileOnSave: true, // These properties can't be present for an external project, so they are undefined instead of false. @@ -195,6 +197,7 @@ namespace ts.projectSystem { const et = new EventTracker([jsconfig, file]); et.service.openClientFile(file.path); et.assertProjectInfoTelemetryEvent({ + projectId: Harness.LanguageService.mockHash("/jsconfig.json"), fileStats: fileStats({ js: 1 }), compilerOptions: autoJsCompilerOptions, typeAcquisition: { @@ -214,6 +217,7 @@ namespace ts.projectSystem { et.service.openClientFile(file.path); et.getEvent(server.ProjectLanguageServiceStateEvent, /*mayBeMore*/ true); et.assertProjectInfoTelemetryEvent({ + projectId: Harness.LanguageService.mockHash("/jsconfig.json"), fileStats: fileStats({ js: 1 }), compilerOptions: autoJsCompilerOptions, configFileName: "jsconfig.json", @@ -248,39 +252,37 @@ namespace ts.projectSystem { } assertProjectInfoTelemetryEvent(partial: Partial): void { - assert.deepEqual(this.getEvent(ts.server.ProjectInfoTelemetryEvent), makePayload(partial)); + assert.deepEqual(this.getEvent(ts.server.ProjectInfoTelemetryEvent), { + projectId: Harness.LanguageService.mockHash("/tsconfig.json"), + fileStats: fileStats({ ts: 1 }), + compilerOptions: {}, + extends: false, + files: false, + include: false, + exclude: false, + compileOnSave: false, + typeAcquisition: { + enable: false, + exclude: false, + include: false, + }, + configFileName: "tsconfig.json", + projectType: "configured", + languageServiceEnabled: true, + version: ts.version, + ...partial, + }); } getEvent(eventName: T["eventName"], mayBeMore = false): T["data"] { - if (mayBeMore) assert(this.events.length !== 0); else assert.equal(this.events.length, 1); + if (mayBeMore) { assert(this.events.length !== 0); } + else { assert.equal(this.events.length, 1); } const event = this.events.shift(); assert.equal(event.eventName, eventName); return event.data; } } - function makePayload(partial: Partial): server.ProjectInfoTelemetryEventData { - return { - fileStats: fileStats({ ts: 1 }), - compilerOptions: {}, - extends: false, - files: false, - include: false, - exclude: false, - compileOnSave: false, - typeAcquisition: { - enable: false, - exclude: false, - include: false, - }, - configFileName: "tsconfig.json", - projectType: "configured", - languageServiceEnabled: true, - version: ts.version, - ...partial - }; - } - function makeFile(path: string, content: {} = ""): projectSystem.FileOrFolder { return { path, content: typeof content === "string" ? "" : JSON.stringify(content) }; } diff --git a/src/harness/unittests/transpile.ts b/src/harness/unittests/transpile.ts index 20552ab9c2e..e0c96797827 100644 --- a/src/harness/unittests/transpile.ts +++ b/src/harness/unittests/transpile.ts @@ -36,7 +36,7 @@ namespace ts { transpileOptions.reportDiagnostics = true; - justName = "transpile/" + name.replace(/[^a-z0-9\-. ]/ig, "") + (transpileOptions.compilerOptions.jsx ? ".tsx" : ".ts"); + justName = "transpile/" + name.replace(/[^a-z0-9\-. ]/ig, "") + (transpileOptions.compilerOptions.jsx ? Extension.Tsx : Extension.Ts); toBeCompiled = [{ unitName: transpileOptions.fileName, content: input @@ -88,7 +88,7 @@ namespace ts { } it("Correct output for " + justName, () => { - Harness.Baseline.runBaseline(justName.replace(/\.tsx?$/, ".js"), () => { + Harness.Baseline.runBaseline(justName.replace(/\.tsx?$/, ts.Extension.Js), () => { if (transpileResult.outputText) { return transpileResult.outputText; } diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 6f898e7f4a6..7c4a3068226 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -13,7 +13,8 @@ namespace ts.projectSystem { express: "express", jquery: "jquery", lodash: "lodash", - moment: "moment" + moment: "moment", + chroma: "chroma-js" }) }; @@ -61,7 +62,6 @@ namespace ts.projectSystem { super(installTypingHost, globalTypingsCacheLocation, safeList.path, throttleLimit, log); } - safeFileList = safeList.path; protected postExecActions: PostExecAction[] = []; executePendingCommands() { @@ -472,7 +472,7 @@ namespace ts.projectSystem { } createHash(s: string): string { - return s; + return Harness.LanguageService.mockHash(s); } triggerDirectoryWatcherCallback(directoryName: string, fileName: string): void { diff --git a/src/harness/unittests/typingsInstaller.ts b/src/harness/unittests/typingsInstaller.ts index 699b1807428..c356d0941c0 100644 --- a/src/harness/unittests/typingsInstaller.ts +++ b/src/harness/unittests/typingsInstaller.ts @@ -1009,6 +1009,26 @@ namespace ts.projectSystem { }); describe("discover typings", () => { + it("should use mappings from safe list", () => { + const app = { + path: "/a/b/app.js", + content: "" + }; + const jquery = { + path: "/a/b/jquery.js", + content: "" + }; + const chroma = { + path: "/a/b/chroma.min.js", + content: "" + }; + const cache = createMap(); + + const host = createServerHost([app, jquery, chroma]); + const result = JsTyping.discoverTypings(host, [app.path, jquery.path, chroma.path], getDirectoryPath(app.path), /*safeListPath*/ undefined, cache, { enable: true }, []); + assert.deepEqual(result.newTypingNames, ["jquery", "chroma-js"]); + }); + it("should return node for core modules", () => { const f = { path: "/a/b/app.js", @@ -1016,6 +1036,7 @@ namespace ts.projectSystem { }; const host = createServerHost([f]); const cache = createMap(); + for (const name of JsTyping.nodeCoreModuleList) { const result = JsTyping.discoverTypings(host, [f.path], getDirectoryPath(f.path), /*safeListPath*/ undefined, cache, { enable: true }, [name, "somename"]); assert.deepEqual(result.newTypingNames.sort(), ["node", "somename"]); @@ -1040,7 +1061,7 @@ namespace ts.projectSystem { }); describe("telemetry events", () => { - it ("should be received", () => { + it("should be received", () => { const f1 = { path: "/a/app.js", content: "" @@ -1089,7 +1110,7 @@ namespace ts.projectSystem { }); describe("progress notifications", () => { - it ("should be sent for success", () => { + it("should be sent for success", () => { const f1 = { path: "/a/app.js", content: "" @@ -1140,7 +1161,7 @@ namespace ts.projectSystem { checkProjectActualFiles(projectService.inferredProjects[0], [f1.path, commander.path]); }); - it ("should be sent for error", () => { + it("should be sent for error", () => { const f1 = { path: "/a/app.js", content: "" diff --git a/src/lib/dom.generated.d.ts b/src/lib/dom.generated.d.ts index 3aa813c0a8a..da81bba5d78 100644 --- a/src/lib/dom.generated.d.ts +++ b/src/lib/dom.generated.d.ts @@ -3483,7 +3483,7 @@ interface DragEvent extends MouseEvent { declare var DragEvent: { prototype: DragEvent; - new(): DragEvent; + new(type: "drag" | "dragend" | "dragenter" | "dragexit" | "dragleave" | "dragover" | "dragstart" | "drop", dragEventInit?: { dataTransfer?: DataTransfer }): DragEvent; }; interface DynamicsCompressorNode extends AudioNode { @@ -8224,6 +8224,7 @@ interface Navigator extends Object, NavigatorID, NavigatorOnLine, NavigatorConte readonly serviceWorker: ServiceWorkerContainer; readonly webdriver: boolean; readonly hardwareConcurrency: number; + readonly languages: string[]; getGamepads(): Gamepad[]; javaEnabled(): boolean; msLaunchUri(uri: string, successCallback?: MSLaunchUriCallback, noHandlerCallback?: MSLaunchUriCallback): void; diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index 3a85f4ddad9..6decc78558a 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.d.ts @@ -67,8 +67,8 @@ interface PropertyDescriptor { enumerable?: boolean; value?: any; writable?: boolean; - get? (): any; - set? (v: any): void; + get?(): any; + set?(v: any): void; } interface PropertyDescriptorMap { @@ -108,7 +108,7 @@ interface Object { } interface ObjectConstructor { - new (value?: any): Object; + new(value?: any): Object; (): any; (value: any): any; @@ -266,7 +266,7 @@ interface FunctionConstructor { * Creates a new function. * @param args A list of arguments the function accepts. */ - new (...args: string[]): Function; + new(...args: string[]): Function; (...args: string[]): Function; readonly prototype: Function; } @@ -403,7 +403,7 @@ interface String { } interface StringConstructor { - new (value?: any): String; + new(value?: any): String; (value?: any): string; readonly prototype: String; fromCharCode(...codes: number[]): string; @@ -420,7 +420,7 @@ interface Boolean { } interface BooleanConstructor { - new (value?: any): Boolean; + new(value?: any): Boolean; (value?: any): boolean; readonly prototype: Boolean; } @@ -457,7 +457,7 @@ interface Number { } interface NumberConstructor { - new (value?: any): Number; + new(value?: any): Number; (value?: any): number; readonly prototype: Number; @@ -759,10 +759,10 @@ interface Date { } interface DateConstructor { - new (): Date; - new (value: number): Date; - new (value: string): Date; - new (year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): Date; + new(): Date; + new(value: number): Date; + new(value: string): Date; + new(year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): Date; (): string; readonly prototype: Date; /** @@ -828,8 +828,8 @@ interface RegExp { } interface RegExpConstructor { - new (pattern: RegExp | string): RegExp; - new (pattern: string, flags?: string): RegExp; + new(pattern: RegExp | string): RegExp; + new(pattern: string, flags?: string): RegExp; (pattern: RegExp | string): RegExp; (pattern: string, flags?: string): RegExp; readonly prototype: RegExp; @@ -856,7 +856,7 @@ interface Error { } interface ErrorConstructor { - new (message?: string): Error; + new(message?: string): Error; (message?: string): Error; readonly prototype: Error; } @@ -867,7 +867,7 @@ interface EvalError extends Error { } interface EvalErrorConstructor { - new (message?: string): EvalError; + new(message?: string): EvalError; (message?: string): EvalError; readonly prototype: EvalError; } @@ -878,7 +878,7 @@ interface RangeError extends Error { } interface RangeErrorConstructor { - new (message?: string): RangeError; + new(message?: string): RangeError; (message?: string): RangeError; readonly prototype: RangeError; } @@ -889,7 +889,7 @@ interface ReferenceError extends Error { } interface ReferenceErrorConstructor { - new (message?: string): ReferenceError; + new(message?: string): ReferenceError; (message?: string): ReferenceError; readonly prototype: ReferenceError; } @@ -900,7 +900,7 @@ interface SyntaxError extends Error { } interface SyntaxErrorConstructor { - new (message?: string): SyntaxError; + new(message?: string): SyntaxError; (message?: string): SyntaxError; readonly prototype: SyntaxError; } @@ -911,7 +911,7 @@ interface TypeError extends Error { } interface TypeErrorConstructor { - new (message?: string): TypeError; + new(message?: string): TypeError; (message?: string): TypeError; readonly prototype: TypeError; } @@ -922,7 +922,7 @@ interface URIError extends Error { } interface URIErrorConstructor { - new (message?: string): URIError; + new(message?: string): URIError; (message?: string): URIError; readonly prototype: URIError; } @@ -972,12 +972,10 @@ interface ReadonlyArray { * Returns a string representation of an array. */ toString(): string; - toLocaleString(): string; /** - * Combines two or more arrays. - * @param items Additional items to add to the end of array1. + * Returns a string representation of an array. The elements are converted to string using thier toLocalString methods. */ - concat>(...items: U[]): T[]; + toLocaleString(): string; /** * Combines two or more arrays. * @param items Additional items to add to the end of array1. @@ -1005,7 +1003,6 @@ interface ReadonlyArray { * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0. */ indexOf(searchElement: T, fromIndex?: number): number; - /** * Returns the index of the last occurrence of a specified value in an array. * @param searchElement The value to locate in the array. @@ -1017,49 +1014,37 @@ interface ReadonlyArray { * @param callbackfn A function that accepts up to three arguments. The every method calls the callbackfn function for each element in array1 until the callbackfn returns false, or until the end of the array. * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value. */ - every(callbackfn: (this: void, value: T, index: number, array: ReadonlyArray) => boolean): boolean; - every(callbackfn: (this: void, value: T, index: number, array: ReadonlyArray) => boolean, thisArg: undefined): boolean; - every(callbackfn: (this: Z, value: T, index: number, array: ReadonlyArray) => boolean, thisArg: Z): boolean; + every(callbackfn: (value: T, index: number, array: ReadonlyArray) => boolean, thisArg?: any): boolean; /** * Determines whether the specified callback function returns true for any element of an array. * @param callbackfn A function that accepts up to three arguments. The some method calls the callbackfn function for each element in array1 until the callbackfn returns true, or until the end of the array. * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value. */ - some(callbackfn: (this: void, value: T, index: number, array: ReadonlyArray) => boolean): boolean; - some(callbackfn: (this: void, value: T, index: number, array: ReadonlyArray) => boolean, thisArg: undefined): boolean; - some(callbackfn: (this: Z, value: T, index: number, array: ReadonlyArray) => boolean, thisArg: Z): boolean; + some(callbackfn: (value: T, index: number, array: ReadonlyArray) => boolean, thisArg?: any): boolean; /** * Performs the specified action for each element in an array. * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array. * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value. */ - forEach(callbackfn: (this: void, value: T, index: number, array: ReadonlyArray) => void): void; - forEach(callbackfn: (this: void, value: T, index: number, array: ReadonlyArray) => void, thisArg: undefined): void; - forEach(callbackfn: (this: Z, value: T, index: number, array: ReadonlyArray) => void, thisArg: Z): void; + forEach(callbackfn: (value: T, index: number, array: ReadonlyArray) => void, thisArg?: any): void; /** * Calls a defined callback function on each element of an array, and returns an array that contains the results. * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array. * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value. */ - map(callbackfn: (this: void, value: T, index: number, array: ReadonlyArray) => U): U[]; - map(callbackfn: (this: void, value: T, index: number, array: ReadonlyArray) => U, thisArg: undefined): U[]; - map(callbackfn: (this: Z, value: T, index: number, array: ReadonlyArray) => U, thisArg: Z): U[]; + map(callbackfn: (value: T, index: number, array: ReadonlyArray) => U, thisArg?: any): U[]; /** * Returns the elements of an array that meet the condition specified in a callback function. * @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array. * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value. */ - filter(callbackfn: (this: void, value: T, index: number, array: ReadonlyArray) => value is S): S[]; - filter(callbackfn: (this: void, value: T, index: number, array: ReadonlyArray) => value is S, thisArg: undefined): S[]; - filter(callbackfn: (this: Z, value: T, index: number, array: ReadonlyArray) => value is S, thisArg: Z): S[]; + filter(callbackfn: (value: T, index: number, array: ReadonlyArray) => value is S, thisArg?: any): S[]; /** * Returns the elements of an array that meet the condition specified in a callback function. * @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array. * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value. */ - filter(callbackfn: (this: void, value: T, index: number, array: ReadonlyArray) => any): T[]; - filter(callbackfn: (this: void, value: T, index: number, array: ReadonlyArray) => any, thisArg: undefined): T[]; - filter(callbackfn: (this: Z, value: T, index: number, array: ReadonlyArray) => any, thisArg: Z): T[]; + filter(callbackfn: (value: T, index: number, array: ReadonlyArray) => any, thisArg?: any): T[]; /** * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array. @@ -1097,6 +1082,9 @@ interface Array { * Returns a string representation of an array. */ toString(): string; + /** + * Returns a string representation of an array. The elements are converted to string using thier toLocalString methods. + */ toLocaleString(): string; /** * Appends new elements to an array, and returns the new length of the array. @@ -1176,73 +1164,37 @@ interface Array { * @param callbackfn A function that accepts up to three arguments. The every method calls the callbackfn function for each element in array1 until the callbackfn returns false, or until the end of the array. * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value. */ - every(callbackfn: (this: void, value: T, index: number, array: T[]) => boolean): boolean; - every(callbackfn: (this: void, value: T, index: number, array: T[]) => boolean, thisArg: undefined): boolean; - every(callbackfn: (this: Z, value: T, index: number, array: T[]) => boolean, thisArg: Z): boolean; + every(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean; /** * Determines whether the specified callback function returns true for any element of an array. * @param callbackfn A function that accepts up to three arguments. The some method calls the callbackfn function for each element in array1 until the callbackfn returns true, or until the end of the array. * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value. */ - some(callbackfn: (this: void, value: T, index: number, array: T[]) => boolean): boolean; - some(callbackfn: (this: void, value: T, index: number, array: T[]) => boolean, thisArg: undefined): boolean; - some(callbackfn: (this: Z, value: T, index: number, array: T[]) => boolean, thisArg: Z): boolean; + some(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean; /** * Performs the specified action for each element in an array. * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array. * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value. */ - forEach(callbackfn: (this: void, value: T, index: number, array: T[]) => void): void; - forEach(callbackfn: (this: void, value: T, index: number, array: T[]) => void, thisArg: undefined): void; - forEach(callbackfn: (this: Z, value: T, index: number, array: T[]) => void, thisArg: Z): void; + forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void; /** * Calls a defined callback function on each element of an array, and returns an array that contains the results. * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array. * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value. */ - map(this: [T, T, T, T, T], callbackfn: (this: void, value: T, index: number, array: T[]) => U): [U, U, U, U, U]; - map(this: [T, T, T, T, T], callbackfn: (this: void, value: T, index: number, array: T[]) => U, thisArg: undefined): [U, U, U, U, U]; - map(this: [T, T, T, T, T], callbackfn: (this: Z, value: T, index: number, array: T[]) => U, thisArg: Z): [U, U, U, U, U]; + map(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; /** - * Calls a defined callback function on each element of an array, and returns an array that contains the results. - * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value. - */ - map(this: [T, T, T, T], callbackfn: (this: void, value: T, index: number, array: T[]) => U): [U, U, U, U]; - map(this: [T, T, T, T], callbackfn: (this: void, value: T, index: number, array: T[]) => U, thisArg: undefined): [U, U, U, U]; - map(this: [T, T, T, T], callbackfn: (this: Z, value: T, index: number, array: T[]) => U, thisArg: Z): [U, U, U, U]; - /** - * Calls a defined callback function on each element of an array, and returns an array that contains the results. - * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value. - */ - map(this: [T, T, T], callbackfn: (this: void, value: T, index: number, array: T[]) => U): [U, U, U]; - map(this: [T, T, T], callbackfn: (this: void, value: T, index: number, array: T[]) => U, thisArg: undefined): [U, U, U]; - map(this: [T, T, T], callbackfn: (this: Z, value: T, index: number, array: T[]) => U, thisArg: Z): [U, U, U]; - /** - * Calls a defined callback function on each element of an array, and returns an array that contains the results. - * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value. - */ - map(this: [T, T], callbackfn: (this: void, value: T, index: number, array: T[]) => U): [U, U]; - map(this: [T, T], callbackfn: (this: void, value: T, index: number, array: T[]) => U, thisArg: undefined): [U, U]; - map(this: [T, T], callbackfn: (this: Z, value: T, index: number, array: T[]) => U, thisArg: Z): [U, U]; - /** - * Calls a defined callback function on each element of an array, and returns an array that contains the results. - * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value. - */ - map(callbackfn: (this: void, value: T, index: number, array: T[]) => U): U[]; - map(callbackfn: (this: void, value: T, index: number, array: T[]) => U, thisArg: undefined): U[]; - map(callbackfn: (this: Z, value: T, index: number, array: T[]) => U, thisArg: Z): U[]; + * Returns the elements of an array that meet the condition specified in a callback function. + * @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value. + */ + filter(callbackfn: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[]; /** * Returns the elements of an array that meet the condition specified in a callback function. * @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array. * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value. */ - filter(callbackfn: (this: void, value: T, index: number, array: T[]) => any): T[]; - filter(callbackfn: (this: void, value: T, index: number, array: T[]) => any, thisArg: undefined): T[]; - filter(callbackfn: (this: Z, value: T, index: number, array: T[]) => any, thisArg: Z): T[]; + filter(callbackfn: (value: T, index: number, array: T[]) => any, thisArg?: any): T[]; /** * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array. @@ -1272,7 +1224,7 @@ interface Array { } interface ArrayConstructor { - new (arrayLength?: number): any[]; + new(arrayLength?: number): any[]; new (arrayLength: number): T[]; new (...items: T[]): T[]; (arrayLength?: number): any[]; @@ -1396,7 +1348,7 @@ type ArrayBufferLike = ArrayBufferTypes[keyof ArrayBufferTypes]; interface ArrayBufferConstructor { readonly prototype: ArrayBuffer; - new (byteLength: number): ArrayBuffer; + new(byteLength: number): ArrayBuffer; isView(arg: any): arg is ArrayBufferView; } declare const ArrayBuffer: ArrayBufferConstructor; @@ -1547,7 +1499,7 @@ interface DataView { } interface DataViewConstructor { - new (buffer: ArrayBufferLike, byteOffset?: number, byteLength?: number): DataView; + new(buffer: ArrayBufferLike, byteOffset?: number, byteLength?: number): DataView; } declare const DataView: DataViewConstructor; @@ -1595,9 +1547,7 @@ interface Int8Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - every(callbackfn: (this: void, value: number, index: number, array: Int8Array) => boolean): boolean; - every(callbackfn: (this: void, value: number, index: number, array: Int8Array) => boolean, thisArg: undefined): boolean; - every(callbackfn: (this: Z, value: number, index: number, array: Int8Array) => boolean, thisArg: Z): boolean; + every(callbackfn: (value: number, index: number, array: Int8Array) => boolean, thisArg?: any): boolean; /** * Returns the this object after filling the section identified by start and end with value @@ -1616,9 +1566,7 @@ interface Int8Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - filter(callbackfn: (this: void, value: number, index: number, array: Int8Array) => any): Int8Array; - filter(callbackfn: (this: void, value: number, index: number, array: Int8Array) => any, thisArg: undefined): Int8Array; - filter(callbackfn: (this: Z, value: number, index: number, array: Int8Array) => any, thisArg: Z): Int8Array; + filter(callbackfn: (value: number, index: number, array: Int8Array) => any, thisArg?: any): Int8Array; /** * Returns the value of the first element in the array where predicate is true, and undefined @@ -1629,9 +1577,7 @@ interface Int8Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - find(predicate: (this: void, value: number, index: number, obj: Array) => boolean): number | undefined; - find(predicate: (this: void, value: number, index: number, obj: Array) => boolean, thisArg: undefined): number | undefined; - find(predicate: (this: Z, value: number, index: number, obj: Array) => boolean, thisArg: Z): number | undefined; + find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** * Returns the index of the first element in the array where predicate is true, and -1 @@ -1642,9 +1588,7 @@ interface Int8Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (this: void, value: number, index: number, obj: Array) => boolean): number; - findIndex(predicate: (this: void, value: number, index: number, obj: Array) => boolean, thisArg: undefined): number; - findIndex(predicate: (this: Z, value: number, index: number, obj: Array) => boolean, thisArg: Z): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -1653,9 +1597,7 @@ interface Int8Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - forEach(callbackfn: (this: void, value: number, index: number, array: Int8Array) => void): void; - forEach(callbackfn: (this: void, value: number, index: number, array: Int8Array) => void, thisArg: undefined): void; - forEach(callbackfn: (this: Z, value: number, index: number, array: Int8Array) => void, thisArg: Z): void; + forEach(callbackfn: (value: number, index: number, array: Int8Array) => void, thisArg?: any): void; /** * Returns the index of the first occurrence of a value in an array. @@ -1693,9 +1635,7 @@ interface Int8Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - map(callbackfn: (this: void, value: number, index: number, array: Int8Array) => number): Int8Array; - map(callbackfn: (this: void, value: number, index: number, array: Int8Array) => number, thisArg: undefined): Int8Array; - map(callbackfn: (this: Z, value: number, index: number, array: Int8Array) => number, thisArg: Z): Int8Array; + map(callbackfn: (this: void, value: number, index: number, array: Int8Array) => number, thisArg: any): Int8Array; /** * Calls the specified callback function for all the elements in an array. The return value of @@ -1772,9 +1712,7 @@ interface Int8Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - some(callbackfn: (this: void, value: number, index: number, array: Int8Array) => boolean): boolean; - some(callbackfn: (this: void, value: number, index: number, array: Int8Array) => boolean, thisArg: undefined): boolean; - some(callbackfn: (this: Z, value: number, index: number, array: Int8Array) => boolean, thisArg: Z): boolean; + some(callbackfn: (value: number, index: number, array: Int8Array) => boolean, thisArg?: any): boolean; /** * Sorts an array. @@ -1805,9 +1743,9 @@ interface Int8Array { } interface Int8ArrayConstructor { readonly prototype: Int8Array; - new (length: number): Int8Array; - new (array: ArrayLike): Int8Array; - new (buffer: ArrayBufferLike, byteOffset?: number, length?: number): Int8Array; + new(length: number): Int8Array; + new(array: ArrayLike): Int8Array; + new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Int8Array; /** * The size in bytes of each element in the array. @@ -1826,11 +1764,8 @@ interface Int8ArrayConstructor { * @param mapfn A mapping function to call on every element of the array. * @param thisArg Value of 'this' used to invoke the mapfn. */ - from(arrayLike: ArrayLike, mapfn: (this: void, v: number, k: number) => number): Int8Array; - from(arrayLike: ArrayLike, mapfn: (this: void, v: number, k: number) => number, thisArg: undefined): Int8Array; - from(arrayLike: ArrayLike, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Int8Array; + from(arrayLike: ArrayLike, mapfn?: (v: number, k: number) => number, thisArg?: any): Int8Array; - from(arrayLike: ArrayLike): Int8Array; } declare const Int8Array: Int8ArrayConstructor; @@ -1879,9 +1814,7 @@ interface Uint8Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - every(callbackfn: (this: void, value: number, index: number, array: Uint8Array) => boolean): boolean; - every(callbackfn: (this: void, value: number, index: number, array: Uint8Array) => boolean, thisArg: undefined): boolean; - every(callbackfn: (this: Z, value: number, index: number, array: Uint8Array) => boolean, thisArg: Z): boolean; + every(callbackfn: (value: number, index: number, array: Uint8Array) => boolean, thisArg?: any): boolean; /** * Returns the this object after filling the section identified by start and end with value @@ -1900,9 +1833,7 @@ interface Uint8Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - filter(callbackfn: (this: void, value: number, index: number, array: Uint8Array) => any): Uint8Array; - filter(callbackfn: (this: void, value: number, index: number, array: Uint8Array) => any, thisArg: undefined): Uint8Array; - filter(callbackfn: (this: Z, value: number, index: number, array: Uint8Array) => any, thisArg: Z): Uint8Array; + filter(callbackfn: (value: number, index: number, array: Uint8Array) => any, thisArg?: any): Uint8Array; /** * Returns the value of the first element in the array where predicate is true, and undefined @@ -1913,9 +1844,7 @@ interface Uint8Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - find(predicate: (this: void, value: number, index: number, obj: Array) => boolean): number | undefined; - find(predicate: (this: void, value: number, index: number, obj: Array) => boolean, thisArg: undefined): number | undefined; - find(predicate: (this: Z, value: number, index: number, obj: Array) => boolean, thisArg: Z): number | undefined; + find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** * Returns the index of the first element in the array where predicate is true, and -1 @@ -1926,9 +1855,7 @@ interface Uint8Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (this: void, value: number, index: number, obj: Array) => boolean): number; - findIndex(predicate: (this: void, value: number, index: number, obj: Array) => boolean, thisArg: undefined): number; - findIndex(predicate: (this: Z, value: number, index: number, obj: Array) => boolean, thisArg: Z): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -1937,9 +1864,7 @@ interface Uint8Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - forEach(callbackfn: (this: void, value: number, index: number, array: Uint8Array) => void): void; - forEach(callbackfn: (this: void, value: number, index: number, array: Uint8Array) => void, thisArg: undefined): void; - forEach(callbackfn: (this: Z, value: number, index: number, array: Uint8Array) => void, thisArg: Z): void; + forEach(callbackfn: (value: number, index: number, array: Uint8Array) => void, thisArg?: any): void; /** * Returns the index of the first occurrence of a value in an array. @@ -1977,9 +1902,7 @@ interface Uint8Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - map(callbackfn: (this: void, value: number, index: number, array: Uint8Array) => number): Uint8Array; - map(callbackfn: (this: void, value: number, index: number, array: Uint8Array) => number, thisArg: undefined): Uint8Array; - map(callbackfn: (this: Z, value: number, index: number, array: Uint8Array) => number, thisArg: Z): Uint8Array; + map(callbackfn: (this: void, value: number, index: number, array: Uint8Array) => number, thisArg: any): Uint8Array; /** * Calls the specified callback function for all the elements in an array. The return value of @@ -2056,9 +1979,7 @@ interface Uint8Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - some(callbackfn: (this: void, value: number, index: number, array: Uint8Array) => boolean): boolean; - some(callbackfn: (this: void, value: number, index: number, array: Uint8Array) => boolean, thisArg: undefined): boolean; - some(callbackfn: (this: Z, value: number, index: number, array: Uint8Array) => boolean, thisArg: Z): boolean; + some(callbackfn: (value: number, index: number, array: Uint8Array) => boolean, thisArg?: any): boolean; /** * Sorts an array. @@ -2090,9 +2011,9 @@ interface Uint8Array { interface Uint8ArrayConstructor { readonly prototype: Uint8Array; - new (length: number): Uint8Array; - new (array: ArrayLike): Uint8Array; - new (buffer: ArrayBufferLike, byteOffset?: number, length?: number): Uint8Array; + new(length: number): Uint8Array; + new(array: ArrayLike): Uint8Array; + new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Uint8Array; /** * The size in bytes of each element in the array. @@ -2111,11 +2032,7 @@ interface Uint8ArrayConstructor { * @param mapfn A mapping function to call on every element of the array. * @param thisArg Value of 'this' used to invoke the mapfn. */ - from(arrayLike: ArrayLike, mapfn: (this: void, v: number, k: number) => number): Uint8Array; - from(arrayLike: ArrayLike, mapfn: (this: void, v: number, k: number) => number, thisArg: undefined): Uint8Array; - from(arrayLike: ArrayLike, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Uint8Array; - - from(arrayLike: ArrayLike): Uint8Array; + from(arrayLike: ArrayLike, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint8Array; } declare const Uint8Array: Uint8ArrayConstructor; @@ -2164,9 +2081,7 @@ interface Uint8ClampedArray { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - every(callbackfn: (this: void, value: number, index: number, array: Uint8ClampedArray) => boolean): boolean; - every(callbackfn: (this: void, value: number, index: number, array: Uint8ClampedArray) => boolean, thisArg: undefined): boolean; - every(callbackfn: (this: Z, value: number, index: number, array: Uint8ClampedArray) => boolean, thisArg: Z): boolean; + every(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => boolean, thisArg?: any): boolean; /** * Returns the this object after filling the section identified by start and end with value @@ -2185,9 +2100,7 @@ interface Uint8ClampedArray { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - filter(callbackfn: (this: void, value: number, index: number, array: Uint8ClampedArray) => any): Uint8ClampedArray; - filter(callbackfn: (this: void, value: number, index: number, array: Uint8ClampedArray) => any, thisArg: undefined): Uint8ClampedArray; - filter(callbackfn: (this: Z, value: number, index: number, array: Uint8ClampedArray) => any, thisArg: Z): Uint8ClampedArray; + filter(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => any, thisArg?: any): Uint8ClampedArray; /** * Returns the value of the first element in the array where predicate is true, and undefined @@ -2198,9 +2111,7 @@ interface Uint8ClampedArray { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - find(predicate: (this: void, value: number, index: number, obj: Array) => boolean): number | undefined; - find(predicate: (this: void, value: number, index: number, obj: Array) => boolean, thisArg: undefined): number | undefined; - find(predicate: (this: Z, value: number, index: number, obj: Array) => boolean, thisArg: Z): number | undefined; + find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** * Returns the index of the first element in the array where predicate is true, and -1 @@ -2211,9 +2122,7 @@ interface Uint8ClampedArray { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (this: void, value: number, index: number, obj: Array) => boolean): number; - findIndex(predicate: (this: void, value: number, index: number, obj: Array) => boolean, thisArg: undefined): number; - findIndex(predicate: (this: Z, value: number, index: number, obj: Array) => boolean, thisArg: Z): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -2222,9 +2131,7 @@ interface Uint8ClampedArray { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - forEach(callbackfn: (this: void, value: number, index: number, array: Uint8ClampedArray) => void): void; - forEach(callbackfn: (this: void, value: number, index: number, array: Uint8ClampedArray) => void, thisArg: undefined): void; - forEach(callbackfn: (this: Z, value: number, index: number, array: Uint8ClampedArray) => void, thisArg: Z): void; + forEach(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => void, thisArg?: any): void; /** * Returns the index of the first occurrence of a value in an array. @@ -2262,9 +2169,7 @@ interface Uint8ClampedArray { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - map(callbackfn: (this: void, value: number, index: number, array: Uint8ClampedArray) => number): Uint8ClampedArray; - map(callbackfn: (this: void, value: number, index: number, array: Uint8ClampedArray) => number, thisArg: undefined): Uint8ClampedArray; - map(callbackfn: (this: Z, value: number, index: number, array: Uint8ClampedArray) => number, thisArg: Z): Uint8ClampedArray; + map(callbackfn: (this: void, value: number, index: number, array: Uint8ClampedArray) => number, thisArg: any): Uint8ClampedArray; /** * Calls the specified callback function for all the elements in an array. The return value of @@ -2341,9 +2246,7 @@ interface Uint8ClampedArray { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - some(callbackfn: (this: void, value: number, index: number, array: Uint8ClampedArray) => boolean): boolean; - some(callbackfn: (this: void, value: number, index: number, array: Uint8ClampedArray) => boolean, thisArg: undefined): boolean; - some(callbackfn: (this: Z, value: number, index: number, array: Uint8ClampedArray) => boolean, thisArg: Z): boolean; + some(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => boolean, thisArg?: any): boolean; /** * Sorts an array. @@ -2375,9 +2278,9 @@ interface Uint8ClampedArray { interface Uint8ClampedArrayConstructor { readonly prototype: Uint8ClampedArray; - new (length: number): Uint8ClampedArray; - new (array: ArrayLike): Uint8ClampedArray; - new (buffer: ArrayBufferLike, byteOffset?: number, length?: number): Uint8ClampedArray; + new(length: number): Uint8ClampedArray; + new(array: ArrayLike): Uint8ClampedArray; + new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Uint8ClampedArray; /** * The size in bytes of each element in the array. @@ -2396,11 +2299,7 @@ interface Uint8ClampedArrayConstructor { * @param mapfn A mapping function to call on every element of the array. * @param thisArg Value of 'this' used to invoke the mapfn. */ - from(arrayLike: ArrayLike, mapfn: (this: void, v: number, k: number) => number): Uint8ClampedArray; - from(arrayLike: ArrayLike, mapfn: (this: void, v: number, k: number) => number, thisArg: undefined): Uint8ClampedArray; - from(arrayLike: ArrayLike, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Uint8ClampedArray; - - from(arrayLike: ArrayLike): Uint8ClampedArray; + from(arrayLike: ArrayLike, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint8ClampedArray; } declare const Uint8ClampedArray: Uint8ClampedArrayConstructor; @@ -2448,9 +2347,7 @@ interface Int16Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - every(callbackfn: (this: void, value: number, index: number, array: Int16Array) => boolean): boolean; - every(callbackfn: (this: void, value: number, index: number, array: Int16Array) => boolean, thisArg: undefined): boolean; - every(callbackfn: (this: Z, value: number, index: number, array: Int16Array) => boolean, thisArg: Z): boolean; + every(callbackfn: (value: number, index: number, array: Int16Array) => boolean, thisArg?: any): boolean; /** * Returns the this object after filling the section identified by start and end with value @@ -2469,9 +2366,7 @@ interface Int16Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - filter(callbackfn: (this: void, value: number, index: number, array: Int16Array) => any): Int16Array; - filter(callbackfn: (this: void, value: number, index: number, array: Int16Array) => any, thisArg: undefined): Int16Array; - filter(callbackfn: (this: Z, value: number, index: number, array: Int16Array) => any, thisArg: Z): Int16Array; + filter(callbackfn: (this: void, value: number, index: number, array: Int16Array) => any, thisArg?: any): Int16Array; /** * Returns the value of the first element in the array where predicate is true, and undefined @@ -2482,9 +2377,7 @@ interface Int16Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - find(predicate: (this: void, value: number, index: number, obj: Array) => boolean): number | undefined; - find(predicate: (this: void, value: number, index: number, obj: Array) => boolean, thisArg: undefined): number | undefined; - find(predicate: (this: Z, value: number, index: number, obj: Array) => boolean, thisArg: Z): number | undefined; + find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** * Returns the index of the first element in the array where predicate is true, and -1 @@ -2495,9 +2388,7 @@ interface Int16Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (this: void, value: number, index: number, obj: Array) => boolean): number; - findIndex(predicate: (this: void, value: number, index: number, obj: Array) => boolean, thisArg: undefined): number; - findIndex(predicate: (this: Z, value: number, index: number, obj: Array) => boolean, thisArg: Z): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -2506,10 +2397,7 @@ interface Int16Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - forEach(callbackfn: (this: void, value: number, index: number, array: Int16Array) => void): void; - forEach(callbackfn: (this: void, value: number, index: number, array: Int16Array) => void, thisArg: undefined): void; - forEach(callbackfn: (this: Z, value: number, index: number, array: Int16Array) => void, thisArg: Z): void; - + forEach(callbackfn: (value: number, index: number, array: Int16Array) => void, thisArg?: any): void; /** * Returns the index of the first occurrence of a value in an array. * @param searchElement The value to locate in the array. @@ -2546,9 +2434,7 @@ interface Int16Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - map(callbackfn: (this: void, value: number, index: number, array: Int16Array) => number): Int16Array; - map(callbackfn: (this: void, value: number, index: number, array: Int16Array) => number, thisArg: undefined): Int16Array; - map(callbackfn: (this: Z, value: number, index: number, array: Int16Array) => number, thisArg: Z): Int16Array; + map(callbackfn: (this: void, value: number, index: number, array: Int16Array) => number, thisArg: any): Int16Array; /** * Calls the specified callback function for all the elements in an array. The return value of @@ -2625,9 +2511,7 @@ interface Int16Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - some(callbackfn: (this: void, value: number, index: number, array: Int16Array) => boolean): boolean; - some(callbackfn: (this: void, value: number, index: number, array: Int16Array) => boolean, thisArg: undefined): boolean; - some(callbackfn: (this: Z, value: number, index: number, array: Int16Array) => boolean, thisArg: Z): boolean; + some(callbackfn: (value: number, index: number, array: Int16Array) => boolean, thisArg?: any): boolean; /** * Sorts an array. @@ -2659,9 +2543,9 @@ interface Int16Array { interface Int16ArrayConstructor { readonly prototype: Int16Array; - new (length: number): Int16Array; - new (array: ArrayLike): Int16Array; - new (buffer: ArrayBufferLike, byteOffset?: number, length?: number): Int16Array; + new(length: number): Int16Array; + new(array: ArrayLike): Int16Array; + new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Int16Array; /** * The size in bytes of each element in the array. @@ -2680,11 +2564,8 @@ interface Int16ArrayConstructor { * @param mapfn A mapping function to call on every element of the array. * @param thisArg Value of 'this' used to invoke the mapfn. */ - from(arrayLike: ArrayLike, mapfn: (this: void, v: number, k: number) => number): Int16Array; - from(arrayLike: ArrayLike, mapfn: (this: void, v: number, k: number) => number, thisArg: undefined): Int16Array; - from(arrayLike: ArrayLike, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Int16Array; + from(arrayLike: ArrayLike, mapfn?: (v: number, k: number) => number, thisArg?: any): Int16Array; - from(arrayLike: ArrayLike): Int16Array; } declare const Int16Array: Int16ArrayConstructor; @@ -2733,9 +2614,7 @@ interface Uint16Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - every(callbackfn: (this: void, value: number, index: number, array: Uint16Array) => boolean): boolean; - every(callbackfn: (this: void, value: number, index: number, array: Uint16Array) => boolean, thisArg: undefined): boolean; - every(callbackfn: (this: Z, value: number, index: number, array: Uint16Array) => boolean, thisArg: Z): boolean; + every(callbackfn: (value: number, index: number, array: Uint16Array) => boolean, thisArg?: any): boolean; /** * Returns the this object after filling the section identified by start and end with value @@ -2754,9 +2633,7 @@ interface Uint16Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - filter(callbackfn: (this: void, value: number, index: number, array: Uint16Array) => any): Uint16Array; - filter(callbackfn: (this: void, value: number, index: number, array: Uint16Array) => any, thisArg: undefined): Uint16Array; - filter(callbackfn: (this: Z, value: number, index: number, array: Uint16Array) => any, thisArg: Z): Uint16Array; + filter(callbackfn: (value: number, index: number, array: Uint16Array) => any, thisArg?: any): Uint16Array; /** * Returns the value of the first element in the array where predicate is true, and undefined @@ -2767,9 +2644,7 @@ interface Uint16Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - find(predicate: (this: void, value: number, index: number, obj: Array) => boolean): number | undefined; - find(predicate: (this: void, value: number, index: number, obj: Array) => boolean, thisArg: undefined): number | undefined; - find(predicate: (this: Z, value: number, index: number, obj: Array) => boolean, thisArg: Z): number | undefined; + find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** * Returns the index of the first element in the array where predicate is true, and -1 @@ -2780,9 +2655,7 @@ interface Uint16Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (this: void, value: number, index: number, obj: Array) => boolean): number; - findIndex(predicate: (this: void, value: number, index: number, obj: Array) => boolean, thisArg: undefined): number; - findIndex(predicate: (this: Z, value: number, index: number, obj: Array) => boolean, thisArg: Z): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -2791,9 +2664,7 @@ interface Uint16Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - forEach(callbackfn: (this: void, value: number, index: number, array: Uint16Array) => void): void; - forEach(callbackfn: (this: void, value: number, index: number, array: Uint16Array) => void, thisArg: undefined): void; - forEach(callbackfn: (this: Z, value: number, index: number, array: Uint16Array) => void, thisArg: Z): void; + forEach(callbackfn: (value: number, index: number, array: Uint16Array) => void, thisArg?: any): void; /** * Returns the index of the first occurrence of a value in an array. @@ -2831,9 +2702,7 @@ interface Uint16Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - map(callbackfn: (this: void, value: number, index: number, array: Uint16Array) => number): Uint16Array; - map(callbackfn: (this: void, value: number, index: number, array: Uint16Array) => number, thisArg: undefined): Uint16Array; - map(callbackfn: (this: Z, value: number, index: number, array: Uint16Array) => number, thisArg: Z): Uint16Array; + map(callbackfn: (this: void, value: number, index: number, array: Uint16Array) => number, thisArg: any): Uint16Array; /** * Calls the specified callback function for all the elements in an array. The return value of @@ -2910,9 +2779,7 @@ interface Uint16Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - some(callbackfn: (this: void, value: number, index: number, array: Uint16Array) => boolean): boolean; - some(callbackfn: (this: void, value: number, index: number, array: Uint16Array) => boolean, thisArg: undefined): boolean; - some(callbackfn: (this: Z, value: number, index: number, array: Uint16Array) => boolean, thisArg: Z): boolean; + some(callbackfn: (value: number, index: number, array: Uint16Array) => boolean, thisArg?: any): boolean; /** * Sorts an array. @@ -2944,9 +2811,9 @@ interface Uint16Array { interface Uint16ArrayConstructor { readonly prototype: Uint16Array; - new (length: number): Uint16Array; - new (array: ArrayLike): Uint16Array; - new (buffer: ArrayBufferLike, byteOffset?: number, length?: number): Uint16Array; + new(length: number): Uint16Array; + new(array: ArrayLike): Uint16Array; + new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Uint16Array; /** * The size in bytes of each element in the array. @@ -2965,11 +2832,8 @@ interface Uint16ArrayConstructor { * @param mapfn A mapping function to call on every element of the array. * @param thisArg Value of 'this' used to invoke the mapfn. */ - from(arrayLike: ArrayLike, mapfn: (this: void, v: number, k: number) => number): Uint16Array; - from(arrayLike: ArrayLike, mapfn: (this: void, v: number, k: number) => number, thisArg: undefined): Uint16Array; - from(arrayLike: ArrayLike, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Uint16Array; + from(arrayLike: ArrayLike, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint16Array; - from(arrayLike: ArrayLike): Uint16Array; } declare const Uint16Array: Uint16ArrayConstructor; @@ -3017,9 +2881,7 @@ interface Int32Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - every(callbackfn: (this: void, value: number, index: number, array: Int32Array) => boolean): boolean; - every(callbackfn: (this: void, value: number, index: number, array: Int32Array) => boolean, thisArg: undefined): boolean; - every(callbackfn: (this: Z, value: number, index: number, array: Int32Array) => boolean, thisArg: Z): boolean; + every(callbackfn: (value: number, index: number, array: Int32Array) => boolean, thisArg?: any): boolean; /** * Returns the this object after filling the section identified by start and end with value @@ -3038,9 +2900,7 @@ interface Int32Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - filter(callbackfn: (this: void, value: number, index: number, array: Int32Array) => any): Int32Array; - filter(callbackfn: (this: void, value: number, index: number, array: Int32Array) => any, thisArg: undefined): Int32Array; - filter(callbackfn: (this: Z, value: number, index: number, array: Int32Array) => any, thisArg: Z): Int32Array; + filter(callbackfn: (value: number, index: number, array: Int32Array) => any, thisArg?: any): Int32Array; /** * Returns the value of the first element in the array where predicate is true, and undefined @@ -3051,9 +2911,7 @@ interface Int32Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - find(predicate: (this: void, value: number, index: number, obj: Array) => boolean): number | undefined; - find(predicate: (this: void, value: number, index: number, obj: Array) => boolean, thisArg: undefined): number | undefined; - find(predicate: (this: Z, value: number, index: number, obj: Array) => boolean, thisArg: Z): number | undefined; + find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** * Returns the index of the first element in the array where predicate is true, and -1 @@ -3064,9 +2922,7 @@ interface Int32Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (this: void, value: number, index: number, obj: Array) => boolean): number; - findIndex(predicate: (this: void, value: number, index: number, obj: Array) => boolean, thisArg: undefined): number; - findIndex(predicate: (this: Z, value: number, index: number, obj: Array) => boolean, thisArg: Z): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -3075,9 +2931,7 @@ interface Int32Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - forEach(callbackfn: (this: void, value: number, index: number, array: Int32Array) => void): void; - forEach(callbackfn: (this: void, value: number, index: number, array: Int32Array) => void, thisArg: undefined): void; - forEach(callbackfn: (this: Z, value: number, index: number, array: Int32Array) => void, thisArg: Z): void; + forEach(callbackfn: (value: number, index: number, array: Int32Array) => void, thisArg?: any): void; /** * Returns the index of the first occurrence of a value in an array. @@ -3115,9 +2969,7 @@ interface Int32Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - map(callbackfn: (this: void, value: number, index: number, array: Int32Array) => number): Int32Array; - map(callbackfn: (this: void, value: number, index: number, array: Int32Array) => number, thisArg: undefined): Int32Array; - map(callbackfn: (this: Z, value: number, index: number, array: Int32Array) => number, thisArg: Z): Int32Array; + map(callbackfn: (value: number, index: number, array: Int32Array) => number, thisArg?: any): Int32Array; /** * Calls the specified callback function for all the elements in an array. The return value of @@ -3194,9 +3046,7 @@ interface Int32Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - some(callbackfn: (this: void, value: number, index: number, array: Int32Array) => boolean): boolean; - some(callbackfn: (this: void, value: number, index: number, array: Int32Array) => boolean, thisArg: undefined): boolean; - some(callbackfn: (this: Z, value: number, index: number, array: Int32Array) => boolean, thisArg: Z): boolean; + some(callbackfn: (value: number, index: number, array: Int32Array) => boolean, thisArg?: any): boolean; /** * Sorts an array. @@ -3228,9 +3078,9 @@ interface Int32Array { interface Int32ArrayConstructor { readonly prototype: Int32Array; - new (length: number): Int32Array; - new (array: ArrayLike): Int32Array; - new (buffer: ArrayBufferLike, byteOffset?: number, length?: number): Int32Array; + new(length: number): Int32Array; + new(array: ArrayLike): Int32Array; + new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Int32Array; /** * The size in bytes of each element in the array. @@ -3249,11 +3099,8 @@ interface Int32ArrayConstructor { * @param mapfn A mapping function to call on every element of the array. * @param thisArg Value of 'this' used to invoke the mapfn. */ - from(arrayLike: ArrayLike, mapfn: (this: void, v: number, k: number) => number): Int32Array; - from(arrayLike: ArrayLike, mapfn: (this: void, v: number, k: number) => number, thisArg: undefined): Int32Array; - from(arrayLike: ArrayLike, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Int32Array; + from(arrayLike: ArrayLike, mapfn?: (v: number, k: number) => number, thisArg?: any): Int32Array; - from(arrayLike: ArrayLike): Int32Array; } declare const Int32Array: Int32ArrayConstructor; @@ -3301,9 +3148,7 @@ interface Uint32Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - every(callbackfn: (this: void, value: number, index: number, array: Uint32Array) => boolean): boolean; - every(callbackfn: (this: void, value: number, index: number, array: Uint32Array) => boolean, thisArg: undefined): boolean; - every(callbackfn: (this: Z, value: number, index: number, array: Uint32Array) => boolean, thisArg: Z): boolean; + every(callbackfn: (value: number, index: number, array: Uint32Array) => boolean, thisArg?: any): boolean; /** * Returns the this object after filling the section identified by start and end with value @@ -3322,9 +3167,7 @@ interface Uint32Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - filter(callbackfn: (this: void, value: number, index: number, array: Uint32Array) => any): Uint32Array; - filter(callbackfn: (this: void, value: number, index: number, array: Uint32Array) => any, thisArg: undefined): Uint32Array; - filter(callbackfn: (this: Z, value: number, index: number, array: Uint32Array) => any, thisArg: Z): Uint32Array; + filter(callbackfn: (value: number, index: number, array: Uint32Array) => any, thisArg?: any): Uint32Array; /** * Returns the value of the first element in the array where predicate is true, and undefined @@ -3335,9 +3178,7 @@ interface Uint32Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - find(predicate: (this: void, value: number, index: number, obj: Array) => boolean): number | undefined; - find(predicate: (this: void, value: number, index: number, obj: Array) => boolean, thisArg: undefined): number | undefined; - find(predicate: (this: Z, value: number, index: number, obj: Array) => boolean, thisArg: Z): number | undefined; + find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** * Returns the index of the first element in the array where predicate is true, and -1 @@ -3348,9 +3189,7 @@ interface Uint32Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (this: void, value: number, index: number, obj: Array) => boolean): number; - findIndex(predicate: (this: void, value: number, index: number, obj: Array) => boolean, thisArg: undefined): number; - findIndex(predicate: (this: Z, value: number, index: number, obj: Array) => boolean, thisArg: Z): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -3359,10 +3198,7 @@ interface Uint32Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - forEach(callbackfn: (this: void, value: number, index: number, array: Uint32Array) => void): void; - forEach(callbackfn: (this: void, value: number, index: number, array: Uint32Array) => void, thisArg: undefined): void; - forEach(callbackfn: (this: Z, value: number, index: number, array: Uint32Array) => void, thisArg: Z): void; - + forEach(callbackfn: (value: number, index: number, array: Uint32Array) => void, thisArg?: any): void; /** * Returns the index of the first occurrence of a value in an array. * @param searchElement The value to locate in the array. @@ -3399,9 +3235,7 @@ interface Uint32Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - map(callbackfn: (this: void, value: number, index: number, array: Uint32Array) => number): Uint32Array; - map(callbackfn: (this: void, value: number, index: number, array: Uint32Array) => number, thisArg: undefined): Uint32Array; - map(callbackfn: (this: Z, value: number, index: number, array: Uint32Array) => number, thisArg: Z): Uint32Array; + map(callbackfn: (this: void, value: number, index: number, array: Uint32Array) => number, thisArg: any): Uint32Array; /** * Calls the specified callback function for all the elements in an array. The return value of @@ -3478,9 +3312,7 @@ interface Uint32Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - some(callbackfn: (this: void, value: number, index: number, array: Uint32Array) => boolean): boolean; - some(callbackfn: (this: void, value: number, index: number, array: Uint32Array) => boolean, thisArg: undefined): boolean; - some(callbackfn: (this: Z, value: number, index: number, array: Uint32Array) => boolean, thisArg: Z): boolean; + some(callbackfn: (value: number, index: number, array: Uint32Array) => boolean, thisArg?: any): boolean; /** * Sorts an array. @@ -3512,9 +3344,9 @@ interface Uint32Array { interface Uint32ArrayConstructor { readonly prototype: Uint32Array; - new (length: number): Uint32Array; - new (array: ArrayLike): Uint32Array; - new (buffer: ArrayBufferLike, byteOffset?: number, length?: number): Uint32Array; + new(length: number): Uint32Array; + new(array: ArrayLike): Uint32Array; + new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Uint32Array; /** * The size in bytes of each element in the array. @@ -3533,11 +3365,8 @@ interface Uint32ArrayConstructor { * @param mapfn A mapping function to call on every element of the array. * @param thisArg Value of 'this' used to invoke the mapfn. */ - from(arrayLike: ArrayLike, mapfn: (this: void, v: number, k: number) => number): Uint32Array; - from(arrayLike: ArrayLike, mapfn: (this: void, v: number, k: number) => number, thisArg: undefined): Uint32Array; - from(arrayLike: ArrayLike, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Uint32Array; + from(arrayLike: ArrayLike, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint32Array; - from(arrayLike: ArrayLike): Uint32Array; } declare const Uint32Array: Uint32ArrayConstructor; @@ -3585,9 +3414,7 @@ interface Float32Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - every(callbackfn: (this: void, value: number, index: number, array: Float32Array) => boolean): boolean; - every(callbackfn: (this: void, value: number, index: number, array: Float32Array) => boolean, thisArg: undefined): boolean; - every(callbackfn: (this: Z, value: number, index: number, array: Float32Array) => boolean, thisArg: Z): boolean; + every(callbackfn: (value: number, index: number, array: Float32Array) => boolean, thisArg?: any): boolean; /** * Returns the this object after filling the section identified by start and end with value @@ -3606,9 +3433,7 @@ interface Float32Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - filter(callbackfn: (this: void, value: number, index: number, array: Float32Array) => any): Float32Array; - filter(callbackfn: (this: void, value: number, index: number, array: Float32Array) => any, thisArg: undefined): Float32Array; - filter(callbackfn: (this: Z, value: number, index: number, array: Float32Array) => any, thisArg: Z): Float32Array; + filter(callbackfn: (value: number, index: number, array: Float32Array) => any, thisArg?: any): Float32Array; /** * Returns the value of the first element in the array where predicate is true, and undefined @@ -3619,9 +3444,7 @@ interface Float32Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - find(predicate: (this: void, value: number, index: number, obj: Array) => boolean): number | undefined; - find(predicate: (this: void, value: number, index: number, obj: Array) => boolean, thisArg: undefined): number | undefined; - find(predicate: (this: Z, value: number, index: number, obj: Array) => boolean, thisArg: Z): number | undefined; + find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** * Returns the index of the first element in the array where predicate is true, and -1 @@ -3632,9 +3455,7 @@ interface Float32Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (this: void, value: number, index: number, obj: Array) => boolean): number; - findIndex(predicate: (this: void, value: number, index: number, obj: Array) => boolean, thisArg: undefined): number; - findIndex(predicate: (this: Z, value: number, index: number, obj: Array) => boolean, thisArg: Z): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -3643,9 +3464,7 @@ interface Float32Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - forEach(callbackfn: (this: void, value: number, index: number, array: Float32Array) => void): void; - forEach(callbackfn: (this: void, value: number, index: number, array: Float32Array) => void, thisArg: undefined): void; - forEach(callbackfn: (this: Z, value: number, index: number, array: Float32Array) => void, thisArg: Z): void; + forEach(callbackfn: (value: number, index: number, array: Float32Array) => void, thisArg?: any): void; /** * Returns the index of the first occurrence of a value in an array. @@ -3683,9 +3502,7 @@ interface Float32Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - map(callbackfn: (this: void, value: number, index: number, array: Float32Array) => number): Float32Array; - map(callbackfn: (this: void, value: number, index: number, array: Float32Array) => number, thisArg: undefined): Float32Array; - map(callbackfn: (this: Z, value: number, index: number, array: Float32Array) => number, thisArg: Z): Float32Array; + map(callbackfn: (this: void, value: number, index: number, array: Float32Array) => number, thisArg: any): Float32Array; /** * Calls the specified callback function for all the elements in an array. The return value of @@ -3762,9 +3579,7 @@ interface Float32Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - some(callbackfn: (this: void, value: number, index: number, array: Float32Array) => boolean): boolean; - some(callbackfn: (this: void, value: number, index: number, array: Float32Array) => boolean, thisArg: undefined): boolean; - some(callbackfn: (this: Z, value: number, index: number, array: Float32Array) => boolean, thisArg: Z): boolean; + some(callbackfn: (value: number, index: number, array: Float32Array) => boolean, thisArg?: any): boolean; /** * Sorts an array. @@ -3796,9 +3611,9 @@ interface Float32Array { interface Float32ArrayConstructor { readonly prototype: Float32Array; - new (length: number): Float32Array; - new (array: ArrayLike): Float32Array; - new (buffer: ArrayBufferLike, byteOffset?: number, length?: number): Float32Array; + new(length: number): Float32Array; + new(array: ArrayLike): Float32Array; + new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Float32Array; /** * The size in bytes of each element in the array. @@ -3817,11 +3632,8 @@ interface Float32ArrayConstructor { * @param mapfn A mapping function to call on every element of the array. * @param thisArg Value of 'this' used to invoke the mapfn. */ - from(arrayLike: ArrayLike, mapfn: (this: void, v: number, k: number) => number): Float32Array; - from(arrayLike: ArrayLike, mapfn: (this: void, v: number, k: number) => number, thisArg: undefined): Float32Array; - from(arrayLike: ArrayLike, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Float32Array; + from(arrayLike: ArrayLike, mapfn?: (v: number, k: number) => number, thisArg?: any): Float32Array; - from(arrayLike: ArrayLike): Float32Array; } declare const Float32Array: Float32ArrayConstructor; @@ -3870,9 +3682,7 @@ interface Float64Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - every(callbackfn: (this: void, value: number, index: number, array: Float64Array) => boolean): boolean; - every(callbackfn: (this: void, value: number, index: number, array: Float64Array) => boolean, thisArg: undefined): boolean; - every(callbackfn: (this: Z, value: number, index: number, array: Float64Array) => boolean, thisArg: Z): boolean; + every(callbackfn: (value: number, index: number, array: Float64Array) => boolean, thisArg?: any): boolean; /** * Returns the this object after filling the section identified by start and end with value @@ -3891,9 +3701,7 @@ interface Float64Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - filter(callbackfn: (this: void, value: number, index: number, array: Float64Array) => any): Float64Array; - filter(callbackfn: (this: void, value: number, index: number, array: Float64Array) => any, thisArg: undefined): Float64Array; - filter(callbackfn: (this: Z, value: number, index: number, array: Float64Array) => any, thisArg: Z): Float64Array; + filter(callbackfn: (value: number, index: number, array: Float64Array) => any, thisArg?: any): Float64Array; /** * Returns the value of the first element in the array where predicate is true, and undefined @@ -3904,9 +3712,7 @@ interface Float64Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - find(predicate: (this: void, value: number, index: number, obj: Array) => boolean): number | undefined; - find(predicate: (this: void, value: number, index: number, obj: Array) => boolean, thisArg: undefined): number | undefined; - find(predicate: (this: Z, value: number, index: number, obj: Array) => boolean, thisArg: Z): number | undefined; + find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** * Returns the index of the first element in the array where predicate is true, and -1 @@ -3917,9 +3723,7 @@ interface Float64Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (this: void, value: number, index: number, obj: Array) => boolean): number; - findIndex(predicate: (this: void, value: number, index: number, obj: Array) => boolean, thisArg: undefined): number; - findIndex(predicate: (this: Z, value: number, index: number, obj: Array) => boolean, thisArg: Z): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -3928,9 +3732,7 @@ interface Float64Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - forEach(callbackfn: (this: void, value: number, index: number, array: Float64Array) => void): void; - forEach(callbackfn: (this: void, value: number, index: number, array: Float64Array) => void, thisArg: undefined): void; - forEach(callbackfn: (this: Z, value: number, index: number, array: Float64Array) => void, thisArg: Z): void; + forEach(callbackfn: (value: number, index: number, array: Float64Array) => void, thisArg?: any): void; /** * Returns the index of the first occurrence of a value in an array. @@ -3968,9 +3770,7 @@ interface Float64Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - map(callbackfn: (this: void, value: number, index: number, array: Float64Array) => number): Float64Array; - map(callbackfn: (this: void, value: number, index: number, array: Float64Array) => number, thisArg: undefined): Float64Array; - map(callbackfn: (this: Z, value: number, index: number, array: Float64Array) => number, thisArg: Z): Float64Array; + map(callbackfn: (this: void, value: number, index: number, array: Float64Array) => number, thisArg?: any): Float64Array; /** * Calls the specified callback function for all the elements in an array. The return value of @@ -4047,9 +3847,7 @@ interface Float64Array { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - some(callbackfn: (this: void, value: number, index: number, array: Float64Array) => boolean): boolean; - some(callbackfn: (this: void, value: number, index: number, array: Float64Array) => boolean, thisArg: undefined): boolean; - some(callbackfn: (this: Z, value: number, index: number, array: Float64Array) => boolean, thisArg: Z): boolean; + some(callbackfn: (value: number, index: number, array: Float64Array) => boolean, thisArg?: any): boolean; /** * Sorts an array. @@ -4081,9 +3879,9 @@ interface Float64Array { interface Float64ArrayConstructor { readonly prototype: Float64Array; - new (length: number): Float64Array; - new (array: ArrayLike): Float64Array; - new (buffer: ArrayBufferLike, byteOffset?: number, length?: number): Float64Array; + new(length: number): Float64Array; + new(array: ArrayLike): Float64Array; + new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Float64Array; /** * The size in bytes of each element in the array. @@ -4102,11 +3900,8 @@ interface Float64ArrayConstructor { * @param mapfn A mapping function to call on every element of the array. * @param thisArg Value of 'this' used to invoke the mapfn. */ - from(arrayLike: ArrayLike, mapfn: (this: void, v: number, k: number) => number): Float64Array; - from(arrayLike: ArrayLike, mapfn: (this: void, v: number, k: number) => number, thisArg: undefined): Float64Array; - from(arrayLike: ArrayLike, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Float64Array; + from(arrayLike: ArrayLike, mapfn?: (v: number, k: number) => number, thisArg?: any): Float64Array; - from(arrayLike: ArrayLike): Float64Array; } declare const Float64Array: Float64ArrayConstructor; @@ -4139,7 +3934,7 @@ declare namespace Intl { resolvedOptions(): ResolvedCollatorOptions; } var Collator: { - new (locales?: string | string[], options?: CollatorOptions): Collator; + new(locales?: string | string[], options?: CollatorOptions): Collator; (locales?: string | string[], options?: CollatorOptions): Collator; supportedLocalesOf(locales: string | string[], options?: CollatorOptions): string[]; }; @@ -4176,7 +3971,7 @@ declare namespace Intl { resolvedOptions(): ResolvedNumberFormatOptions; } var NumberFormat: { - new (locales?: string | string[], options?: NumberFormatOptions): NumberFormat; + new(locales?: string | string[], options?: NumberFormatOptions): NumberFormat; (locales?: string | string[], options?: NumberFormatOptions): NumberFormat; supportedLocalesOf(locales: string | string[], options?: NumberFormatOptions): string[]; }; @@ -4219,7 +4014,7 @@ declare namespace Intl { resolvedOptions(): ResolvedDateTimeFormatOptions; } var DateTimeFormat: { - new (locales?: string | string[], options?: DateTimeFormatOptions): DateTimeFormat; + new(locales?: string | string[], options?: DateTimeFormatOptions): DateTimeFormat; (locales?: string | string[], options?: DateTimeFormatOptions): DateTimeFormat; supportedLocalesOf(locales: string | string[], options?: DateTimeFormatOptions): string[]; }; diff --git a/src/server/client.ts b/src/server/client.ts index aca52422e44..2cfe32f521a 100644 --- a/src/server/client.ts +++ b/src/server/client.ts @@ -719,20 +719,49 @@ namespace ts.server { return response.body; } - getRefactorCodeActions( + getEditsForRefactor( fileName: string, _formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, - refactorName: string) { + refactorName: string, + actionName: string): RefactorEditInfo { - const args = this.createFileLocationOrRangeRequestArgs(positionOrRange, fileName) as protocol.GetRefactorCodeActionsRequestArgs; - args.refactorName = refactorName; + const args = this.createFileLocationOrRangeRequestArgs(positionOrRange, fileName) as protocol.GetEditsForRefactorRequestArgs; + args.refactor = refactorName; + args.action = actionName; - const request = this.processRequest(CommandNames.GetRefactorCodeActions, args); - const response = this.processResponse(request); - const codeActions = response.body.actions; + const request = this.processRequest(CommandNames.GetEditsForRefactor, args); + const response = this.processResponse(request); - return map(codeActions, codeAction => this.convertCodeActions(codeAction, fileName)); + if (!response.body) { + return { + edits: [] + }; + } + + const edits: FileTextChanges[] = this.convertCodeEditsToTextChanges(response.body.edits); + + const renameFilename: string | undefined = response.body.renameFilename; + let renameLocation: number | undefined = undefined; + if (renameFilename !== undefined) { + renameLocation = this.lineOffsetToPosition(renameFilename, response.body.renameLocation); + } + + return { + edits, + renameFilename, + renameLocation + }; + } + + private convertCodeEditsToTextChanges(edits: ts.server.protocol.FileCodeEdits[]): FileTextChanges[] { + return edits.map(edit => { + const fileName = edit.fileName; + return { + fileName, + textChanges: edit.textChanges.map(t => this.convertTextChangeToCodeEdit(t, fileName)) + }; + }); } convertCodeActions(entry: protocol.CodeAction, fileName: string): CodeAction { diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 7c0e0a0fb92..dd58935119b 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -37,6 +37,8 @@ namespace ts.server { } export interface ProjectInfoTelemetryEventData { + /** Cryptographically secure hash of project file location. */ + readonly projectId: string; /** Count of file extensions seen in the project. */ readonly fileStats: FileStats; /** @@ -1049,6 +1051,7 @@ namespace ts.server { if (!this.eventHandler) return; const data: ProjectInfoTelemetryEventData = { + projectId: this.host.createHash(projectKey), fileStats: countEachFileTypes(project.getScriptInfos()), compilerOptions: convertCompilerOptionsForTelemetry(project.getCompilerOptions()), typeAcquisition: convertTypeAcquisition(project.getTypeAcquisition()), diff --git a/src/server/project.ts b/src/server/project.ts index 0646497acc5..65933b2e1bd 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -25,7 +25,7 @@ namespace ts.server { result.jsx += 1; break; case ScriptKind.TS: - fileExtensionIs(info.fileName, ".d.ts") + fileExtensionIs(info.fileName, Extension.Dts) ? result.dts += 1 : result.ts += 1; break; @@ -106,6 +106,7 @@ namespace ts.server { private rootFiles: ScriptInfo[] = []; private rootFilesMap: FileMap = createFileMap(); private program: ts.Program; + private externalFiles: SortedReadonlyArray; private cachedUnresolvedImportsPerFile = new UnresolvedImportsMap(); private lastCachedUnresolvedImportsList: SortedReadonlyArray; @@ -261,8 +262,8 @@ namespace ts.server { abstract getProjectRootPath(): string | undefined; abstract getTypeAcquisition(): TypeAcquisition; - getExternalFiles(): string[] { - return []; + getExternalFiles(): SortedReadonlyArray { + return emptyArray as SortedReadonlyArray; } getSourceFile(path: Path) { @@ -561,6 +562,24 @@ namespace ts.server { } } } + + const oldExternalFiles = this.externalFiles || emptyArray as SortedReadonlyArray; + this.externalFiles = this.getExternalFiles(); + enumerateInsertsAndDeletes(this.externalFiles, oldExternalFiles, + // Ensure a ScriptInfo is created for new external files. This is performed indirectly + // by the LSHost for files in the program when the program is retrieved above but + // the program doesn't contain external files so this must be done explicitly. + inserted => { + const scriptInfo = this.projectService.getOrCreateScriptInfo(inserted, /*openedByClient*/ false); + scriptInfo.attachToProject(this); + }, + removed => { + const scriptInfoToDetach = this.projectService.getScriptInfo(removed); + if (scriptInfoToDetach) { + scriptInfoToDetach.detachFromProject(this); + } + }); + return hasChanges; } @@ -646,7 +665,7 @@ namespace ts.server { const added: string[] = []; const removed: string[] = []; - const updated: string[] = arrayFrom(updatedFileNames.keys()); + const updated: string[] = updatedFileNames ? arrayFrom(updatedFileNames.keys()) : []; forEachKey(currentFiles, id => { if (!lastReportedFileNames.has(id)) { @@ -956,19 +975,16 @@ namespace ts.server { return this.typeAcquisition; } - getExternalFiles(): string[] { - const items: string[] = []; - for (const plugin of this.plugins) { - if (typeof plugin.getExternalFiles === "function") { - try { - items.push(...plugin.getExternalFiles(this)); - } - catch (e) { - this.projectService.logger.info(`A plugin threw an exception in getExternalFiles: ${e}`); - } + getExternalFiles(): SortedReadonlyArray { + return toSortedReadonlyArray(flatMap(this.plugins, plugin => { + if (typeof plugin.getExternalFiles !== "function") return; + try { + return plugin.getExternalFiles(this); } - } - return items; + catch (e) { + this.projectService.logger.info(`A plugin threw an exception in getExternalFiles: ${e}`); + } + })); } watchConfigFile(callback: (project: ConfiguredProject) => void) { diff --git a/src/server/protocol.ts b/src/server/protocol.ts index 4e474edd0c4..f79774abf20 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -98,8 +98,11 @@ namespace ts.server.protocol { GetSupportedCodeFixes = "getSupportedCodeFixes", GetApplicableRefactors = "getApplicableRefactors", - GetRefactorCodeActions = "getRefactorCodeActions", - GetRefactorCodeActionsFull = "getRefactorCodeActions-full", + GetEditsForRefactor = "getEditsForRefactor", + /* @internal */ + GetEditsForRefactorFull = "getEditsForRefactor-full", + + // NOTE: If updating this, be sure to also update `allCommandNames` in `harness/unittests/session.ts`. } /** @@ -401,52 +404,98 @@ namespace ts.server.protocol { export type FileLocationOrRangeRequestArgs = FileLocationRequestArgs | FileRangeRequestArgs; + /** + * Request refactorings at a given position or selection area. + */ export interface GetApplicableRefactorsRequest extends Request { command: CommandTypes.GetApplicableRefactors; arguments: GetApplicableRefactorsRequestArgs; } - export type GetApplicableRefactorsRequestArgs = FileLocationOrRangeRequestArgs; - export interface ApplicableRefactorInfo { - name: string; - description: string; - } - + /** + * Response is a list of available refactorings. + * Each refactoring exposes one or more "Actions"; a user selects one action to invoke a refactoring + */ export interface GetApplicableRefactorsResponse extends Response { body?: ApplicableRefactorInfo[]; } - export interface GetRefactorCodeActionsRequest extends Request { - command: CommandTypes.GetRefactorCodeActions; - arguments: GetRefactorCodeActionsRequestArgs; + /** + * A set of one or more available refactoring actions, grouped under a parent refactoring. + */ + export interface ApplicableRefactorInfo { + /** + * The programmatic name of the refactoring + */ + name: string; + /** + * A description of this refactoring category to show to the user. + * If the refactoring gets inlined (see below), this text will not be visible. + */ + description: string; + /** + * Inlineable refactorings can have their actions hoisted out to the top level + * of a context menu. Non-inlineanable refactorings should always be shown inside + * their parent grouping. + * + * If not specified, this value is assumed to be 'true' + */ + inlineable?: boolean; + + actions: RefactorActionInfo[]; } - export type GetRefactorCodeActionsRequestArgs = FileLocationOrRangeRequestArgs & { - /* The kind of the applicable refactor */ - refactorName: string; + /** + * Represents a single refactoring action - for example, the "Extract Method..." refactor might + * offer several actions, each corresponding to a surround class or closure to extract into. + */ + export type RefactorActionInfo = { + /** + * The programmatic name of the refactoring action + */ + name: string; + + /** + * A description of this refactoring action to show to the user. + * If the parent refactoring is inlined away, this will be the only text shown, + * so this description should make sense by itself if the parent is inlineable=true + */ + description: string; }; - export type RefactorCodeActions = { - actions: protocol.CodeAction[]; - renameLocation?: number - }; - - /* @internal */ - export type RefactorCodeActionsFull = { - actions: ts.CodeAction[]; - renameLocation?: number - }; - - export interface GetRefactorCodeActionsResponse extends Response { - body: RefactorCodeActions; + export interface GetEditsForRefactorRequest extends Request { + command: CommandTypes.GetEditsForRefactor; + arguments: GetEditsForRefactorRequestArgs; } - /* @internal */ - export interface GetRefactorCodeActionsFullResponse extends Response { - body: RefactorCodeActionsFull; + /** + * Request the edits that a particular refactoring action produces. + * Callers must specify the name of the refactor and the name of the action. + */ + export type GetEditsForRefactorRequestArgs = FileLocationOrRangeRequestArgs & { + /* The 'name' property from the refactoring that offered this action */ + refactor: string; + /* The 'name' property from the refactoring action */ + action: string; + }; + + + export interface GetEditsForRefactorResponse extends Response { + body?: RefactorEditInfo; } + export type RefactorEditInfo = { + edits: FileCodeEdits[]; + + /** + * An optional location where the editor should start a rename operation once + * the refactoring edits have been applied + */ + renameLocation?: Location; + renameFilename?: string; + }; + /** * Request for the available codefixes at a specific position. */ diff --git a/src/server/server.ts b/src/server/server.ts index 390a0f2f6f4..5f2b7054755 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -35,6 +35,7 @@ namespace ts.server { } = require("os"); function getGlobalTypingsCacheLocation() { + const versionMajorMinor = ts.version.match(/\d+\.\d+/)[0]; switch (process.platform) { case "win32": { const basePath = process.env.LOCALAPPDATA || @@ -43,13 +44,15 @@ namespace ts.server { process.env.USERPROFILE || (process.env.HOMEDRIVE && process.env.HOMEPATH && normalizeSlashes(process.env.HOMEDRIVE + process.env.HOMEPATH)) || os.tmpdir(); - return combinePaths(normalizeSlashes(basePath), "Microsoft/TypeScript"); + return combinePaths(combinePaths(normalizeSlashes(basePath), "Microsoft/TypeScript"), versionMajorMinor); } + case "openbsd": + case "freebsd": case "darwin": case "linux": case "android": { const cacheLocation = getNonWindowsCacheLocation(process.platform === "darwin"); - return combinePaths(cacheLocation, "typescript"); + return combinePaths(combinePaths(cacheLocation, "typescript"), versionMajorMinor); } default: Debug.fail(`unsupported platform '${process.platform}'`); @@ -524,7 +527,7 @@ namespace ts.server { watchedFile.callback(watchedFile.fileName); } else if (watchedFile.mtime.getTime() !== stats.mtime.getTime()) { - watchedFile.mtime = getModifiedTime(watchedFile.fileName); + watchedFile.mtime = stats.mtime; watchedFile.callback(watchedFile.fileName, watchedFile.mtime.getTime() === 0); } }); diff --git a/src/server/session.ts b/src/server/session.ts index 6ec234952db..c06e33eb979 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -112,7 +112,13 @@ namespace ts.server { return true; } - export import CommandNames = protocol.CommandTypes; + // CommandNames used to be exposed before TS 2.4 as a namespace + // In TS 2.4 we switched to an enum, keep this for backward compatibility + // The var assignment ensures that even though CommandTypes are a const enum + // we want to ensure the value is maintained in the out since the file is + // built using --preseveConstEnum. + export type CommandNames = protocol.CommandTypes; + export const CommandNames = (protocol).CommandTypes; export function formatMessage(msg: T, logger: server.Logger, byteLength: (s: string, encoding: string) => number, newLine: string): string { const verboseLogging = logger.hasLevel(LogLevel.verbose); @@ -1425,29 +1431,40 @@ namespace ts.server { return project.getLanguageService().getApplicableRefactors(file, position || textRange); } - private getRefactorCodeActions(args: protocol.GetRefactorCodeActionsRequestArgs, simplifiedResult: boolean): protocol.RefactorCodeActions | protocol.RefactorCodeActionsFull { + private getEditsForRefactor(args: protocol.GetEditsForRefactorRequestArgs, simplifiedResult: boolean): ts.RefactorEditInfo | protocol.RefactorEditInfo { const { file, project } = this.getFileAndProjectWithoutRefreshingInferredProjects(args); const scriptInfo = project.getScriptInfoForNormalizedPath(file); const { position, textRange } = this.extractPositionAndRange(args, scriptInfo); - const result: ts.CodeAction[] = project.getLanguageService().getRefactorCodeActions( + const result = project.getLanguageService().getEditsForRefactor( file, this.projectService.getFormatCodeOptions(), position || textRange, - args.refactorName + args.refactor, + args.action ); - if (simplifiedResult) { - // Not full + if (result === undefined) { return { - actions: result.map(action => this.mapCodeAction(action, scriptInfo)) + edits: [] + }; + } + + if (simplifiedResult) { + const file = result.renameFilename; + let location: ILineInfo | undefined = undefined; + if (file !== undefined && result.renameLocation !== undefined) { + const renameScriptInfo = project.getScriptInfoForNormalizedPath(toNormalizedPath(file)); + location = renameScriptInfo.positionToLineOffset(result.renameLocation); + } + return { + renameLocation: location, + renameFilename: file, + edits: result.edits.map(change => this.mapTextChangesToCodeEdits(project, change)) }; } else { - // Full - return { - actions: result - }; + return result; } } @@ -1505,6 +1522,14 @@ namespace ts.server { }; } + private mapTextChangesToCodeEdits(project: Project, textChanges: FileTextChanges): protocol.FileCodeEdits { + const scriptInfo = project.getScriptInfoForNormalizedPath(toNormalizedPath(textChanges.fileName)); + return { + fileName: textChanges.fileName, + textChanges: textChanges.textChanges.map(textChange => this.convertTextChangeToCodeEdit(textChange, scriptInfo)) + }; + } + private convertTextChangeToCodeEdit(change: ts.TextChange, scriptInfo: ScriptInfo): protocol.CodeEdit { return { start: scriptInfo.positionToLineOffset(change.span.start), @@ -1544,18 +1569,22 @@ namespace ts.server { const normalizedFileName = toNormalizedPath(fileName); const project = this.projectService.getDefaultProjectForFile(normalizedFileName, /*refreshInferredProjects*/ true); for (const fileNameInProject of fileNamesInProject) { - if (this.getCanonicalFileName(fileNameInProject) === this.getCanonicalFileName(fileName)) + if (this.getCanonicalFileName(fileNameInProject) === this.getCanonicalFileName(fileName)) { highPriorityFiles.push(fileNameInProject); + } else { const info = this.projectService.getScriptInfo(fileNameInProject); if (!info.isScriptOpen()) { - if (fileNameInProject.indexOf(".d.ts") > 0) + if (fileNameInProject.indexOf(Extension.Dts) > 0) { veryLowPriorityFiles.push(fileNameInProject); - else + } + else { lowPriorityFiles.push(fileNameInProject); + } } - else + else { mediumPriorityFiles.push(fileNameInProject); + } } } @@ -1833,11 +1862,11 @@ namespace ts.server { [CommandNames.GetApplicableRefactors]: (request: protocol.GetApplicableRefactorsRequest) => { return this.requiredResponse(this.getApplicableRefactors(request.arguments)); }, - [CommandNames.GetRefactorCodeActions]: (request: protocol.GetRefactorCodeActionsRequest) => { - return this.requiredResponse(this.getRefactorCodeActions(request.arguments, /*simplifiedResult*/ true)); + [CommandNames.GetEditsForRefactor]: (request: protocol.GetEditsForRefactorRequest) => { + return this.requiredResponse(this.getEditsForRefactor(request.arguments, /*simplifiedResult*/ true)); }, - [CommandNames.GetRefactorCodeActionsFull]: (request: protocol.GetRefactorCodeActionsRequest) => { - return this.requiredResponse(this.getRefactorCodeActions(request.arguments, /*simplifiedResult*/ false)); + [CommandNames.GetEditsForRefactorFull]: (request: protocol.GetEditsForRefactorRequest) => { + return this.requiredResponse(this.getEditsForRefactor(request.arguments, /*simplifiedResult*/ false)); } }); diff --git a/src/server/utilities.ts b/src/server/utilities.ts index 093958b60c5..9e492601430 100644 --- a/src/server/utilities.ts +++ b/src/server/utilities.ts @@ -195,6 +195,37 @@ namespace ts.server { return arr; } + export function enumerateInsertsAndDeletes(a: SortedReadonlyArray, b: SortedReadonlyArray, inserted: (item: T) => void, deleted: (item: T) => void, compare?: (a: T, b: T) => Comparison) { + compare = compare || ts.compareValues; + let aIndex = 0; + let bIndex = 0; + const aLen = a.length; + const bLen = b.length; + while (aIndex < aLen && bIndex < bLen) { + const aItem = a[aIndex]; + const bItem = b[bIndex]; + const compareResult = compare(aItem, bItem); + if (compareResult === Comparison.LessThan) { + inserted(aItem); + aIndex++; + } + else if (compareResult === Comparison.GreaterThan) { + deleted(bItem); + bIndex++; + } + else { + aIndex++; + bIndex++; + } + } + while (aIndex < aLen) { + inserted(a[aIndex++]); + } + while (bIndex < bLen) { + deleted(b[bIndex++]); + } + } + export class ThrottledOperations { private pendingTimeouts: Map = createMap(); constructor(private readonly host: ServerHost) { diff --git a/src/services/breakpoints.ts b/src/services/breakpoints.ts index 38da43bdee8..37aa8df0ca1 100644 --- a/src/services/breakpoints.ts +++ b/src/services/breakpoints.ts @@ -146,7 +146,7 @@ namespace ts.BreakpointResolver { case SyntaxKind.ForOfStatement: // span in initializer - return spanInInitializerOfForLike(node); + return spanInInitializerOfForLike(node); case SyntaxKind.SwitchStatement: // span on switch(...) diff --git a/src/services/classifier.ts b/src/services/classifier.ts index beeddda434e..ff33059630d 100644 --- a/src/services/classifier.ts +++ b/src/services/classifier.ts @@ -724,8 +724,8 @@ namespace ts { pushCommentRange(pos, tag.pos - pos); } - pushClassification(tag.atToken.pos, tag.atToken.end - tag.atToken.pos, ClassificationType.punctuation); - pushClassification(tag.tagName.pos, tag.tagName.end - tag.tagName.pos, ClassificationType.docCommentTagName); + pushClassification(tag.atToken.pos, tag.atToken.end - tag.atToken.pos, ClassificationType.punctuation); // "@" + pushClassification(tag.tagName.pos, tag.tagName.end - tag.tagName.pos, ClassificationType.docCommentTagName); // e.g. "param" pos = tag.tagName.end; @@ -814,7 +814,7 @@ namespace ts { * False will mean that node is not classified and traverse routine should recurse into node contents. */ function tryClassifyNode(node: Node): boolean { - if (isJSDocTag(node)) { + if (isJSDoc(node)) { return true; } diff --git a/src/services/codefixes/fixAddMissingMember.ts b/src/services/codefixes/fixAddMissingMember.ts index 64e7e560094..1587b47c01b 100644 --- a/src/services/codefixes/fixAddMissingMember.ts +++ b/src/services/codefixes/fixAddMissingMember.ts @@ -8,107 +8,161 @@ namespace ts.codefix { function getActionsForAddMissingMember(context: CodeFixContext): CodeAction[] | undefined { - const sourceFile = context.sourceFile; + const tokenSourceFile = context.sourceFile; const start = context.span.start; - // This is the identifier of the missing property. eg: + // The identifier of the missing property. eg: // this.missing = 1; // ^^^^^^^ - const token = getTokenAtPosition(sourceFile, start, /*includeJsDocComment*/ false); + const token = getTokenAtPosition(tokenSourceFile, start, /*includeJsDocComment*/ false); if (token.kind !== SyntaxKind.Identifier) { return undefined; } - if (!isPropertyAccessExpression(token.parent) || token.parent.expression.kind !== SyntaxKind.ThisKeyword) { + if (!isPropertyAccessExpression(token.parent)) { return undefined; } - const classMemberDeclaration = getThisContainer(token, /*includeArrowFunctions*/ false); - if (!isClassElement(classMemberDeclaration)) { - return undefined; + const tokenName = token.getText(tokenSourceFile); + + let makeStatic = false; + let classDeclaration: ClassLikeDeclaration; + + if (token.parent.expression.kind === SyntaxKind.ThisKeyword) { + const containingClassMemberDeclaration = getThisContainer(token, /*includeArrowFunctions*/ false); + if (!isClassElement(containingClassMemberDeclaration)) { + return undefined; + } + + classDeclaration = containingClassMemberDeclaration.parent; + + // Property accesses on `this` in a static method are accesses of a static member. + makeStatic = classDeclaration && hasModifier(containingClassMemberDeclaration, ModifierFlags.Static); + } + else { + + const checker = context.program.getTypeChecker(); + const leftExpression = token.parent.expression; + const leftExpressionType = checker.getTypeAtLocation(leftExpression); + + if (leftExpressionType.flags & TypeFlags.Object) { + const symbol = leftExpressionType.symbol; + if (symbol.flags & SymbolFlags.Class) { + classDeclaration = symbol.declarations && symbol.declarations[0]; + if (leftExpressionType !== checker.getDeclaredTypeOfSymbol(symbol)) { + // The expression is a class symbol but the type is not the instance-side. + makeStatic = true; + } + } + } } - const classDeclaration = classMemberDeclaration.parent; if (!classDeclaration || !isClassLike(classDeclaration)) { return undefined; } - const isStatic = hasModifier(classMemberDeclaration, ModifierFlags.Static); + const classDeclarationSourceFile = getSourceFileOfNode(classDeclaration); + const classOpenBrace = getOpenBraceOfClassLike(classDeclaration, classDeclarationSourceFile); - return isInJavaScriptFile(sourceFile) ? getActionsForAddMissingMemberInJavaScriptFile() : getActionsForAddMissingMemberInTypeScriptFile(); + return isInJavaScriptFile(classDeclarationSourceFile) ? + getActionsForAddMissingMemberInJavaScriptFile(classDeclaration, makeStatic) : + getActionsForAddMissingMemberInTypeScriptFile(classDeclaration, makeStatic); - function getActionsForAddMissingMemberInJavaScriptFile(): CodeAction[] | undefined { - const memberName = token.getText(); + function getActionsForAddMissingMemberInJavaScriptFile(classDeclaration: ClassLikeDeclaration, makeStatic: boolean): CodeAction[] | undefined { + let actions: CodeAction[]; - if (isStatic) { + const methodCodeAction = getActionForMethodDeclaration(/*includeTypeScriptSyntax*/ false); + if (methodCodeAction) { + actions = [methodCodeAction]; + } + + if (makeStatic) { if (classDeclaration.kind === SyntaxKind.ClassExpression) { - return undefined; + return actions; } const className = classDeclaration.name.getText(); - return [{ - description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Initialize_static_property_0), [memberName]), - changes: [{ - fileName: sourceFile.fileName, - textChanges: [{ - span: { start: classDeclaration.getEnd(), length: 0 }, - newText: `${context.newLineCharacter}${className}.${memberName} = undefined;${context.newLineCharacter}` - }] - }] - }]; + const staticInitialization = createStatement(createAssignment( + createPropertyAccess(createIdentifier(className), tokenName), + createIdentifier("undefined"))); + const staticInitializationChangeTracker = textChanges.ChangeTracker.fromCodeFixContext(context); + staticInitializationChangeTracker.insertNodeAfter( + classDeclarationSourceFile, + classDeclaration, + staticInitialization, + { suffix: context.newLineCharacter }); + const initializeStaticAction = { + description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Initialize_static_property_0), [tokenName]), + changes: staticInitializationChangeTracker.getChanges() + }; + + (actions || (actions = [])).push(initializeStaticAction); + return actions; } else { const classConstructor = getFirstConstructorWithBody(classDeclaration); if (!classConstructor) { - return undefined; + return actions; } - return [{ - description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Initialize_property_0_in_the_constructor), [memberName]), - changes: [{ - fileName: sourceFile.fileName, - textChanges: [{ - span: { start: classConstructor.body.getEnd() - 1, length: 0 }, - newText: `this.${memberName} = undefined;${context.newLineCharacter}` - }] - }] - }]; + const propertyInitialization = createStatement(createAssignment( + createPropertyAccess(createThis(), tokenName), + createIdentifier("undefined"))); + + const propertyInitializationChangeTracker = textChanges.ChangeTracker.fromCodeFixContext(context); + propertyInitializationChangeTracker.insertNodeAt( + classDeclarationSourceFile, + classConstructor.body.getEnd() - 1, + propertyInitialization, + { prefix: context.newLineCharacter, suffix: context.newLineCharacter }); + + const initializeAction = { + description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Initialize_property_0_in_the_constructor), [tokenName]), + changes: propertyInitializationChangeTracker.getChanges() + }; + + (actions || (actions = [])).push(initializeAction); + return actions; } } - function getActionsForAddMissingMemberInTypeScriptFile(): CodeAction[] | undefined { - let typeNode: TypeNode; + function getActionsForAddMissingMemberInTypeScriptFile(classDeclaration: ClassLikeDeclaration, makeStatic: boolean): CodeAction[] | undefined { + let actions: CodeAction[]; - if (token.parent.parent.kind === SyntaxKind.BinaryExpression) { - const binaryExpression = token.parent.parent as BinaryExpression; - - const checker = context.program.getTypeChecker(); - const widenedType = checker.getWidenedType(checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(binaryExpression.right))); - typeNode = checker.typeToTypeNode(widenedType, classDeclaration); + const methodCodeAction = getActionForMethodDeclaration(/*includeTypeScriptSyntax*/ true); + if (methodCodeAction) { + actions = [methodCodeAction]; } + let typeNode: TypeNode; + if (token.parent.parent.kind === SyntaxKind.BinaryExpression) { + const binaryExpression = token.parent.parent as BinaryExpression; + const otherExpression = token.parent === binaryExpression.left ? binaryExpression.right : binaryExpression.left; + const checker = context.program.getTypeChecker(); + const widenedType = checker.getWidenedType(checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(otherExpression))); + typeNode = checker.typeToTypeNode(widenedType, classDeclaration); + } typeNode = typeNode || createKeywordTypeNode(SyntaxKind.AnyKeyword); - const openBrace = getOpenBraceOfClassLike(classDeclaration, sourceFile); - const property = createProperty( /*decorators*/undefined, - /*modifiers*/ isStatic ? [createToken(SyntaxKind.StaticKeyword)] : undefined, - token.getText(sourceFile), + /*modifiers*/ makeStatic ? [createToken(SyntaxKind.StaticKeyword)] : undefined, + tokenName, /*questionToken*/ undefined, typeNode, /*initializer*/ undefined); const propertyChangeTracker = textChanges.ChangeTracker.fromCodeFixContext(context); - propertyChangeTracker.insertNodeAfter(sourceFile, openBrace, property, { suffix: context.newLineCharacter }); + propertyChangeTracker.insertNodeAfter(classDeclarationSourceFile, classOpenBrace, property, { suffix: context.newLineCharacter }); - const actions = [{ - description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Add_declaration_for_missing_property_0), [token.getText()]), + (actions || (actions = [])).push({ + description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Declare_property_0), [tokenName]), changes: propertyChangeTracker.getChanges() - }]; + }); - if (!isStatic) { + if (!makeStatic) { + // Index signatures cannot have the static modifier. const stringTypeNode = createKeywordTypeNode(SyntaxKind.StringKeyword); const indexingParameter = createParameter( /*decorators*/ undefined, @@ -125,15 +179,32 @@ namespace ts.codefix { typeNode); const indexSignatureChangeTracker = textChanges.ChangeTracker.fromCodeFixContext(context); - indexSignatureChangeTracker.insertNodeAfter(sourceFile, openBrace, indexSignature, { suffix: context.newLineCharacter }); + indexSignatureChangeTracker.insertNodeAfter(classDeclarationSourceFile, classOpenBrace, indexSignature, { suffix: context.newLineCharacter }); actions.push({ - description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Add_index_signature_for_missing_property_0), [token.getText()]), + description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Add_index_signature_for_property_0), [tokenName]), changes: indexSignatureChangeTracker.getChanges() }); } return actions; } + + function getActionForMethodDeclaration(includeTypeScriptSyntax: boolean): CodeAction | undefined { + if (token.parent.parent.kind === SyntaxKind.CallExpression) { + const callExpression = token.parent.parent; + const methodDeclaration = createMethodFromCallExpression(callExpression, tokenName, includeTypeScriptSyntax, makeStatic); + + const methodDeclarationChangeTracker = textChanges.ChangeTracker.fromCodeFixContext(context); + methodDeclarationChangeTracker.insertNodeAfter(classDeclarationSourceFile, classOpenBrace, methodDeclaration, { suffix: context.newLineCharacter }); + return { + description: formatStringFromArgs(getLocaleSpecificMessage(makeStatic ? + Diagnostics.Declare_method_0 : + Diagnostics.Declare_static_method_0), + [tokenName]), + changes: methodDeclarationChangeTracker.getChanges() + }; + } + } } } diff --git a/src/services/codefixes/helpers.ts b/src/services/codefixes/helpers.ts index 39d8e13dde9..81aae4c0e5e 100644 --- a/src/services/codefixes/helpers.ts +++ b/src/services/codefixes/helpers.ts @@ -142,6 +142,50 @@ namespace ts.codefix { } } + export function createMethodFromCallExpression(callExpression: CallExpression, methodName: string, includeTypeScriptSyntax: boolean, makeStatic: boolean): MethodDeclaration { + const parameters = createDummyParameters(callExpression.arguments.length, /*names*/ undefined, /*minArgumentCount*/ undefined, includeTypeScriptSyntax); + + let typeParameters: TypeParameterDeclaration[]; + if (includeTypeScriptSyntax) { + const typeArgCount = length(callExpression.typeArguments); + for (let i = 0; i < typeArgCount; i++) { + const name = typeArgCount < 8 ? String.fromCharCode(CharacterCodes.T + i) : `T${i}`; + const typeParameter = createTypeParameterDeclaration(name, /*constraint*/ undefined, /*defaultType*/ undefined); + (typeParameters ? typeParameters : typeParameters = []).push(typeParameter); + } + } + + const newMethod = createMethod( + /*decorators*/ undefined, + /*modifiers*/ makeStatic ? [createToken(SyntaxKind.StaticKeyword)] : undefined, + /*asteriskToken*/ undefined, + methodName, + /*questionToken*/ undefined, + typeParameters, + parameters, + /*type*/ includeTypeScriptSyntax ? createKeywordTypeNode(SyntaxKind.AnyKeyword) : undefined, + createStubbedMethodBody() + ); + return newMethod; + } + + function createDummyParameters(argCount: number, names: string[] | undefined, minArgumentCount: number | undefined, addAnyType: boolean) { + const parameters: ParameterDeclaration[] = []; + for (let i = 0; i < argCount; i++) { + const newParameter = createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, + /*name*/ names && names[i] || `arg${i}`, + /*questionToken*/ minArgumentCount !== undefined && i >= minArgumentCount ? createToken(SyntaxKind.QuestionToken) : undefined, + /*type*/ addAnyType ? createKeywordTypeNode(SyntaxKind.AnyKeyword) : undefined, + /*initializer*/ undefined); + parameters.push(newParameter); + } + + return parameters; + } + function createMethodImplementingSignatures(signatures: Signature[], name: PropertyName, optional: boolean, modifiers: Modifier[] | undefined): MethodDeclaration { /** This is *a* signature with the maximal number of arguments, * such that if there is a "maximal" signature without rest arguments, @@ -163,19 +207,7 @@ namespace ts.codefix { const maxNonRestArgs = maxArgsSignature.parameters.length - (maxArgsSignature.hasRestParameter ? 1 : 0); const maxArgsParameterSymbolNames = maxArgsSignature.parameters.map(symbol => symbol.getName()); - const parameters: ParameterDeclaration[] = []; - for (let i = 0; i < maxNonRestArgs; i++) { - const anyType = createKeywordTypeNode(SyntaxKind.AnyKeyword); - const newParameter = createParameter( - /*decorators*/ undefined, - /*modifiers*/ undefined, - /*dotDotDotToken*/ undefined, - maxArgsParameterSymbolNames[i], - /*questionToken*/ i >= minArgumentCount ? createToken(SyntaxKind.QuestionToken) : undefined, - anyType, - /*initializer*/ undefined); - parameters.push(newParameter); - } + const parameters = createDummyParameters(maxNonRestArgs, maxArgsParameterSymbolNames, minArgumentCount, /*addAnyType*/ true); if (someSigHasRestParameter) { const anyArrayType = createArrayTypeNode(createKeywordTypeNode(SyntaxKind.AnyKeyword)); diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index 53ec99fac81..c2d26da4392 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -138,8 +138,23 @@ namespace ts.codefix { const currentTokenMeaning = getMeaningFromLocation(token); if (context.errorCode === Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead.code) { - const symbol = checker.getAliasedSymbol(checker.getSymbolAtLocation(token)); - return getCodeActionForImport(symbol, /*isDefault*/ false, /*isNamespaceImport*/ true); + const umdSymbol = checker.getSymbolAtLocation(token); + let symbol: ts.Symbol; + let symbolName: string; + if (umdSymbol.flags & ts.SymbolFlags.Alias) { + symbol = checker.getAliasedSymbol(umdSymbol); + symbolName = name; + } + else if (isJsxOpeningLikeElement(token.parent) && token.parent.tagName === token) { + // The error wasn't for the symbolAtLocation, it was for the JSX tag itself, which needs access to e.g. `React`. + symbol = checker.getAliasedSymbol(checker.resolveNameAtLocation(token, checker.getJsxNamespace(), SymbolFlags.Value)); + symbolName = symbol.name; + } + else { + Debug.fail("Either the symbol or the JSX namespace should be a UMD global if we got here"); + } + + return getCodeActionForImport(symbol, symbolName, /*isDefault*/ false, /*isNamespaceImport*/ true); } const candidateModules = checker.getAmbientModules(); @@ -159,7 +174,7 @@ namespace ts.codefix { if (localSymbol && localSymbol.name === name && checkSymbolHasMeaning(localSymbol, currentTokenMeaning)) { // check if this symbol is already used const symbolId = getUniqueSymbolId(localSymbol); - symbolIdActionMap.addActions(symbolId, getCodeActionForImport(moduleSymbol, /*isDefault*/ true)); + symbolIdActionMap.addActions(symbolId, getCodeActionForImport(moduleSymbol, name, /*isDefault*/ true)); } } @@ -167,7 +182,7 @@ namespace ts.codefix { const exportSymbolWithIdenticalName = checker.tryGetMemberInModuleExports(name, moduleSymbol); if (exportSymbolWithIdenticalName && checkSymbolHasMeaning(exportSymbolWithIdenticalName, currentTokenMeaning)) { const symbolId = getUniqueSymbolId(exportSymbolWithIdenticalName); - symbolIdActionMap.addActions(symbolId, getCodeActionForImport(moduleSymbol)); + symbolIdActionMap.addActions(symbolId, getCodeActionForImport(moduleSymbol, name)); } } @@ -218,7 +233,7 @@ namespace ts.codefix { return declarations ? some(symbol.declarations, decl => !!(getMeaningFromDeclaration(decl) & meaning)) : false; } - function getCodeActionForImport(moduleSymbol: Symbol, isDefault?: boolean, isNamespaceImport?: boolean): ImportCodeAction[] { + function getCodeActionForImport(moduleSymbol: Symbol, symbolName: string, isDefault?: boolean, isNamespaceImport?: boolean): ImportCodeAction[] { const existingDeclarations = getImportDeclarations(moduleSymbol); if (existingDeclarations.length > 0) { // With an existing import statement, there are more than one actions the user can do. @@ -375,10 +390,10 @@ namespace ts.codefix { const moduleSpecifierWithoutQuotes = stripQuotes(moduleSpecifier || getModuleSpecifierForNewImport()); const changeTracker = createChangeTracker(); const importClause = isDefault - ? createImportClause(createIdentifier(name), /*namedBindings*/ undefined) + ? createImportClause(createIdentifier(symbolName), /*namedBindings*/ undefined) : isNamespaceImport - ? createImportClause(/*name*/ undefined, createNamespaceImport(createIdentifier(name))) - : createImportClause(/*name*/ undefined, createNamedImports([createImportSpecifier(/*propertyName*/ undefined, createIdentifier(name))])); + ? createImportClause(/*name*/ undefined, createNamespaceImport(createIdentifier(symbolName))) + : createImportClause(/*name*/ undefined, createNamedImports([createImportSpecifier(/*propertyName*/ undefined, createIdentifier(symbolName))])); const importDecl = createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, importClause, createLiteral(moduleSpecifierWithoutQuotes)); if (!lastImportDeclaration) { changeTracker.insertNodeAt(sourceFile, sourceFile.getStart(), importDecl, { suffix: `${context.newLineCharacter}${context.newLineCharacter}` }); @@ -392,7 +407,7 @@ namespace ts.codefix { // are there are already a new line seperating code and import statements. return createCodeAction( Diagnostics.Import_0_from_1, - [name, `"${moduleSpecifierWithoutQuotes}"`], + [symbolName, `"${moduleSpecifierWithoutQuotes}"`], changeTracker.getChanges(), "NewImport", moduleSpecifierWithoutQuotes @@ -412,8 +427,9 @@ namespace ts.codefix { removeFileExtension(getRelativePath(moduleFileName, sourceDirectory)); function tryGetModuleNameFromAmbientModule(): string { - if (moduleSymbol.valueDeclaration.kind !== SyntaxKind.SourceFile) { - return moduleSymbol.name; + const decl = moduleSymbol.valueDeclaration; + if (isModuleDeclaration(decl) && isStringLiteral(decl.name)) { + return decl.name.text; } } diff --git a/src/services/completions.ts b/src/services/completions.ts index 8b11eb74e61..6f1f3fae1ea 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -18,16 +18,33 @@ namespace ts.Completions { return undefined; } - const { symbols, isGlobalCompletion, isMemberCompletion, isNewIdentifierLocation, location, requestJsDocTagName, requestJsDocTag, hasFilteredClassMemberKeywords } = completionData; + const { symbols, isGlobalCompletion, isMemberCompletion, isNewIdentifierLocation, location, request, hasFilteredClassMemberKeywords } = completionData; - 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.getJSDocTagNameCompletions() }; + if (sourceFile.languageVariant === LanguageVariant.JSX && + location && location.parent && location.parent.kind === SyntaxKind.JsxClosingElement) { + // In the TypeScript JSX element, if such element is not defined. When users query for completion at closing tag, + // instead of simply giving unknown value, the completion will return the tag-name of an associated opening-element. + // For example: + // var x =
completion list at "1" will contain "div" with type any + const tagName = (location.parent.parent).openingElement.tagName; + return { isGlobalCompletion: false, isMemberCompletion: true, isNewIdentifierLocation: false, + entries: [{ + name: (tagName).getFullText(), + kind: ScriptElementKind.classElement, + kindModifiers: undefined, + sortText: "0", + }]}; } - 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() }; + if (request) { + const entries = request.kind === "JsDocTagName" + // If the current position is a jsDoc tag name, only tag names should be provided for completion + ? JsDoc.getJSDocTagNameCompletions() + : request.kind === "JsDocTag" + // If the current position is a jsDoc tag, only tags should be provided for completion + ? JsDoc.getJSDocTagCompletions() + : JsDoc.getJSDocParameterNameCompletions(request.tag); + return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, entries }; } const entries: CompletionEntry[] = []; @@ -38,21 +55,7 @@ namespace ts.Completions { } else { if (!symbols || symbols.length === 0) { - if (sourceFile.languageVariant === LanguageVariant.JSX && - location.parent && location.parent.kind === SyntaxKind.JsxClosingElement) { - // In the TypeScript JSX element, if such element is not defined. When users query for completion at closing tag, - // instead of simply giving unknown value, the completion will return the tag-name of an associated opening-element. - // For example: - // var x =
completion list at "1" will contain "div" with type any - const tagName = (location.parent.parent).openingElement.tagName; - entries.push({ - name: (tagName).text, - kind: undefined, - kindModifiers: undefined, - sortText: "0", - }); - } - else if (!hasFilteredClassMemberKeywords) { + if (!hasFilteredClassMemberKeywords) { return undefined; } } @@ -64,7 +67,7 @@ namespace ts.Completions { addRange(entries, classMemberKeywordCompletions); } // Add keywords if this is not a member completion list - else if (!isMemberCompletion && !requestJsDocTag && !requestJsDocTagName) { + else if (!isMemberCompletion) { addRange(entries, keywordCompletions); } @@ -345,16 +348,27 @@ namespace ts.Completions { return undefined; } - function getCompletionData(typeChecker: TypeChecker, log: (message: string) => void, sourceFile: SourceFile, position: number) { + interface CompletionData { + symbols: Symbol[]; + isGlobalCompletion: boolean; + isMemberCompletion: boolean; + isNewIdentifierLocation: boolean; + location: Node; + isRightOfDot: boolean; + request?: Request; + hasFilteredClassMemberKeywords: boolean; + } + type Request = { kind: "JsDocTagName" } | { kind: "JsDocTag" } | { kind: "JsDocParameterName", tag: JSDocParameterTag }; + + function getCompletionData(typeChecker: TypeChecker, log: (message: string) => void, sourceFile: SourceFile, position: number): CompletionData { const isJavaScriptFile = isSourceFileJavaScript(sourceFile); - // 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 request: Request | undefined; let start = timestamp(); let currentToken = getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false); // TODO: GH#15853 + // We will check for jsdoc comments with insideComment and getJsDocTagAtPosition. (TODO: that seems rather inefficient to check the same thing so many times.) + log("getCompletionData: Get current token: " + (timestamp() - start)); start = timestamp(); @@ -365,10 +379,10 @@ namespace ts.Completions { let insideJsDocTagTypeExpression = false; if (insideComment) { 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; + // The current position is next to the '@' sign, when no tag name being provided yet. + // Provide a full list of tag names + request = { kind: "JsDocTagName" }; } else { // When completion is requested without "@", we will have check to make sure that @@ -388,17 +402,19 @@ namespace ts.Completions { // * |c| // */ const lineStart = getLineStartPositionForPosition(position, sourceFile); - requestJsDocTag = !(sourceFile.text.substring(lineStart, position).match(/[^\*|\s|(/\*\*)]/)); + if (!(sourceFile.text.substring(lineStart, position).match(/[^\*|\s|(/\*\*)]/))) { + request = { kind: "JsDocTag" }; + } } } // Completion should work inside certain JsDoc tags. For example: // /** @type {number | string} */ // Completion should work in the brackets - const tag = getJsDocTagAtPosition(sourceFile, position); + const tag = getJsDocTagAtPosition(currentToken, position); if (tag) { if (tag.tagName.pos <= position && position <= tag.tagName.end) { - requestJsDocTagName = true; + request = { kind: "JsDocTagName" }; } if (isTagWithTypeExpression(tag) && tag.typeExpression) { currentToken = getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ true); @@ -410,10 +426,13 @@ namespace ts.Completions { insideJsDocTagTypeExpression = isCurrentlyEditingNode(tag.typeExpression); } } + if (isJSDocParameterTag(tag) && (nodeIsMissing(tag.name) || tag.name.pos <= position && position <= tag.name.end)) { + request = { kind: "JsDocParameterName", tag }; + } } - if (requestJsDocTagName || requestJsDocTag) { - return { symbols: undefined, isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, location: undefined, isRightOfDot: false, requestJsDocTagName, requestJsDocTag, hasFilteredClassMemberKeywords: false }; + if (request) { + return { symbols: undefined, isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, location: undefined, isRightOfDot: false, request, hasFilteredClassMemberKeywords: false }; } if (!insideJsDocTagTypeExpression) { @@ -494,7 +513,7 @@ namespace ts.Completions { // It has a left-hand side, so we're not in an opening JSX tag. break; } - // falls through + // falls through case SyntaxKind.JsxSelfClosingElement: case SyntaxKind.JsxElement: @@ -550,7 +569,7 @@ namespace ts.Completions { log("getCompletionData: Semantic work: " + (timestamp() - semanticStart)); - return { symbols, isGlobalCompletion, isMemberCompletion, isNewIdentifierLocation, location, isRightOfDot: (isRightOfDot || isRightOfOpenTag), requestJsDocTagName, requestJsDocTag, hasFilteredClassMemberKeywords }; + return { symbols, isGlobalCompletion, isMemberCompletion, isNewIdentifierLocation, location, isRightOfDot: (isRightOfDot || isRightOfOpenTag), request, hasFilteredClassMemberKeywords }; type JSDocTagWithTypeExpression = JSDocAugmentsTag | JSDocParameterTag | JSDocPropertyTag | JSDocReturnTag | JSDocTypeTag | JSDocTypedefTag; @@ -923,7 +942,7 @@ namespace ts.Completions { * * @returns true if 'symbols' was successfully populated; false otherwise. */ - function tryGetObjectLikeCompletionSymbols(objectLikeContainer: ObjectLiteralExpression | BindingPattern): boolean { + function tryGetObjectLikeCompletionSymbols(objectLikeContainer: ObjectLiteralExpression | ObjectBindingPattern): boolean { // We're looking up possible property names from contextual/inferred/declared type. isMemberCompletion = true; @@ -939,41 +958,36 @@ namespace ts.Completions { typeMembers = typeChecker.getAllPossiblePropertiesOfType(typeForObject); existingMembers = (objectLikeContainer).properties; } - else if (objectLikeContainer.kind === SyntaxKind.ObjectBindingPattern) { + else { + Debug.assert(objectLikeContainer.kind === SyntaxKind.ObjectBindingPattern); // We are *only* completing on properties from the type being destructured. isNewIdentifierLocation = false; const rootDeclaration = getRootDeclaration(objectLikeContainer.parent); - if (isVariableLike(rootDeclaration)) { - // We don't want to complete using the type acquired by the shape - // of the binding pattern; we are only interested in types acquired - // through type declaration or inference. - // Also proceed if rootDeclaration is a parameter and if its containing function expression/arrow function is contextually typed - - // type of parameter will flow in from the contextual type of the function - let canGetType = !!(rootDeclaration.initializer || rootDeclaration.type); - if (!canGetType && rootDeclaration.kind === SyntaxKind.Parameter) { - if (isExpression(rootDeclaration.parent)) { - canGetType = !!typeChecker.getContextualType(rootDeclaration.parent); - } - else if (rootDeclaration.parent.kind === SyntaxKind.MethodDeclaration || rootDeclaration.parent.kind === SyntaxKind.SetAccessor) { - canGetType = isExpression(rootDeclaration.parent.parent) && !!typeChecker.getContextualType(rootDeclaration.parent.parent); - } + if (!isVariableLike(rootDeclaration)) throw Debug.fail("Root declaration is not variable-like."); + + // We don't want to complete using the type acquired by the shape + // of the binding pattern; we are only interested in types acquired + // through type declaration or inference. + // Also proceed if rootDeclaration is a parameter and if its containing function expression/arrow function is contextually typed - + // type of parameter will flow in from the contextual type of the function + let canGetType = rootDeclaration.initializer || rootDeclaration.type || rootDeclaration.parent.parent.kind === SyntaxKind.ForOfStatement; + if (!canGetType && rootDeclaration.kind === SyntaxKind.Parameter) { + if (isExpression(rootDeclaration.parent)) { + canGetType = !!typeChecker.getContextualType(rootDeclaration.parent); } - if (canGetType) { - const typeForObject = typeChecker.getTypeAtLocation(objectLikeContainer); - if (!typeForObject) return false; - // In a binding pattern, get only known properties. Everywhere else we will get all possible properties. - typeMembers = typeChecker.getPropertiesOfType(typeForObject); - existingMembers = (objectLikeContainer).elements; + else if (rootDeclaration.parent.kind === SyntaxKind.MethodDeclaration || rootDeclaration.parent.kind === SyntaxKind.SetAccessor) { + canGetType = isExpression(rootDeclaration.parent.parent) && !!typeChecker.getContextualType(rootDeclaration.parent.parent); } } - else { - Debug.fail("Root declaration is not variable-like."); + if (canGetType) { + const typeForObject = typeChecker.getTypeAtLocation(objectLikeContainer); + if (!typeForObject) return false; + // In a binding pattern, get only known properties. Everywhere else we will get all possible properties. + typeMembers = typeChecker.getPropertiesOfType(typeForObject); + existingMembers = (objectLikeContainer).elements; } } - else { - Debug.fail("Expected object literal or binding pattern, got " + objectLikeContainer.kind); - } if (typeMembers && typeMembers.length > 0) { // Add filtered items to the completion list @@ -1082,14 +1096,14 @@ namespace ts.Completions { * Returns the immediate owning object literal or binding pattern of a context token, * on the condition that one exists and that the context implies completion should be given. */ - function tryGetObjectLikeCompletionContainer(contextToken: Node): ObjectLiteralExpression | BindingPattern { + function tryGetObjectLikeCompletionContainer(contextToken: Node): ObjectLiteralExpression | ObjectBindingPattern { if (contextToken) { switch (contextToken.kind) { case SyntaxKind.OpenBraceToken: // const x = { | case SyntaxKind.CommaToken: // const x = { a: 0, | const parent = contextToken.parent; - if (parent && (parent.kind === SyntaxKind.ObjectLiteralExpression || parent.kind === SyntaxKind.ObjectBindingPattern)) { - return parent; + if (isObjectLiteralExpression(parent) || isObjectBindingPattern(parent)) { + return parent; } break; } @@ -1148,7 +1162,7 @@ namespace ts.Completions { default: if (isFromClassElementDeclaration(contextToken) && (isClassMemberCompletionKeyword(contextToken.kind) || - isClassMemberCompletionKeywordText(contextToken.getText()))) { + isClassMemberCompletionKeywordText(contextToken.getText()))) { return contextToken.parent.parent as ClassLikeDeclaration; } } @@ -1296,7 +1310,7 @@ namespace ts.Completions { if (isFromClassElementDeclaration(contextToken)) { return false; } - // falls through + // falls through case SyntaxKind.ClassKeyword: case SyntaxKind.EnumKeyword: case SyntaxKind.InterfaceKeyword: @@ -1603,4 +1617,34 @@ namespace ts.Completions { kind === SyntaxKind.EqualsEqualsEqualsToken || kind === SyntaxKind.ExclamationEqualsEqualsToken; } + + /** Get the corresponding JSDocTag node if the position is in a jsDoc comment */ + function getJsDocTagAtPosition(node: Node, position: number): JSDocTag | undefined { + const { jsDoc } = getJsDocHavingNode(node); + if (!jsDoc) return undefined; + + for (const { pos, end, tags } of jsDoc) { + if (!tags || position < pos || position > end) continue; + for (let i = tags.length - 1; i >= 0; i--) { + const tag = tags[i]; + if (position >= tag.pos) { + return tag; + } + } + } + } + + function getJsDocHavingNode(node: Node): Node { + if (!isToken(node)) return node; + + switch (node.kind) { + case SyntaxKind.VarKeyword: + case SyntaxKind.LetKeyword: + case SyntaxKind.ConstKeyword: + // if the current token is var, let or const, skip the VariableDeclarationList + return node.parent.parent; + default: + return node.parent; + } + } } diff --git a/src/services/documentHighlights.ts b/src/services/documentHighlights.ts index 36b72ecfa78..7ea8c519646 100644 --- a/src/services/documentHighlights.ts +++ b/src/services/documentHighlights.ts @@ -1,17 +1,23 @@ /* @internal */ namespace ts.DocumentHighlights { - export function getDocumentHighlights(program: Program, cancellationToken: CancellationToken, sourceFile: SourceFile, position: number, sourceFilesToSearch: SourceFile[]): DocumentHighlights[] { + export function getDocumentHighlights(program: Program, cancellationToken: CancellationToken, sourceFile: SourceFile, position: number, sourceFilesToSearch: SourceFile[]): DocumentHighlights[] | undefined { const node = getTouchingWord(sourceFile, position, /*includeJsDocComment*/ true); - return node && (getSemanticDocumentHighlights(node, program, cancellationToken, sourceFilesToSearch) || getSyntacticDocumentHighlights(node, sourceFile)); + if (!node) return undefined; + + if (isJsxOpeningElement(node.parent) && node.parent.tagName === node || isJsxClosingElement(node.parent)) { + // For a JSX element, just highlight the matching tag, not all references. + const { openingElement, closingElement } = node.parent.parent; + const highlightSpans = [openingElement, closingElement].map(({ tagName }) => getHighlightSpanForNode(tagName, sourceFile)); + return [{ fileName: sourceFile.fileName, highlightSpans }]; + } + + return getSemanticDocumentHighlights(node, program, cancellationToken, sourceFilesToSearch) || getSyntacticDocumentHighlights(node, sourceFile); } function getHighlightSpanForNode(node: Node, sourceFile: SourceFile): HighlightSpan { - const start = node.getStart(sourceFile); - const end = node.getEnd(); - return { fileName: sourceFile.fileName, - textSpan: createTextSpanFromBounds(start, end), + textSpan: createTextSpanFromNode(node, sourceFile), kind: HighlightSpanKind.none }; } diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index df499cbd38a..42d06e35f10 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -185,7 +185,8 @@ namespace ts.FindAllReferences { if (entry.type === "node") { const { node } = entry; return { textSpan: getTextSpan(node), fileName: node.getSourceFile().fileName, ...implementationKindDisplayParts(node, checker) }; - } else { + } + else { const { textSpan, fileName } = entry; return { textSpan, fileName, kind: ScriptElementKind.unknown, displayParts: [] }; } @@ -495,11 +496,10 @@ namespace ts.FindAllReferences.Core { const { text = stripQuotes(getDeclaredName(this.checker, symbol, location)), allSearchSymbols = undefined } = searchOptions; const escapedText = escapeIdentifier(text); const parents = this.options.implementations && getParentSymbolsOfPropertyAccess(location, symbol, this.checker); - return { location, symbol, comingFrom, text, escapedText, parents, includes }; - - function includes(referenceSymbol: Symbol): boolean { - return allSearchSymbols ? contains(allSearchSymbols, referenceSymbol) : referenceSymbol === symbol; - } + return { + location, symbol, comingFrom, text, escapedText, parents, + includes: referenceSymbol => allSearchSymbols ? contains(allSearchSymbols, referenceSymbol) : referenceSymbol === symbol, + }; } private readonly symbolIdToReferences: Entry[][] = []; @@ -678,9 +678,7 @@ namespace ts.FindAllReferences.Core { return parent ? scope.getSourceFile() : scope; } - function getPossibleSymbolReferencePositions(sourceFile: SourceFile, symbolName: string, container: Node = sourceFile, fullStart = false): number[] { - const start = fullStart ? container.getFullStart() : container.getStart(sourceFile); - const end = container.getEnd(); + function getPossibleSymbolReferencePositions(sourceFile: SourceFile, symbolName: string, container: Node = sourceFile): number[] { const positions: number[] = []; /// TODO: Cache symbol existence for files to save text search @@ -695,10 +693,10 @@ namespace ts.FindAllReferences.Core { const sourceLength = text.length; const symbolNameLength = symbolName.length; - let position = text.indexOf(symbolName, start); + let position = text.indexOf(symbolName, container.pos); while (position >= 0) { // If we are past the end, stop looking - if (position > end) break; + if (position > container.end) break; // We found a match. Make sure it's not part of a larger word (i.e. the char // before and after it have to be a non-identifier char). @@ -759,8 +757,7 @@ namespace ts.FindAllReferences.Core { } function addReferencesForKeywordInFile(sourceFile: SourceFile, kind: SyntaxKind, searchText: string, references: Push): void { - // Want fullStart so we can find the symbol in JSDoc comments - const possiblePositions = getPossibleSymbolReferencePositions(sourceFile, searchText, sourceFile, /*fullStart*/ true); + const possiblePositions = getPossibleSymbolReferencePositions(sourceFile, searchText, sourceFile); for (const position of possiblePositions) { const referenceLocation = getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true); if (referenceLocation.kind === kind) { @@ -784,8 +781,7 @@ namespace ts.FindAllReferences.Core { return; } - const fullStart = state.options.findInComments || container.jsDoc !== undefined || forEach(search.symbol.declarations, d => d.kind === ts.SyntaxKind.JSDocTypedefTag); - for (const position of getPossibleSymbolReferencePositions(sourceFile, search.text, container, fullStart)) { + for (const position of getPossibleSymbolReferencePositions(sourceFile, search.text, container)) { getReferencesAtLocation(sourceFile, position, search, state); } } diff --git a/src/services/importTracker.ts b/src/services/importTracker.ts index f20c80c14ef..5e8e7b8b3a7 100644 --- a/src/services/importTracker.ts +++ b/src/services/importTracker.ts @@ -73,54 +73,56 @@ namespace ts.FindAllReferences { function handleDirectImports(exportingModuleSymbol: Symbol): void { const theseDirectImports = getDirectImports(exportingModuleSymbol); - if (theseDirectImports) for (const direct of theseDirectImports) { - if (!markSeenDirectImport(direct)) { - continue; - } + if (theseDirectImports) { + for (const direct of theseDirectImports) { + if (!markSeenDirectImport(direct)) { + continue; + } - cancellationToken.throwIfCancellationRequested(); + cancellationToken.throwIfCancellationRequested(); - switch (direct.kind) { - case SyntaxKind.CallExpression: - if (!isAvailableThroughGlobal) { - const parent = direct.parent!; - if (exportKind === ExportKind.ExportEquals && parent.kind === SyntaxKind.VariableDeclaration) { - const { name } = parent as ts.VariableDeclaration; - if (name.kind === SyntaxKind.Identifier) { - directImports.push(name); - break; + switch (direct.kind) { + case SyntaxKind.CallExpression: + if (!isAvailableThroughGlobal) { + const parent = direct.parent!; + if (exportKind === ExportKind.ExportEquals && parent.kind === SyntaxKind.VariableDeclaration) { + const { name } = parent as ts.VariableDeclaration; + if (name.kind === SyntaxKind.Identifier) { + directImports.push(name); + break; + } } + + // Don't support re-exporting 'require()' calls, so just add a single indirect user. + addIndirectUser(direct.getSourceFile()); } + break; - // Don't support re-exporting 'require()' calls, so just add a single indirect user. - addIndirectUser(direct.getSourceFile()); - } - break; + case SyntaxKind.ImportEqualsDeclaration: + handleNamespaceImport(direct, direct.name, hasModifier(direct, ModifierFlags.Export)); + break; - case SyntaxKind.ImportEqualsDeclaration: - handleNamespaceImport(direct, direct.name, hasModifier(direct, ModifierFlags.Export)); - break; + case SyntaxKind.ImportDeclaration: + const namedBindings = direct.importClause && direct.importClause.namedBindings; + if (namedBindings && namedBindings.kind === SyntaxKind.NamespaceImport) { + handleNamespaceImport(direct, namedBindings.name); + } + else { + directImports.push(direct); + } + break; - case SyntaxKind.ImportDeclaration: - const namedBindings = direct.importClause && direct.importClause.namedBindings; - if (namedBindings && namedBindings.kind === SyntaxKind.NamespaceImport) { - handleNamespaceImport(direct, namedBindings.name); - } - else { - directImports.push(direct); - } - break; - - case SyntaxKind.ExportDeclaration: - if (!direct.exportClause) { - // This is `export * from "foo"`, so imports of this module may import the export too. - handleDirectImports(getContainingModuleSymbol(direct, checker)); - } - else { - // This is `export { foo } from "foo"` and creates an alias symbol, so recursive search will get handle re-exports. - directImports.push(direct); - } - break; + case SyntaxKind.ExportDeclaration: + if (!direct.exportClause) { + // This is `export * from "foo"`, so imports of this module may import the export too. + handleDirectImports(getContainingModuleSymbol(direct, checker)); + } + else { + // This is `export { foo } from "foo"` and creates an alias symbol, so recursive search will get handle re-exports. + directImports.push(direct); + } + break; + } } } } @@ -160,8 +162,10 @@ namespace ts.FindAllReferences { const moduleSymbol = checker.getMergedSymbol(sourceFileLike.symbol); Debug.assert(!!(moduleSymbol.flags & SymbolFlags.Module)); const directImports = getDirectImports(moduleSymbol); - if (directImports) for (const directImport of directImports) { - addIndirectUsers(getSourceFileLikeForImportDeclaration(directImport)); + if (directImports) { + for (const directImport of directImports) { + addIndirectUsers(getSourceFileLikeForImportDeclaration(directImport)); + } } } @@ -183,8 +187,10 @@ namespace ts.FindAllReferences { importSearches.push([location, symbol]); } - if (directImports) for (const decl of directImports) { - handleImport(decl); + if (directImports) { + for (const decl of directImports) { + handleImport(decl); + } } return { importSearches, singleReferences }; @@ -258,25 +264,27 @@ namespace ts.FindAllReferences { } function searchForNamedImport(namedBindings: NamedImportsOrExports | undefined): void { - if (namedBindings) for (const element of namedBindings.elements) { - const { name, propertyName } = element; - if ((propertyName || name).text !== exportName) { - continue; - } + if (namedBindings) { + for (const element of namedBindings.elements) { + const { name, propertyName } = element; + if ((propertyName || name).text !== exportName) { + continue; + } - if (propertyName) { - // This is `import { foo as bar } from "./a"` or `export { foo as bar } from "./a"`. `foo` isn't a local in the file, so just add it as a single reference. - singleReferences.push(propertyName); - if (!isForRename) { // If renaming `foo`, don't touch `bar`, just `foo`. - // Search locally for `bar`. - addSearch(name, checker.getSymbolAtLocation(name)); + if (propertyName) { + // This is `import { foo as bar } from "./a"` or `export { foo as bar } from "./a"`. `foo` isn't a local in the file, so just add it as a single reference. + singleReferences.push(propertyName); + if (!isForRename) { // If renaming `foo`, don't touch `bar`, just `foo`. + // Search locally for `bar`. + addSearch(name, checker.getSymbolAtLocation(name)); + } + } + else { + const localSymbol = element.kind === SyntaxKind.ExportSpecifier && element.propertyName + ? checker.getExportSpecifierLocalTargetSymbol(element) // For re-exporting under a different name, we want to get the re-exported symbol. + : checker.getSymbolAtLocation(name); + addSearch(name, localSymbol); } - } - else { - const localSymbol = element.kind === SyntaxKind.ExportSpecifier && element.propertyName - ? checker.getExportSpecifierLocalTargetSymbol(element) // For re-exporting under a different name, we want to get the re-exported symbol. - : checker.getSymbolAtLocation(name); - addSearch(name, localSymbol); } } } @@ -436,8 +444,8 @@ namespace ts.FindAllReferences { if (parent.kind === SyntaxKind.PropertyAccessExpression) { // When accessing an export of a JS module, there's no alias. The symbol will still be flagged as an export even though we're at the use. // So check that we are at the declaration. - return symbol.declarations.some(d => d === parent) && parent.parent.kind === ts.SyntaxKind.BinaryExpression - ? getSpecialPropertyExport(parent.parent as ts.BinaryExpression, /*useLhsSymbol*/ false) + return symbol.declarations.some(d => d === parent) && isBinaryExpression(parent.parent) + ? getSpecialPropertyExport(parent.parent, /*useLhsSymbol*/ false) : undefined; } else { @@ -449,31 +457,41 @@ namespace ts.FindAllReferences { else { const exportNode = getExportNode(parent); if (exportNode && hasModifier(exportNode, ModifierFlags.Export)) { - if (exportNode.kind === SyntaxKind.ImportEqualsDeclaration && (exportNode as ImportEqualsDeclaration).moduleReference === node) { + if (isImportEqualsDeclaration(exportNode) && exportNode.moduleReference === node) { // We're at `Y` in `export import X = Y`. This is not the exported symbol, the left-hand-side is. So treat this as an import statement. if (comingFromExport) { return undefined; } - const lhsSymbol = checker.getSymbolAtLocation((exportNode as ImportEqualsDeclaration).name); + const lhsSymbol = checker.getSymbolAtLocation(exportNode.name); return { kind: ImportExport.Import, symbol: lhsSymbol, isNamedImport: false }; } else { return exportInfo(symbol, getExportKindForDeclaration(exportNode)); } } - else if (parent.kind === SyntaxKind.ExportAssignment) { - // Get the symbol for the `export =` node; its parent is the module it's the export of. - const exportingModuleSymbol = parent.symbol.parent; - Debug.assert(!!exportingModuleSymbol); - return { kind: ImportExport.Export, symbol, exportInfo: { exportingModuleSymbol, exportKind: ExportKind.ExportEquals } }; + // If we are in `export = a;`, `parent` is the export assignment. + else if (isExportAssignment(parent)) { + return getExportAssignmentExport(parent); } - else if (parent.kind === ts.SyntaxKind.BinaryExpression) { - return getSpecialPropertyExport(parent as ts.BinaryExpression, /*useLhsSymbol*/ true); + // If we are in `export = class A {};` at `A`, `parent.parent` is the export assignment. + else if (isExportAssignment(parent.parent)) { + return getExportAssignmentExport(parent.parent); } - else if (parent.parent.kind === SyntaxKind.BinaryExpression) { - return getSpecialPropertyExport(parent.parent as ts.BinaryExpression, /*useLhsSymbol*/ true); + // Similar for `module.exports =` and `exports.A =`. + else if (isBinaryExpression(parent)) { + return getSpecialPropertyExport(parent, /*useLhsSymbol*/ true); } + else if (isBinaryExpression(parent.parent)) { + return getSpecialPropertyExport(parent.parent, /*useLhsSymbol*/ true); + } + } + + function getExportAssignmentExport(ex: ExportAssignment): ExportedSymbol { + // Get the symbol for the `export =` node; its parent is the module it's the export of. + const exportingModuleSymbol = ex.symbol.parent; + Debug.assert(!!exportingModuleSymbol); + return { kind: ImportExport.Export, symbol, exportInfo: { exportingModuleSymbol, exportKind: ExportKind.ExportEquals } }; } function getSpecialPropertyExport(node: ts.BinaryExpression, useLhsSymbol: boolean): ExportedSymbol | undefined { @@ -496,21 +514,21 @@ namespace ts.FindAllReferences { function getImport(): ImportedSymbol | undefined { const isImport = isNodeImport(node); - if (!isImport) return; + if (!isImport) return undefined; // A symbol being imported is always an alias. So get what that aliases to find the local symbol. let importedSymbol = checker.getImmediateAliasedSymbol(symbol); - if (importedSymbol) { - // Search on the local symbol in the exporting module, not the exported symbol. - importedSymbol = skipExportSpecifierSymbol(importedSymbol, checker); - // Similarly, skip past the symbol for 'export =' - if (importedSymbol.name === "export=") { - importedSymbol = checker.getImmediateAliasedSymbol(importedSymbol); - } + if (!importedSymbol) return undefined; - if (symbolName(importedSymbol) === symbol.name) { // If this is a rename import, do not continue searching. - return { kind: ImportExport.Import, symbol: importedSymbol, ...isImport }; - } + // Search on the local symbol in the exporting module, not the exported symbol. + importedSymbol = skipExportSpecifierSymbol(importedSymbol, checker); + // Similarly, skip past the symbol for 'export =' + if (importedSymbol.name === "export=") { + importedSymbol = getExportEqualsLocalSymbol(importedSymbol, checker); + } + + if (symbolName(importedSymbol) === symbol.name) { // If this is a rename import, do not continue searching. + return { kind: ImportExport.Import, symbol: importedSymbol, ...isImport }; } } @@ -525,12 +543,29 @@ namespace ts.FindAllReferences { } } + function getExportEqualsLocalSymbol(importedSymbol: Symbol, checker: TypeChecker): Symbol { + if (importedSymbol.flags & SymbolFlags.Alias) { + return checker.getImmediateAliasedSymbol(importedSymbol); + } + + const decl = importedSymbol.valueDeclaration; + if (isExportAssignment(decl)) { // `export = class {}` + return decl.expression.symbol; + } + else if (isBinaryExpression(decl)) { // `module.exports = class {}` + return decl.right.symbol; + } + Debug.fail(); + } + + // If a reference is a class expression, the exported node would be its parent. // If a reference is a variable declaration, the exported node would be the variable statement. function getExportNode(parent: Node): Node | undefined { if (parent.kind === SyntaxKind.VariableDeclaration) { const p = parent as ts.VariableDeclaration; return p.parent.kind === ts.SyntaxKind.CatchClause ? undefined : p.parent.parent.kind === SyntaxKind.VariableStatement ? p.parent.parent : undefined; - } else { + } + else { return parent; } } @@ -577,12 +612,13 @@ namespace ts.FindAllReferences { /** If at an export specifier, go to the symbol it refers to. */ function skipExportSpecifierSymbol(symbol: Symbol, checker: TypeChecker): Symbol { // For `export { foo } from './bar", there's nothing to skip, because it does not create a new alias. But `export { foo } does. - if (symbol.declarations) for (const declaration of symbol.declarations) { - if (isExportSpecifier(declaration) && !(declaration as ExportSpecifier).propertyName && !(declaration as ExportSpecifier).parent.parent.moduleSpecifier) { - return checker.getExportSpecifierLocalTargetSymbol(declaration); + if (symbol.declarations) { + for (const declaration of symbol.declarations) { + if (isExportSpecifier(declaration) && !(declaration as ExportSpecifier).propertyName && !(declaration as ExportSpecifier).parent.parent.moduleSpecifier) { + return checker.getExportSpecifierLocalTargetSymbol(declaration); + } } } - return symbol; } diff --git a/src/services/jsDoc.ts b/src/services/jsDoc.ts index 8ca55029603..5d03ad03b0c 100644 --- a/src/services/jsDoc.ts +++ b/src/services/jsDoc.ts @@ -132,6 +132,25 @@ namespace ts.JsDoc { })); } + export function getJSDocParameterNameCompletions(tag: JSDocParameterTag): CompletionEntry[] { + const nameThusFar = tag.name.text; + const jsdoc = tag.parent; + const fn = jsdoc.parent; + if (!ts.isFunctionLike(fn)) return []; + + return mapDefined(fn.parameters, param => { + if (!isIdentifier(param.name)) return undefined; + + const name = param.name.text; + if (jsdoc.tags.some(t => t !== tag && isJSDocParameterTag(t) && t.name.text === name) + || nameThusFar !== undefined && !startsWith(name, nameThusFar)) { + return undefined; + } + + return { name, kind: ScriptElementKind.parameterElement, 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/jsTyping.ts b/src/services/jsTyping.ts index f601c9604de..5e31d6a0190 100644 --- a/src/services/jsTyping.ts +++ b/src/services/jsTyping.ts @@ -143,7 +143,7 @@ namespace ts.JsTyping { /** * Merge a given list of typingNames to the inferredTypings map */ - function mergeTypings(typingNames: string[]) { + function mergeTypings(typingNames: ReadonlyArray) { if (!typingNames) { return; } @@ -192,7 +192,7 @@ namespace ts.JsTyping { const cleanedTypingNames = map(inferredTypingNames, f => f.replace(/((?:\.|-)min(?=\.|$))|((?:-|\.)\d+)/g, "")); if (safeList !== EmptySafeList) { - mergeTypings(filter(cleanedTypingNames, f => safeList.has(f))); + mergeTypings(ts.mapDefined(cleanedTypingNames, f => safeList.get(f))); } const hasJsxFile = forEach(fileNames, f => ensureScriptKind(f, getScriptKindFromFileName(f)) === ScriptKind.JSX); diff --git a/src/services/navigateTo.ts b/src/services/navigateTo.ts index d4adeaea974..304f64f3cdb 100644 --- a/src/services/navigateTo.ts +++ b/src/services/navigateTo.ts @@ -10,7 +10,7 @@ namespace ts.NavigateTo { for (const sourceFile of sourceFiles) { cancellationToken.throwIfCancellationRequested(); - if (excludeDtsFiles && fileExtensionIs(sourceFile.fileName, ".d.ts")) { + if (excludeDtsFiles && fileExtensionIs(sourceFile.fileName, Extension.Dts)) { continue; } diff --git a/src/services/preProcess.ts b/src/services/preProcess.ts index 0f0702066e1..7efc174c423 100644 --- a/src/services/preProcess.ts +++ b/src/services/preProcess.ts @@ -95,9 +95,16 @@ namespace ts { function tryConsumeImport(): boolean { let token = scanner.getToken(); if (token === SyntaxKind.ImportKeyword) { - token = nextToken(); - if (token === SyntaxKind.StringLiteral) { + if (token === SyntaxKind.OpenParenToken) { + token = nextToken(); + if (token === SyntaxKind.StringLiteral) { + // import("mod"); + recordModuleName(); + return true; + } + } + else if (token === SyntaxKind.StringLiteral) { // import "mod"; recordModuleName(); return true; @@ -297,7 +304,8 @@ namespace ts { // import * as NS from "mod" // import d, {a, b as B} from "mod" // import i = require("mod"); - // + // import("mod"); + // export * from "mod" // export {a as b} from "mod" // export import i = require("mod") diff --git a/src/services/refactorProvider.ts b/src/services/refactorProvider.ts index 0b6ea3487ec..3c02ddf671c 100644 --- a/src/services/refactorProvider.ts +++ b/src/services/refactorProvider.ts @@ -8,10 +8,10 @@ namespace ts { description: string; /** Compute the associated code actions */ - getCodeActions(context: RefactorContext): CodeAction[]; + getEditsForAction(context: RefactorContext, actionName: string): RefactorEditInfo | undefined; - /** A fast syntactic check to see if the refactor is applicable at given position. */ - isApplicable(context: RefactorContext): boolean; + /** Compute (quickly) which actions are available here */ + getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] | undefined; } export interface RefactorContext { @@ -34,7 +34,6 @@ namespace ts { } export function getApplicableRefactors(context: RefactorContext): ApplicableRefactorInfo[] | undefined { - let results: ApplicableRefactorInfo[]; const refactorList: Refactor[] = []; refactors.forEach(refactor => { @@ -44,26 +43,17 @@ namespace ts { if (context.cancellationToken && context.cancellationToken.isCancellationRequested()) { return results; } - if (refactor.isApplicable(context)) { - (results || (results = [])).push({ name: refactor.name, description: refactor.description }); + const infos = refactor.getAvailableActions(context); + if (infos && infos.length) { + (results || (results = [])).push(...infos); } } return results; } - export function getRefactorCodeActions(context: RefactorContext, refactorName: string): CodeAction[] | undefined { - - let result: CodeAction[]; + export function getEditsForRefactor(context: RefactorContext, refactorName: string, actionName: string): RefactorEditInfo | undefined { const refactor = refactors.get(refactorName); - if (!refactor) { - return undefined; - } - - const codeActions = refactor.getCodeActions(context); - if (codeActions) { - addRange((result || (result = [])), codeActions); - } - return result; + return refactor && refactor.getEditsForAction(context, actionName); } } } diff --git a/src/services/refactors/convertFunctionToEs6Class.ts b/src/services/refactors/convertFunctionToEs6Class.ts index a34e0ccca2f..d275924b76a 100644 --- a/src/services/refactors/convertFunctionToEs6Class.ts +++ b/src/services/refactors/convertFunctionToEs6Class.ts @@ -1,16 +1,18 @@ /* @internal */ namespace ts.refactor { + const actionName = "convert"; + const convertFunctionToES6Class: Refactor = { name: "Convert to ES2015 class", description: Diagnostics.Convert_function_to_an_ES2015_class.message, - getCodeActions, - isApplicable + getEditsForAction, + getAvailableActions }; registerRefactor(convertFunctionToES6Class); - function isApplicable(context: RefactorContext): boolean { + function getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] { const start = context.startPosition; const node = getTokenAtPosition(context.file, start, /*includeJsDocComment*/ false); const checker = context.program.getTypeChecker(); @@ -20,10 +22,28 @@ namespace ts.refactor { symbol = (symbol.valueDeclaration as VariableDeclaration).initializer.symbol; } - return symbol && symbol.flags & SymbolFlags.Function && symbol.members && symbol.members.size > 0; + if (symbol && (symbol.flags & SymbolFlags.Function) && symbol.members && (symbol.members.size > 0)) { + return [ + { + name: convertFunctionToES6Class.name, + description: convertFunctionToES6Class.description, + actions: [ + { + description: convertFunctionToES6Class.description, + name: actionName + } + ] + } + ]; + } } - function getCodeActions(context: RefactorContext): CodeAction[] | undefined { + function getEditsForAction(context: RefactorContext, action: string): RefactorEditInfo | undefined { + // Somehow wrong action got invoked? + if (actionName !== action) { + return undefined; + } + const start = context.startPosition; const sourceFile = context.file; const checker = context.program.getTypeChecker(); @@ -35,7 +55,7 @@ namespace ts.refactor { const deletes: (() => any)[] = []; if (!(ctorSymbol.flags & (SymbolFlags.Function | SymbolFlags.Variable))) { - return []; + return undefined; } const ctorDeclaration = ctorSymbol.valueDeclaration; @@ -63,7 +83,7 @@ namespace ts.refactor { } if (!newClassDeclaration) { - return []; + return undefined; } // Because the preceding node could be touched, we need to insert nodes before delete nodes. @@ -72,10 +92,9 @@ namespace ts.refactor { deleteCallback(); } - return [{ - description: formatStringFromArgs(Diagnostics.Convert_function_0_to_class.message, [ctorSymbol.name]), - changes: changeTracker.getChanges() - }]; + return { + edits: changeTracker.getChanges() + }; function deleteNode(node: Node, inList = false) { if (deletedNodes.some(n => isNodeDescendantOf(node, n))) { diff --git a/src/services/services.ts b/src/services/services.ts index 05fe59084b4..2f835d7de64 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -37,7 +37,7 @@ namespace ts { let ruleProvider: formatting.RulesProvider; function createNode(kind: TKind, pos: number, end: number, parent?: Node): NodeObject | TokenObject | IdentifierObject { - const node = kind >= SyntaxKind.FirstNode ? new NodeObject(kind, pos, end) : + const node = isNodeKind(kind) ? new NodeObject(kind, pos, end) : kind === SyntaxKind.Identifier ? new IdentifierObject(SyntaxKind.Identifier, pos, end) : new TokenObject(kind, pos, end); node.parent = parent; @@ -103,10 +103,10 @@ namespace ts { return sourceFile.text.substring(this.getStart(sourceFile), this.getEnd()); } - private addSyntheticNodes(nodes: Node[], pos: number, end: number, useJSDocScanner?: boolean): number { + private addSyntheticNodes(nodes: Node[], pos: number, end: number): number { scanner.setTextPos(pos); while (pos < end) { - const token = useJSDocScanner ? scanner.scanJSDocToken() : scanner.scan(); + const token = scanner.scan(); Debug.assert(token !== SyntaxKind.EndOfFileToken); // Else it would infinitely loop const textPos = scanner.getTextPos(); if (textPos <= end) { @@ -136,54 +136,50 @@ namespace ts { } private createChildren(sourceFile?: SourceFileLike) { - if (isJSDocTag(this)) { + if (!isNodeKind(this.kind)) { + this._children = emptyArray; + return; + } + + if (isJSDocCommentContainingNode(this)) { /** Don't add trivia for "tokens" since this is in a comment. */ const children: Node[] = []; this.forEachChild(child => { children.push(child); }); this._children = children; + return; } - else if (this.kind >= SyntaxKind.FirstNode) { - const children: Node[] = []; - scanner.setText((sourceFile || this.getSourceFile()).text); - let pos = this.pos; - const useJSDocScanner = this.kind >= SyntaxKind.FirstJSDocTagNode && this.kind <= SyntaxKind.LastJSDocTagNode; - const processNode = (node: Node) => { - const isJSDocTagNode = isJSDocTag(node); - if (!isJSDocTagNode && pos < node.pos) { - pos = this.addSyntheticNodes(children, pos, node.pos, useJSDocScanner); - } - children.push(node); - if (!isJSDocTagNode) { - pos = node.end; - } - }; - const processNodes = (nodes: NodeArray) => { - if (pos < nodes.pos) { - pos = this.addSyntheticNodes(children, pos, nodes.pos, useJSDocScanner); - } - children.push(this.createSyntaxList(nodes)); - pos = nodes.end; - }; - // jsDocComments need to be the first children - if (this.jsDoc) { - for (const jsDocComment of this.jsDoc) { - processNode(jsDocComment); - } + + const children: Node[] = []; + scanner.setText((sourceFile || this.getSourceFile()).text); + let pos = this.pos; + const processNode = (node: Node) => { + pos = this.addSyntheticNodes(children, pos, node.pos); + children.push(node); + pos = node.end; + }; + const processNodes = (nodes: NodeArray) => { + if (pos < nodes.pos) { + pos = this.addSyntheticNodes(children, pos, nodes.pos); } - // For syntactic classifications, all trivia are classcified together, including jsdoc comments. - // For that to work, the jsdoc comments should still be the leading trivia of the first child. - // Restoring the scanner position ensures that. - pos = this.pos; - forEachChild(this, processNode, processNodes); - if (pos < this.end) { - this.addSyntheticNodes(children, pos, this.end); + children.push(this.createSyntaxList(nodes)); + pos = nodes.end; + }; + // jsDocComments need to be the first children + if (this.jsDoc) { + for (const jsDocComment of this.jsDoc) { + processNode(jsDocComment); } - scanner.setText(undefined); - this._children = children; } - else { - this._children = emptyArray; + // For syntactic classifications, all trivia are classcified together, including jsdoc comments. + // For that to work, the jsdoc comments should still be the leading trivia of the first child. + // Restoring the scanner position ensures that. + pos = this.pos; + forEachChild(this, processNode, processNodes); + if (pos < this.end) { + this.addSyntheticNodes(children, pos, this.end); } + scanner.setText(undefined); + this._children = children; } public getChildCount(sourceFile?: SourceFile): number { @@ -368,7 +364,7 @@ namespace ts { _primaryExpressionBrand: any; _memberExpressionBrand: any; _leftHandSideExpressionBrand: any; - _incrementExpressionBrand: any; + _updateExpressionBrand: any; _unaryExpressionBrand: any; _expressionBrand: any; /*@internal*/typeArguments: NodeArray; @@ -521,6 +517,7 @@ namespace ts { private namedDeclarations: Map; public ambientModuleNames: string[]; public checkJsDirective: CheckJsDirective | undefined; + public possiblyContainDynamicImport: boolean; constructor(kind: SyntaxKind, pos: number, end: number) { super(kind, pos, end); @@ -683,8 +680,9 @@ namespace ts { forEachChild(decl.name, visit); break; } - if (decl.initializer) + if (decl.initializer) { visit(decl.initializer); + } } // falls through case SyntaxKind.EnumMember: @@ -731,6 +729,15 @@ namespace ts { } } + class SourceMapSourceObject implements SourceMapSource { + lineMap: number[]; + constructor (public fileName: string, public text: string, public skipTrivia?: (pos: number) => number) {} + + public getLineAndCharacterOfPosition(pos: number): LineAndCharacter { + return ts.getLineAndCharacterOfPosition(this, pos); + } + } + function getServicesObjectAllocator(): ObjectAllocator { return { getNodeConstructor: () => NodeObject, @@ -741,6 +748,7 @@ namespace ts { getSymbolConstructor: () => SymbolObject, getTypeConstructor: () => TypeObject, getSignatureConstructor: () => SignatureObject, + getSourceMapSourceConstructor: () => SourceMapSourceObject, }; } @@ -1988,15 +1996,16 @@ namespace ts { return refactor.getApplicableRefactors(getRefactorContext(file, positionOrRange)); } - function getRefactorCodeActions( + function getEditsForRefactor( fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, - refactorName: string): CodeAction[] | undefined { + refactorName: string, + actionName: string): RefactorEditInfo { synchronizeHostData(); const file = getValidSourceFile(fileName); - return refactor.getRefactorCodeActions(getRefactorContext(file, positionOrRange, formatOptions), refactorName); + return refactor.getEditsForRefactor(getRefactorContext(file, positionOrRange, formatOptions), refactorName, actionName); } return { @@ -2004,8 +2013,6 @@ namespace ts { cleanupSemanticCache, getSyntacticDiagnostics, getSemanticDiagnostics, - getApplicableRefactors, - getRefactorCodeActions, getCompilerOptionsDiagnostics, getSyntacticClassifications, getSemanticClassifications, @@ -2043,7 +2050,9 @@ namespace ts { getEmitOutput, getNonBoundSourceFile, getSourceFile, - getProgram + getProgram, + getApplicableRefactors, + getEditsForRefactor, }; } diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index 910c31c36b3..345f0718fe3 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -4,8 +4,10 @@ namespace ts.SymbolDisplay { export function getSymbolKind(typeChecker: TypeChecker, symbol: Symbol, location: Node): ScriptElementKind { const { flags } = symbol; - if (flags & SymbolFlags.Class) return getDeclarationOfKind(symbol, SyntaxKind.ClassExpression) ? + if (flags & SymbolFlags.Class) { + return getDeclarationOfKind(symbol, SyntaxKind.ClassExpression) ? ScriptElementKind.localClassElement : ScriptElementKind.classElement; + } if (flags & SymbolFlags.Enum) return ScriptElementKind.enumElement; if (flags & SymbolFlags.TypeAlias) return ScriptElementKind.typeElement; if (flags & SymbolFlags.Interface) return ScriptElementKind.interfaceElement; diff --git a/src/services/types.ts b/src/services/types.ts index e042276e650..2d47da2fd1d 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -71,6 +71,10 @@ namespace ts { getLineAndCharacterOfPosition(pos: number): LineAndCharacter; } + export interface SourceMapSource { + getLineAndCharacterOfPosition(pos: number): LineAndCharacter; + } + /** * Represents an immutable snapshot of a script at a specified time.Once acquired, the * snapshot is observably immutable. i.e. the same calls with the same parameters will return @@ -261,8 +265,9 @@ namespace ts { isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean; getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: number[], formatOptions: FormatCodeSettings): CodeAction[]; + getApplicableRefactors(fileName: string, positionOrRaneg: number | TextRange): ApplicableRefactorInfo[]; - getRefactorCodeActions(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string): CodeAction[] | undefined; + getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string): RefactorEditInfo | undefined; getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean): EmitOutput; @@ -353,11 +358,60 @@ namespace ts { changes: FileTextChanges[]; } + /** + * A set of one or more available refactoring actions, grouped under a parent refactoring. + */ export interface ApplicableRefactorInfo { + /** + * The programmatic name of the refactoring + */ name: string; + /** + * A description of this refactoring category to show to the user. + * If the refactoring gets inlined (see below), this text will not be visible. + */ description: string; + /** + * Inlineable refactorings can have their actions hoisted out to the top level + * of a context menu. Non-inlineanable refactorings should always be shown inside + * their parent grouping. + * + * If not specified, this value is assumed to be 'true' + */ + inlineable?: boolean; + + actions: RefactorActionInfo[]; } + /** + * Represents a single refactoring action - for example, the "Extract Method..." refactor might + * offer several actions, each corresponding to a surround class or closure to extract into. + */ + export type RefactorActionInfo = { + /** + * The programmatic name of the refactoring action + */ + name: string; + + /** + * A description of this refactoring action to show to the user. + * If the parent refactoring is inlined away, this will be the only text shown, + * so this description should make sense by itself if the parent is inlineable=true + */ + description: string; + }; + + /** + * A set of edits to make in response to a refactor action, plus an optional + * location where renaming should be invoked from + */ + export type RefactorEditInfo = { + edits: FileTextChanges[]; + renameFilename?: string; + renameLocation?: number; + }; + + export interface TextInsertion { newText: string; /** The position in newText the caret should point to after the insertion. */ diff --git a/src/services/utilities.ts b/src/services/utilities.ts index d40824ced33..b7717edd867 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -94,6 +94,10 @@ namespace ts { else if (isNamespaceReference(node)) { return SemanticMeaning.Namespace; } + else if (isTypeParameterDeclaration(node.parent)) { + Debug.assert(isJSDocTemplateTag(node.parent.parent)); // Else would be handled by isDeclarationName + return SemanticMeaning.Type; + } else { return SemanticMeaning.Value; } @@ -615,18 +619,21 @@ namespace ts { return getTouchingToken(sourceFile, position, includeJsDocComment, n => isPropertyName(n.kind)); } - /** Returns the token if position is in [start, end) or if position === end and includeItemAtEndPosition(token) === true */ - export function getTouchingToken(sourceFile: SourceFile, position: number, includeJsDocComment: boolean, includeItemAtEndPosition?: (n: Node) => boolean): Node { - return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ false, includeItemAtEndPosition, includeJsDocComment); + /** + * Returns the token if position is in [start, end). + * If position === end, returns the preceding token if includeItemAtEndPosition(previousToken) === true + */ + export function getTouchingToken(sourceFile: SourceFile, position: number, includeJsDocComment: boolean, includePrecedingTokenAtEndPosition?: (n: Node) => boolean): Node { + return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ false, includePrecedingTokenAtEndPosition, /*includeEndPosition*/ false, includeJsDocComment); } /** Returns a token if position is in [start-of-leading-trivia, end) */ - export function getTokenAtPosition(sourceFile: SourceFile, position: number, includeJsDocComment: boolean): Node { - return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ true, /*includeItemAtEndPosition*/ undefined, includeJsDocComment); + export function getTokenAtPosition(sourceFile: SourceFile, position: number, includeJsDocComment: boolean, includeEndPosition?: boolean): Node { + return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ true, /*includePrecedingTokenAtEndPosition*/ undefined, includeEndPosition, includeJsDocComment); } /** Get the token whose text contains the position */ - function getTokenAtPositionWorker(sourceFile: SourceFile, position: number, allowPositionInLeadingTrivia: boolean, includeItemAtEndPosition: (n: Node) => boolean, includeJsDocComment: boolean): Node { + function getTokenAtPositionWorker(sourceFile: SourceFile, position: number, allowPositionInLeadingTrivia: boolean, includePrecedingTokenAtEndPosition: (n: Node) => boolean, includeEndPosition: boolean, includeJsDocComment: boolean): Node { let current: Node = sourceFile; outer: while (true) { if (isToken(current)) { @@ -636,7 +643,7 @@ namespace ts { // find the child that contains 'position' for (const child of current.getChildren()) { - if (isJSDocNode(child) && !includeJsDocComment) { + if (!includeJsDocComment && isJSDocNode(child)) { continue; } @@ -646,13 +653,13 @@ namespace ts { } const end = child.getEnd(); - if (position < end || (position === end && child.kind === SyntaxKind.EndOfFileToken)) { + if (position < end || (position === end && (child.kind === SyntaxKind.EndOfFileToken || includeEndPosition))) { current = child; continue outer; } - else if (includeItemAtEndPosition && end === position) { + else if (includePrecedingTokenAtEndPosition && end === position) { const previousToken = findPrecedingToken(position, sourceFile, child); - if (previousToken && includeItemAtEndPosition(previousToken)) { + if (previousToken && includePrecedingTokenAtEndPosition(previousToken)) { return previousToken; } } @@ -707,7 +714,7 @@ namespace ts { } } - export function findPrecedingToken(position: number, sourceFile: SourceFile, startNode?: Node, includeJsDocComment?: boolean): Node { + export function findPrecedingToken(position: number, sourceFile: SourceFile, startNode?: Node, includeJsDoc?: boolean): Node { return find(startNode || sourceFile); function findRightmostToken(n: Node): Node { @@ -738,7 +745,7 @@ namespace ts { // NOTE: JsxText is a weird kind of node that can contain only whitespaces (since they are not counted as trivia). // if this is the case - then we should assume that token in question is located in previous child. if (position < child.end && (nodeHasTokens(child) || child.kind === SyntaxKind.JsxText)) { - const start = child.getStart(sourceFile, includeJsDocComment); + const start = child.getStart(sourceFile, includeJsDoc); const lookInPreviousChild = (start >= position) || // cursor in the leading trivia (child.kind === SyntaxKind.JsxText && start === child.end); // whitespace only JsxText @@ -755,7 +762,7 @@ namespace ts { } } - Debug.assert(startNode !== undefined || n.kind === SyntaxKind.SourceFile); + Debug.assert(startNode !== undefined || n.kind === SyntaxKind.SourceFile || isJSDocCommentContainingNode(n)); // Here we know that none of child token nodes embrace the position, // the only known case is when position is at the end of the file. @@ -901,42 +908,6 @@ namespace ts { } } - /** - * Get the corresponding JSDocTag node if the position is in a jsDoc comment - */ - export function getJsDocTagAtPosition(sourceFile: SourceFile, position: number): JSDocTag { - let node = ts.getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false); - if (isToken(node)) { - switch (node.kind) { - case SyntaxKind.VarKeyword: - case SyntaxKind.LetKeyword: - case SyntaxKind.ConstKeyword: - // if the current token is var, let or const, skip the VariableDeclarationList - node = node.parent === undefined ? undefined : node.parent.parent; - break; - default: - node = node.parent; - break; - } - } - - if (node) { - if (node.jsDoc) { - for (const jsDoc of node.jsDoc) { - if (jsDoc.tags) { - for (const tag of jsDoc.tags) { - if (tag.pos <= position && position <= tag.end) { - return tag; - } - } - } - } - } - } - - return undefined; - } - function nodeHasTokens(n: Node): boolean { // If we have a token or node that has a non-zero width, it must have tokens. // Note, that getWidth() does not take trivia into account. diff --git a/tests/baselines/reference/2dArrays.symbols b/tests/baselines/reference/2dArrays.symbols index 6f02cdcf963..8d6b6b167e6 100644 --- a/tests/baselines/reference/2dArrays.symbols +++ b/tests/baselines/reference/2dArrays.symbols @@ -25,11 +25,11 @@ class Board { >allShipsSunk : Symbol(Board.allShipsSunk, Decl(2dArrays.ts, 9, 18)) return this.ships.every(function (val) { return val.isSunk; }); ->this.ships.every : Symbol(Array.every, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>this.ships.every : Symbol(Array.every, Decl(lib.d.ts, --, --)) >this.ships : Symbol(Board.ships, Decl(2dArrays.ts, 7, 13)) >this : Symbol(Board, Decl(2dArrays.ts, 5, 1)) >ships : Symbol(Board.ships, Decl(2dArrays.ts, 7, 13)) ->every : Symbol(Array.every, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>every : Symbol(Array.every, Decl(lib.d.ts, --, --)) >val : Symbol(val, Decl(2dArrays.ts, 12, 42)) >val.isSunk : Symbol(Ship.isSunk, Decl(2dArrays.ts, 3, 12)) >val : Symbol(val, Decl(2dArrays.ts, 12, 42)) diff --git a/tests/baselines/reference/2dArrays.types b/tests/baselines/reference/2dArrays.types index 45672187306..00805899294 100644 --- a/tests/baselines/reference/2dArrays.types +++ b/tests/baselines/reference/2dArrays.types @@ -26,12 +26,12 @@ class Board { return this.ships.every(function (val) { return val.isSunk; }); >this.ships.every(function (val) { return val.isSunk; }) : boolean ->this.ships.every : { (callbackfn: (this: void, value: Ship, index: number, array: Ship[]) => boolean): boolean; (callbackfn: (this: void, value: Ship, index: number, array: Ship[]) => boolean, thisArg: undefined): boolean; (callbackfn: (this: Z, value: Ship, index: number, array: Ship[]) => boolean, thisArg: Z): boolean; } +>this.ships.every : (callbackfn: (value: Ship, index: number, array: Ship[]) => boolean, thisArg?: any) => boolean >this.ships : Ship[] >this : this >ships : Ship[] ->every : { (callbackfn: (this: void, value: Ship, index: number, array: Ship[]) => boolean): boolean; (callbackfn: (this: void, value: Ship, index: number, array: Ship[]) => boolean, thisArg: undefined): boolean; (callbackfn: (this: Z, value: Ship, index: number, array: Ship[]) => boolean, thisArg: Z): boolean; } ->function (val) { return val.isSunk; } : (this: void, val: Ship) => boolean +>every : (callbackfn: (value: Ship, index: number, array: Ship[]) => boolean, thisArg?: any) => boolean +>function (val) { return val.isSunk; } : (val: Ship) => boolean >val : Ship >val.isSunk : boolean >val : Ship diff --git a/tests/baselines/reference/APISample_watcher.js b/tests/baselines/reference/APISample_watcher.js index b813a44f53e..f4d03f8f62f 100644 --- a/tests/baselines/reference/APISample_watcher.js +++ b/tests/baselines/reference/APISample_watcher.js @@ -11,7 +11,7 @@ declare var fs: { existsSync(path: string): boolean; readdirSync(path: string): string[]; readFileSync(filename: string, encoding?: string): string; - writeFileSync(filename: string, data: any, options?: { encoding?: string; mode?: number; flag?: string; }): void; + writeFileSync(filename: string, data: any, options?: { encoding?: string; mode?: number; flag?: string; } | string): void; watchFile(filename: string, options: { persistent?: boolean; interval?: number; }, listener: (curr: { mtime: Date }, prev: { mtime: Date }) => void): void; }; declare var path: any; diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.argSynonymForParamTag.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.argSynonymForParamTag.json index 92b9cb450e6..b47a07e8487 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.argSynonymForParamTag.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.argSynonymForParamTag.json @@ -40,6 +40,7 @@ "end": 27, "text": "name1" }, + "isBracketed": false, "comment": "Description" }, "length": 1, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.argumentSynonymForParamTag.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.argumentSynonymForParamTag.json index f398fb3af41..cf86fda872e 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.argumentSynonymForParamTag.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.argumentSynonymForParamTag.json @@ -40,6 +40,7 @@ "end": 32, "text": "name1" }, + "isBracketed": false, "comment": "Description" }, "length": 1, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.oneParamTag.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.oneParamTag.json index e70fc95367f..506487232e0 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.oneParamTag.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.oneParamTag.json @@ -40,6 +40,7 @@ "end": 29, "text": "name1" }, + "isBracketed": false, "comment": "" }, "length": 1, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTag1.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTag1.json index 0dbdd83d2ba..abc116d7452 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTag1.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTag1.json @@ -40,6 +40,7 @@ "end": 29, "text": "name1" }, + "isBracketed": false, "comment": "Description text follows" }, "length": 1, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagNameThenType1.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagNameThenType1.json index 204d94779b3..9d66ca3dd55 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagNameThenType1.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagNameThenType1.json @@ -40,6 +40,7 @@ "end": 20, "text": "name1" }, + "isBracketed": false, "comment": "" }, "length": 1, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagNameThenType2.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagNameThenType2.json index 7c79459768b..01d08a103c1 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagNameThenType2.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagNameThenType2.json @@ -40,6 +40,7 @@ "end": 20, "text": "name1" }, + "isBracketed": false, "comment": "Description" }, "length": 1, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramWithoutType.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramWithoutType.json index 2ff182483d9..ab15d24f618 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramWithoutType.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramWithoutType.json @@ -30,6 +30,7 @@ "end": 18, "text": "foo" }, + "isBracketed": false, "comment": "" }, "length": 1, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.twoParamTag2.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.twoParamTag2.json index b51ab3598e6..5ba60030f1b 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.twoParamTag2.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.twoParamTag2.json @@ -40,6 +40,7 @@ "end": 29, "text": "name1" }, + "isBracketed": false, "comment": "" }, "1": { @@ -79,6 +80,7 @@ "end": 55, "text": "name2" }, + "isBracketed": false, "comment": "" }, "length": 2, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.twoParamTagOnSameLine.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.twoParamTagOnSameLine.json index 3c20d5edcbc..7d26097bb34 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.twoParamTagOnSameLine.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.twoParamTagOnSameLine.json @@ -40,6 +40,7 @@ "end": 29, "text": "name1" }, + "isBracketed": false, "comment": "" }, "1": { @@ -79,6 +80,7 @@ "end": 51, "text": "name2" }, + "isBracketed": false, "comment": "" }, "length": 2, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.typedefTagWithChildrenTags.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.typedefTagWithChildrenTags.json index 7a8f9c4bcc9..13826b63d9c 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.typedefTagWithChildrenTags.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.typedefTagWithChildrenTags.json @@ -103,7 +103,8 @@ "pos": 66, "end": 69, "text": "age" - } + }, + "isBracketed": false }, { "kind": "JSDocPropertyTag", @@ -141,7 +142,8 @@ "pos": 93, "end": 97, "text": "name" - } + }, + "isBracketed": false } ] }, diff --git a/tests/baselines/reference/anyInferenceAnonymousFunctions.symbols b/tests/baselines/reference/anyInferenceAnonymousFunctions.symbols index 750c7ba85af..c1b5df88fb0 100644 --- a/tests/baselines/reference/anyInferenceAnonymousFunctions.symbols +++ b/tests/baselines/reference/anyInferenceAnonymousFunctions.symbols @@ -35,16 +35,16 @@ paired.reduce((b3, b4) => b3.concat({}), []); >b3 : Symbol(b3, Decl(anyInferenceAnonymousFunctions.ts, 13, 15)) paired.map((c1) => c1.count); ->paired.map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>paired.map : Symbol(Array.map, Decl(lib.d.ts, --, --)) >paired : Symbol(paired, Decl(anyInferenceAnonymousFunctions.ts, 0, 3)) ->map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>map : Symbol(Array.map, Decl(lib.d.ts, --, --)) >c1 : Symbol(c1, Decl(anyInferenceAnonymousFunctions.ts, 15, 12)) >c1 : Symbol(c1, Decl(anyInferenceAnonymousFunctions.ts, 15, 12)) paired.map(function (c2) { return c2.count; }); ->paired.map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>paired.map : Symbol(Array.map, Decl(lib.d.ts, --, --)) >paired : Symbol(paired, Decl(anyInferenceAnonymousFunctions.ts, 0, 3)) ->map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>map : Symbol(Array.map, Decl(lib.d.ts, --, --)) >c2 : Symbol(c2, Decl(anyInferenceAnonymousFunctions.ts, 16, 21)) >c2 : Symbol(c2, Decl(anyInferenceAnonymousFunctions.ts, 16, 21)) diff --git a/tests/baselines/reference/anyInferenceAnonymousFunctions.types b/tests/baselines/reference/anyInferenceAnonymousFunctions.types index b015d350760..8dc7fdcb90f 100644 --- a/tests/baselines/reference/anyInferenceAnonymousFunctions.types +++ b/tests/baselines/reference/anyInferenceAnonymousFunctions.types @@ -57,10 +57,10 @@ paired.reduce((b3, b4) => b3.concat({}), []); paired.map((c1) => c1.count); >paired.map((c1) => c1.count) : any[] ->paired.map : { (this: [any, any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U, U, U]; (this: [any, any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [any, any, any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U, U]; (this: [any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U, U]; (this: [any, any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U, U]; (this: [any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U]; (this: [any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U]; (this: [any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U]; (this: [any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U]; (this: [any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U]; (this: [any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: any, index: number, array: any[]) => U): U[]; (callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): U[]; } +>paired.map : (callbackfn: (value: any, index: number, array: any[]) => U, thisArg?: any) => U[] >paired : any[] ->map : { (this: [any, any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U, U, U]; (this: [any, any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [any, any, any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U, U]; (this: [any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U, U]; (this: [any, any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U, U]; (this: [any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U]; (this: [any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U]; (this: [any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U]; (this: [any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U]; (this: [any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U]; (this: [any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: any, index: number, array: any[]) => U): U[]; (callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): U[]; } ->(c1) => c1.count : (this: void, c1: any) => any +>map : (callbackfn: (value: any, index: number, array: any[]) => U, thisArg?: any) => U[] +>(c1) => c1.count : (c1: any) => any >c1 : any >c1.count : any >c1 : any @@ -68,10 +68,10 @@ paired.map((c1) => c1.count); paired.map(function (c2) { return c2.count; }); >paired.map(function (c2) { return c2.count; }) : any[] ->paired.map : { (this: [any, any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U, U, U]; (this: [any, any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [any, any, any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U, U]; (this: [any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U, U]; (this: [any, any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U, U]; (this: [any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U]; (this: [any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U]; (this: [any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U]; (this: [any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U]; (this: [any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U]; (this: [any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: any, index: number, array: any[]) => U): U[]; (callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): U[]; } +>paired.map : (callbackfn: (value: any, index: number, array: any[]) => U, thisArg?: any) => U[] >paired : any[] ->map : { (this: [any, any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U, U, U]; (this: [any, any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [any, any, any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U, U]; (this: [any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U, U]; (this: [any, any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U, U]; (this: [any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U]; (this: [any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U]; (this: [any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U]; (this: [any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U]; (this: [any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U]; (this: [any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: any, index: number, array: any[]) => U): U[]; (callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): U[]; } ->function (c2) { return c2.count; } : (this: void, c2: any) => any +>map : (callbackfn: (value: any, index: number, array: any[]) => U, thisArg?: any) => U[] +>function (c2) { return c2.count; } : (c2: any) => any >c2 : any >c2.count : any >c2 : any diff --git a/tests/baselines/reference/argumentsAsPropertyName.symbols b/tests/baselines/reference/argumentsAsPropertyName.symbols index a17c660374c..1e3e41abb6e 100644 --- a/tests/baselines/reference/argumentsAsPropertyName.symbols +++ b/tests/baselines/reference/argumentsAsPropertyName.symbols @@ -34,8 +34,8 @@ function myFunction(myType: MyType) { >x : Symbol(x, Decl(argumentsAsPropertyName.ts, 11, 13)) [1, 2, 3].forEach(function(j) { use(x); }) ->[1, 2, 3].forEach : Symbol(Array.forEach, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) ->forEach : Symbol(Array.forEach, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>[1, 2, 3].forEach : Symbol(Array.forEach, Decl(lib.d.ts, --, --)) +>forEach : Symbol(Array.forEach, Decl(lib.d.ts, --, --)) >j : Symbol(j, Decl(argumentsAsPropertyName.ts, 12, 35)) >use : Symbol(use, Decl(argumentsAsPropertyName.ts, 3, 1)) >x : Symbol(x, Decl(argumentsAsPropertyName.ts, 11, 13)) diff --git a/tests/baselines/reference/argumentsAsPropertyName.types b/tests/baselines/reference/argumentsAsPropertyName.types index 73397199436..d0aaaa1cc72 100644 --- a/tests/baselines/reference/argumentsAsPropertyName.types +++ b/tests/baselines/reference/argumentsAsPropertyName.types @@ -42,13 +42,13 @@ function myFunction(myType: MyType) { [1, 2, 3].forEach(function(j) { use(x); }) >[1, 2, 3].forEach(function(j) { use(x); }) : void ->[1, 2, 3].forEach : { (callbackfn: (this: void, value: number, index: number, array: number[]) => void): void; (callbackfn: (this: void, value: number, index: number, array: number[]) => void, thisArg: undefined): void; (callbackfn: (this: Z, value: number, index: number, array: number[]) => void, thisArg: Z): void; } +>[1, 2, 3].forEach : (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void >[1, 2, 3] : number[] >1 : 1 >2 : 2 >3 : 3 ->forEach : { (callbackfn: (this: void, value: number, index: number, array: number[]) => void): void; (callbackfn: (this: void, value: number, index: number, array: number[]) => void, thisArg: undefined): void; (callbackfn: (this: Z, value: number, index: number, array: number[]) => void, thisArg: Z): void; } ->function(j) { use(x); } : (this: void, j: number) => void +>forEach : (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void +>function(j) { use(x); } : (j: number) => void >j : number >use(x) : any >use : (s: any) => any diff --git a/tests/baselines/reference/argumentsObjectCreatesRestForJs.symbols b/tests/baselines/reference/argumentsObjectCreatesRestForJs.symbols new file mode 100644 index 00000000000..6a95dbc86d8 --- /dev/null +++ b/tests/baselines/reference/argumentsObjectCreatesRestForJs.symbols @@ -0,0 +1,44 @@ +=== tests/cases/compiler/main.js === +function allRest() { arguments; } +>allRest : Symbol(allRest, Decl(main.js, 0, 0)) +>arguments : Symbol(arguments) + +allRest(); +>allRest : Symbol(allRest, Decl(main.js, 0, 0)) + +allRest(1, 2, 3); +>allRest : Symbol(allRest, Decl(main.js, 0, 0)) + +function someRest(x, y) { arguments; } +>someRest : Symbol(someRest, Decl(main.js, 2, 17)) +>x : Symbol(x, Decl(main.js, 3, 18)) +>y : Symbol(y, Decl(main.js, 3, 20)) +>arguments : Symbol(arguments) + +someRest(); // x and y are still optional because they are in a JS file +>someRest : Symbol(someRest, Decl(main.js, 2, 17)) + +someRest(1, 2, 3); +>someRest : Symbol(someRest, Decl(main.js, 2, 17)) + +/** + * @param {number} x - a thing + */ +function jsdocced(x) { arguments; } +>jsdocced : Symbol(jsdocced, Decl(main.js, 5, 18)) +>x : Symbol(x, Decl(main.js, 10, 18)) +>arguments : Symbol(arguments) + +jsdocced(1); +>jsdocced : Symbol(jsdocced, Decl(main.js, 5, 18)) + +function dontDoubleRest(x, ...y) { arguments; } +>dontDoubleRest : Symbol(dontDoubleRest, Decl(main.js, 11, 12)) +>x : Symbol(x, Decl(main.js, 13, 24)) +>y : Symbol(y, Decl(main.js, 13, 26)) +>arguments : Symbol(arguments) + +dontDoubleRest(1, 2, 3); +>dontDoubleRest : Symbol(dontDoubleRest, Decl(main.js, 11, 12)) + + diff --git a/tests/baselines/reference/argumentsObjectCreatesRestForJs.types b/tests/baselines/reference/argumentsObjectCreatesRestForJs.types new file mode 100644 index 00000000000..10596fb10c7 --- /dev/null +++ b/tests/baselines/reference/argumentsObjectCreatesRestForJs.types @@ -0,0 +1,60 @@ +=== tests/cases/compiler/main.js === +function allRest() { arguments; } +>allRest : (...args: any[]) => void +>arguments : IArguments + +allRest(); +>allRest() : void +>allRest : (...args: any[]) => void + +allRest(1, 2, 3); +>allRest(1, 2, 3) : void +>allRest : (...args: any[]) => void +>1 : 1 +>2 : 2 +>3 : 3 + +function someRest(x, y) { arguments; } +>someRest : (x: any, y: any, ...args: any[]) => void +>x : any +>y : any +>arguments : IArguments + +someRest(); // x and y are still optional because they are in a JS file +>someRest() : void +>someRest : (x: any, y: any, ...args: any[]) => void + +someRest(1, 2, 3); +>someRest(1, 2, 3) : void +>someRest : (x: any, y: any, ...args: any[]) => void +>1 : 1 +>2 : 2 +>3 : 3 + +/** + * @param {number} x - a thing + */ +function jsdocced(x) { arguments; } +>jsdocced : (x: number) => void +>x : number +>arguments : IArguments + +jsdocced(1); +>jsdocced(1) : void +>jsdocced : (x: number) => void +>1 : 1 + +function dontDoubleRest(x, ...y) { arguments; } +>dontDoubleRest : (x: any, ...y: any[]) => void +>x : any +>y : any[] +>arguments : IArguments + +dontDoubleRest(1, 2, 3); +>dontDoubleRest(1, 2, 3) : void +>dontDoubleRest : (x: any, ...y: any[]) => void +>1 : 1 +>2 : 2 +>3 : 3 + + diff --git a/tests/baselines/reference/arrayConcatMap.symbols b/tests/baselines/reference/arrayConcatMap.symbols index 1b26708ae94..5ef9d811723 100644 --- a/tests/baselines/reference/arrayConcatMap.symbols +++ b/tests/baselines/reference/arrayConcatMap.symbols @@ -1,14 +1,14 @@ === tests/cases/compiler/arrayConcatMap.ts === var x = [].concat([{ a: 1 }], [{ a: 2 }]) >x : Symbol(x, Decl(arrayConcatMap.ts, 0, 3)) ->[].concat([{ a: 1 }], [{ a: 2 }]) .map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>[].concat([{ a: 1 }], [{ a: 2 }]) .map : Symbol(Array.map, Decl(lib.d.ts, --, --)) >[].concat : Symbol(Array.concat, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >concat : Symbol(Array.concat, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >a : Symbol(a, Decl(arrayConcatMap.ts, 0, 20)) >a : Symbol(a, Decl(arrayConcatMap.ts, 0, 32)) .map(b => b.a); ->map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>map : Symbol(Array.map, Decl(lib.d.ts, --, --)) >b : Symbol(b, Decl(arrayConcatMap.ts, 1, 15)) >b : Symbol(b, Decl(arrayConcatMap.ts, 1, 15)) diff --git a/tests/baselines/reference/arrayConcatMap.types b/tests/baselines/reference/arrayConcatMap.types index b234b7beb26..89289e58d4e 100644 --- a/tests/baselines/reference/arrayConcatMap.types +++ b/tests/baselines/reference/arrayConcatMap.types @@ -2,7 +2,7 @@ var x = [].concat([{ a: 1 }], [{ a: 2 }]) >x : any[] >[].concat([{ a: 1 }], [{ a: 2 }]) .map(b => b.a) : any[] ->[].concat([{ a: 1 }], [{ a: 2 }]) .map : { (this: [any, any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U, U, U]; (this: [any, any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [any, any, any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U, U]; (this: [any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U, U]; (this: [any, any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U, U]; (this: [any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U]; (this: [any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U]; (this: [any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U]; (this: [any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U]; (this: [any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U]; (this: [any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: any, index: number, array: any[]) => U): U[]; (callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): U[]; } +>[].concat([{ a: 1 }], [{ a: 2 }]) .map : (callbackfn: (value: any, index: number, array: any[]) => U, thisArg?: any) => U[] >[].concat([{ a: 1 }], [{ a: 2 }]) : any[] >[].concat : { (...items: any[][]): any[]; (...items: any[]): any[]; } >[] : undefined[] @@ -17,8 +17,8 @@ var x = [].concat([{ a: 1 }], [{ a: 2 }]) >2 : 2 .map(b => b.a); ->map : { (this: [any, any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U, U, U]; (this: [any, any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [any, any, any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U, U]; (this: [any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U, U]; (this: [any, any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U, U]; (this: [any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U]; (this: [any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U]; (this: [any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U]; (this: [any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U]; (this: [any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U]; (this: [any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: any, index: number, array: any[]) => U): U[]; (callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): U[]; } ->b => b.a : (this: void, b: any) => any +>map : (callbackfn: (value: any, index: number, array: any[]) => U, thisArg?: any) => U[] +>b => b.a : (b: any) => any >b : any >b.a : any >b : any diff --git a/tests/baselines/reference/arrayFilter.symbols b/tests/baselines/reference/arrayFilter.symbols index 81d92ba04b6..cba8f48c89f 100644 --- a/tests/baselines/reference/arrayFilter.symbols +++ b/tests/baselines/reference/arrayFilter.symbols @@ -14,9 +14,9 @@ var foo = [ ] foo.filter(x => x.name); //should accepted all possible types not only boolean! ->foo.filter : Symbol(Array.filter, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>foo.filter : Symbol(Array.filter, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >foo : Symbol(foo, Decl(arrayFilter.ts, 0, 3)) ->filter : Symbol(Array.filter, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>filter : Symbol(Array.filter, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >x : Symbol(x, Decl(arrayFilter.ts, 6, 11)) >x.name : Symbol(name, Decl(arrayFilter.ts, 1, 5)) >x : Symbol(x, Decl(arrayFilter.ts, 6, 11)) diff --git a/tests/baselines/reference/arrayFilter.types b/tests/baselines/reference/arrayFilter.types index 23ab4d915bd..7d91ef4ed32 100644 --- a/tests/baselines/reference/arrayFilter.types +++ b/tests/baselines/reference/arrayFilter.types @@ -22,10 +22,10 @@ var foo = [ foo.filter(x => x.name); //should accepted all possible types not only boolean! >foo.filter(x => x.name) : { name: string; }[] ->foo.filter : { (callbackfn: (this: void, value: { name: string; }, index: number, array: { name: string; }[]) => any): { name: string; }[]; (callbackfn: (this: void, value: { name: string; }, index: number, array: { name: string; }[]) => any, thisArg: undefined): { name: string; }[]; (callbackfn: (this: Z, value: { name: string; }, index: number, array: { name: string; }[]) => any, thisArg: Z): { name: string; }[]; } +>foo.filter : { (callbackfn: (value: { name: string; }, index: number, array: { name: string; }[]) => value is S, thisArg?: any): S[]; (callbackfn: (value: { name: string; }, index: number, array: { name: string; }[]) => any, thisArg?: any): { name: string; }[]; } >foo : { name: string; }[] ->filter : { (callbackfn: (this: void, value: { name: string; }, index: number, array: { name: string; }[]) => any): { name: string; }[]; (callbackfn: (this: void, value: { name: string; }, index: number, array: { name: string; }[]) => any, thisArg: undefined): { name: string; }[]; (callbackfn: (this: Z, value: { name: string; }, index: number, array: { name: string; }[]) => any, thisArg: Z): { name: string; }[]; } ->x => x.name : (this: void, x: { name: string; }) => string +>filter : { (callbackfn: (value: { name: string; }, index: number, array: { name: string; }[]) => value is S, thisArg?: any): S[]; (callbackfn: (value: { name: string; }, index: number, array: { name: string; }[]) => any, thisArg?: any): { name: string; }[]; } +>x => x.name : (x: { name: string; }) => string >x : { name: string; } >x.name : string >x : { name: string; } diff --git a/tests/baselines/reference/arrayOfSubtypeIsAssignableToReadonlyArray.errors.txt b/tests/baselines/reference/arrayOfSubtypeIsAssignableToReadonlyArray.errors.txt index 90dc909b11a..df24be3a020 100644 --- a/tests/baselines/reference/arrayOfSubtypeIsAssignableToReadonlyArray.errors.txt +++ b/tests/baselines/reference/arrayOfSubtypeIsAssignableToReadonlyArray.errors.txt @@ -1,12 +1,12 @@ tests/cases/compiler/arrayOfSubtypeIsAssignableToReadonlyArray.ts(13,1): error TS2322: Type 'A[]' is not assignable to type 'ReadonlyArray'. Types of property 'concat' are incompatible. - Type '{ (...items: A[][]): A[]; (...items: (A | A[])[]): A[]; }' is not assignable to type '{ >(...items: U[]): B[]; (...items: B[][]): B[]; (...items: (B | B[])[]): B[]; }'. + Type '{ (...items: A[][]): A[]; (...items: (A | A[])[]): A[]; }' is not assignable to type '{ (...items: B[][]): B[]; (...items: (B | B[])[]): B[]; }'. Type 'A[]' is not assignable to type 'B[]'. Type 'A' is not assignable to type 'B'. Property 'b' is missing in type 'A'. tests/cases/compiler/arrayOfSubtypeIsAssignableToReadonlyArray.ts(18,1): error TS2322: Type 'C' is not assignable to type 'ReadonlyArray'. Types of property 'concat' are incompatible. - Type '{ (...items: A[][]): A[]; (...items: (A | A[])[]): A[]; }' is not assignable to type '{ >(...items: U[]): B[]; (...items: B[][]): B[]; (...items: (B | B[])[]): B[]; }'. + Type '{ (...items: A[][]): A[]; (...items: (A | A[])[]): A[]; }' is not assignable to type '{ (...items: B[][]): B[]; (...items: (B | B[])[]): B[]; }'. Type 'A[]' is not assignable to type 'B[]'. @@ -27,7 +27,7 @@ tests/cases/compiler/arrayOfSubtypeIsAssignableToReadonlyArray.ts(18,1): error T ~~~ !!! error TS2322: Type 'A[]' is not assignable to type 'ReadonlyArray'. !!! error TS2322: Types of property 'concat' are incompatible. -!!! error TS2322: Type '{ (...items: A[][]): A[]; (...items: (A | A[])[]): A[]; }' is not assignable to type '{ >(...items: U[]): B[]; (...items: B[][]): B[]; (...items: (B | B[])[]): B[]; }'. +!!! error TS2322: Type '{ (...items: A[][]): A[]; (...items: (A | A[])[]): A[]; }' is not assignable to type '{ (...items: B[][]): B[]; (...items: (B | B[])[]): B[]; }'. !!! error TS2322: Type 'A[]' is not assignable to type 'B[]'. !!! error TS2322: Type 'A' is not assignable to type 'B'. !!! error TS2322: Property 'b' is missing in type 'A'. @@ -39,6 +39,6 @@ tests/cases/compiler/arrayOfSubtypeIsAssignableToReadonlyArray.ts(18,1): error T ~~~ !!! error TS2322: Type 'C' is not assignable to type 'ReadonlyArray'. !!! error TS2322: Types of property 'concat' are incompatible. -!!! error TS2322: Type '{ (...items: A[][]): A[]; (...items: (A | A[])[]): A[]; }' is not assignable to type '{ >(...items: U[]): B[]; (...items: B[][]): B[]; (...items: (B | B[])[]): B[]; }'. +!!! error TS2322: Type '{ (...items: A[][]): A[]; (...items: (A | A[])[]): A[]; }' is not assignable to type '{ (...items: B[][]): B[]; (...items: (B | B[])[]): B[]; }'. !!! error TS2322: Type 'A[]' is not assignable to type 'B[]'. \ No newline at end of file diff --git a/tests/baselines/reference/assignmentCompatWithCallSignatures3.errors.txt b/tests/baselines/reference/assignmentCompatWithCallSignatures3.errors.txt index 0e8605efafd..28fe7c738a6 100644 --- a/tests/baselines/reference/assignmentCompatWithCallSignatures3.errors.txt +++ b/tests/baselines/reference/assignmentCompatWithCallSignatures3.errors.txt @@ -1,11 +1,58 @@ +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures3.ts(47,1): error TS2322: Type '(x: number) => number[]' is not assignable to type '(x: T) => T[]'. + Types of parameters 'x' and 'x' are incompatible. + Type 'T' is not assignable to type 'number'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures3.ts(50,1): error TS2322: Type '(x: number) => string[]' is not assignable to type '(x: T) => string[]'. + Types of parameters 'x' and 'x' are incompatible. + Type 'T' is not assignable to type 'number'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures3.ts(53,1): error TS2322: Type '(x: number) => void' is not assignable to type '(x: T) => T'. + Types of parameters 'x' and 'x' are incompatible. + Type 'T' is not assignable to type 'number'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures3.ts(56,1): error TS2322: Type '(x: string, y: number) => string' is not assignable to type '(x: T, y: U) => T'. + Types of parameters 'x' and 'x' are incompatible. + Type 'T' is not assignable to type 'string'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures3.ts(59,1): error TS2322: Type '(x: (arg: string) => number) => string' is not assignable to type '(x: (arg: T) => U) => T'. + Types of parameters 'x' and 'x' are incompatible. + Types of parameters 'arg' and 'arg' are incompatible. + Type 'string' is not assignable to type 'T'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures3.ts(62,1): error TS2322: Type '(x: (arg: Base) => Derived) => Base' is not assignable to type '(x: (arg: T) => U) => T'. + Types of parameters 'x' and 'x' are incompatible. + Types of parameters 'arg' and 'arg' are incompatible. + Type 'Base' is not assignable to type 'T'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures3.ts(65,1): error TS2322: Type '(x: (arg: Base) => Derived) => (r: Base) => Derived' is not assignable to type '(x: (arg: T) => U) => (r: T) => U'. + Types of parameters 'x' and 'x' are incompatible. + Types of parameters 'arg' and 'arg' are incompatible. + Type 'Base' is not assignable to type 'T'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures3.ts(68,1): error TS2322: Type '(x: (arg: Base) => Derived, y: (arg2: Base) => Derived) => (r: Base) => Derived' is not assignable to type '(x: (arg: T) => U, y: (arg2: T) => U) => (r: T) => U'. + Types of parameters 'x' and 'x' are incompatible. + Types of parameters 'arg' and 'arg' are incompatible. + Type 'Base' is not assignable to type 'T'. tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures3.ts(71,1): error TS2322: Type '(x: (arg: Base) => Derived, y: (arg2: Base) => Derived) => (r: Base) => Derived' is not assignable to type '(x: (arg: T) => U, y: (arg2: { foo: string; bing: number; }) => U) => (r: T) => U'. + Types of parameters 'x' and 'x' are incompatible. + Types of parameters 'arg' and 'arg' are incompatible. + Type 'Base' is not assignable to type 'T'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures3.ts(74,1): error TS2322: Type '(...x: Derived[]) => Derived' is not assignable to type '(...x: T[]) => T'. + Type 'Derived' is not assignable to type 'T'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures3.ts(77,1): error TS2322: Type '(x: { foo: string; }, y: { foo: string; bar: string; }) => Base' is not assignable to type '(x: T, y: T) => T'. Types of parameters 'y' and 'y' are incompatible. - Types of parameters 'arg2' and 'arg2' are incompatible. - Type 'Base' is not assignable to type '{ foo: string; bing: number; }'. - Property 'bing' is missing in type 'Base'. + Type 'T' is not assignable to type '{ foo: string; bar: string; }'. + Type 'Base' is not assignable to type '{ foo: string; bar: string; }'. + Property 'bar' is missing in type 'Base'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures3.ts(80,1): error TS2322: Type '(x: Base[], y: Derived2[]) => Derived[]' is not assignable to type '(x: Base[], y: T) => Derived[]'. + Types of parameters 'y' and 'y' are incompatible. + Type 'T' is not assignable to type 'Derived2[]'. + Type 'Base[]' is not assignable to type 'Derived2[]'. + Type 'Base' is not assignable to type 'Derived2'. + Property 'baz' is missing in type 'Base'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures3.ts(83,1): error TS2322: Type '(x: Base[], y: Derived[]) => Derived[]' is not assignable to type '(x: Base[], y: T) => T'. + Type 'Derived[]' is not assignable to type 'T'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures3.ts(86,1): error TS2322: Type '(x: { a: string; b: number; }) => Object' is not assignable to type '(x: { a: T; b: T; }) => T'. + Types of parameters 'x' and 'x' are incompatible. + Type '{ a: T; b: T; }' is not assignable to type '{ a: string; b: number; }'. + Types of property 'a' are incompatible. + Type 'T' is not assignable to type 'string'. -==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures3.ts (1 errors) ==== +==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures3.ts (14 errors) ==== // these are all permitted with the current rules, since we do not do contextual signature instantiation class Base { foo: string; } @@ -53,51 +100,111 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme var b: (x: T) => T[]; a = b; // ok b = a; // ok + ~ +!!! error TS2322: Type '(x: number) => number[]' is not assignable to type '(x: T) => T[]'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'number'. var b2: (x: T) => string[]; a2 = b2; // ok b2 = a2; // ok + ~~ +!!! error TS2322: Type '(x: number) => string[]' is not assignable to type '(x: T) => string[]'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'number'. var b3: (x: T) => T; a3 = b3; // ok b3 = a3; // ok + ~~ +!!! error TS2322: Type '(x: number) => void' is not assignable to type '(x: T) => T'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'number'. var b4: (x: T, y: U) => T; a4 = b4; // ok b4 = a4; // ok + ~~ +!!! error TS2322: Type '(x: string, y: number) => string' is not assignable to type '(x: T, y: U) => T'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'string'. var b5: (x: (arg: T) => U) => T; a5 = b5; // ok b5 = a5; // ok + ~~ +!!! error TS2322: Type '(x: (arg: string) => number) => string' is not assignable to type '(x: (arg: T) => U) => T'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Types of parameters 'arg' and 'arg' are incompatible. +!!! error TS2322: Type 'string' is not assignable to type 'T'. var b6: (x: (arg: T) => U) => T; a6 = b6; // ok b6 = a6; // ok + ~~ +!!! error TS2322: Type '(x: (arg: Base) => Derived) => Base' is not assignable to type '(x: (arg: T) => U) => T'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Types of parameters 'arg' and 'arg' are incompatible. +!!! error TS2322: Type 'Base' is not assignable to type 'T'. var b7: (x: (arg: T) => U) => (r: T) => U; a7 = b7; // ok b7 = a7; // ok + ~~ +!!! error TS2322: Type '(x: (arg: Base) => Derived) => (r: Base) => Derived' is not assignable to type '(x: (arg: T) => U) => (r: T) => U'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Types of parameters 'arg' and 'arg' are incompatible. +!!! error TS2322: Type 'Base' is not assignable to type 'T'. var b8: (x: (arg: T) => U, y: (arg2: T) => U) => (r: T) => U; a8 = b8; // ok b8 = a8; // ok + ~~ +!!! error TS2322: Type '(x: (arg: Base) => Derived, y: (arg2: Base) => Derived) => (r: Base) => Derived' is not assignable to type '(x: (arg: T) => U, y: (arg2: T) => U) => (r: T) => U'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Types of parameters 'arg' and 'arg' are incompatible. +!!! error TS2322: Type 'Base' is not assignable to type 'T'. var b9: (x: (arg: T) => U, y: (arg2: { foo: string; bing: number }) => U) => (r: T) => U; a9 = b9; // ok b9 = a9; // ok ~~ !!! error TS2322: Type '(x: (arg: Base) => Derived, y: (arg2: Base) => Derived) => (r: Base) => Derived' is not assignable to type '(x: (arg: T) => U, y: (arg2: { foo: string; bing: number; }) => U) => (r: T) => U'. -!!! error TS2322: Types of parameters 'y' and 'y' are incompatible. -!!! error TS2322: Types of parameters 'arg2' and 'arg2' are incompatible. -!!! error TS2322: Type 'Base' is not assignable to type '{ foo: string; bing: number; }'. -!!! error TS2322: Property 'bing' is missing in type 'Base'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Types of parameters 'arg' and 'arg' are incompatible. +!!! error TS2322: Type 'Base' is not assignable to type 'T'. var b10: (...x: T[]) => T; a10 = b10; // ok b10 = a10; // ok + ~~~ +!!! error TS2322: Type '(...x: Derived[]) => Derived' is not assignable to type '(...x: T[]) => T'. +!!! error TS2322: Type 'Derived' is not assignable to type 'T'. var b11: (x: T, y: T) => T; a11 = b11; // ok b11 = a11; // ok + ~~~ +!!! error TS2322: Type '(x: { foo: string; }, y: { foo: string; bar: string; }) => Base' is not assignable to type '(x: T, y: T) => T'. +!!! error TS2322: Types of parameters 'y' and 'y' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type '{ foo: string; bar: string; }'. +!!! error TS2322: Type 'Base' is not assignable to type '{ foo: string; bar: string; }'. +!!! error TS2322: Property 'bar' is missing in type 'Base'. var b12: >(x: Array, y: T) => Array; a12 = b12; // ok b12 = a12; // ok + ~~~ +!!! error TS2322: Type '(x: Base[], y: Derived2[]) => Derived[]' is not assignable to type '(x: Base[], y: T) => Derived[]'. +!!! error TS2322: Types of parameters 'y' and 'y' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'Derived2[]'. +!!! error TS2322: Type 'Base[]' is not assignable to type 'Derived2[]'. +!!! error TS2322: Type 'Base' is not assignable to type 'Derived2'. +!!! error TS2322: Property 'baz' is missing in type 'Base'. var b13: >(x: Array, y: T) => T; a13 = b13; // ok b13 = a13; // ok + ~~~ +!!! error TS2322: Type '(x: Base[], y: Derived[]) => Derived[]' is not assignable to type '(x: Base[], y: T) => T'. +!!! error TS2322: Type 'Derived[]' is not assignable to type 'T'. var b14: (x: { a: T; b: T }) => T; a14 = b14; // ok b14 = a14; // ok + ~~~ +!!! error TS2322: Type '(x: { a: string; b: number; }) => Object' is not assignable to type '(x: { a: T; b: T; }) => T'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type '{ a: T; b: T; }' is not assignable to type '{ a: string; b: number; }'. +!!! error TS2322: Types of property 'a' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'string'. var b15: (x: T) => T[]; a15 = b15; // ok b15 = a15; // ok diff --git a/tests/baselines/reference/assignmentCompatWithCallSignatures4.errors.txt b/tests/baselines/reference/assignmentCompatWithCallSignatures4.errors.txt index df391b27f98..39d3a2a3593 100644 --- a/tests/baselines/reference/assignmentCompatWithCallSignatures4.errors.txt +++ b/tests/baselines/reference/assignmentCompatWithCallSignatures4.errors.txt @@ -1,3 +1,10 @@ +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures4.ts(45,9): error TS2322: Type '(x: number) => string[]' is not assignable to type '(x: T) => U[]'. + Types of parameters 'x' and 'x' are incompatible. + Type 'T' is not assignable to type 'number'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures4.ts(49,9): error TS2322: Type '(x: (arg: Base) => Derived) => (r: Base) => Derived2' is not assignable to type '(x: (arg: T) => U) => (r: T) => V'. + Types of parameters 'x' and 'x' are incompatible. + Types of parameters 'arg' and 'arg' are incompatible. + Type 'Base' is not assignable to type 'T'. tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures4.ts(52,9): error TS2322: Type '(x: (arg: T) => U, y: (arg2: { foo: number; }) => U) => (r: T) => U' is not assignable to type '(x: (arg: Base) => Derived, y: (arg2: Base) => Derived) => (r: Base) => Derived'. Types of parameters 'y' and 'y' are incompatible. Types of parameters 'arg2' and 'arg2' are incompatible. @@ -5,14 +12,49 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme Types of property 'foo' are incompatible. Type 'number' is not assignable to type 'string'. tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures4.ts(53,9): error TS2322: Type '(x: (arg: Base) => Derived, y: (arg2: Base) => Derived) => (r: Base) => Derived' is not assignable to type '(x: (arg: T) => U, y: (arg2: { foo: number; }) => U) => (r: T) => U'. - Types of parameters 'y' and 'y' are incompatible. - Types of parameters 'arg2' and 'arg2' are incompatible. - Type 'Base' is not assignable to type '{ foo: number; }'. - Types of property 'foo' are incompatible. - Type 'string' is not assignable to type 'number'. + Types of parameters 'x' and 'x' are incompatible. + Types of parameters 'arg' and 'arg' are incompatible. + Type 'Base' is not assignable to type 'T'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures4.ts(58,9): error TS2322: Type '(...x: Base[]) => Base' is not assignable to type '(...x: T[]) => T'. + Type 'Base' is not assignable to type 'T'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures4.ts(62,9): error TS2322: Type '(x: { foo: string; }, y: { foo: string; bar: string; }) => Base' is not assignable to type '(x: T, y: T) => T'. + Type 'Base' is not assignable to type 'T'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures4.ts(66,9): error TS2322: Type '(x: Base[], y: Derived2[]) => Derived[]' is not assignable to type '(x: Base[], y: Base[]) => T'. + Type 'Derived[]' is not assignable to type 'T'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures4.ts(69,9): error TS2322: Type '(x: { a: T; b: T; }) => T' is not assignable to type '(x: { a: string; b: number; }) => number'. + Type 'string | number' is not assignable to type 'number'. + Type 'string' is not assignable to type 'number'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures4.ts(70,9): error TS2322: Type '(x: { a: string; b: number; }) => number' is not assignable to type '(x: { a: T; b: T; }) => T'. + Types of parameters 'x' and 'x' are incompatible. + Type '{ a: T; b: T; }' is not assignable to type '{ a: string; b: number; }'. + Types of property 'a' are incompatible. + Type 'T' is not assignable to type 'string'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures4.ts(73,9): error TS2322: Type '(x: { a: T; b: T; }) => number' is not assignable to type '(x: { a: string; b: number; }) => number'. + Types of parameters 'x' and 'x' are incompatible. + Type '{ a: string; b: number; }' is not assignable to type '{ a: Base; b: Base; }'. + Types of property 'a' are incompatible. + Type 'string' is not assignable to type 'Base'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures4.ts(74,9): error TS2322: Type '(x: { a: string; b: number; }) => number' is not assignable to type '(x: { a: T; b: T; }) => number'. + Types of parameters 'x' and 'x' are incompatible. + Type '{ a: T; b: T; }' is not assignable to type '{ a: string; b: number; }'. + Types of property 'a' are incompatible. + Type 'T' is not assignable to type 'string'. + Type 'Base' is not assignable to type 'string'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures4.ts(89,9): error TS2322: Type '(x: T) => string[]' is not assignable to type '(x: T) => T[]'. + Type 'string[]' is not assignable to type 'T[]'. + Type 'string' is not assignable to type 'T'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures4.ts(90,9): error TS2322: Type '(x: T) => T[]' is not assignable to type '(x: T) => string[]'. + Type 'T[]' is not assignable to type 'string[]'. + Type 'T' is not assignable to type 'string'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures4.ts(95,9): error TS2322: Type '(x: T) => T[]' is not assignable to type '(x: T) => string[]'. + Type 'T[]' is not assignable to type 'string[]'. + Type 'T' is not assignable to type 'string'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures4.ts(96,9): error TS2322: Type '(x: T) => string[]' is not assignable to type '(x: T) => T[]'. + Type 'string[]' is not assignable to type 'T[]'. + Type 'string' is not assignable to type 'T'. -==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures4.ts (2 errors) ==== +==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures4.ts (15 errors) ==== // These are mostly permitted with the current loose rules. All ok unless otherwise noted. module Errors { @@ -58,10 +100,19 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme var b2: (x: T) => U[]; a2 = b2; b2 = a2; + ~~ +!!! error TS2322: Type '(x: number) => string[]' is not assignable to type '(x: T) => U[]'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'number'. var b7: (x: (arg: T) => U) => (r: T) => V; a7 = b7; b7 = a7; + ~~ +!!! error TS2322: Type '(x: (arg: Base) => Derived) => (r: Base) => Derived2' is not assignable to type '(x: (arg: T) => U) => (r: T) => V'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Types of parameters 'arg' and 'arg' are incompatible. +!!! error TS2322: Type 'Base' is not assignable to type 'T'. var b8: (x: (arg: T) => U, y: (arg2: { foo: number; }) => U) => (r: T) => U; a8 = b8; // error, { foo: number } and Base are incompatible @@ -75,32 +126,62 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme b8 = a8; // error, { foo: number } and Base are incompatible ~~ !!! error TS2322: Type '(x: (arg: Base) => Derived, y: (arg2: Base) => Derived) => (r: Base) => Derived' is not assignable to type '(x: (arg: T) => U, y: (arg2: { foo: number; }) => U) => (r: T) => U'. -!!! error TS2322: Types of parameters 'y' and 'y' are incompatible. -!!! error TS2322: Types of parameters 'arg2' and 'arg2' are incompatible. -!!! error TS2322: Type 'Base' is not assignable to type '{ foo: number; }'. -!!! error TS2322: Types of property 'foo' are incompatible. -!!! error TS2322: Type 'string' is not assignable to type 'number'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Types of parameters 'arg' and 'arg' are incompatible. +!!! error TS2322: Type 'Base' is not assignable to type 'T'. var b10: (...x: T[]) => T; a10 = b10; b10 = a10; + ~~~ +!!! error TS2322: Type '(...x: Base[]) => Base' is not assignable to type '(...x: T[]) => T'. +!!! error TS2322: Type 'Base' is not assignable to type 'T'. var b11: (x: T, y: T) => T; a11 = b11; b11 = a11; + ~~~ +!!! error TS2322: Type '(x: { foo: string; }, y: { foo: string; bar: string; }) => Base' is not assignable to type '(x: T, y: T) => T'. +!!! error TS2322: Type 'Base' is not assignable to type 'T'. var b12: >(x: Array, y: Array) => T; a12 = b12; b12 = a12; + ~~~ +!!! error TS2322: Type '(x: Base[], y: Derived2[]) => Derived[]' is not assignable to type '(x: Base[], y: Base[]) => T'. +!!! error TS2322: Type 'Derived[]' is not assignable to type 'T'. var b15: (x: { a: T; b: T }) => T; a15 = b15; + ~~~ +!!! error TS2322: Type '(x: { a: T; b: T; }) => T' is not assignable to type '(x: { a: string; b: number; }) => number'. +!!! error TS2322: Type 'string | number' is not assignable to type 'number'. +!!! error TS2322: Type 'string' is not assignable to type 'number'. b15 = a15; + ~~~ +!!! error TS2322: Type '(x: { a: string; b: number; }) => number' is not assignable to type '(x: { a: T; b: T; }) => T'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type '{ a: T; b: T; }' is not assignable to type '{ a: string; b: number; }'. +!!! error TS2322: Types of property 'a' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'string'. var b15a: (x: { a: T; b: T }) => number; a15 = b15a; + ~~~ +!!! error TS2322: Type '(x: { a: T; b: T; }) => number' is not assignable to type '(x: { a: string; b: number; }) => number'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type '{ a: string; b: number; }' is not assignable to type '{ a: Base; b: Base; }'. +!!! error TS2322: Types of property 'a' are incompatible. +!!! error TS2322: Type 'string' is not assignable to type 'Base'. b15a = a15; + ~~~~ +!!! error TS2322: Type '(x: { a: string; b: number; }) => number' is not assignable to type '(x: { a: T; b: T; }) => number'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type '{ a: T; b: T; }' is not assignable to type '{ a: string; b: number; }'. +!!! error TS2322: Types of property 'a' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'string'. +!!! error TS2322: Type 'Base' is not assignable to type 'string'. var b16: (x: (a: T) => T) => T[]; a16 = b16; @@ -116,12 +197,28 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme var a2: (x: T) => T[]; var b2: (x: T) => string[]; a2 = b2; + ~~ +!!! error TS2322: Type '(x: T) => string[]' is not assignable to type '(x: T) => T[]'. +!!! error TS2322: Type 'string[]' is not assignable to type 'T[]'. +!!! error TS2322: Type 'string' is not assignable to type 'T'. b2 = a2; + ~~ +!!! error TS2322: Type '(x: T) => T[]' is not assignable to type '(x: T) => string[]'. +!!! error TS2322: Type 'T[]' is not assignable to type 'string[]'. +!!! error TS2322: Type 'T' is not assignable to type 'string'. // target type has generic call signature var a3: (x: T) => string[]; var b3: (x: T) => T[]; a3 = b3; + ~~ +!!! error TS2322: Type '(x: T) => T[]' is not assignable to type '(x: T) => string[]'. +!!! error TS2322: Type 'T[]' is not assignable to type 'string[]'. +!!! error TS2322: Type 'T' is not assignable to type 'string'. b3 = a3; + ~~ +!!! error TS2322: Type '(x: T) => string[]' is not assignable to type '(x: T) => T[]'. +!!! error TS2322: Type 'string[]' is not assignable to type 'T[]'. +!!! error TS2322: Type 'string' is not assignable to type 'T'. } } \ No newline at end of file diff --git a/tests/baselines/reference/assignmentCompatWithCallSignatures5.errors.txt b/tests/baselines/reference/assignmentCompatWithCallSignatures5.errors.txt new file mode 100644 index 00000000000..ba8f5304aa2 --- /dev/null +++ b/tests/baselines/reference/assignmentCompatWithCallSignatures5.errors.txt @@ -0,0 +1,93 @@ +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures5.ts(40,1): error TS2322: Type '(x: T) => void' is not assignable to type '(x: T) => T'. + Type 'void' is not assignable to type 'T'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures5.ts(55,1): error TS2322: Type '(x: { a: T; b: T; }) => T[]' is not assignable to type '(x: { a: U; b: V; }) => U[]'. + Type '(U | V)[]' is not assignable to type 'U[]'. + Type 'U | V' is not assignable to type 'U'. + Type 'V' is not assignable to type 'U'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures5.ts(58,1): error TS2322: Type '(x: { a: T; b: T; }) => T[]' is not assignable to type '(x: { a: U; b: V; }) => U[]'. + Types of parameters 'x' and 'x' are incompatible. + Type '{ a: U; b: V; }' is not assignable to type '{ a: Base; b: Base; }'. + Types of property 'a' are incompatible. + Type 'U' is not assignable to type 'Base'. + + +==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures5.ts (3 errors) ==== + // checking assignment compat for function types. No errors in this file + + class Base { foo: string; } + class Derived extends Base { bar: string; } + class Derived2 extends Derived { baz: string; } + class OtherDerived extends Base { bing: string; } + + var a: (x: T) => T[]; + var a2: (x: T) => string[]; + var a3: (x: T) => void; + var a4: (x: T, y: U) => string; + var a5: (x: (arg: T) => U) => T; + var a6: (x: (arg: T) => Derived) => T; + var a11: (x: { foo: T }, y: { foo: T; bar: T }) => Base; + var a15: (x: { a: T; b: T }) => T[]; + var a16: (x: { a: T; b: T }) => T[]; + var a17: { + (x: (a: T) => T): T[]; + (x: (a: T) => T): T[]; + }; + var a18: { + (x: { + (a: T): T; + (a: T): T; + }): any[]; + (x: { + (a: T): T; + (a: T): T; + }): any[]; + }; + + var b: (x: T) => T[]; + a = b; // ok + b = a; // ok + var b2: (x: T) => string[]; + a2 = b2; // ok + b2 = a2; // ok + var b3: (x: T) => T; + a3 = b3; // ok + b3 = a3; // ok + ~~ +!!! error TS2322: Type '(x: T) => void' is not assignable to type '(x: T) => T'. +!!! error TS2322: Type 'void' is not assignable to type 'T'. + var b4: (x: T, y: U) => string; + a4 = b4; // ok + b4 = a4; // ok + var b5: (x: (arg: T) => U) => T; + a5 = b5; // ok + b5 = a5; // ok + var b6: (x: (arg: T) => U) => T; + a6 = b6; // ok + b6 = a6; // ok + var b11: (x: { foo: T }, y: { foo: U; bar: U }) => Base; + a11 = b11; // ok + b11 = a11; // ok + var b15: (x: { a: U; b: V; }) => U[]; + a15 = b15; // ok, T = U, T = V + b15 = a15; // ok + ~~~ +!!! error TS2322: Type '(x: { a: T; b: T; }) => T[]' is not assignable to type '(x: { a: U; b: V; }) => U[]'. +!!! error TS2322: Type '(U | V)[]' is not assignable to type 'U[]'. +!!! error TS2322: Type 'U | V' is not assignable to type 'U'. +!!! error TS2322: Type 'V' is not assignable to type 'U'. + var b16: (x: { a: T; b: T }) => T[]; + a15 = b16; // ok + b15 = a16; // ok + ~~~ +!!! error TS2322: Type '(x: { a: T; b: T; }) => T[]' is not assignable to type '(x: { a: U; b: V; }) => U[]'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type '{ a: U; b: V; }' is not assignable to type '{ a: Base; b: Base; }'. +!!! error TS2322: Types of property 'a' are incompatible. +!!! error TS2322: Type 'U' is not assignable to type 'Base'. + var b17: (x: (a: T) => T) => T[]; + a17 = b17; // ok + b17 = a17; // ok + var b18: (x: (a: T) => T) => any[]; + a18 = b18; // ok + b18 = a18; // ok + \ No newline at end of file diff --git a/tests/baselines/reference/assignmentCompatWithCallSignatures6.errors.txt b/tests/baselines/reference/assignmentCompatWithCallSignatures6.errors.txt new file mode 100644 index 00000000000..b8399a1855b --- /dev/null +++ b/tests/baselines/reference/assignmentCompatWithCallSignatures6.errors.txt @@ -0,0 +1,61 @@ +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures6.ts(30,1): error TS2322: Type '(x: T) => void' is not assignable to type '(x: T) => T'. + Type 'void' is not assignable to type 'T'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures6.ts(42,1): error TS2322: Type '(x: { a: T; b: T; }) => T[]' is not assignable to type '(x: { a: T; b: T; }) => T[]'. + Types of parameters 'x' and 'x' are incompatible. + Type '{ a: T; b: T; }' is not assignable to type '{ a: Base; b: Base; }'. + Types of property 'a' are incompatible. + Type 'T' is not assignable to type 'Base'. + + +==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures6.ts (2 errors) ==== + // checking assignment compatibility relations for function types. All valid + + class Base { foo: string; } + class Derived extends Base { bar: string; } + class Derived2 extends Derived { baz: string; } + class OtherDerived extends Base { bing: string; } + + interface A { + a: (x: T) => T[]; + a2: (x: T) => string[]; + a3: (x: T) => void; + a4: (x: T, y: U) => string; + a5: (x: (arg: T) => U) => T; + a6: (x: (arg: T) => Derived) => T; + a11: (x: { foo: T }, y: { foo: T; bar: T }) => Base; + a15: (x: { a: T; b: T }) => T[]; + a16: (x: { a: T; b: T }) => T[]; + } + + var x: A; + + var b: (x: T) => T[]; + x.a = b; + b = x.a; + var b2: (x: T) => string[]; + x.a2 = b2; + b2 = x.a2; + var b3: (x: T) => T; + x.a3 = b3; + b3 = x.a3; + ~~ +!!! error TS2322: Type '(x: T) => void' is not assignable to type '(x: T) => T'. +!!! error TS2322: Type 'void' is not assignable to type 'T'. + var b4: (x: T, y: U) => string; + x.a4 = b4; + b4 = x.a4; + var b5: (x: (arg: T) => U) => T; + x.a5 = b5; + b5 = x.a5; + var b11: (x: { foo: T }, y: { foo: U; bar: U }) => Base; + x.a11 = b11; + b11 = x.a11; + var b16: (x: { a: T; b: T }) => T[]; + x.a16 = b16; + b16 = x.a16; + ~~~ +!!! error TS2322: Type '(x: { a: T; b: T; }) => T[]' is not assignable to type '(x: { a: T; b: T; }) => T[]'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type '{ a: T; b: T; }' is not assignable to type '{ a: Base; b: Base; }'. +!!! error TS2322: Types of property 'a' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'Base'. \ No newline at end of file diff --git a/tests/baselines/reference/assignmentCompatWithConstructSignatures3.errors.txt b/tests/baselines/reference/assignmentCompatWithConstructSignatures3.errors.txt index 995a9b67ccd..f9a5be732c9 100644 --- a/tests/baselines/reference/assignmentCompatWithConstructSignatures3.errors.txt +++ b/tests/baselines/reference/assignmentCompatWithConstructSignatures3.errors.txt @@ -1,11 +1,58 @@ +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures3.ts(47,1): error TS2322: Type 'new (x: number) => number[]' is not assignable to type 'new (x: T) => T[]'. + Types of parameters 'x' and 'x' are incompatible. + Type 'T' is not assignable to type 'number'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures3.ts(50,1): error TS2322: Type 'new (x: number) => string[]' is not assignable to type 'new (x: T) => string[]'. + Types of parameters 'x' and 'x' are incompatible. + Type 'T' is not assignable to type 'number'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures3.ts(53,1): error TS2322: Type 'new (x: number) => void' is not assignable to type 'new (x: T) => T'. + Types of parameters 'x' and 'x' are incompatible. + Type 'T' is not assignable to type 'number'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures3.ts(56,1): error TS2322: Type 'new (x: string, y: number) => string' is not assignable to type 'new (x: T, y: U) => T'. + Types of parameters 'x' and 'x' are incompatible. + Type 'T' is not assignable to type 'string'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures3.ts(59,1): error TS2322: Type 'new (x: (arg: string) => number) => string' is not assignable to type 'new (x: (arg: T) => U) => T'. + Types of parameters 'x' and 'x' are incompatible. + Types of parameters 'arg' and 'arg' are incompatible. + Type 'string' is not assignable to type 'T'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures3.ts(62,1): error TS2322: Type 'new (x: (arg: Base) => Derived) => Base' is not assignable to type 'new (x: (arg: T) => U) => T'. + Types of parameters 'x' and 'x' are incompatible. + Types of parameters 'arg' and 'arg' are incompatible. + Type 'Base' is not assignable to type 'T'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures3.ts(65,1): error TS2322: Type 'new (x: (arg: Base) => Derived) => (r: Base) => Derived' is not assignable to type 'new (x: (arg: T) => U) => (r: T) => U'. + Types of parameters 'x' and 'x' are incompatible. + Types of parameters 'arg' and 'arg' are incompatible. + Type 'Base' is not assignable to type 'T'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures3.ts(68,1): error TS2322: Type 'new (x: (arg: Base) => Derived, y: (arg2: Base) => Derived) => (r: Base) => Derived' is not assignable to type 'new (x: (arg: T) => U, y: (arg2: T) => U) => (r: T) => U'. + Types of parameters 'x' and 'x' are incompatible. + Types of parameters 'arg' and 'arg' are incompatible. + Type 'Base' is not assignable to type 'T'. tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures3.ts(71,1): error TS2322: Type 'new (x: (arg: Base) => Derived, y: (arg2: Base) => Derived) => (r: Base) => Derived' is not assignable to type 'new (x: (arg: T) => U, y: (arg2: { foo: string; bing: number; }) => U) => (r: T) => U'. + Types of parameters 'x' and 'x' are incompatible. + Types of parameters 'arg' and 'arg' are incompatible. + Type 'Base' is not assignable to type 'T'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures3.ts(74,1): error TS2322: Type 'new (...x: Derived[]) => Derived' is not assignable to type 'new (...x: T[]) => T'. + Type 'Derived' is not assignable to type 'T'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures3.ts(77,1): error TS2322: Type 'new (x: { foo: string; }, y: { foo: string; bar: string; }) => Base' is not assignable to type 'new (x: T, y: T) => T'. Types of parameters 'y' and 'y' are incompatible. - Types of parameters 'arg2' and 'arg2' are incompatible. - Type 'Base' is not assignable to type '{ foo: string; bing: number; }'. - Property 'bing' is missing in type 'Base'. + Type 'T' is not assignable to type '{ foo: string; bar: string; }'. + Type 'Base' is not assignable to type '{ foo: string; bar: string; }'. + Property 'bar' is missing in type 'Base'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures3.ts(80,1): error TS2322: Type 'new (x: Base[], y: Derived2[]) => Derived[]' is not assignable to type 'new (x: Base[], y: T) => Derived[]'. + Types of parameters 'y' and 'y' are incompatible. + Type 'T' is not assignable to type 'Derived2[]'. + Type 'Base[]' is not assignable to type 'Derived2[]'. + Type 'Base' is not assignable to type 'Derived2'. + Property 'baz' is missing in type 'Base'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures3.ts(83,1): error TS2322: Type 'new (x: Base[], y: Derived[]) => Derived[]' is not assignable to type 'new (x: Base[], y: T) => T'. + Type 'Derived[]' is not assignable to type 'T'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures3.ts(86,1): error TS2322: Type 'new (x: { a: string; b: number; }) => Object' is not assignable to type 'new (x: { a: T; b: T; }) => T'. + Types of parameters 'x' and 'x' are incompatible. + Type '{ a: T; b: T; }' is not assignable to type '{ a: string; b: number; }'. + Types of property 'a' are incompatible. + Type 'T' is not assignable to type 'string'. -==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures3.ts (1 errors) ==== +==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures3.ts (14 errors) ==== // checking assignment compatibility relations for function types. All of these are valid. class Base { foo: string; } @@ -53,51 +100,111 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme var b: new (x: T) => T[]; a = b; // ok b = a; // ok + ~ +!!! error TS2322: Type 'new (x: number) => number[]' is not assignable to type 'new (x: T) => T[]'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'number'. var b2: new (x: T) => string[]; a2 = b2; // ok b2 = a2; // ok + ~~ +!!! error TS2322: Type 'new (x: number) => string[]' is not assignable to type 'new (x: T) => string[]'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'number'. var b3: new (x: T) => T; a3 = b3; // ok b3 = a3; // ok + ~~ +!!! error TS2322: Type 'new (x: number) => void' is not assignable to type 'new (x: T) => T'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'number'. var b4: new (x: T, y: U) => T; a4 = b4; // ok b4 = a4; // ok + ~~ +!!! error TS2322: Type 'new (x: string, y: number) => string' is not assignable to type 'new (x: T, y: U) => T'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'string'. var b5: new (x: (arg: T) => U) => T; a5 = b5; // ok b5 = a5; // ok + ~~ +!!! error TS2322: Type 'new (x: (arg: string) => number) => string' is not assignable to type 'new (x: (arg: T) => U) => T'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Types of parameters 'arg' and 'arg' are incompatible. +!!! error TS2322: Type 'string' is not assignable to type 'T'. var b6: new (x: (arg: T) => U) => T; a6 = b6; // ok b6 = a6; // ok + ~~ +!!! error TS2322: Type 'new (x: (arg: Base) => Derived) => Base' is not assignable to type 'new (x: (arg: T) => U) => T'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Types of parameters 'arg' and 'arg' are incompatible. +!!! error TS2322: Type 'Base' is not assignable to type 'T'. var b7: new (x: (arg: T) => U) => (r: T) => U; a7 = b7; // ok b7 = a7; // ok + ~~ +!!! error TS2322: Type 'new (x: (arg: Base) => Derived) => (r: Base) => Derived' is not assignable to type 'new (x: (arg: T) => U) => (r: T) => U'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Types of parameters 'arg' and 'arg' are incompatible. +!!! error TS2322: Type 'Base' is not assignable to type 'T'. var b8: new (x: (arg: T) => U, y: (arg2: T) => U) => (r: T) => U; a8 = b8; // ok b8 = a8; // ok + ~~ +!!! error TS2322: Type 'new (x: (arg: Base) => Derived, y: (arg2: Base) => Derived) => (r: Base) => Derived' is not assignable to type 'new (x: (arg: T) => U, y: (arg2: T) => U) => (r: T) => U'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Types of parameters 'arg' and 'arg' are incompatible. +!!! error TS2322: Type 'Base' is not assignable to type 'T'. var b9: new (x: (arg: T) => U, y: (arg2: { foo: string; bing: number }) => U) => (r: T) => U; a9 = b9; // ok b9 = a9; // ok ~~ !!! error TS2322: Type 'new (x: (arg: Base) => Derived, y: (arg2: Base) => Derived) => (r: Base) => Derived' is not assignable to type 'new (x: (arg: T) => U, y: (arg2: { foo: string; bing: number; }) => U) => (r: T) => U'. -!!! error TS2322: Types of parameters 'y' and 'y' are incompatible. -!!! error TS2322: Types of parameters 'arg2' and 'arg2' are incompatible. -!!! error TS2322: Type 'Base' is not assignable to type '{ foo: string; bing: number; }'. -!!! error TS2322: Property 'bing' is missing in type 'Base'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Types of parameters 'arg' and 'arg' are incompatible. +!!! error TS2322: Type 'Base' is not assignable to type 'T'. var b10: new (...x: T[]) => T; a10 = b10; // ok b10 = a10; // ok + ~~~ +!!! error TS2322: Type 'new (...x: Derived[]) => Derived' is not assignable to type 'new (...x: T[]) => T'. +!!! error TS2322: Type 'Derived' is not assignable to type 'T'. var b11: new (x: T, y: T) => T; a11 = b11; // ok b11 = a11; // ok + ~~~ +!!! error TS2322: Type 'new (x: { foo: string; }, y: { foo: string; bar: string; }) => Base' is not assignable to type 'new (x: T, y: T) => T'. +!!! error TS2322: Types of parameters 'y' and 'y' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type '{ foo: string; bar: string; }'. +!!! error TS2322: Type 'Base' is not assignable to type '{ foo: string; bar: string; }'. +!!! error TS2322: Property 'bar' is missing in type 'Base'. var b12: new >(x: Array, y: T) => Array; a12 = b12; // ok b12 = a12; // ok + ~~~ +!!! error TS2322: Type 'new (x: Base[], y: Derived2[]) => Derived[]' is not assignable to type 'new (x: Base[], y: T) => Derived[]'. +!!! error TS2322: Types of parameters 'y' and 'y' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'Derived2[]'. +!!! error TS2322: Type 'Base[]' is not assignable to type 'Derived2[]'. +!!! error TS2322: Type 'Base' is not assignable to type 'Derived2'. +!!! error TS2322: Property 'baz' is missing in type 'Base'. var b13: new >(x: Array, y: T) => T; a13 = b13; // ok b13 = a13; // ok + ~~~ +!!! error TS2322: Type 'new (x: Base[], y: Derived[]) => Derived[]' is not assignable to type 'new (x: Base[], y: T) => T'. +!!! error TS2322: Type 'Derived[]' is not assignable to type 'T'. var b14: new (x: { a: T; b: T }) => T; a14 = b14; // ok b14 = a14; // ok + ~~~ +!!! error TS2322: Type 'new (x: { a: string; b: number; }) => Object' is not assignable to type 'new (x: { a: T; b: T; }) => T'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type '{ a: T; b: T; }' is not assignable to type '{ a: string; b: number; }'. +!!! error TS2322: Types of property 'a' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'string'. var b15: new (x: T) => T[]; a15 = b15; // ok b15 = a15; // ok diff --git a/tests/baselines/reference/assignmentCompatWithConstructSignatures4.errors.txt b/tests/baselines/reference/assignmentCompatWithConstructSignatures4.errors.txt index 6b2f4a0de17..8679b1d85f1 100644 --- a/tests/baselines/reference/assignmentCompatWithConstructSignatures4.errors.txt +++ b/tests/baselines/reference/assignmentCompatWithConstructSignatures4.errors.txt @@ -1,3 +1,10 @@ +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures4.ts(45,9): error TS2322: Type 'new (x: number) => string[]' is not assignable to type 'new (x: T) => U[]'. + Types of parameters 'x' and 'x' are incompatible. + Type 'T' is not assignable to type 'number'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures4.ts(49,9): error TS2322: Type 'new (x: (arg: Base) => Derived) => (r: Base) => Derived2' is not assignable to type 'new (x: (arg: T) => U) => (r: T) => V'. + Types of parameters 'x' and 'x' are incompatible. + Types of parameters 'arg' and 'arg' are incompatible. + Type 'Base' is not assignable to type 'T'. tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures4.ts(52,9): error TS2322: Type 'new (x: (arg: T) => U, y: (arg2: { foo: number; }) => U) => (r: T) => U' is not assignable to type 'new (x: (arg: Base) => Derived, y: (arg2: Base) => Derived) => (r: Base) => Derived'. Types of parameters 'y' and 'y' are incompatible. Types of parameters 'arg2' and 'arg2' are incompatible. @@ -5,11 +12,34 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme Types of property 'foo' are incompatible. Type 'number' is not assignable to type 'string'. tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures4.ts(53,9): error TS2322: Type 'new (x: (arg: Base) => Derived, y: (arg2: Base) => Derived) => (r: Base) => Derived' is not assignable to type 'new (x: (arg: T) => U, y: (arg2: { foo: number; }) => U) => (r: T) => U'. - Types of parameters 'y' and 'y' are incompatible. - Types of parameters 'arg2' and 'arg2' are incompatible. - Type 'Base' is not assignable to type '{ foo: number; }'. - Types of property 'foo' are incompatible. - Type 'string' is not assignable to type 'number'. + Types of parameters 'x' and 'x' are incompatible. + Types of parameters 'arg' and 'arg' are incompatible. + Type 'Base' is not assignable to type 'T'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures4.ts(58,9): error TS2322: Type 'new (...x: Base[]) => Base' is not assignable to type 'new (...x: T[]) => T'. + Type 'Base' is not assignable to type 'T'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures4.ts(62,9): error TS2322: Type 'new (x: { foo: string; }, y: { foo: string; bar: string; }) => Base' is not assignable to type 'new (x: T, y: T) => T'. + Type 'Base' is not assignable to type 'T'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures4.ts(66,9): error TS2322: Type 'new (x: Base[], y: Derived2[]) => Derived[]' is not assignable to type 'new (x: Base[], y: Base[]) => T'. + Type 'Derived[]' is not assignable to type 'T'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures4.ts(69,9): error TS2322: Type 'new (x: { a: T; b: T; }) => T' is not assignable to type 'new (x: { a: string; b: number; }) => number'. + Type 'string | number' is not assignable to type 'number'. + Type 'string' is not assignable to type 'number'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures4.ts(70,9): error TS2322: Type 'new (x: { a: string; b: number; }) => number' is not assignable to type 'new (x: { a: T; b: T; }) => T'. + Types of parameters 'x' and 'x' are incompatible. + Type '{ a: T; b: T; }' is not assignable to type '{ a: string; b: number; }'. + Types of property 'a' are incompatible. + Type 'T' is not assignable to type 'string'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures4.ts(73,9): error TS2322: Type 'new (x: { a: T; b: T; }) => number' is not assignable to type 'new (x: { a: string; b: number; }) => number'. + Types of parameters 'x' and 'x' are incompatible. + Type '{ a: string; b: number; }' is not assignable to type '{ a: Base; b: Base; }'. + Types of property 'a' are incompatible. + Type 'string' is not assignable to type 'Base'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures4.ts(74,9): error TS2322: Type 'new (x: { a: string; b: number; }) => number' is not assignable to type 'new (x: { a: T; b: T; }) => number'. + Types of parameters 'x' and 'x' are incompatible. + Type '{ a: T; b: T; }' is not assignable to type '{ a: string; b: number; }'. + Types of property 'a' are incompatible. + Type 'T' is not assignable to type 'string'. + Type 'Base' is not assignable to type 'string'. tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures4.ts(77,9): error TS2322: Type 'new (x: (a: T) => T) => T[]' is not assignable to type '{ new (x: { new (a: number): number; new (a?: number): number; }): number[]; new (x: { new (a: boolean): boolean; new (a?: boolean): boolean; }): boolean[]; }'. Types of parameters 'x' and 'x' are incompatible. Type '{ new (a: number): number; new (a?: number): number; }' is not assignable to type '(a: any) => any'. @@ -26,9 +56,21 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme Types of parameters 'x' and 'x' are incompatible. Type '(a: any) => any' is not assignable to type '{ new (a: T): T; new (a: T): T; }'. Type '(a: any) => any' provides no match for the signature 'new (a: T): T'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures4.ts(89,9): error TS2322: Type 'new (x: T) => string[]' is not assignable to type 'new (x: T) => T[]'. + Type 'string[]' is not assignable to type 'T[]'. + Type 'string' is not assignable to type 'T'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures4.ts(90,9): error TS2322: Type 'new (x: T) => T[]' is not assignable to type 'new (x: T) => string[]'. + Type 'T[]' is not assignable to type 'string[]'. + Type 'T' is not assignable to type 'string'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures4.ts(95,9): error TS2322: Type 'new (x: T) => T[]' is not assignable to type 'new (x: T) => string[]'. + Type 'T[]' is not assignable to type 'string[]'. + Type 'T' is not assignable to type 'string'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures4.ts(96,9): error TS2322: Type 'new (x: T) => string[]' is not assignable to type 'new (x: T) => T[]'. + Type 'string[]' is not assignable to type 'T[]'. + Type 'string' is not assignable to type 'T'. -==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures4.ts (6 errors) ==== +==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures4.ts (19 errors) ==== // checking assignment compatibility relations for function types. module Errors { @@ -74,10 +116,19 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme var b2: new (x: T) => U[]; a2 = b2; // ok b2 = a2; // ok + ~~ +!!! error TS2322: Type 'new (x: number) => string[]' is not assignable to type 'new (x: T) => U[]'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'number'. var b7: new (x: (arg: T) => U) => (r: T) => V; a7 = b7; // ok b7 = a7; // ok + ~~ +!!! error TS2322: Type 'new (x: (arg: Base) => Derived) => (r: Base) => Derived2' is not assignable to type 'new (x: (arg: T) => U) => (r: T) => V'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Types of parameters 'arg' and 'arg' are incompatible. +!!! error TS2322: Type 'Base' is not assignable to type 'T'. var b8: new (x: (arg: T) => U, y: (arg2: { foo: number; }) => U) => (r: T) => U; a8 = b8; // error, type mismatch @@ -91,32 +142,62 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme b8 = a8; // error ~~ !!! error TS2322: Type 'new (x: (arg: Base) => Derived, y: (arg2: Base) => Derived) => (r: Base) => Derived' is not assignable to type 'new (x: (arg: T) => U, y: (arg2: { foo: number; }) => U) => (r: T) => U'. -!!! error TS2322: Types of parameters 'y' and 'y' are incompatible. -!!! error TS2322: Types of parameters 'arg2' and 'arg2' are incompatible. -!!! error TS2322: Type 'Base' is not assignable to type '{ foo: number; }'. -!!! error TS2322: Types of property 'foo' are incompatible. -!!! error TS2322: Type 'string' is not assignable to type 'number'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Types of parameters 'arg' and 'arg' are incompatible. +!!! error TS2322: Type 'Base' is not assignable to type 'T'. var b10: new (...x: T[]) => T; a10 = b10; // ok b10 = a10; // ok + ~~~ +!!! error TS2322: Type 'new (...x: Base[]) => Base' is not assignable to type 'new (...x: T[]) => T'. +!!! error TS2322: Type 'Base' is not assignable to type 'T'. var b11: new (x: T, y: T) => T; a11 = b11; // ok b11 = a11; // ok + ~~~ +!!! error TS2322: Type 'new (x: { foo: string; }, y: { foo: string; bar: string; }) => Base' is not assignable to type 'new (x: T, y: T) => T'. +!!! error TS2322: Type 'Base' is not assignable to type 'T'. var b12: new >(x: Array, y: Array) => T; a12 = b12; // ok b12 = a12; // ok + ~~~ +!!! error TS2322: Type 'new (x: Base[], y: Derived2[]) => Derived[]' is not assignable to type 'new (x: Base[], y: Base[]) => T'. +!!! error TS2322: Type 'Derived[]' is not assignable to type 'T'. var b15: new (x: { a: T; b: T }) => T; a15 = b15; // ok + ~~~ +!!! error TS2322: Type 'new (x: { a: T; b: T; }) => T' is not assignable to type 'new (x: { a: string; b: number; }) => number'. +!!! error TS2322: Type 'string | number' is not assignable to type 'number'. +!!! error TS2322: Type 'string' is not assignable to type 'number'. b15 = a15; // ok + ~~~ +!!! error TS2322: Type 'new (x: { a: string; b: number; }) => number' is not assignable to type 'new (x: { a: T; b: T; }) => T'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type '{ a: T; b: T; }' is not assignable to type '{ a: string; b: number; }'. +!!! error TS2322: Types of property 'a' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'string'. var b15a: new (x: { a: T; b: T }) => number; a15 = b15a; // ok + ~~~ +!!! error TS2322: Type 'new (x: { a: T; b: T; }) => number' is not assignable to type 'new (x: { a: string; b: number; }) => number'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type '{ a: string; b: number; }' is not assignable to type '{ a: Base; b: Base; }'. +!!! error TS2322: Types of property 'a' are incompatible. +!!! error TS2322: Type 'string' is not assignable to type 'Base'. b15a = a15; // ok + ~~~~ +!!! error TS2322: Type 'new (x: { a: string; b: number; }) => number' is not assignable to type 'new (x: { a: T; b: T; }) => number'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type '{ a: T; b: T; }' is not assignable to type '{ a: string; b: number; }'. +!!! error TS2322: Types of property 'a' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'string'. +!!! error TS2322: Type 'Base' is not assignable to type 'string'. var b16: new (x: (a: T) => T) => T[]; a16 = b16; // error @@ -152,12 +233,28 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme var a2: new (x: T) => T[]; var b2: new (x: T) => string[]; a2 = b2; // ok + ~~ +!!! error TS2322: Type 'new (x: T) => string[]' is not assignable to type 'new (x: T) => T[]'. +!!! error TS2322: Type 'string[]' is not assignable to type 'T[]'. +!!! error TS2322: Type 'string' is not assignable to type 'T'. b2 = a2; // ok + ~~ +!!! error TS2322: Type 'new (x: T) => T[]' is not assignable to type 'new (x: T) => string[]'. +!!! error TS2322: Type 'T[]' is not assignable to type 'string[]'. +!!! error TS2322: Type 'T' is not assignable to type 'string'. // target type has generic call signature var a3: new (x: T) => string[]; var b3: new (x: T) => T[]; a3 = b3; // ok + ~~ +!!! error TS2322: Type 'new (x: T) => T[]' is not assignable to type 'new (x: T) => string[]'. +!!! error TS2322: Type 'T[]' is not assignable to type 'string[]'. +!!! error TS2322: Type 'T' is not assignable to type 'string'. b3 = a3; // ok + ~~ +!!! error TS2322: Type 'new (x: T) => string[]' is not assignable to type 'new (x: T) => T[]'. +!!! error TS2322: Type 'string[]' is not assignable to type 'T[]'. +!!! error TS2322: Type 'string' is not assignable to type 'T'. } } \ No newline at end of file diff --git a/tests/baselines/reference/assignmentCompatWithConstructSignatures5.errors.txt b/tests/baselines/reference/assignmentCompatWithConstructSignatures5.errors.txt new file mode 100644 index 00000000000..23e0c682fdc --- /dev/null +++ b/tests/baselines/reference/assignmentCompatWithConstructSignatures5.errors.txt @@ -0,0 +1,93 @@ +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures5.ts(40,1): error TS2322: Type 'new (x: T) => void' is not assignable to type 'new (x: T) => T'. + Type 'void' is not assignable to type 'T'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures5.ts(55,1): error TS2322: Type 'new (x: { a: T; b: T; }) => T[]' is not assignable to type 'new (x: { a: U; b: V; }) => U[]'. + Type '(U | V)[]' is not assignable to type 'U[]'. + Type 'U | V' is not assignable to type 'U'. + Type 'V' is not assignable to type 'U'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures5.ts(58,1): error TS2322: Type 'new (x: { a: T; b: T; }) => T[]' is not assignable to type 'new (x: { a: U; b: V; }) => U[]'. + Types of parameters 'x' and 'x' are incompatible. + Type '{ a: U; b: V; }' is not assignable to type '{ a: Base; b: Base; }'. + Types of property 'a' are incompatible. + Type 'U' is not assignable to type 'Base'. + + +==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures5.ts (3 errors) ==== + // checking assignment compat for function types. All valid + + class Base { foo: string; } + class Derived extends Base { bar: string; } + class Derived2 extends Derived { baz: string; } + class OtherDerived extends Base { bing: string; } + + var a: new (x: T) => T[]; + var a2: new (x: T) => string[]; + var a3: new (x: T) => void; + var a4: new (x: T, y: U) => string; + var a5: new (x: new (arg: T) => U) => T; + var a6: new (x: new (arg: T) => Derived) => T; + var a11: new (x: { foo: T }, y: { foo: T; bar: T }) => Base; + var a15: new (x: { a: T; b: T }) => T[]; + var a16: new (x: { a: T; b: T }) => T[]; + var a17: { + new (x: new (a: T) => T): T[]; + new (x: new (a: T) => T): T[]; + }; + var a18: { + new (x: { + new (a: T): T; + new (a: T): T; + }): any[]; + new (x: { + new (a: T): T; + new (a: T): T; + }): any[]; + }; + + var b: new (x: T) => T[]; + a = b; // ok + b = a; // ok + var b2: new (x: T) => string[]; + a2 = b2; // ok + b2 = a2; // ok + var b3: new (x: T) => T; + a3 = b3; // ok + b3 = a3; // ok + ~~ +!!! error TS2322: Type 'new (x: T) => void' is not assignable to type 'new (x: T) => T'. +!!! error TS2322: Type 'void' is not assignable to type 'T'. + var b4: new (x: T, y: U) => string; + a4 = b4; // ok + b4 = a4; // ok + var b5: new (x: new (arg: T) => U) => T; + a5 = b5; // ok + b5 = a5; // ok + var b6: new (x: new (arg: T) => U) => T; + a6 = b6; // ok + b6 = a6; // ok + var b11: new (x: { foo: T }, y: { foo: U; bar: U }) => Base; + a11 = b11; // ok + b11 = a11; // ok + var b15: new (x: { a: U; b: V; }) => U[]; + a15 = b15; // ok + b15 = a15; // ok + ~~~ +!!! error TS2322: Type 'new (x: { a: T; b: T; }) => T[]' is not assignable to type 'new (x: { a: U; b: V; }) => U[]'. +!!! error TS2322: Type '(U | V)[]' is not assignable to type 'U[]'. +!!! error TS2322: Type 'U | V' is not assignable to type 'U'. +!!! error TS2322: Type 'V' is not assignable to type 'U'. + var b16: new (x: { a: T; b: T }) => T[]; + a15 = b16; // ok + b15 = a16; // ok + ~~~ +!!! error TS2322: Type 'new (x: { a: T; b: T; }) => T[]' is not assignable to type 'new (x: { a: U; b: V; }) => U[]'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type '{ a: U; b: V; }' is not assignable to type '{ a: Base; b: Base; }'. +!!! error TS2322: Types of property 'a' are incompatible. +!!! error TS2322: Type 'U' is not assignable to type 'Base'. + var b17: new (x: new (a: T) => T) => T[]; + a17 = b17; // ok + b17 = a17; // ok + var b18: new (x: new (a: T) => T) => any[]; + a18 = b18; // ok + b18 = a18; // ok + \ No newline at end of file diff --git a/tests/baselines/reference/assignmentCompatWithConstructSignatures6.errors.txt b/tests/baselines/reference/assignmentCompatWithConstructSignatures6.errors.txt new file mode 100644 index 00000000000..f89db500202 --- /dev/null +++ b/tests/baselines/reference/assignmentCompatWithConstructSignatures6.errors.txt @@ -0,0 +1,61 @@ +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures6.ts(30,1): error TS2322: Type 'new (x: T) => void' is not assignable to type 'new (x: T) => T'. + Type 'void' is not assignable to type 'T'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures6.ts(42,1): error TS2322: Type 'new (x: { a: T; b: T; }) => T[]' is not assignable to type 'new (x: { a: T; b: T; }) => T[]'. + Types of parameters 'x' and 'x' are incompatible. + Type '{ a: T; b: T; }' is not assignable to type '{ a: Base; b: Base; }'. + Types of property 'a' are incompatible. + Type 'T' is not assignable to type 'Base'. + + +==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithConstructSignatures6.ts (2 errors) ==== + // checking assignment compatibility relations for function types. All valid. + + class Base { foo: string; } + class Derived extends Base { bar: string; } + class Derived2 extends Derived { baz: string; } + class OtherDerived extends Base { bing: string; } + + interface A { + a: new (x: T) => T[]; + a2: new (x: T) => string[]; + a3: new (x: T) => void; + a4: new (x: T, y: U) => string; + a5: new (x: (arg: T) => U) => T; + a6: new (x: (arg: T) => Derived) => T; + a11: new (x: { foo: T }, y: { foo: T; bar: T }) => Base; + a15: new (x: { a: T; b: T }) => T[]; + a16: new (x: { a: T; b: T }) => T[]; + } + + var x: A; + + var b: new (x: T) => T[]; + x.a = b; + b = x.a; + var b2: new (x: T) => string[]; + x.a2 = b2; + b2 = x.a2; + var b3: new (x: T) => T; + x.a3 = b3; + b3 = x.a3; + ~~ +!!! error TS2322: Type 'new (x: T) => void' is not assignable to type 'new (x: T) => T'. +!!! error TS2322: Type 'void' is not assignable to type 'T'. + var b4: new (x: T, y: U) => string; + x.a4 = b4; + b4 = x.a4; + var b5: new (x: (arg: T) => U) => T; + x.a5 = b5; + b5 = x.a5; + var b11: new (x: { foo: T }, y: { foo: U; bar: U }) => Base; + x.a11 = b11; + b11 = x.a11; + var b16: new (x: { a: T; b: T }) => T[]; + x.a16 = b16; + b16 = x.a16; + ~~~ +!!! error TS2322: Type 'new (x: { a: T; b: T; }) => T[]' is not assignable to type 'new (x: { a: T; b: T; }) => T[]'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type '{ a: T; b: T; }' is not assignable to type '{ a: Base; b: Base; }'. +!!! error TS2322: Types of property 'a' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'Base'. \ No newline at end of file diff --git a/tests/baselines/reference/assignmentCompatWithGenericCallSignatures2.errors.txt b/tests/baselines/reference/assignmentCompatWithGenericCallSignatures2.errors.txt new file mode 100644 index 00000000000..7e39c3305a3 --- /dev/null +++ b/tests/baselines/reference/assignmentCompatWithGenericCallSignatures2.errors.txt @@ -0,0 +1,27 @@ +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignatures2.ts(16,1): error TS2322: Type 'A' is not assignable to type 'B'. + Types of parameters 'y' and 'y' are incompatible. + Type 'S' is not assignable to type 'S[]'. + + +==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignatures2.ts (1 errors) ==== + // some complex cases of assignment compat of generic signatures. No contextual signature instantiation + + interface A { + (x: T, ...y: T[][]): void + } + + interface B { + (x: S, ...y: S[]): void + } + + var a: A; + var b: B; + + // Both ok + a = b; + b = a; + ~ +!!! error TS2322: Type 'A' is not assignable to type 'B'. +!!! error TS2322: Types of parameters 'y' and 'y' are incompatible. +!!! error TS2322: Type 'S' is not assignable to type 'S[]'. + \ No newline at end of file diff --git a/tests/baselines/reference/assignmentCompatWithGenericCallSignatures4.errors.txt b/tests/baselines/reference/assignmentCompatWithGenericCallSignatures4.errors.txt new file mode 100644 index 00000000000..a38822b8044 --- /dev/null +++ b/tests/baselines/reference/assignmentCompatWithGenericCallSignatures4.errors.txt @@ -0,0 +1,27 @@ +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignatures4.ts(12,1): error TS2322: Type '>(z: T) => void' is not assignable to type '>>(z: T) => void'. + Types of parameters 'z' and 'z' are incompatible. + Type 'T' is not assignable to type 'I2'. + Type 'I2>' is not assignable to type 'I2'. + Type 'I2' is not assignable to type 'T'. + + +==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignatures4.ts (1 errors) ==== + // some complex cases of assignment compat of generic signatures. + + interface I2 { + p: T + } + + var x: >(z: T) => void + var y: >>(z: T) => void + + // These both do not make sense as we would eventually be comparing I2 to I2>, and they are self referencing anyway + x = y + y = x + ~ +!!! error TS2322: Type '>(z: T) => void' is not assignable to type '>>(z: T) => void'. +!!! error TS2322: Types of parameters 'z' and 'z' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'I2'. +!!! error TS2322: Type 'I2>' is not assignable to type 'I2'. +!!! error TS2322: Type 'I2' is not assignable to type 'T'. + \ No newline at end of file diff --git a/tests/baselines/reference/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.errors.txt b/tests/baselines/reference/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.errors.txt index a18da8fd8f7..dbad415c5f8 100644 --- a/tests/baselines/reference/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.errors.txt +++ b/tests/baselines/reference/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.errors.txt @@ -1,12 +1,74 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.ts(14,13): error TS2322: Type '(x: T) => any' is not assignable to type '() => T'. tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.ts(23,13): error TS2322: Type '(x: T, y: T) => any' is not assignable to type '(x: T) => T'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.ts(63,9): error TS2322: Type '() => T' is not assignable to type '() => T'. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.ts(64,9): error TS2322: Type '(x?: T) => T' is not assignable to type '() => T'. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.ts(65,9): error TS2322: Type '(x: T) => T' is not assignable to type '() => T'. tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.ts(66,9): error TS2322: Type '(x: T, y?: T) => T' is not assignable to type '() => T'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.ts(67,9): error TS2322: Type '(x?: T, y?: T) => T' is not assignable to type '() => T'. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.ts(69,9): error TS2322: Type '() => T' is not assignable to type '(x?: T) => T'. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.ts(70,9): error TS2322: Type '(x?: T) => T' is not assignable to type '(x?: T) => T'. + Types of parameters 'x' and 'x' are incompatible. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.ts(71,9): error TS2322: Type '(x: T) => T' is not assignable to type '(x?: T) => T'. + Types of parameters 'x' and 'x' are incompatible. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.ts(72,9): error TS2322: Type '(x: T, y?: T) => T' is not assignable to type '(x?: T) => T'. + Types of parameters 'x' and 'x' are incompatible. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.ts(73,9): error TS2322: Type '(x?: T, y?: T) => T' is not assignable to type '(x?: T) => T'. + Types of parameters 'x' and 'x' are incompatible. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.ts(75,9): error TS2322: Type '() => T' is not assignable to type '(x: T) => T'. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.ts(76,9): error TS2322: Type '(x?: T) => T' is not assignable to type '(x: T) => T'. + Types of parameters 'x' and 'x' are incompatible. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.ts(77,9): error TS2322: Type '(x: T) => T' is not assignable to type '(x: T) => T'. + Types of parameters 'x' and 'x' are incompatible. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.ts(78,9): error TS2322: Type '(x: T, y?: T) => T' is not assignable to type '(x: T) => T'. + Types of parameters 'x' and 'x' are incompatible. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.ts(79,9): error TS2322: Type '(x?: T, y?: T) => T' is not assignable to type '(x: T) => T'. + Types of parameters 'x' and 'x' are incompatible. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.ts(81,9): error TS2322: Type '() => T' is not assignable to type '(x: T, y?: T) => T'. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.ts(82,9): error TS2322: Type '(x?: T) => T' is not assignable to type '(x: T, y?: T) => T'. + Types of parameters 'x' and 'x' are incompatible. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.ts(83,9): error TS2322: Type '(x: T) => T' is not assignable to type '(x: T, y?: T) => T'. + Types of parameters 'x' and 'x' are incompatible. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.ts(84,9): error TS2322: Type '(x: T, y?: T) => T' is not assignable to type '(x: T, y?: T) => T'. + Types of parameters 'x' and 'x' are incompatible. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.ts(85,9): error TS2322: Type '(x?: T, y?: T) => T' is not assignable to type '(x: T, y?: T) => T'. + Types of parameters 'x' and 'x' are incompatible. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.ts(87,9): error TS2322: Type '() => T' is not assignable to type '(x?: T, y?: T) => T'. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.ts(88,9): error TS2322: Type '(x?: T) => T' is not assignable to type '(x?: T, y?: T) => T'. + Types of parameters 'x' and 'x' are incompatible. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.ts(89,9): error TS2322: Type '(x: T) => T' is not assignable to type '(x?: T, y?: T) => T'. + Types of parameters 'x' and 'x' are incompatible. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.ts(90,9): error TS2322: Type '(x: T, y?: T) => T' is not assignable to type '(x?: T, y?: T) => T'. + Types of parameters 'x' and 'x' are incompatible. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.ts(91,9): error TS2322: Type '(x?: T, y?: T) => T' is not assignable to type '(x?: T, y?: T) => T'. + Types of parameters 'x' and 'x' are incompatible. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.ts(107,13): error TS2322: Type '(x: T) => any' is not assignable to type '() => T'. tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.ts(116,13): error TS2322: Type '(x: T, y: T) => any' is not assignable to type '(x: T) => T'. -==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.ts (6 errors) ==== +==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithGenericCallSignaturesWithOptionalParameters.ts (29 errors) ==== // call signatures in derived types must have the same or fewer optional parameters as the target for assignment module ClassTypeParam { @@ -74,7 +136,13 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme // all errors b.a = t.a; + ~~~ +!!! error TS2322: Type '() => T' is not assignable to type '() => T'. +!!! error TS2322: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. b.a = t.a2; + ~~~ +!!! error TS2322: Type '(x?: T) => T' is not assignable to type '() => T'. +!!! error TS2322: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. b.a = t.a3; ~~~ !!! error TS2322: Type '(x: T) => T' is not assignable to type '() => T'. @@ -82,30 +150,109 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme ~~~ !!! error TS2322: Type '(x: T, y?: T) => T' is not assignable to type '() => T'. b.a = t.a5; + ~~~ +!!! error TS2322: Type '(x?: T, y?: T) => T' is not assignable to type '() => T'. +!!! error TS2322: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. b.a2 = t.a; + ~~~~ +!!! error TS2322: Type '() => T' is not assignable to type '(x?: T) => T'. +!!! error TS2322: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. b.a2 = t.a2; + ~~~~ +!!! error TS2322: Type '(x?: T) => T' is not assignable to type '(x?: T) => T'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. b.a2 = t.a3; + ~~~~ +!!! error TS2322: Type '(x: T) => T' is not assignable to type '(x?: T) => T'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. b.a2 = t.a4; + ~~~~ +!!! error TS2322: Type '(x: T, y?: T) => T' is not assignable to type '(x?: T) => T'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. b.a2 = t.a5; + ~~~~ +!!! error TS2322: Type '(x?: T, y?: T) => T' is not assignable to type '(x?: T) => T'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. b.a3 = t.a; + ~~~~ +!!! error TS2322: Type '() => T' is not assignable to type '(x: T) => T'. +!!! error TS2322: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. b.a3 = t.a2; + ~~~~ +!!! error TS2322: Type '(x?: T) => T' is not assignable to type '(x: T) => T'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. b.a3 = t.a3; + ~~~~ +!!! error TS2322: Type '(x: T) => T' is not assignable to type '(x: T) => T'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. b.a3 = t.a4; + ~~~~ +!!! error TS2322: Type '(x: T, y?: T) => T' is not assignable to type '(x: T) => T'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. b.a3 = t.a5; + ~~~~ +!!! error TS2322: Type '(x?: T, y?: T) => T' is not assignable to type '(x: T) => T'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. b.a4 = t.a; + ~~~~ +!!! error TS2322: Type '() => T' is not assignable to type '(x: T, y?: T) => T'. +!!! error TS2322: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. b.a4 = t.a2; + ~~~~ +!!! error TS2322: Type '(x?: T) => T' is not assignable to type '(x: T, y?: T) => T'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. b.a4 = t.a3; + ~~~~ +!!! error TS2322: Type '(x: T) => T' is not assignable to type '(x: T, y?: T) => T'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. b.a4 = t.a4; + ~~~~ +!!! error TS2322: Type '(x: T, y?: T) => T' is not assignable to type '(x: T, y?: T) => T'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. b.a4 = t.a5; + ~~~~ +!!! error TS2322: Type '(x?: T, y?: T) => T' is not assignable to type '(x: T, y?: T) => T'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. b.a5 = t.a; + ~~~~ +!!! error TS2322: Type '() => T' is not assignable to type '(x?: T, y?: T) => T'. +!!! error TS2322: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. b.a5 = t.a2; + ~~~~ +!!! error TS2322: Type '(x?: T) => T' is not assignable to type '(x?: T, y?: T) => T'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. b.a5 = t.a3; + ~~~~ +!!! error TS2322: Type '(x: T) => T' is not assignable to type '(x?: T, y?: T) => T'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. b.a5 = t.a4; + ~~~~ +!!! error TS2322: Type '(x: T, y?: T) => T' is not assignable to type '(x?: T, y?: T) => T'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. b.a5 = t.a5; + ~~~~ +!!! error TS2322: Type '(x?: T, y?: T) => T' is not assignable to type '(x?: T, y?: T) => T'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. } } diff --git a/tests/baselines/reference/assignmentCompatWithObjectMembersOptionality2.errors.txt b/tests/baselines/reference/assignmentCompatWithObjectMembersOptionality2.errors.txt index de2751beaca..0d7fe1071e9 100644 --- a/tests/baselines/reference/assignmentCompatWithObjectMembersOptionality2.errors.txt +++ b/tests/baselines/reference/assignmentCompatWithObjectMembersOptionality2.errors.txt @@ -1,3 +1,12 @@ +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithObjectMembersOptionality2.ts(33,5): error TS2559: Type 'D' has no properties in common with type 'C'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithObjectMembersOptionality2.ts(34,5): error TS2559: Type 'E' has no properties in common with type 'C'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithObjectMembersOptionality2.ts(35,5): error TS2559: Type 'F' has no properties in common with type 'C'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithObjectMembersOptionality2.ts(36,5): error TS2559: Type 'D' has no properties in common with type '{ opt?: Base; }'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithObjectMembersOptionality2.ts(37,5): error TS2559: Type 'E' has no properties in common with type '{ opt?: Base; }'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithObjectMembersOptionality2.ts(38,5): error TS2559: Type 'F' has no properties in common with type '{ opt?: Base; }'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithObjectMembersOptionality2.ts(39,5): error TS2559: Type 'D' has no properties in common with type '{ opt?: Base; }'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithObjectMembersOptionality2.ts(40,5): error TS2559: Type 'E' has no properties in common with type '{ opt?: Base; }'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithObjectMembersOptionality2.ts(41,5): error TS2559: Type 'F' has no properties in common with type '{ opt?: Base; }'. tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithObjectMembersOptionality2.ts(74,5): error TS2322: Type 'D' is not assignable to type 'C'. Property 'opt' is missing in type 'D'. tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithObjectMembersOptionality2.ts(75,5): error TS2322: Type 'E' is not assignable to type 'C'. @@ -18,7 +27,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme Property 'opt' is missing in type 'F'. -==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithObjectMembersOptionality2.ts (9 errors) ==== +==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithObjectMembersOptionality2.ts (18 errors) ==== // M is optional and S contains no property with the same name as M // N is optional and T contains no property with the same name as N @@ -50,20 +59,38 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme var e: E; var f: F; - // all ok + // disallowed by weak type checking c = d; + ~ +!!! error TS2559: Type 'D' has no properties in common with type 'C'. c = e; + ~ +!!! error TS2559: Type 'E' has no properties in common with type 'C'. c = f; - c = a; - + ~ +!!! error TS2559: Type 'F' has no properties in common with type 'C'. a = d; + ~ +!!! error TS2559: Type 'D' has no properties in common with type '{ opt?: Base; }'. a = e; + ~ +!!! error TS2559: Type 'E' has no properties in common with type '{ opt?: Base; }'. a = f; - a = c; - + ~ +!!! error TS2559: Type 'F' has no properties in common with type '{ opt?: Base; }'. b = d; + ~ +!!! error TS2559: Type 'D' has no properties in common with type '{ opt?: Base; }'. b = e; + ~ +!!! error TS2559: Type 'E' has no properties in common with type '{ opt?: Base; }'. b = f; + ~ +!!! error TS2559: Type 'F' has no properties in common with type '{ opt?: Base; }'. + + // ok + c = a; + a = c; b = a; b = c; } @@ -134,4 +161,5 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme !!! error TS2322: Property 'opt' is missing in type 'F'. b = a; // ok b = c; // ok - } \ No newline at end of file + } + \ No newline at end of file diff --git a/tests/baselines/reference/assignmentCompatWithObjectMembersOptionality2.js b/tests/baselines/reference/assignmentCompatWithObjectMembersOptionality2.js index e158a787878..d83f3182531 100644 --- a/tests/baselines/reference/assignmentCompatWithObjectMembersOptionality2.js +++ b/tests/baselines/reference/assignmentCompatWithObjectMembersOptionality2.js @@ -30,20 +30,20 @@ module TargetHasOptional { var e: E; var f: F; - // all ok + // disallowed by weak type checking c = d; c = e; c = f; - c = a; - a = d; a = e; a = f; - a = c; - b = d; b = e; b = f; + + // ok + c = a; + a = c; b = a; b = c; } @@ -87,7 +87,8 @@ module SourceHasOptional { b = f; // error b = a; // ok b = c; // ok -} +} + //// [assignmentCompatWithObjectMembersOptionality2.js] // M is optional and S contains no property with the same name as M @@ -129,18 +130,19 @@ var TargetHasOptional; var d; var e; var f; - // all ok + // disallowed by weak type checking c = d; c = e; c = f; - c = a; a = d; a = e; a = f; - a = c; b = d; b = e; b = f; + // ok + c = a; + a = c; b = a; b = c; })(TargetHasOptional || (TargetHasOptional = {})); diff --git a/tests/baselines/reference/assignmentStricterConstraints.errors.txt b/tests/baselines/reference/assignmentStricterConstraints.errors.txt new file mode 100644 index 00000000000..c83e2fa3440 --- /dev/null +++ b/tests/baselines/reference/assignmentStricterConstraints.errors.txt @@ -0,0 +1,19 @@ +tests/cases/compiler/assignmentStricterConstraints.ts(7,1): error TS2322: Type '(x: T, y: S) => void' is not assignable to type '(x: T, y: S) => void'. + Types of parameters 'y' and 'y' are incompatible. + Type 'S' is not assignable to type 'T'. + + +==== tests/cases/compiler/assignmentStricterConstraints.ts (1 errors) ==== + var f = function (x: T, y: S): void { + x = y + } + + var g = function (x: T, y: S): void { } + + g = f + ~ +!!! error TS2322: Type '(x: T, y: S) => void' is not assignable to type '(x: T, y: S) => void'. +!!! error TS2322: Types of parameters 'y' and 'y' are incompatible. +!!! error TS2322: Type 'S' is not assignable to type 'T'. + g(1, "") + \ No newline at end of file diff --git a/tests/baselines/reference/asyncFunctionDeclaration15_es5.errors.txt b/tests/baselines/reference/asyncFunctionDeclaration15_es5.errors.txt index 42940c0e412..027551ae4b8 100644 --- a/tests/baselines/reference/asyncFunctionDeclaration15_es5.errors.txt +++ b/tests/baselines/reference/asyncFunctionDeclaration15_es5.errors.txt @@ -4,10 +4,10 @@ tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration1 tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(9,23): error TS1055: Type 'PromiseLike' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value. tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(10,23): error TS1055: Type 'typeof Thenable' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value. tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(10,23): error TS1055: Type 'typeof Thenable' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value. - Type 'Thenable' is not assignable to type 'PromiseLike'. + Type 'Thenable' is not assignable to type 'PromiseLike'. Types of property 'then' are incompatible. - Type '() => void' is not assignable to type '(onfulfilled?: (value: any) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => PromiseLike'. - Type 'void' is not assignable to type 'PromiseLike'. + Type '() => void' is not assignable to type '(onfulfilled?: (value: T) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => PromiseLike'. + Type 'void' is not assignable to type 'PromiseLike'. tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(17,16): error TS1058: The return type of an async function must either be a valid promise or must not contain a callable 'then' member. tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(23,25): error TS1320: Type of 'await' operand must either be a valid promise or must not contain a callable 'then' member. @@ -35,10 +35,10 @@ tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration1 !!! error TS1055: Type 'typeof Thenable' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value. ~~~~~~~~ !!! error TS1055: Type 'typeof Thenable' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value. -!!! error TS1055: Type 'Thenable' is not assignable to type 'PromiseLike'. +!!! error TS1055: Type 'Thenable' is not assignable to type 'PromiseLike'. !!! error TS1055: Types of property 'then' are incompatible. -!!! error TS1055: Type '() => void' is not assignable to type '(onfulfilled?: (value: any) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => PromiseLike'. -!!! error TS1055: Type 'void' is not assignable to type 'PromiseLike'. +!!! error TS1055: Type '() => void' is not assignable to type '(onfulfilled?: (value: T) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => PromiseLike'. +!!! error TS1055: Type 'void' is not assignable to type 'PromiseLike'. async function fn7() { return; } // valid: Promise async function fn8() { return 1; } // valid: Promise async function fn9() { return null; } // valid: Promise diff --git a/tests/baselines/reference/bestChoiceType.symbols b/tests/baselines/reference/bestChoiceType.symbols index dc4ea663efc..c65dba1e7c2 100644 --- a/tests/baselines/reference/bestChoiceType.symbols +++ b/tests/baselines/reference/bestChoiceType.symbols @@ -2,10 +2,10 @@ // Repro from #10041 (''.match(/ /) || []).map(s => s.toLowerCase()); ->(''.match(/ /) || []).map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>(''.match(/ /) || []).map : Symbol(Array.map, Decl(lib.d.ts, --, --)) >''.match : Symbol(String.match, Decl(lib.d.ts, --, --)) >match : Symbol(String.match, Decl(lib.d.ts, --, --)) ->map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>map : Symbol(Array.map, Decl(lib.d.ts, --, --)) >s : Symbol(s, Decl(bestChoiceType.ts, 2, 26)) >s.toLowerCase : Symbol(String.toLowerCase, Decl(lib.d.ts, --, --)) >s : Symbol(s, Decl(bestChoiceType.ts, 2, 26)) @@ -27,9 +27,9 @@ function f1() { let z = y.map(s => s.toLowerCase()); >z : Symbol(z, Decl(bestChoiceType.ts, 9, 7)) ->y.map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>y.map : Symbol(Array.map, Decl(lib.d.ts, --, --)) >y : Symbol(y, Decl(bestChoiceType.ts, 8, 7)) ->map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>map : Symbol(Array.map, Decl(lib.d.ts, --, --)) >s : Symbol(s, Decl(bestChoiceType.ts, 9, 18)) >s.toLowerCase : Symbol(String.toLowerCase, Decl(lib.d.ts, --, --)) >s : Symbol(s, Decl(bestChoiceType.ts, 9, 18)) @@ -51,9 +51,9 @@ function f2() { let z = y.map(s => s.toLowerCase()); >z : Symbol(z, Decl(bestChoiceType.ts, 15, 7)) ->y.map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>y.map : Symbol(Array.map, Decl(lib.d.ts, --, --)) >y : Symbol(y, Decl(bestChoiceType.ts, 14, 7)) ->map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>map : Symbol(Array.map, Decl(lib.d.ts, --, --)) >s : Symbol(s, Decl(bestChoiceType.ts, 15, 18)) >s.toLowerCase : Symbol(String.toLowerCase, Decl(lib.d.ts, --, --)) >s : Symbol(s, Decl(bestChoiceType.ts, 15, 18)) diff --git a/tests/baselines/reference/bestChoiceType.types b/tests/baselines/reference/bestChoiceType.types index 15c5ecd4858..49997d1e273 100644 --- a/tests/baselines/reference/bestChoiceType.types +++ b/tests/baselines/reference/bestChoiceType.types @@ -3,7 +3,7 @@ (''.match(/ /) || []).map(s => s.toLowerCase()); >(''.match(/ /) || []).map(s => s.toLowerCase()) : string[] ->(''.match(/ /) || []).map : { (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; (this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; (this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; } +>(''.match(/ /) || []).map : (callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[] >(''.match(/ /) || []) : RegExpMatchArray >''.match(/ /) || [] : RegExpMatchArray >''.match(/ /) : RegExpMatchArray | null @@ -12,8 +12,8 @@ >match : (regexp: string | RegExp) => RegExpMatchArray | null >/ / : RegExp >[] : never[] ->map : { (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; (this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; (this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; } ->s => s.toLowerCase() : (this: void, s: string) => string +>map : (callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[] +>s => s.toLowerCase() : (s: string) => string >s : string >s.toLowerCase() : string >s.toLowerCase : () => string @@ -42,10 +42,10 @@ function f1() { let z = y.map(s => s.toLowerCase()); >z : string[] >y.map(s => s.toLowerCase()) : string[] ->y.map : { (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; (this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; (this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; } +>y.map : (callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[] >y : RegExpMatchArray ->map : { (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; (this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; (this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; } ->s => s.toLowerCase() : (this: void, s: string) => string +>map : (callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[] +>s => s.toLowerCase() : (s: string) => string >s : string >s.toLowerCase() : string >s.toLowerCase : () => string @@ -74,10 +74,10 @@ function f2() { let z = y.map(s => s.toLowerCase()); >z : string[] >y.map(s => s.toLowerCase()) : string[] ->y.map : { (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; (this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; (this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; } +>y.map : (callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[] >y : RegExpMatchArray ->map : { (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; (this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; (this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; } ->s => s.toLowerCase() : (this: void, s: string) => string +>map : (callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[] +>s => s.toLowerCase() : (s: string) => string >s : string >s.toLowerCase() : string >s.toLowerCase : () => string diff --git a/tests/baselines/reference/blockScopedClassDeclarationAcrossFiles.js b/tests/baselines/reference/blockScopedClassDeclarationAcrossFiles.js new file mode 100644 index 00000000000..b89943b24ff --- /dev/null +++ b/tests/baselines/reference/blockScopedClassDeclarationAcrossFiles.js @@ -0,0 +1,15 @@ +//// [tests/cases/compiler/blockScopedClassDeclarationAcrossFiles.ts] //// + +//// [c.ts] +let foo: typeof C; +//// [b.ts] +class C { } + + +//// [foo.js] +var foo; +var C = (function () { + function C() { + } + return C; +}()); diff --git a/tests/baselines/reference/blockScopedClassDeclarationAcrossFiles.symbols b/tests/baselines/reference/blockScopedClassDeclarationAcrossFiles.symbols new file mode 100644 index 00000000000..c5c6e40da20 --- /dev/null +++ b/tests/baselines/reference/blockScopedClassDeclarationAcrossFiles.symbols @@ -0,0 +1,9 @@ +=== tests/cases/compiler/c.ts === +let foo: typeof C; +>foo : Symbol(foo, Decl(c.ts, 0, 3)) +>C : Symbol(C, Decl(b.ts, 0, 0)) + +=== tests/cases/compiler/b.ts === +class C { } +>C : Symbol(C, Decl(b.ts, 0, 0)) + diff --git a/tests/baselines/reference/blockScopedClassDeclarationAcrossFiles.types b/tests/baselines/reference/blockScopedClassDeclarationAcrossFiles.types new file mode 100644 index 00000000000..5bc8862b2aa --- /dev/null +++ b/tests/baselines/reference/blockScopedClassDeclarationAcrossFiles.types @@ -0,0 +1,9 @@ +=== tests/cases/compiler/c.ts === +let foo: typeof C; +>foo : typeof C +>C : typeof C + +=== tests/cases/compiler/b.ts === +class C { } +>C : C + diff --git a/tests/baselines/reference/callSignatureAssignabilityInInheritance.errors.txt b/tests/baselines/reference/callSignatureAssignabilityInInheritance.errors.txt index d6efdd66868..3d9ecd65e3d 100644 --- a/tests/baselines/reference/callSignatureAssignabilityInInheritance.errors.txt +++ b/tests/baselines/reference/callSignatureAssignabilityInInheritance.errors.txt @@ -2,9 +2,13 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/callSign Types of property 'a' are incompatible. Type '(x: number) => string' is not assignable to type '(x: number) => number'. Type 'string' is not assignable to type 'number'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/callSignatureAssignabilityInInheritance.ts(63,15): error TS2430: Interface 'I3' incorrectly extends interface 'Base2'. + Types of property 'a2' are incompatible. + Type '(x: T) => string' is not assignable to type '(x: T) => T'. + Type 'string' is not assignable to type 'T'. -==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/callSignatureAssignabilityInInheritance.ts (1 errors) ==== +==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/callSignatureAssignabilityInInheritance.ts (2 errors) ==== module CallSignature { interface Base { // T // M's @@ -73,6 +77,11 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/callSign // S's interface I3 extends Base2 { + ~~ +!!! error TS2430: Interface 'I3' incorrectly extends interface 'Base2'. +!!! error TS2430: Types of property 'a2' are incompatible. +!!! error TS2430: Type '(x: T) => string' is not assignable to type '(x: T) => T'. +!!! error TS2430: Type 'string' is not assignable to type 'T'. // N's a2: (x: T) => string; // error because base returns non-void; } diff --git a/tests/baselines/reference/callSignatureAssignabilityInInheritance3.errors.txt b/tests/baselines/reference/callSignatureAssignabilityInInheritance3.errors.txt index f5e05567b25..5bf725b06e3 100644 --- a/tests/baselines/reference/callSignatureAssignabilityInInheritance3.errors.txt +++ b/tests/baselines/reference/callSignatureAssignabilityInInheritance3.errors.txt @@ -11,9 +11,31 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/callSign Type '{ foo: number; }' is not assignable to type 'Base'. Types of property 'foo' are incompatible. Type 'number' is not assignable to type 'string'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/callSignatureAssignabilityInInheritance3.ts(76,19): error TS2430: Interface 'I6' incorrectly extends interface 'A'. + Types of property 'a15' are incompatible. + Type '(x: { a: T; b: T; }) => T' is not assignable to type '(x: { a: string; b: number; }) => number'. + Type 'string | number' is not assignable to type 'number'. + Type 'string' is not assignable to type 'number'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/callSignatureAssignabilityInInheritance3.ts(80,19): error TS2430: Interface 'I7' incorrectly extends interface 'A'. + Types of property 'a15' are incompatible. + Type '(x: { a: T; b: T; }) => number' is not assignable to type '(x: { a: string; b: number; }) => number'. + Types of parameters 'x' and 'x' are incompatible. + Type '{ a: string; b: number; }' is not assignable to type '{ a: Base; b: Base; }'. + Types of property 'a' are incompatible. + Type 'string' is not assignable to type 'Base'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/callSignatureAssignabilityInInheritance3.ts(100,19): error TS2430: Interface 'I6' incorrectly extends interface 'B'. + Types of property 'a2' are incompatible. + Type '(x: T) => string[]' is not assignable to type '(x: T) => T[]'. + Type 'string[]' is not assignable to type 'T[]'. + Type 'string' is not assignable to type 'T'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/callSignatureAssignabilityInInheritance3.ts(109,19): error TS2430: Interface 'I7' incorrectly extends interface 'C'. + Types of property 'a2' are incompatible. + Type '(x: T) => T[]' is not assignable to type '(x: T) => string[]'. + Type 'T[]' is not assignable to type 'string[]'. + Type 'T' is not assignable to type 'string'. -==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/callSignatureAssignabilityInInheritance3.ts (2 errors) ==== +==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/callSignatureAssignabilityInInheritance3.ts (6 errors) ==== // checking subtype relations for function types as it relates to contextual signature instantiation // error cases @@ -105,10 +127,24 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/callSign } interface I6 extends A { + ~~ +!!! error TS2430: Interface 'I6' incorrectly extends interface 'A'. +!!! error TS2430: Types of property 'a15' are incompatible. +!!! error TS2430: Type '(x: { a: T; b: T; }) => T' is not assignable to type '(x: { a: string; b: number; }) => number'. +!!! error TS2430: Type 'string | number' is not assignable to type 'number'. +!!! error TS2430: Type 'string' is not assignable to type 'number'. a15: (x: { a: T; b: T }) => T; // error, T is {} which isn't an acceptable return type } interface I7 extends A { + ~~ +!!! error TS2430: Interface 'I7' incorrectly extends interface 'A'. +!!! error TS2430: Types of property 'a15' are incompatible. +!!! error TS2430: Type '(x: { a: T; b: T; }) => number' is not assignable to type '(x: { a: string; b: number; }) => number'. +!!! error TS2430: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2430: Type '{ a: string; b: number; }' is not assignable to type '{ a: Base; b: Base; }'. +!!! error TS2430: Types of property 'a' are incompatible. +!!! error TS2430: Type 'string' is not assignable to type 'Base'. a15: (x: { a: T; b: T }) => number; // error, T defaults to Base, which is not compatible with number or string } @@ -129,6 +165,12 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/callSign } interface I6 extends B { + ~~ +!!! error TS2430: Interface 'I6' incorrectly extends interface 'B'. +!!! error TS2430: Types of property 'a2' are incompatible. +!!! error TS2430: Type '(x: T) => string[]' is not assignable to type '(x: T) => T[]'. +!!! error TS2430: Type 'string[]' is not assignable to type 'T[]'. +!!! error TS2430: Type 'string' is not assignable to type 'T'. a2: (x: T) => string[]; // error } @@ -138,6 +180,12 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/callSign } interface I7 extends C { + ~~ +!!! error TS2430: Interface 'I7' incorrectly extends interface 'C'. +!!! error TS2430: Types of property 'a2' are incompatible. +!!! error TS2430: Type '(x: T) => T[]' is not assignable to type '(x: T) => string[]'. +!!! error TS2430: Type 'T[]' is not assignable to type 'string[]'. +!!! error TS2430: Type 'T' is not assignable to type 'string'. a2: (x: T) => T[]; // error } } diff --git a/tests/baselines/reference/callSignatureAssignabilityInInheritance6.errors.txt b/tests/baselines/reference/callSignatureAssignabilityInInheritance6.errors.txt new file mode 100644 index 00000000000..602e40dfcfb --- /dev/null +++ b/tests/baselines/reference/callSignatureAssignabilityInInheritance6.errors.txt @@ -0,0 +1,142 @@ +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/callSignatureAssignabilityInInheritance6.ts(24,11): error TS2430: Interface 'I' incorrectly extends interface 'A'. + Types of property 'a' are incompatible. + Type '(x: T) => T[]' is not assignable to type '(x: T) => T[]'. + Types of parameters 'x' and 'x' are incompatible. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/callSignatureAssignabilityInInheritance6.ts(28,11): error TS2430: Interface 'I2' incorrectly extends interface 'A'. + Types of property 'a2' are incompatible. + Type '(x: T) => string[]' is not assignable to type '(x: T) => string[]'. + Types of parameters 'x' and 'x' are incompatible. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/callSignatureAssignabilityInInheritance6.ts(32,11): error TS2430: Interface 'I3' incorrectly extends interface 'A'. + Types of property 'a3' are incompatible. + Type '(x: T) => T' is not assignable to type '(x: T) => void'. + Types of parameters 'x' and 'x' are incompatible. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/callSignatureAssignabilityInInheritance6.ts(36,11): error TS2430: Interface 'I4' incorrectly extends interface 'A'. + Types of property 'a4' are incompatible. + Type '(x: T, y: U) => string' is not assignable to type '(x: T, y: U) => string'. + Types of parameters 'x' and 'x' are incompatible. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/callSignatureAssignabilityInInheritance6.ts(40,11): error TS2430: Interface 'I5' incorrectly extends interface 'A'. + Types of property 'a5' are incompatible. + Type '(x: (arg: T) => U) => T' is not assignable to type '(x: (arg: T) => U) => T'. + Types of parameters 'x' and 'x' are incompatible. + Types of parameters 'arg' and 'arg' are incompatible. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/callSignatureAssignabilityInInheritance6.ts(44,11): error TS2430: Interface 'I7' incorrectly extends interface 'A'. + Types of property 'a11' are incompatible. + Type '(x: { foo: T; }, y: { foo: U; bar: U; }) => Base' is not assignable to type '(x: { foo: T; }, y: { foo: T; bar: T; }) => Base'. + Types of parameters 'x' and 'x' are incompatible. + Type '{ foo: T; }' is not assignable to type '{ foo: T; }'. Two different types with this name exist, but they are unrelated. + Types of property 'foo' are incompatible. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/callSignatureAssignabilityInInheritance6.ts(48,11): error TS2430: Interface 'I9' incorrectly extends interface 'A'. + Types of property 'a16' are incompatible. + Type '(x: { a: T; b: T; }) => T[]' is not assignable to type '(x: { a: T; b: T; }) => T[]'. + Types of parameters 'x' and 'x' are incompatible. + Type '{ a: T; b: T; }' is not assignable to type '{ a: T; b: T; }'. Two different types with this name exist, but they are unrelated. + Types of property 'a' are incompatible. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. + Type 'Base' is not assignable to type 'T'. + + +==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/callSignatureAssignabilityInInheritance6.ts (7 errors) ==== + // checking subtype relations for function types as it relates to contextual signature instantiation + // same as subtypingWithCallSignatures4 but using class type parameters instead of generic signatures + // all are errors + + class Base { foo: string; } + class Derived extends Base { bar: string; } + class Derived2 extends Derived { baz: string; } + class OtherDerived extends Base { bing: string; } + + interface A { // T + // M's + a: (x: T) => T[]; + a2: (x: T) => string[]; + a3: (x: T) => void; + a4: (x: T, y: U) => string; + a5: (x: (arg: T) => U) => T; + a6: (x: (arg: T) => Derived) => T; + a11: (x: { foo: T }, y: { foo: T; bar: T }) => Base; + a15: (x: { a: T; b: T }) => T[]; + a16: (x: { a: T; b: T }) => T[]; + } + + // S's + interface I extends A { + ~ +!!! error TS2430: Interface 'I' incorrectly extends interface 'A'. +!!! error TS2430: Types of property 'a' are incompatible. +!!! error TS2430: Type '(x: T) => T[]' is not assignable to type '(x: T) => T[]'. +!!! error TS2430: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2430: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. + a: (x: T) => T[]; + } + + interface I2 extends A { + ~~ +!!! error TS2430: Interface 'I2' incorrectly extends interface 'A'. +!!! error TS2430: Types of property 'a2' are incompatible. +!!! error TS2430: Type '(x: T) => string[]' is not assignable to type '(x: T) => string[]'. +!!! error TS2430: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2430: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. + a2: (x: T) => string[]; + } + + interface I3 extends A { + ~~ +!!! error TS2430: Interface 'I3' incorrectly extends interface 'A'. +!!! error TS2430: Types of property 'a3' are incompatible. +!!! error TS2430: Type '(x: T) => T' is not assignable to type '(x: T) => void'. +!!! error TS2430: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2430: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. + a3: (x: T) => T; + } + + interface I4 extends A { + ~~ +!!! error TS2430: Interface 'I4' incorrectly extends interface 'A'. +!!! error TS2430: Types of property 'a4' are incompatible. +!!! error TS2430: Type '(x: T, y: U) => string' is not assignable to type '(x: T, y: U) => string'. +!!! error TS2430: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2430: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. + a4: (x: T, y: U) => string; + } + + interface I5 extends A { + ~~ +!!! error TS2430: Interface 'I5' incorrectly extends interface 'A'. +!!! error TS2430: Types of property 'a5' are incompatible. +!!! error TS2430: Type '(x: (arg: T) => U) => T' is not assignable to type '(x: (arg: T) => U) => T'. +!!! error TS2430: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2430: Types of parameters 'arg' and 'arg' are incompatible. +!!! error TS2430: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. + a5: (x: (arg: T) => U) => T; + } + + interface I7 extends A { + ~~ +!!! error TS2430: Interface 'I7' incorrectly extends interface 'A'. +!!! error TS2430: Types of property 'a11' are incompatible. +!!! error TS2430: Type '(x: { foo: T; }, y: { foo: U; bar: U; }) => Base' is not assignable to type '(x: { foo: T; }, y: { foo: T; bar: T; }) => Base'. +!!! error TS2430: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2430: Type '{ foo: T; }' is not assignable to type '{ foo: T; }'. Two different types with this name exist, but they are unrelated. +!!! error TS2430: Types of property 'foo' are incompatible. +!!! error TS2430: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. + a11: (x: { foo: T }, y: { foo: U; bar: U }) => Base; + } + + interface I9 extends A { + ~~ +!!! error TS2430: Interface 'I9' incorrectly extends interface 'A'. +!!! error TS2430: Types of property 'a16' are incompatible. +!!! error TS2430: Type '(x: { a: T; b: T; }) => T[]' is not assignable to type '(x: { a: T; b: T; }) => T[]'. +!!! error TS2430: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2430: Type '{ a: T; b: T; }' is not assignable to type '{ a: T; b: T; }'. Two different types with this name exist, but they are unrelated. +!!! error TS2430: Types of property 'a' are incompatible. +!!! error TS2430: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +!!! error TS2430: Type 'Base' is not assignable to type 'T'. + a16: (x: { a: T; b: T }) => T[]; + } \ No newline at end of file diff --git a/tests/baselines/reference/checkJsdocParamTag1.js b/tests/baselines/reference/checkJsdocParamTag1.js new file mode 100644 index 00000000000..577460626a1 --- /dev/null +++ b/tests/baselines/reference/checkJsdocParamTag1.js @@ -0,0 +1,22 @@ +//// [0.js] +// @ts-check +/** + * @param {number=} n + * @param {string} [s] + */ +function foo(n, s) {} + +foo(); +foo(1); +foo(1, "hi"); + +//// [0.js] +// @ts-check +/** + * @param {number=} n + * @param {string} [s] + */ +function foo(n, s) { } +foo(); +foo(1); +foo(1, "hi"); diff --git a/tests/baselines/reference/checkJsdocParamTag1.symbols b/tests/baselines/reference/checkJsdocParamTag1.symbols new file mode 100644 index 00000000000..d16816f908b --- /dev/null +++ b/tests/baselines/reference/checkJsdocParamTag1.symbols @@ -0,0 +1,20 @@ +=== tests/cases/conformance/jsdoc/0.js === +// @ts-check +/** + * @param {number=} n + * @param {string} [s] + */ +function foo(n, s) {} +>foo : Symbol(foo, Decl(0.js, 0, 0)) +>n : Symbol(n, Decl(0.js, 5, 13)) +>s : Symbol(s, Decl(0.js, 5, 15)) + +foo(); +>foo : Symbol(foo, Decl(0.js, 0, 0)) + +foo(1); +>foo : Symbol(foo, Decl(0.js, 0, 0)) + +foo(1, "hi"); +>foo : Symbol(foo, Decl(0.js, 0, 0)) + diff --git a/tests/baselines/reference/checkJsdocParamTag1.types b/tests/baselines/reference/checkJsdocParamTag1.types new file mode 100644 index 00000000000..5b24c3d8887 --- /dev/null +++ b/tests/baselines/reference/checkJsdocParamTag1.types @@ -0,0 +1,26 @@ +=== tests/cases/conformance/jsdoc/0.js === +// @ts-check +/** + * @param {number=} n + * @param {string} [s] + */ +function foo(n, s) {} +>foo : (n?: number, s?: string) => void +>n : number +>s : string + +foo(); +>foo() : void +>foo : (n?: number, s?: string) => void + +foo(1); +>foo(1) : void +>foo : (n?: number, s?: string) => void +>1 : 1 + +foo(1, "hi"); +>foo(1, "hi") : void +>foo : (n?: number, s?: string) => void +>1 : 1 +>"hi" : "hi" + diff --git a/tests/baselines/reference/checkJsdocReturnTag1.js b/tests/baselines/reference/checkJsdocReturnTag1.js new file mode 100644 index 00000000000..31c30e54dfc --- /dev/null +++ b/tests/baselines/reference/checkJsdocReturnTag1.js @@ -0,0 +1,43 @@ +//// [returns.js] +// @ts-check +/** + * @returns {string} This comment is not currently exposed + */ +function f() { + return "hello"; +} + +/** + * @returns {string=} This comment is not currently exposed + */ +function f1() { + return "hello world"; +} + +/** + * @returns {string|number} This comment is not currently exposed + */ +function f2() { + return 5 || "hello"; +} + +//// [dummy.js] +// @ts-check +/** + * @returns {string} This comment is not currently exposed + */ +function f() { + return "hello"; +} +/** + * @returns {string=} This comment is not currently exposed + */ +function f1() { + return "hello world"; +} +/** + * @returns {string|number} This comment is not currently exposed + */ +function f2() { + return 5 || "hello"; +} diff --git a/tests/baselines/reference/checkJsdocReturnTag1.symbols b/tests/baselines/reference/checkJsdocReturnTag1.symbols new file mode 100644 index 00000000000..ec6376d02ab --- /dev/null +++ b/tests/baselines/reference/checkJsdocReturnTag1.symbols @@ -0,0 +1,28 @@ +=== tests/cases/conformance/jsdoc/returns.js === +// @ts-check +/** + * @returns {string} This comment is not currently exposed + */ +function f() { +>f : Symbol(f, Decl(returns.js, 0, 0)) + + return "hello"; +} + +/** + * @returns {string=} This comment is not currently exposed + */ +function f1() { +>f1 : Symbol(f1, Decl(returns.js, 6, 1)) + + return "hello world"; +} + +/** + * @returns {string|number} This comment is not currently exposed + */ +function f2() { +>f2 : Symbol(f2, Decl(returns.js, 13, 1)) + + return 5 || "hello"; +} diff --git a/tests/baselines/reference/checkJsdocReturnTag1.types b/tests/baselines/reference/checkJsdocReturnTag1.types new file mode 100644 index 00000000000..04a2df87c01 --- /dev/null +++ b/tests/baselines/reference/checkJsdocReturnTag1.types @@ -0,0 +1,33 @@ +=== tests/cases/conformance/jsdoc/returns.js === +// @ts-check +/** + * @returns {string} This comment is not currently exposed + */ +function f() { +>f : () => string + + return "hello"; +>"hello" : "hello" +} + +/** + * @returns {string=} This comment is not currently exposed + */ +function f1() { +>f1 : () => string + + return "hello world"; +>"hello world" : "hello world" +} + +/** + * @returns {string|number} This comment is not currently exposed + */ +function f2() { +>f2 : () => string | number + + return 5 || "hello"; +>5 || "hello" : "hello" | 5 +>5 : 5 +>"hello" : "hello" +} diff --git a/tests/baselines/reference/checkJsdocReturnTag2.errors.txt b/tests/baselines/reference/checkJsdocReturnTag2.errors.txt new file mode 100644 index 00000000000..23a450c83ca --- /dev/null +++ b/tests/baselines/reference/checkJsdocReturnTag2.errors.txt @@ -0,0 +1,25 @@ +tests/cases/conformance/jsdoc/returns.js(6,5): error TS2322: Type '5' is not assignable to type 'string'. +tests/cases/conformance/jsdoc/returns.js(13,5): error TS2322: Type 'true | 5' is not assignable to type 'string | number'. + Type 'true' is not assignable to type 'string | number'. + + +==== tests/cases/conformance/jsdoc/returns.js (2 errors) ==== + // @ts-check + /** + * @returns {string} This comment is not currently exposed + */ + function f() { + return 5; + ~~~~~~~~~ +!!! error TS2322: Type '5' is not assignable to type 'string'. + } + + /** + * @returns {string | number} This comment is not currently exposed + */ + function f1() { + return 5 || true; + ~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type 'true | 5' is not assignable to type 'string | number'. +!!! error TS2322: Type 'true' is not assignable to type 'string | number'. + } \ No newline at end of file diff --git a/tests/baselines/reference/checkJsdocReturnTag2.js b/tests/baselines/reference/checkJsdocReturnTag2.js new file mode 100644 index 00000000000..4a68e5d85b7 --- /dev/null +++ b/tests/baselines/reference/checkJsdocReturnTag2.js @@ -0,0 +1,30 @@ +//// [returns.js] +// @ts-check +/** + * @returns {string} This comment is not currently exposed + */ +function f() { + return 5; +} + +/** + * @returns {string | number} This comment is not currently exposed + */ +function f1() { + return 5 || true; +} + +//// [dummy.js] +// @ts-check +/** + * @returns {string} This comment is not currently exposed + */ +function f() { + return 5; +} +/** + * @returns {string | number} This comment is not currently exposed + */ +function f1() { + return 5 || true; +} diff --git a/tests/baselines/reference/checkJsdocReturnTag2.symbols b/tests/baselines/reference/checkJsdocReturnTag2.symbols new file mode 100644 index 00000000000..43fa1a800e1 --- /dev/null +++ b/tests/baselines/reference/checkJsdocReturnTag2.symbols @@ -0,0 +1,19 @@ +=== tests/cases/conformance/jsdoc/returns.js === +// @ts-check +/** + * @returns {string} This comment is not currently exposed + */ +function f() { +>f : Symbol(f, Decl(returns.js, 0, 0)) + + return 5; +} + +/** + * @returns {string | number} This comment is not currently exposed + */ +function f1() { +>f1 : Symbol(f1, Decl(returns.js, 6, 1)) + + return 5 || true; +} diff --git a/tests/baselines/reference/checkJsdocReturnTag2.types b/tests/baselines/reference/checkJsdocReturnTag2.types new file mode 100644 index 00000000000..fe7dca7a364 --- /dev/null +++ b/tests/baselines/reference/checkJsdocReturnTag2.types @@ -0,0 +1,23 @@ +=== tests/cases/conformance/jsdoc/returns.js === +// @ts-check +/** + * @returns {string} This comment is not currently exposed + */ +function f() { +>f : () => string + + return 5; +>5 : 5 +} + +/** + * @returns {string | number} This comment is not currently exposed + */ +function f1() { +>f1 : () => string | number + + return 5 || true; +>5 || true : true | 5 +>5 : 5 +>true : true +} diff --git a/tests/baselines/reference/jsDocTypes2.js b/tests/baselines/reference/checkJsdocTypeTag1.js similarity index 77% rename from tests/baselines/reference/jsDocTypes2.js rename to tests/baselines/reference/checkJsdocTypeTag1.js index ba59043978c..e4586643c22 100644 --- a/tests/baselines/reference/jsDocTypes2.js +++ b/tests/baselines/reference/checkJsdocTypeTag1.js @@ -1,7 +1,14 @@ //// [0.js] // @ts-check +/** @type {String} */ +var S = "hello world"; + +/** @type {number} */ +var n = 10; + /** @type {*} */ var anyT = 2; +anyT = "hello"; /** @type {?} */ var anyT1 = 2; @@ -25,8 +32,13 @@ x2(0); //// [0.js] // @ts-check +/** @type {String} */ +var S = "hello world"; +/** @type {number} */ +var n = 10; /** @type {*} */ var anyT = 2; +anyT = "hello"; /** @type {?} */ var anyT1 = 2; anyT1 = "hi"; diff --git a/tests/baselines/reference/checkJsdocTypeTag1.symbols b/tests/baselines/reference/checkJsdocTypeTag1.symbols new file mode 100644 index 00000000000..fff51499bc4 --- /dev/null +++ b/tests/baselines/reference/checkJsdocTypeTag1.symbols @@ -0,0 +1,60 @@ +=== tests/cases/conformance/jsdoc/0.js === +// @ts-check +/** @type {String} */ +var S = "hello world"; +>S : Symbol(S, Decl(0.js, 2, 3)) + +/** @type {number} */ +var n = 10; +>n : Symbol(n, Decl(0.js, 5, 3)) + +/** @type {*} */ +var anyT = 2; +>anyT : Symbol(anyT, Decl(0.js, 8, 3)) + +anyT = "hello"; +>anyT : Symbol(anyT, Decl(0.js, 8, 3)) + +/** @type {?} */ +var anyT1 = 2; +>anyT1 : Symbol(anyT1, Decl(0.js, 12, 3)) + +anyT1 = "hi"; +>anyT1 : Symbol(anyT1, Decl(0.js, 12, 3)) + +/** @type {Function} */ +const x = (a) => a + 1; +>x : Symbol(x, Decl(0.js, 16, 5)) +>a : Symbol(a, Decl(0.js, 16, 11)) +>a : Symbol(a, Decl(0.js, 16, 11)) + +x(1); +>x : Symbol(x, Decl(0.js, 16, 5)) + +/** @type {function} */ +const y = (a) => a + 1; +>y : Symbol(y, Decl(0.js, 20, 5)) +>a : Symbol(a, Decl(0.js, 20, 11)) +>a : Symbol(a, Decl(0.js, 20, 11)) + +x(1); +>x : Symbol(x, Decl(0.js, 16, 5)) + +/** @type {function (number)} */ +const x1 = (a) => a + 1; +>x1 : Symbol(x1, Decl(0.js, 24, 5)) +>a : Symbol(a, Decl(0.js, 24, 12)) +>a : Symbol(a, Decl(0.js, 24, 12)) + +x1(0); +>x1 : Symbol(x1, Decl(0.js, 24, 5)) + +/** @type {function (number): number} */ +const x2 = (a) => a + 1; +>x2 : Symbol(x2, Decl(0.js, 28, 5)) +>a : Symbol(a, Decl(0.js, 28, 12)) +>a : Symbol(a, Decl(0.js, 28, 12)) + +x2(0); +>x2 : Symbol(x2, Decl(0.js, 28, 5)) + diff --git a/tests/baselines/reference/jsDocTypes2.types b/tests/baselines/reference/checkJsdocTypeTag1.types similarity index 62% rename from tests/baselines/reference/jsDocTypes2.types rename to tests/baselines/reference/checkJsdocTypeTag1.types index 599c19c7ffc..898cf58806a 100644 --- a/tests/baselines/reference/jsDocTypes2.types +++ b/tests/baselines/reference/checkJsdocTypeTag1.types @@ -1,10 +1,25 @@ -=== tests/cases/conformance/salsa/0.js === +=== tests/cases/conformance/jsdoc/0.js === // @ts-check +/** @type {String} */ +var S = "hello world"; +>S : string +>"hello world" : "hello world" + +/** @type {number} */ +var n = 10; +>n : number +>10 : 10 + /** @type {*} */ var anyT = 2; >anyT : any >2 : 2 +anyT = "hello"; +>anyT = "hello" : "hello" +>anyT : any +>"hello" : "hello" + /** @type {?} */ var anyT1 = 2; >anyT1 : any @@ -46,10 +61,10 @@ x(1); /** @type {function (number)} */ const x1 = (a) => a + 1; >x1 : (arg0: number) => any ->(a) => a + 1 : (a: any) => any ->a : any ->a + 1 : any ->a : any +>(a) => a + 1 : (a: number) => number +>a : number +>a + 1 : number +>a : number >1 : 1 x1(0); @@ -60,10 +75,10 @@ x1(0); /** @type {function (number): number} */ const x2 = (a) => a + 1; >x2 : (arg0: number) => number ->(a) => a + 1 : (a: any) => any ->a : any ->a + 1 : any ->a : any +>(a) => a + 1 : (a: number) => number +>a : number +>a + 1 : number +>a : number >1 : 1 x2(0); diff --git a/tests/baselines/reference/checkJsdocTypeTag2.errors.txt b/tests/baselines/reference/checkJsdocTypeTag2.errors.txt new file mode 100644 index 00000000000..3590c10e278 --- /dev/null +++ b/tests/baselines/reference/checkJsdocTypeTag2.errors.txt @@ -0,0 +1,48 @@ +tests/cases/conformance/jsdoc/0.js(3,5): error TS2322: Type 'true' is not assignable to type 'string'. +tests/cases/conformance/jsdoc/0.js(6,5): error TS2322: Type '"hello"' is not assignable to type 'number'. +tests/cases/conformance/jsdoc/0.js(10,4): error TS2345: Argument of type '"string"' is not assignable to parameter of type 'number'. +tests/cases/conformance/jsdoc/0.js(17,1): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/conformance/jsdoc/0.js(20,21): error TS2339: Property 'concat' does not exist on type 'number'. +tests/cases/conformance/jsdoc/0.js(24,7): error TS2322: Type '(a: number) => number' is not assignable to type '(arg0: number) => string'. + Type 'number' is not assignable to type 'string'. + + +==== tests/cases/conformance/jsdoc/0.js (6 errors) ==== + // @ts-check + /** @type {String} */ + var S = true; + ~ +!!! error TS2322: Type 'true' is not assignable to type 'string'. + + /** @type {number} */ + var n = "hello"; + ~ +!!! error TS2322: Type '"hello"' is not assignable to type 'number'. + + /** @type {function (number)} */ + const x1 = (a) => a + 1; + x1("string"); + ~~~~~~~~ +!!! error TS2345: Argument of type '"string"' is not assignable to parameter of type 'number'. + + /** @type {function (number): number} */ + const x2 = (a) => a + 1; + + /** @type {string} */ + var a; + a = x2(0); + ~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. + + /** @type {function (number): number} */ + const x3 = (a) => a.concat("hi"); + ~~~~~~ +!!! error TS2339: Property 'concat' does not exist on type 'number'. + x3(0); + + /** @type {function (number): string} */ + const x4 = (a) => a + 1; + ~~ +!!! error TS2322: Type '(a: number) => number' is not assignable to type '(arg0: number) => string'. +!!! error TS2322: Type 'number' is not assignable to type 'string'. + x4(0); \ No newline at end of file diff --git a/tests/baselines/reference/checkJsdocTypeTag2.js b/tests/baselines/reference/checkJsdocTypeTag2.js new file mode 100644 index 00000000000..0e550d3ba33 --- /dev/null +++ b/tests/baselines/reference/checkJsdocTypeTag2.js @@ -0,0 +1,47 @@ +//// [0.js] +// @ts-check +/** @type {String} */ +var S = true; + +/** @type {number} */ +var n = "hello"; + +/** @type {function (number)} */ +const x1 = (a) => a + 1; +x1("string"); + +/** @type {function (number): number} */ +const x2 = (a) => a + 1; + +/** @type {string} */ +var a; +a = x2(0); + +/** @type {function (number): number} */ +const x3 = (a) => a.concat("hi"); +x3(0); + +/** @type {function (number): string} */ +const x4 = (a) => a + 1; +x4(0); + +//// [0.js] +// @ts-check +/** @type {String} */ +var S = true; +/** @type {number} */ +var n = "hello"; +/** @type {function (number)} */ +var x1 = function (a) { return a + 1; }; +x1("string"); +/** @type {function (number): number} */ +var x2 = function (a) { return a + 1; }; +/** @type {string} */ +var a; +a = x2(0); +/** @type {function (number): number} */ +var x3 = function (a) { return a.concat("hi"); }; +x3(0); +/** @type {function (number): string} */ +var x4 = function (a) { return a + 1; }; +x4(0); diff --git a/tests/baselines/reference/jsDocTypes3.errors.txt b/tests/baselines/reference/checkJsdocTypeTag3.errors.txt similarity index 72% rename from tests/baselines/reference/jsDocTypes3.errors.txt rename to tests/baselines/reference/checkJsdocTypeTag3.errors.txt index 5f5feeaf0a7..d53c0972fa3 100644 --- a/tests/baselines/reference/jsDocTypes3.errors.txt +++ b/tests/baselines/reference/checkJsdocTypeTag3.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/salsa/0.js(5,4): error TS2345: Argument of type '"string"' is not assignable to parameter of type 'number'. -tests/cases/conformance/salsa/0.js(12,1): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/conformance/jsdoc/0.js(5,4): error TS2345: Argument of type '"string"' is not assignable to parameter of type 'number'. +tests/cases/conformance/jsdoc/0.js(12,1): error TS2322: Type 'number' is not assignable to type 'string'. -==== tests/cases/conformance/salsa/0.js (2 errors) ==== +==== tests/cases/conformance/jsdoc/0.js (2 errors) ==== // @ts-check /** @type {function (number)} */ diff --git a/tests/baselines/reference/jsDocTypes3.js b/tests/baselines/reference/checkJsdocTypeTag3.js similarity index 100% rename from tests/baselines/reference/jsDocTypes3.js rename to tests/baselines/reference/checkJsdocTypeTag3.js diff --git a/tests/baselines/reference/checkJsxChildrenProperty1.symbols b/tests/baselines/reference/checkJsxChildrenProperty1.symbols index 8793d0edd49..ede60746f4b 100644 --- a/tests/baselines/reference/checkJsxChildrenProperty1.symbols +++ b/tests/baselines/reference/checkJsxChildrenProperty1.symbols @@ -13,8 +13,8 @@ interface Prop { children: string | JSX.Element >children : Symbol(Prop.children, Decl(file.tsx, 4, 14)) ->JSX : Symbol(JSX, Decl(react.d.ts, 2352, 1)) ->Element : Symbol(JSX.Element, Decl(react.d.ts, 2355, 27)) +>JSX : Symbol(JSX, Decl(react.d.ts, 2353, 1)) +>Element : Symbol(JSX.Element, Decl(react.d.ts, 2356, 27)) } function Comp(p: Prop) { @@ -23,11 +23,11 @@ function Comp(p: Prop) { >Prop : Symbol(Prop, Decl(file.tsx, 0, 32)) return
{p.b}
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45)) >p.b : Symbol(Prop.b, Decl(file.tsx, 3, 14)) >p : Symbol(p, Decl(file.tsx, 8, 14)) >b : Symbol(Prop.b, Decl(file.tsx, 3, 14)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45)) } // OK @@ -59,8 +59,8 @@ let k2 = >b : Symbol(b, Decl(file.tsx, 19, 16))
hi hi hi!
->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45)) ; >Comp : Symbol(Comp, Decl(file.tsx, 6, 1)) diff --git a/tests/baselines/reference/checkJsxChildrenProperty12.symbols b/tests/baselines/reference/checkJsxChildrenProperty12.symbols index ccfb4b18875..09080234ea9 100644 --- a/tests/baselines/reference/checkJsxChildrenProperty12.symbols +++ b/tests/baselines/reference/checkJsxChildrenProperty12.symbols @@ -18,9 +18,9 @@ interface ButtonProp { class Button extends React.Component { >Button : Symbol(Button, Decl(file.tsx, 6, 1)) ->React.Component : Symbol(React.Component, Decl(react.d.ts, 158, 55)) +>React.Component : Symbol(React.Component, Decl(react.d.ts, 158, 55), Decl(react.d.ts, 161, 66)) >React : Symbol(React, Decl(file.tsx, 0, 0)) ->Component : Symbol(React.Component, Decl(react.d.ts, 158, 55)) +>Component : Symbol(React.Component, Decl(react.d.ts, 158, 55), Decl(react.d.ts, 161, 66)) >ButtonProp : Symbol(ButtonProp, Decl(file.tsx, 0, 32)) render() { @@ -34,20 +34,20 @@ class Button extends React.Component { return >InnerButton : Symbol(InnerButton, Decl(file.tsx, 24, 1)) ->this.props : Symbol(React.Component.props, Decl(react.d.ts, 166, 37)) +>this.props : Symbol(React.Component.props, Decl(react.d.ts, 167, 37)) >this : Symbol(Button, Decl(file.tsx, 6, 1)) ->props : Symbol(React.Component.props, Decl(react.d.ts, 166, 37)) +>props : Symbol(React.Component.props, Decl(react.d.ts, 167, 37)) } else { return ( >InnerButton : Symbol(InnerButton, Decl(file.tsx, 24, 1)) ->this.props : Symbol(React.Component.props, Decl(react.d.ts, 166, 37)) +>this.props : Symbol(React.Component.props, Decl(react.d.ts, 167, 37)) >this : Symbol(Button, Decl(file.tsx, 6, 1)) ->props : Symbol(React.Component.props, Decl(react.d.ts, 166, 37)) +>props : Symbol(React.Component.props, Decl(react.d.ts, 167, 37))
Hello World
->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45))
); >InnerButton : Symbol(InnerButton, Decl(file.tsx, 24, 1)) @@ -64,17 +64,17 @@ interface InnerButtonProp { class InnerButton extends React.Component { >InnerButton : Symbol(InnerButton, Decl(file.tsx, 24, 1)) ->React.Component : Symbol(React.Component, Decl(react.d.ts, 158, 55)) +>React.Component : Symbol(React.Component, Decl(react.d.ts, 158, 55), Decl(react.d.ts, 161, 66)) >React : Symbol(React, Decl(file.tsx, 0, 0)) ->Component : Symbol(React.Component, Decl(react.d.ts, 158, 55)) +>Component : Symbol(React.Component, Decl(react.d.ts, 158, 55), Decl(react.d.ts, 161, 66)) >InnerButtonProp : Symbol(InnerButtonProp, Decl(file.tsx, 20, 1)) render() { >render : Symbol(InnerButton.render, Decl(file.tsx, 26, 65)) return (); ->button : Symbol(JSX.IntrinsicElements.button, Decl(react.d.ts, 2385, 43)) ->button : Symbol(JSX.IntrinsicElements.button, Decl(react.d.ts, 2385, 43)) +>button : Symbol(JSX.IntrinsicElements.button, Decl(react.d.ts, 2386, 43)) +>button : Symbol(JSX.IntrinsicElements.button, Decl(react.d.ts, 2386, 43)) } } diff --git a/tests/baselines/reference/checkJsxChildrenProperty3.symbols b/tests/baselines/reference/checkJsxChildrenProperty3.symbols index 49d146f07da..ea1beff75ac 100644 --- a/tests/baselines/reference/checkJsxChildrenProperty3.symbols +++ b/tests/baselines/reference/checkJsxChildrenProperty3.symbols @@ -16,34 +16,34 @@ interface IFetchUserProps { >children : Symbol(IFetchUserProps.children, Decl(file.tsx, 6, 27)) >user : Symbol(user, Decl(file.tsx, 7, 15)) >IUser : Symbol(IUser, Decl(file.tsx, 0, 32)) ->JSX : Symbol(JSX, Decl(react.d.ts, 2352, 1)) ->Element : Symbol(JSX.Element, Decl(react.d.ts, 2355, 27)) +>JSX : Symbol(JSX, Decl(react.d.ts, 2353, 1)) +>Element : Symbol(JSX.Element, Decl(react.d.ts, 2356, 27)) } class FetchUser extends React.Component { >FetchUser : Symbol(FetchUser, Decl(file.tsx, 8, 1)) ->React.Component : Symbol(React.Component, Decl(react.d.ts, 158, 55)) +>React.Component : Symbol(React.Component, Decl(react.d.ts, 158, 55), Decl(react.d.ts, 161, 66)) >React : Symbol(React, Decl(file.tsx, 0, 0)) ->Component : Symbol(React.Component, Decl(react.d.ts, 158, 55)) +>Component : Symbol(React.Component, Decl(react.d.ts, 158, 55), Decl(react.d.ts, 161, 66)) >IFetchUserProps : Symbol(IFetchUserProps, Decl(file.tsx, 4, 1)) render() { >render : Symbol(FetchUser.render, Decl(file.tsx, 10, 63)) return this.state ->this.state : Symbol(React.Component.state, Decl(react.d.ts, 173, 44)) +>this.state : Symbol(React.Component.state, Decl(react.d.ts, 174, 44)) >this : Symbol(FetchUser, Decl(file.tsx, 8, 1)) ->state : Symbol(React.Component.state, Decl(react.d.ts, 173, 44)) +>state : Symbol(React.Component.state, Decl(react.d.ts, 174, 44)) ? this.props.children(this.state.result) ->this.props.children : Symbol(children, Decl(file.tsx, 6, 27), Decl(react.d.ts, 173, 20)) ->this.props : Symbol(React.Component.props, Decl(react.d.ts, 166, 37)) +>this.props.children : Symbol(children, Decl(file.tsx, 6, 27), Decl(react.d.ts, 174, 20)) +>this.props : Symbol(React.Component.props, Decl(react.d.ts, 167, 37)) >this : Symbol(FetchUser, Decl(file.tsx, 8, 1)) ->props : Symbol(React.Component.props, Decl(react.d.ts, 166, 37)) ->children : Symbol(children, Decl(file.tsx, 6, 27), Decl(react.d.ts, 173, 20)) ->this.state : Symbol(React.Component.state, Decl(react.d.ts, 173, 44)) +>props : Symbol(React.Component.props, Decl(react.d.ts, 167, 37)) +>children : Symbol(children, Decl(file.tsx, 6, 27), Decl(react.d.ts, 174, 20)) +>this.state : Symbol(React.Component.state, Decl(react.d.ts, 174, 44)) >this : Symbol(FetchUser, Decl(file.tsx, 8, 1)) ->state : Symbol(React.Component.state, Decl(react.d.ts, 173, 44)) +>state : Symbol(React.Component.state, Decl(react.d.ts, 174, 44)) : null; } @@ -61,11 +61,11 @@ function UserName0() { >user : Symbol(user, Decl(file.tsx, 22, 13))

{ user.Name }

->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2409, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2410, 47)) >user.Name : Symbol(IUser.Name, Decl(file.tsx, 2, 17)) >user : Symbol(user, Decl(file.tsx, 22, 13)) >Name : Symbol(IUser.Name, Decl(file.tsx, 2, 17)) ->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2409, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2410, 47)) ) } @@ -85,11 +85,11 @@ function UserName1() { >user : Symbol(user, Decl(file.tsx, 33, 13))

{ user.Name }

->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2409, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2410, 47)) >user.Name : Symbol(IUser.Name, Decl(file.tsx, 2, 17)) >user : Symbol(user, Decl(file.tsx, 33, 13)) >Name : Symbol(IUser.Name, Decl(file.tsx, 2, 17)) ->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2409, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2410, 47)) ) } diff --git a/tests/baselines/reference/checkJsxChildrenProperty6.symbols b/tests/baselines/reference/checkJsxChildrenProperty6.symbols index e69b24a89ab..3fc70d41883 100644 --- a/tests/baselines/reference/checkJsxChildrenProperty6.symbols +++ b/tests/baselines/reference/checkJsxChildrenProperty6.symbols @@ -13,24 +13,24 @@ interface Prop { children: JSX.Element | JSX.Element[]; >children : Symbol(Prop.children, Decl(file.tsx, 4, 14)) ->JSX : Symbol(JSX, Decl(react.d.ts, 2352, 1)) ->Element : Symbol(JSX.Element, Decl(react.d.ts, 2355, 27)) ->JSX : Symbol(JSX, Decl(react.d.ts, 2352, 1)) ->Element : Symbol(JSX.Element, Decl(react.d.ts, 2355, 27)) +>JSX : Symbol(JSX, Decl(react.d.ts, 2353, 1)) +>Element : Symbol(JSX.Element, Decl(react.d.ts, 2356, 27)) +>JSX : Symbol(JSX, Decl(react.d.ts, 2353, 1)) +>Element : Symbol(JSX.Element, Decl(react.d.ts, 2356, 27)) } class Button extends React.Component { >Button : Symbol(Button, Decl(file.tsx, 6, 1)) ->React.Component : Symbol(React.Component, Decl(react.d.ts, 158, 55)) +>React.Component : Symbol(React.Component, Decl(react.d.ts, 158, 55), Decl(react.d.ts, 161, 66)) >React : Symbol(React, Decl(file.tsx, 0, 0)) ->Component : Symbol(React.Component, Decl(react.d.ts, 158, 55)) +>Component : Symbol(React.Component, Decl(react.d.ts, 158, 55), Decl(react.d.ts, 161, 66)) render() { >render : Symbol(Button.render, Decl(file.tsx, 8, 48)) return (
My Button
) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45)) } } @@ -39,8 +39,8 @@ function AnotherButton(p: any) { >p : Symbol(p, Decl(file.tsx, 14, 23)) return

Just Another Button

; ->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2409, 47)) ->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2409, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2410, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2410, 47)) } function Comp(p: Prop) { @@ -49,11 +49,11 @@ function Comp(p: Prop) { >Prop : Symbol(Prop, Decl(file.tsx, 0, 32)) return
{p.b}
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45)) >p.b : Symbol(Prop.b, Decl(file.tsx, 3, 14)) >p : Symbol(p, Decl(file.tsx, 18, 14)) >b : Symbol(Prop.b, Decl(file.tsx, 3, 14)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45)) } // Ok diff --git a/tests/baselines/reference/checkJsxChildrenProperty8.symbols b/tests/baselines/reference/checkJsxChildrenProperty8.symbols index b6f5f97adac..3d2e232203b 100644 --- a/tests/baselines/reference/checkJsxChildrenProperty8.symbols +++ b/tests/baselines/reference/checkJsxChildrenProperty8.symbols @@ -13,24 +13,24 @@ interface Prop { children: string | JSX.Element | (string | JSX.Element)[]; >children : Symbol(Prop.children, Decl(file.tsx, 4, 14)) ->JSX : Symbol(JSX, Decl(react.d.ts, 2352, 1)) ->Element : Symbol(JSX.Element, Decl(react.d.ts, 2355, 27)) ->JSX : Symbol(JSX, Decl(react.d.ts, 2352, 1)) ->Element : Symbol(JSX.Element, Decl(react.d.ts, 2355, 27)) +>JSX : Symbol(JSX, Decl(react.d.ts, 2353, 1)) +>Element : Symbol(JSX.Element, Decl(react.d.ts, 2356, 27)) +>JSX : Symbol(JSX, Decl(react.d.ts, 2353, 1)) +>Element : Symbol(JSX.Element, Decl(react.d.ts, 2356, 27)) } class Button extends React.Component { >Button : Symbol(Button, Decl(file.tsx, 6, 1)) ->React.Component : Symbol(React.Component, Decl(react.d.ts, 158, 55)) +>React.Component : Symbol(React.Component, Decl(react.d.ts, 158, 55), Decl(react.d.ts, 161, 66)) >React : Symbol(React, Decl(file.tsx, 0, 0)) ->Component : Symbol(React.Component, Decl(react.d.ts, 158, 55)) +>Component : Symbol(React.Component, Decl(react.d.ts, 158, 55), Decl(react.d.ts, 161, 66)) render() { >render : Symbol(Button.render, Decl(file.tsx, 8, 48)) return (
My Button
) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45)) } } @@ -39,8 +39,8 @@ function AnotherButton(p: any) { >p : Symbol(p, Decl(file.tsx, 14, 23)) return

Just Another Button

; ->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2409, 47)) ->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2409, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2410, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2410, 47)) } function Comp(p: Prop) { @@ -49,11 +49,11 @@ function Comp(p: Prop) { >Prop : Symbol(Prop, Decl(file.tsx, 0, 32)) return
{p.b}
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45)) >p.b : Symbol(Prop.b, Decl(file.tsx, 3, 14)) >p : Symbol(p, Decl(file.tsx, 18, 14)) >b : Symbol(Prop.b, Decl(file.tsx, 3, 14)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45)) } // OK diff --git a/tests/baselines/reference/checkJsxChildrenProperty9.symbols b/tests/baselines/reference/checkJsxChildrenProperty9.symbols index 25a32aae695..147fc4939f5 100644 --- a/tests/baselines/reference/checkJsxChildrenProperty9.symbols +++ b/tests/baselines/reference/checkJsxChildrenProperty9.symbols @@ -5,26 +5,26 @@ import React = require('react'); // OK let k1 =

Hello

world

; >k1 : Symbol(k1, Decl(file.tsx, 3, 3)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) ->h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2410, 48)) ->h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2410, 48)) ->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2409, 47)) ->h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2409, 47)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45)) +>h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2411, 48)) +>h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2411, 48)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2410, 47)) +>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react.d.ts, 2410, 47)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45)) let k2 =

Hello

{(user: any) =>

{user.name}

}
; >k2 : Symbol(k2, Decl(file.tsx, 4, 3)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) ->h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2410, 48)) ->h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2410, 48)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45)) +>h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2411, 48)) +>h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2411, 48)) >user : Symbol(user, Decl(file.tsx, 4, 34)) ->h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2410, 48)) +>h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2411, 48)) >user : Symbol(user, Decl(file.tsx, 4, 34)) ->h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2410, 48)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>h2 : Symbol(JSX.IntrinsicElements.h2, Decl(react.d.ts, 2411, 48)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45)) let k3 =
{1} {"That is a number"}
; >k3 : Symbol(k3, Decl(file.tsx, 5, 3)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45)) diff --git a/tests/baselines/reference/checkSwitchStatementIfCaseTypeIsString.symbols b/tests/baselines/reference/checkSwitchStatementIfCaseTypeIsString.symbols index 33f8f88f9e0..2a6ba238b4b 100644 --- a/tests/baselines/reference/checkSwitchStatementIfCaseTypeIsString.symbols +++ b/tests/baselines/reference/checkSwitchStatementIfCaseTypeIsString.symbols @@ -12,9 +12,9 @@ class A { >Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) x.forEach((v) => { ->x.forEach : Symbol(Array.forEach, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>x.forEach : Symbol(Array.forEach, Decl(lib.d.ts, --, --)) >x : Symbol(x, Decl(checkSwitchStatementIfCaseTypeIsString.ts, 3, 9)) ->forEach : Symbol(Array.forEach, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>forEach : Symbol(Array.forEach, Decl(lib.d.ts, --, --)) >v : Symbol(v, Decl(checkSwitchStatementIfCaseTypeIsString.ts, 4, 19)) switch(v) { diff --git a/tests/baselines/reference/checkSwitchStatementIfCaseTypeIsString.types b/tests/baselines/reference/checkSwitchStatementIfCaseTypeIsString.types index 115930df20a..30f584894fc 100644 --- a/tests/baselines/reference/checkSwitchStatementIfCaseTypeIsString.types +++ b/tests/baselines/reference/checkSwitchStatementIfCaseTypeIsString.types @@ -13,10 +13,10 @@ class A { x.forEach((v) => { >x.forEach((v) => { switch(v) { case "test": use(this); } }) : void ->x.forEach : { (callbackfn: (this: void, value: string, index: number, array: string[]) => void): void; (callbackfn: (this: void, value: string, index: number, array: string[]) => void, thisArg: undefined): void; (callbackfn: (this: Z, value: string, index: number, array: string[]) => void, thisArg: Z): void; } +>x.forEach : (callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any) => void >x : string[] ->forEach : { (callbackfn: (this: void, value: string, index: number, array: string[]) => void): void; (callbackfn: (this: void, value: string, index: number, array: string[]) => void, thisArg: undefined): void; (callbackfn: (this: Z, value: string, index: number, array: string[]) => void, thisArg: Z): void; } ->(v) => { switch(v) { case "test": use(this); } } : (this: void, v: string) => void +>forEach : (callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any) => void +>(v) => { switch(v) { case "test": use(this); } } : (v: string) => void >v : string switch(v) { diff --git a/tests/baselines/reference/classExpressionWithStaticProperties3.symbols b/tests/baselines/reference/classExpressionWithStaticProperties3.symbols index cd7cbdba7bd..2cf04ac05d3 100644 --- a/tests/baselines/reference/classExpressionWithStaticProperties3.symbols +++ b/tests/baselines/reference/classExpressionWithStaticProperties3.symbols @@ -30,9 +30,9 @@ for (let i = 0; i < 3; i++) { }); } arr.forEach(C => console.log(C.y())); ->arr.forEach : Symbol(Array.forEach, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>arr.forEach : Symbol(Array.forEach, Decl(lib.d.ts, --, --)) >arr : Symbol(arr, Decl(classExpressionWithStaticProperties3.ts, 1, 5)) ->forEach : Symbol(Array.forEach, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>forEach : Symbol(Array.forEach, Decl(lib.d.ts, --, --)) >C : Symbol(C, Decl(classExpressionWithStaticProperties3.ts, 8, 12)) >console : Symbol(console, Decl(classExpressionWithStaticProperties3.ts, 0, 11)) >C.y : Symbol(y, Decl(classExpressionWithStaticProperties3.ts, 1, 12)) diff --git a/tests/baselines/reference/classExpressionWithStaticProperties3.types b/tests/baselines/reference/classExpressionWithStaticProperties3.types index 6f598e6e42e..67823ea8340 100644 --- a/tests/baselines/reference/classExpressionWithStaticProperties3.types +++ b/tests/baselines/reference/classExpressionWithStaticProperties3.types @@ -41,10 +41,10 @@ for (let i = 0; i < 3; i++) { } arr.forEach(C => console.log(C.y())); >arr.forEach(C => console.log(C.y())) : void ->arr.forEach : { (callbackfn: (this: void, value: { y(): number; }, index: number, array: { y(): number; }[]) => void): void; (callbackfn: (this: void, value: { y(): number; }, index: number, array: { y(): number; }[]) => void, thisArg: undefined): void; (callbackfn: (this: Z, value: { y(): number; }, index: number, array: { y(): number; }[]) => void, thisArg: Z): void; } +>arr.forEach : (callbackfn: (value: { y(): number; }, index: number, array: { y(): number; }[]) => void, thisArg?: any) => void >arr : { y(): number; }[] ->forEach : { (callbackfn: (this: void, value: { y(): number; }, index: number, array: { y(): number; }[]) => void): void; (callbackfn: (this: void, value: { y(): number; }, index: number, array: { y(): number; }[]) => void, thisArg: undefined): void; (callbackfn: (this: Z, value: { y(): number; }, index: number, array: { y(): number; }[]) => void, thisArg: Z): void; } ->C => console.log(C.y()) : (this: void, C: { y(): number; }) => any +>forEach : (callbackfn: (value: { y(): number; }, index: number, array: { y(): number; }[]) => void, thisArg?: any) => void +>C => console.log(C.y()) : (C: { y(): number; }) => any >C : { y(): number; } >console.log(C.y()) : any >console.log : any diff --git a/tests/baselines/reference/classExpressionWithStaticPropertiesES63.symbols b/tests/baselines/reference/classExpressionWithStaticPropertiesES63.symbols index 822dfaf81a0..d39463b228c 100644 --- a/tests/baselines/reference/classExpressionWithStaticPropertiesES63.symbols +++ b/tests/baselines/reference/classExpressionWithStaticPropertiesES63.symbols @@ -30,9 +30,9 @@ for (let i = 0; i < 3; i++) { }); } arr.forEach(C => console.log(C.y())); ->arr.forEach : Symbol(Array.forEach, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>arr.forEach : Symbol(Array.forEach, Decl(lib.es5.d.ts, --, --)) >arr : Symbol(arr, Decl(classExpressionWithStaticPropertiesES63.ts, 1, 5)) ->forEach : Symbol(Array.forEach, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>forEach : Symbol(Array.forEach, Decl(lib.es5.d.ts, --, --)) >C : Symbol(C, Decl(classExpressionWithStaticPropertiesES63.ts, 8, 12)) >console : Symbol(console, Decl(classExpressionWithStaticPropertiesES63.ts, 0, 11)) >C.y : Symbol(y, Decl(classExpressionWithStaticPropertiesES63.ts, 1, 12)) diff --git a/tests/baselines/reference/classExpressionWithStaticPropertiesES63.types b/tests/baselines/reference/classExpressionWithStaticPropertiesES63.types index b5cd81e8590..5a948f54402 100644 --- a/tests/baselines/reference/classExpressionWithStaticPropertiesES63.types +++ b/tests/baselines/reference/classExpressionWithStaticPropertiesES63.types @@ -41,10 +41,10 @@ for (let i = 0; i < 3; i++) { } arr.forEach(C => console.log(C.y())); >arr.forEach(C => console.log(C.y())) : void ->arr.forEach : { (callbackfn: (this: void, value: { y(): number; }, index: number, array: { y(): number; }[]) => void): void; (callbackfn: (this: void, value: { y(): number; }, index: number, array: { y(): number; }[]) => void, thisArg: undefined): void; (callbackfn: (this: Z, value: { y(): number; }, index: number, array: { y(): number; }[]) => void, thisArg: Z): void; } +>arr.forEach : (callbackfn: (value: { y(): number; }, index: number, array: { y(): number; }[]) => void, thisArg?: any) => void >arr : { y(): number; }[] ->forEach : { (callbackfn: (this: void, value: { y(): number; }, index: number, array: { y(): number; }[]) => void): void; (callbackfn: (this: void, value: { y(): number; }, index: number, array: { y(): number; }[]) => void, thisArg: undefined): void; (callbackfn: (this: Z, value: { y(): number; }, index: number, array: { y(): number; }[]) => void, thisArg: Z): void; } ->C => console.log(C.y()) : (this: void, C: { y(): number; }) => any +>forEach : (callbackfn: (value: { y(): number; }, index: number, array: { y(): number; }[]) => void, thisArg?: any) => void +>C => console.log(C.y()) : (C: { y(): number; }) => any >C : { y(): number; } >console.log(C.y()) : any >console.log : any diff --git a/tests/baselines/reference/commaOperatorInConditionalExpression.symbols b/tests/baselines/reference/commaOperatorInConditionalExpression.symbols index cb124f21f15..c5734cbbc9b 100644 --- a/tests/baselines/reference/commaOperatorInConditionalExpression.symbols +++ b/tests/baselines/reference/commaOperatorInConditionalExpression.symbols @@ -4,8 +4,8 @@ function f (m: string) { >m : Symbol(m, Decl(commaOperatorInConditionalExpression.ts, 0, 12)) [1, 2, 3].map(i => { ->[1, 2, 3].map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) ->map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>[1, 2, 3].map : Symbol(Array.map, Decl(lib.d.ts, --, --)) +>map : Symbol(Array.map, Decl(lib.d.ts, --, --)) >i : Symbol(i, Decl(commaOperatorInConditionalExpression.ts, 1, 18)) return true? { [m]: i } : { [m]: i + 1 } diff --git a/tests/baselines/reference/commaOperatorInConditionalExpression.types b/tests/baselines/reference/commaOperatorInConditionalExpression.types index 7ee2ab72c77..1d1037c1206 100644 --- a/tests/baselines/reference/commaOperatorInConditionalExpression.types +++ b/tests/baselines/reference/commaOperatorInConditionalExpression.types @@ -5,13 +5,13 @@ function f (m: string) { [1, 2, 3].map(i => { >[1, 2, 3].map(i => { return true? { [m]: i } : { [m]: i + 1 } }) : { [x: string]: number; }[] ->[1, 2, 3].map : { (this: [number, number, number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U): [U, U, U, U, U]; (this: [number, number, number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [number, number, number, number, number], callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [number, number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U): [U, U, U, U]; (this: [number, number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): [U, U, U, U]; (this: [number, number, number, number], callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): [U, U, U, U]; (this: [number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U): [U, U, U]; (this: [number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): [U, U, U]; (this: [number, number, number], callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): [U, U, U]; (this: [number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U): [U, U]; (this: [number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): [U, U]; (this: [number, number], callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: number, index: number, array: number[]) => U): U[]; (callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): U[]; } +>[1, 2, 3].map : (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[] >[1, 2, 3] : number[] >1 : 1 >2 : 2 >3 : 3 ->map : { (this: [number, number, number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U): [U, U, U, U, U]; (this: [number, number, number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [number, number, number, number, number], callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [number, number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U): [U, U, U, U]; (this: [number, number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): [U, U, U, U]; (this: [number, number, number, number], callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): [U, U, U, U]; (this: [number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U): [U, U, U]; (this: [number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): [U, U, U]; (this: [number, number, number], callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): [U, U, U]; (this: [number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U): [U, U]; (this: [number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): [U, U]; (this: [number, number], callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: number, index: number, array: number[]) => U): U[]; (callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): U[]; } ->i => { return true? { [m]: i } : { [m]: i + 1 } } : (this: void, i: number) => { [x: string]: number; } +>map : (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[] +>i => { return true? { [m]: i } : { [m]: i + 1 } } : (i: number) => { [x: string]: number; } >i : number return true? { [m]: i } : { [m]: i + 1 } diff --git a/tests/baselines/reference/commentEmittingInPreserveJsx1.symbols b/tests/baselines/reference/commentEmittingInPreserveJsx1.symbols index 43d833e27b1..9accc8af0b6 100644 --- a/tests/baselines/reference/commentEmittingInPreserveJsx1.symbols +++ b/tests/baselines/reference/commentEmittingInPreserveJsx1.symbols @@ -3,14 +3,14 @@ import React = require('react'); >React : Symbol(React, Decl(file.tsx, 0, 0))
->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45)) // Not Comment
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45))
->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45)) // Not Comment { @@ -18,10 +18,10 @@ import React = require('react'); } // Another not Comment
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45))
->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45)) // Not Comment { @@ -30,10 +30,10 @@ import React = require('react'); } // Another not Comment
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45))
->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45)) /* Not Comment */ { @@ -41,5 +41,5 @@ import React = require('react'); "Hi" }
; ->div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45)) diff --git a/tests/baselines/reference/commentInMethodCall.symbols b/tests/baselines/reference/commentInMethodCall.symbols index e082d24daf3..9db0719cf89 100644 --- a/tests/baselines/reference/commentInMethodCall.symbols +++ b/tests/baselines/reference/commentInMethodCall.symbols @@ -4,9 +4,9 @@ var s: string[]; >s : Symbol(s, Decl(commentInMethodCall.ts, 1, 3)) s.map(// do something ->s.map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>s.map : Symbol(Array.map, Decl(lib.d.ts, --, --)) >s : Symbol(s, Decl(commentInMethodCall.ts, 1, 3)) ->map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>map : Symbol(Array.map, Decl(lib.d.ts, --, --)) function () { }); diff --git a/tests/baselines/reference/commentInMethodCall.types b/tests/baselines/reference/commentInMethodCall.types index b74323d1477..e9543a8c6f2 100644 --- a/tests/baselines/reference/commentInMethodCall.types +++ b/tests/baselines/reference/commentInMethodCall.types @@ -5,10 +5,10 @@ var s: string[]; s.map(// do something >s.map(// do something function () { }) : void[] ->s.map : { (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; (this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; (this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; } +>s.map : (callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[] >s : string[] ->map : { (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; (this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; (this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; } +>map : (callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[] function () { }); ->function () { } : (this: void) => void +>function () { } : () => void diff --git a/tests/baselines/reference/constructSignatureAssignabilityInInheritance.errors.txt b/tests/baselines/reference/constructSignatureAssignabilityInInheritance.errors.txt index 51278fc3f44..cc2c1e871e5 100644 --- a/tests/baselines/reference/constructSignatureAssignabilityInInheritance.errors.txt +++ b/tests/baselines/reference/constructSignatureAssignabilityInInheritance.errors.txt @@ -2,9 +2,13 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/construc Types of property 'a' are incompatible. Type 'new (x: number) => string' is not assignable to type 'new (x: number) => number'. Type 'string' is not assignable to type 'number'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/constructSignatureAssignabilityInInheritance.ts(67,15): error TS2430: Interface 'I3' incorrectly extends interface 'Base2'. + Types of property 'a2' are incompatible. + Type 'new (x: T) => string' is not assignable to type 'new (x: T) => T'. + Type 'string' is not assignable to type 'T'. -==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/constructSignatureAssignabilityInInheritance.ts (1 errors) ==== +==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/constructSignatureAssignabilityInInheritance.ts (2 errors) ==== // Checking basic subtype relations with construct signatures module ConstructSignature { @@ -77,6 +81,11 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/construc // S's interface I3 extends Base2 { + ~~ +!!! error TS2430: Interface 'I3' incorrectly extends interface 'Base2'. +!!! error TS2430: Types of property 'a2' are incompatible. +!!! error TS2430: Type 'new (x: T) => string' is not assignable to type 'new (x: T) => T'. +!!! error TS2430: Type 'string' is not assignable to type 'T'. // N's a2: new (x: T) => string; // error because base returns non-void; } diff --git a/tests/baselines/reference/constructSignatureAssignabilityInInheritance3.errors.txt b/tests/baselines/reference/constructSignatureAssignabilityInInheritance3.errors.txt index 7bd76159391..9646acd071f 100644 --- a/tests/baselines/reference/constructSignatureAssignabilityInInheritance3.errors.txt +++ b/tests/baselines/reference/constructSignatureAssignabilityInInheritance3.errors.txt @@ -11,9 +11,31 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/construc Type '{ foo: number; }' is not assignable to type 'Base'. Types of property 'foo' are incompatible. Type 'number' is not assignable to type 'string'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/constructSignatureAssignabilityInInheritance3.ts(66,19): error TS2430: Interface 'I6' incorrectly extends interface 'A'. + Types of property 'a15' are incompatible. + Type 'new (x: { a: T; b: T; }) => T' is not assignable to type 'new (x: { a: string; b: number; }) => number'. + Type 'string | number' is not assignable to type 'number'. + Type 'string' is not assignable to type 'number'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/constructSignatureAssignabilityInInheritance3.ts(70,19): error TS2430: Interface 'I7' incorrectly extends interface 'A'. + Types of property 'a15' are incompatible. + Type 'new (x: { a: T; b: T; }) => number' is not assignable to type 'new (x: { a: string; b: number; }) => number'. + Types of parameters 'x' and 'x' are incompatible. + Type '{ a: string; b: number; }' is not assignable to type '{ a: Base; b: Base; }'. + Types of property 'a' are incompatible. + Type 'string' is not assignable to type 'Base'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/constructSignatureAssignabilityInInheritance3.ts(86,19): error TS2430: Interface 'I6' incorrectly extends interface 'B'. + Types of property 'a2' are incompatible. + Type 'new (x: T) => string[]' is not assignable to type 'new (x: T) => T[]'. + Type 'string[]' is not assignable to type 'T[]'. + Type 'string' is not assignable to type 'T'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/constructSignatureAssignabilityInInheritance3.ts(95,19): error TS2430: Interface 'I7' incorrectly extends interface 'C'. + Types of property 'a2' are incompatible. + Type 'new (x: T) => T[]' is not assignable to type 'new (x: T) => string[]'. + Type 'T[]' is not assignable to type 'string[]'. + Type 'T' is not assignable to type 'string'. -==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/constructSignatureAssignabilityInInheritance3.ts (2 errors) ==== +==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/constructSignatureAssignabilityInInheritance3.ts (6 errors) ==== // checking subtype relations for function types as it relates to contextual signature instantiation // error cases @@ -95,10 +117,24 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/construc } interface I6 extends A { + ~~ +!!! error TS2430: Interface 'I6' incorrectly extends interface 'A'. +!!! error TS2430: Types of property 'a15' are incompatible. +!!! error TS2430: Type 'new (x: { a: T; b: T; }) => T' is not assignable to type 'new (x: { a: string; b: number; }) => number'. +!!! error TS2430: Type 'string | number' is not assignable to type 'number'. +!!! error TS2430: Type 'string' is not assignable to type 'number'. a15: new (x: { a: T; b: T }) => T; // error, T is {} which isn't an acceptable return type } interface I7 extends A { + ~~ +!!! error TS2430: Interface 'I7' incorrectly extends interface 'A'. +!!! error TS2430: Types of property 'a15' are incompatible. +!!! error TS2430: Type 'new (x: { a: T; b: T; }) => number' is not assignable to type 'new (x: { a: string; b: number; }) => number'. +!!! error TS2430: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2430: Type '{ a: string; b: number; }' is not assignable to type '{ a: Base; b: Base; }'. +!!! error TS2430: Types of property 'a' are incompatible. +!!! error TS2430: Type 'string' is not assignable to type 'Base'. a15: new (x: { a: T; b: T }) => number; // error, T defaults to Base, which is not compatible with number or string } @@ -115,6 +151,12 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/construc } interface I6 extends B { + ~~ +!!! error TS2430: Interface 'I6' incorrectly extends interface 'B'. +!!! error TS2430: Types of property 'a2' are incompatible. +!!! error TS2430: Type 'new (x: T) => string[]' is not assignable to type 'new (x: T) => T[]'. +!!! error TS2430: Type 'string[]' is not assignable to type 'T[]'. +!!! error TS2430: Type 'string' is not assignable to type 'T'. a2: new (x: T) => string[]; // error } @@ -124,6 +166,12 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/construc } interface I7 extends C { + ~~ +!!! error TS2430: Interface 'I7' incorrectly extends interface 'C'. +!!! error TS2430: Types of property 'a2' are incompatible. +!!! error TS2430: Type 'new (x: T) => T[]' is not assignable to type 'new (x: T) => string[]'. +!!! error TS2430: Type 'T[]' is not assignable to type 'string[]'. +!!! error TS2430: Type 'T' is not assignable to type 'string'. a2: new (x: T) => T[]; // error } diff --git a/tests/baselines/reference/constructSignatureAssignabilityInInheritance6.errors.txt b/tests/baselines/reference/constructSignatureAssignabilityInInheritance6.errors.txt new file mode 100644 index 00000000000..6245fead919 --- /dev/null +++ b/tests/baselines/reference/constructSignatureAssignabilityInInheritance6.errors.txt @@ -0,0 +1,142 @@ +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/constructSignatureAssignabilityInInheritance6.ts(24,11): error TS2430: Interface 'I' incorrectly extends interface 'A'. + Types of property 'a' are incompatible. + Type 'new (x: T) => T[]' is not assignable to type 'new (x: T) => T[]'. + Types of parameters 'x' and 'x' are incompatible. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/constructSignatureAssignabilityInInheritance6.ts(28,11): error TS2430: Interface 'I2' incorrectly extends interface 'A'. + Types of property 'a2' are incompatible. + Type 'new (x: T) => string[]' is not assignable to type 'new (x: T) => string[]'. + Types of parameters 'x' and 'x' are incompatible. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/constructSignatureAssignabilityInInheritance6.ts(32,11): error TS2430: Interface 'I3' incorrectly extends interface 'A'. + Types of property 'a3' are incompatible. + Type 'new (x: T) => T' is not assignable to type 'new (x: T) => void'. + Types of parameters 'x' and 'x' are incompatible. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/constructSignatureAssignabilityInInheritance6.ts(36,11): error TS2430: Interface 'I4' incorrectly extends interface 'A'. + Types of property 'a4' are incompatible. + Type 'new (x: T, y: U) => string' is not assignable to type 'new (x: T, y: U) => string'. + Types of parameters 'x' and 'x' are incompatible. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/constructSignatureAssignabilityInInheritance6.ts(40,11): error TS2430: Interface 'I5' incorrectly extends interface 'A'. + Types of property 'a5' are incompatible. + Type 'new (x: (arg: T) => U) => T' is not assignable to type 'new (x: (arg: T) => U) => T'. + Types of parameters 'x' and 'x' are incompatible. + Types of parameters 'arg' and 'arg' are incompatible. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/constructSignatureAssignabilityInInheritance6.ts(44,11): error TS2430: Interface 'I7' incorrectly extends interface 'A'. + Types of property 'a11' are incompatible. + Type 'new (x: { foo: T; }, y: { foo: U; bar: U; }) => Base' is not assignable to type 'new (x: { foo: T; }, y: { foo: T; bar: T; }) => Base'. + Types of parameters 'x' and 'x' are incompatible. + Type '{ foo: T; }' is not assignable to type '{ foo: T; }'. Two different types with this name exist, but they are unrelated. + Types of property 'foo' are incompatible. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/constructSignatureAssignabilityInInheritance6.ts(48,11): error TS2430: Interface 'I9' incorrectly extends interface 'A'. + Types of property 'a16' are incompatible. + Type 'new (x: { a: T; b: T; }) => T[]' is not assignable to type 'new (x: { a: T; b: T; }) => T[]'. + Types of parameters 'x' and 'x' are incompatible. + Type '{ a: T; b: T; }' is not assignable to type '{ a: T; b: T; }'. Two different types with this name exist, but they are unrelated. + Types of property 'a' are incompatible. + Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. + Type 'Base' is not assignable to type 'T'. + + +==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/constructSignatureAssignabilityInInheritance6.ts (7 errors) ==== + // checking subtype relations for function types as it relates to contextual signature instantiation + // same as subtypingWithConstructSignatures4 but using class type parameters instead of generic signatures + // all are errors + + class Base { foo: string; } + class Derived extends Base { bar: string; } + class Derived2 extends Derived { baz: string; } + class OtherDerived extends Base { bing: string; } + + interface A { // T + // M's + a: new (x: T) => T[]; + a2: new (x: T) => string[]; + a3: new (x: T) => void; + a4: new (x: T, y: U) => string; + a5: new (x: (arg: T) => U) => T; + a6: new (x: (arg: T) => Derived) => T; + a11: new (x: { foo: T }, y: { foo: T; bar: T }) => Base; + a15: new (x: { a: T; b: T }) => T[]; + a16: new (x: { a: T; b: T }) => T[]; + } + + // S's + interface I extends A { + ~ +!!! error TS2430: Interface 'I' incorrectly extends interface 'A'. +!!! error TS2430: Types of property 'a' are incompatible. +!!! error TS2430: Type 'new (x: T) => T[]' is not assignable to type 'new (x: T) => T[]'. +!!! error TS2430: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2430: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. + a: new (x: T) => T[]; + } + + interface I2 extends A { + ~~ +!!! error TS2430: Interface 'I2' incorrectly extends interface 'A'. +!!! error TS2430: Types of property 'a2' are incompatible. +!!! error TS2430: Type 'new (x: T) => string[]' is not assignable to type 'new (x: T) => string[]'. +!!! error TS2430: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2430: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. + a2: new (x: T) => string[]; + } + + interface I3 extends A { + ~~ +!!! error TS2430: Interface 'I3' incorrectly extends interface 'A'. +!!! error TS2430: Types of property 'a3' are incompatible. +!!! error TS2430: Type 'new (x: T) => T' is not assignable to type 'new (x: T) => void'. +!!! error TS2430: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2430: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. + a3: new (x: T) => T; + } + + interface I4 extends A { + ~~ +!!! error TS2430: Interface 'I4' incorrectly extends interface 'A'. +!!! error TS2430: Types of property 'a4' are incompatible. +!!! error TS2430: Type 'new (x: T, y: U) => string' is not assignable to type 'new (x: T, y: U) => string'. +!!! error TS2430: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2430: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. + a4: new (x: T, y: U) => string; + } + + interface I5 extends A { + ~~ +!!! error TS2430: Interface 'I5' incorrectly extends interface 'A'. +!!! error TS2430: Types of property 'a5' are incompatible. +!!! error TS2430: Type 'new (x: (arg: T) => U) => T' is not assignable to type 'new (x: (arg: T) => U) => T'. +!!! error TS2430: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2430: Types of parameters 'arg' and 'arg' are incompatible. +!!! error TS2430: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. + a5: new (x: (arg: T) => U) => T; + } + + interface I7 extends A { + ~~ +!!! error TS2430: Interface 'I7' incorrectly extends interface 'A'. +!!! error TS2430: Types of property 'a11' are incompatible. +!!! error TS2430: Type 'new (x: { foo: T; }, y: { foo: U; bar: U; }) => Base' is not assignable to type 'new (x: { foo: T; }, y: { foo: T; bar: T; }) => Base'. +!!! error TS2430: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2430: Type '{ foo: T; }' is not assignable to type '{ foo: T; }'. Two different types with this name exist, but they are unrelated. +!!! error TS2430: Types of property 'foo' are incompatible. +!!! error TS2430: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. + a11: new (x: { foo: T }, y: { foo: U; bar: U }) => Base; + } + + interface I9 extends A { + ~~ +!!! error TS2430: Interface 'I9' incorrectly extends interface 'A'. +!!! error TS2430: Types of property 'a16' are incompatible. +!!! error TS2430: Type 'new (x: { a: T; b: T; }) => T[]' is not assignable to type 'new (x: { a: T; b: T; }) => T[]'. +!!! error TS2430: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2430: Type '{ a: T; b: T; }' is not assignable to type '{ a: T; b: T; }'. Two different types with this name exist, but they are unrelated. +!!! error TS2430: Types of property 'a' are incompatible. +!!! error TS2430: Type 'T' is not assignable to type 'T'. Two different types with this name exist, but they are unrelated. +!!! error TS2430: Type 'Base' is not assignable to type 'T'. + a16: new (x: { a: T; b: T }) => T[]; + } \ No newline at end of file diff --git a/tests/baselines/reference/constructorFunctions.symbols b/tests/baselines/reference/constructorFunctions.symbols new file mode 100644 index 00000000000..f55075794ab --- /dev/null +++ b/tests/baselines/reference/constructorFunctions.symbols @@ -0,0 +1,76 @@ +=== tests/cases/conformance/salsa/index.js === +function C1() { +>C1 : Symbol(C1, Decl(index.js, 0, 0)) + + if (!(this instanceof C1)) return new C1(); +>C1 : Symbol(C1, Decl(index.js, 0, 0)) +>C1 : Symbol(C1, Decl(index.js, 0, 0)) + + this.x = 1; +>x : Symbol(C1.x, Decl(index.js, 1, 47)) +} + +const c1_v1 = C1(); +>c1_v1 : Symbol(c1_v1, Decl(index.js, 5, 5)) +>C1 : Symbol(C1, Decl(index.js, 0, 0)) + +const c1_v2 = new C1(); +>c1_v2 : Symbol(c1_v2, Decl(index.js, 6, 5)) +>C1 : Symbol(C1, Decl(index.js, 0, 0)) + +var C2 = function () { +>C2 : Symbol(C2, Decl(index.js, 8, 3)) + + if (!(this instanceof C2)) return new C2(); +>C2 : Symbol(C2, Decl(index.js, 8, 3)) +>C2 : Symbol(C2, Decl(index.js, 8, 3)) + + this.x = 1; +>x : Symbol(C2.x, Decl(index.js, 9, 47)) + +}; + +const c2_v1 = C2(); +>c2_v1 : Symbol(c2_v1, Decl(index.js, 13, 5)) +>C2 : Symbol(C2, Decl(index.js, 8, 3)) + +const c2_v2 = new C2(); +>c2_v2 : Symbol(c2_v2, Decl(index.js, 14, 5)) +>C2 : Symbol(C2, Decl(index.js, 8, 3)) + +/** @class */ +function C3() { +>C3 : Symbol(C3, Decl(index.js, 14, 23)) + + if (!(this instanceof C3)) return new C3(); +>C3 : Symbol(C3, Decl(index.js, 14, 23)) +>C3 : Symbol(C3, Decl(index.js, 14, 23)) + +}; + +const c3_v1 = C3(); +>c3_v1 : Symbol(c3_v1, Decl(index.js, 21, 5)) +>C3 : Symbol(C3, Decl(index.js, 14, 23)) + +const c3_v2 = new C3(); +>c3_v2 : Symbol(c3_v2, Decl(index.js, 22, 5)) +>C3 : Symbol(C3, Decl(index.js, 14, 23)) + +/** @class */ +var C4 = function () { +>C4 : Symbol(C4, Decl(index.js, 25, 3)) + + if (!(this instanceof C4)) return new C4(); +>C4 : Symbol(C4, Decl(index.js, 25, 3)) +>C4 : Symbol(C4, Decl(index.js, 25, 3)) + +}; + +const c4_v1 = C4(); +>c4_v1 : Symbol(c4_v1, Decl(index.js, 29, 5)) +>C4 : Symbol(C4, Decl(index.js, 25, 3)) + +const c4_v2 = new C4(); +>c4_v2 : Symbol(c4_v2, Decl(index.js, 30, 5)) +>C4 : Symbol(C4, Decl(index.js, 25, 3)) + diff --git a/tests/baselines/reference/constructorFunctions.types b/tests/baselines/reference/constructorFunctions.types new file mode 100644 index 00000000000..3429758b017 --- /dev/null +++ b/tests/baselines/reference/constructorFunctions.types @@ -0,0 +1,114 @@ +=== tests/cases/conformance/salsa/index.js === +function C1() { +>C1 : () => typeof C1 + + if (!(this instanceof C1)) return new C1(); +>!(this instanceof C1) : boolean +>(this instanceof C1) : boolean +>this instanceof C1 : boolean +>this : any +>C1 : () => typeof C1 +>new C1() : { x: number; } +>C1 : () => typeof C1 + + this.x = 1; +>this.x = 1 : 1 +>this.x : any +>this : any +>x : any +>1 : 1 +} + +const c1_v1 = C1(); +>c1_v1 : { x: number; } +>C1() : { x: number; } +>C1 : () => typeof C1 + +const c1_v2 = new C1(); +>c1_v2 : { x: number; } +>new C1() : { x: number; } +>C1 : () => typeof C1 + +var C2 = function () { +>C2 : () => any +>function () { if (!(this instanceof C2)) return new C2(); this.x = 1;} : () => any + + if (!(this instanceof C2)) return new C2(); +>!(this instanceof C2) : boolean +>(this instanceof C2) : boolean +>this instanceof C2 : boolean +>this : any +>C2 : () => any +>new C2() : { x: number; } +>C2 : () => any + + this.x = 1; +>this.x = 1 : 1 +>this.x : any +>this : any +>x : any +>1 : 1 + +}; + +const c2_v1 = C2(); +>c2_v1 : { x: number; } +>C2() : { x: number; } +>C2 : () => any + +const c2_v2 = new C2(); +>c2_v2 : { x: number; } +>new C2() : { x: number; } +>C2 : () => any + +/** @class */ +function C3() { +>C3 : () => typeof C3 + + if (!(this instanceof C3)) return new C3(); +>!(this instanceof C3) : boolean +>(this instanceof C3) : boolean +>this instanceof C3 : boolean +>this : any +>C3 : () => typeof C3 +>new C3() : {} +>C3 : () => typeof C3 + +}; + +const c3_v1 = C3(); +>c3_v1 : {} +>C3() : {} +>C3 : () => typeof C3 + +const c3_v2 = new C3(); +>c3_v2 : {} +>new C3() : {} +>C3 : () => typeof C3 + +/** @class */ +var C4 = function () { +>C4 : () => any +>function () { if (!(this instanceof C4)) return new C4();} : () => any + + if (!(this instanceof C4)) return new C4(); +>!(this instanceof C4) : boolean +>(this instanceof C4) : boolean +>this instanceof C4 : boolean +>this : any +>C4 : () => any +>new C4() : {} +>C4 : () => any + +}; + +const c4_v1 = C4(); +>c4_v1 : {} +>C4() : {} +>C4 : () => any + +const c4_v2 = new C4(); +>c4_v2 : {} +>new C4() : {} +>C4 : () => any + diff --git a/tests/baselines/reference/contextualSignatureInstantiation3.symbols b/tests/baselines/reference/contextualSignatureInstantiation3.symbols index a9653673ff2..6d480a7aef4 100644 --- a/tests/baselines/reference/contextualSignatureInstantiation3.symbols +++ b/tests/baselines/reference/contextualSignatureInstantiation3.symbols @@ -12,9 +12,9 @@ function map(items: T[], f: (x: T) => U): U[]{ >U : Symbol(U, Decl(contextualSignatureInstantiation3.ts, 0, 15)) return items.map(f); ->items.map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>items.map : Symbol(Array.map, Decl(lib.d.ts, --, --)) >items : Symbol(items, Decl(contextualSignatureInstantiation3.ts, 0, 19)) ->map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>map : Symbol(Array.map, Decl(lib.d.ts, --, --)) >f : Symbol(f, Decl(contextualSignatureInstantiation3.ts, 0, 30)) } @@ -47,9 +47,9 @@ var v1: number[]; var v1 = xs.map(identity); // Error if not number[] >v1 : Symbol(v1, Decl(contextualSignatureInstantiation3.ts, 15, 3), Decl(contextualSignatureInstantiation3.ts, 16, 3), Decl(contextualSignatureInstantiation3.ts, 17, 3)) ->xs.map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>xs.map : Symbol(Array.map, Decl(lib.d.ts, --, --)) >xs : Symbol(xs, Decl(contextualSignatureInstantiation3.ts, 12, 3)) ->map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>map : Symbol(Array.map, Decl(lib.d.ts, --, --)) >identity : Symbol(identity, Decl(contextualSignatureInstantiation3.ts, 2, 1)) var v1 = map(xs, identity); // Error if not number[] @@ -63,9 +63,9 @@ var v2: number[][]; var v2 = xs.map(singleton); // Error if not number[][] >v2 : Symbol(v2, Decl(contextualSignatureInstantiation3.ts, 19, 3), Decl(contextualSignatureInstantiation3.ts, 20, 3), Decl(contextualSignatureInstantiation3.ts, 21, 3)) ->xs.map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>xs.map : Symbol(Array.map, Decl(lib.d.ts, --, --)) >xs : Symbol(xs, Decl(contextualSignatureInstantiation3.ts, 12, 3)) ->map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>map : Symbol(Array.map, Decl(lib.d.ts, --, --)) >singleton : Symbol(singleton, Decl(contextualSignatureInstantiation3.ts, 6, 1)) var v2 = map(xs, singleton); // Error if not number[][] diff --git a/tests/baselines/reference/contextualSignatureInstantiation3.types b/tests/baselines/reference/contextualSignatureInstantiation3.types index 60ad7c31bf6..945a4374ad1 100644 --- a/tests/baselines/reference/contextualSignatureInstantiation3.types +++ b/tests/baselines/reference/contextualSignatureInstantiation3.types @@ -13,9 +13,9 @@ function map(items: T[], f: (x: T) => U): U[]{ return items.map(f); >items.map(f) : U[] ->items.map : { (this: [T, T, T, T, T], callbackfn: (this: void, value: T, index: number, array: T[]) => U): [U, U, U, U, U]; (this: [T, T, T, T, T], callbackfn: (this: void, value: T, index: number, array: T[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [T, T, T, T, T], callbackfn: (this: Z, value: T, index: number, array: T[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [T, T, T, T], callbackfn: (this: void, value: T, index: number, array: T[]) => U): [U, U, U, U]; (this: [T, T, T, T], callbackfn: (this: void, value: T, index: number, array: T[]) => U, thisArg: undefined): [U, U, U, U]; (this: [T, T, T, T], callbackfn: (this: Z, value: T, index: number, array: T[]) => U, thisArg: Z): [U, U, U, U]; (this: [T, T, T], callbackfn: (this: void, value: T, index: number, array: T[]) => U): [U, U, U]; (this: [T, T, T], callbackfn: (this: void, value: T, index: number, array: T[]) => U, thisArg: undefined): [U, U, U]; (this: [T, T, T], callbackfn: (this: Z, value: T, index: number, array: T[]) => U, thisArg: Z): [U, U, U]; (this: [T, T], callbackfn: (this: void, value: T, index: number, array: T[]) => U): [U, U]; (this: [T, T], callbackfn: (this: void, value: T, index: number, array: T[]) => U, thisArg: undefined): [U, U]; (this: [T, T], callbackfn: (this: Z, value: T, index: number, array: T[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: T, index: number, array: T[]) => U): U[]; (callbackfn: (this: void, value: T, index: number, array: T[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: T, index: number, array: T[]) => U, thisArg: Z): U[]; } +>items.map : (callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any) => U[] >items : T[] ->map : { (this: [T, T, T, T, T], callbackfn: (this: void, value: T, index: number, array: T[]) => U): [U, U, U, U, U]; (this: [T, T, T, T, T], callbackfn: (this: void, value: T, index: number, array: T[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [T, T, T, T, T], callbackfn: (this: Z, value: T, index: number, array: T[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [T, T, T, T], callbackfn: (this: void, value: T, index: number, array: T[]) => U): [U, U, U, U]; (this: [T, T, T, T], callbackfn: (this: void, value: T, index: number, array: T[]) => U, thisArg: undefined): [U, U, U, U]; (this: [T, T, T, T], callbackfn: (this: Z, value: T, index: number, array: T[]) => U, thisArg: Z): [U, U, U, U]; (this: [T, T, T], callbackfn: (this: void, value: T, index: number, array: T[]) => U): [U, U, U]; (this: [T, T, T], callbackfn: (this: void, value: T, index: number, array: T[]) => U, thisArg: undefined): [U, U, U]; (this: [T, T, T], callbackfn: (this: Z, value: T, index: number, array: T[]) => U, thisArg: Z): [U, U, U]; (this: [T, T], callbackfn: (this: void, value: T, index: number, array: T[]) => U): [U, U]; (this: [T, T], callbackfn: (this: void, value: T, index: number, array: T[]) => U, thisArg: undefined): [U, U]; (this: [T, T], callbackfn: (this: Z, value: T, index: number, array: T[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: T, index: number, array: T[]) => U): U[]; (callbackfn: (this: void, value: T, index: number, array: T[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: T, index: number, array: T[]) => U, thisArg: Z): U[]; } +>map : (callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any) => U[] >f : (x: T) => U } @@ -54,9 +54,9 @@ var v1: number[]; var v1 = xs.map(identity); // Error if not number[] >v1 : number[] >xs.map(identity) : number[] ->xs.map : { (this: [number, number, number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U): [U, U, U, U, U]; (this: [number, number, number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [number, number, number, number, number], callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [number, number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U): [U, U, U, U]; (this: [number, number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): [U, U, U, U]; (this: [number, number, number, number], callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): [U, U, U, U]; (this: [number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U): [U, U, U]; (this: [number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): [U, U, U]; (this: [number, number, number], callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): [U, U, U]; (this: [number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U): [U, U]; (this: [number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): [U, U]; (this: [number, number], callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: number, index: number, array: number[]) => U): U[]; (callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): U[]; } +>xs.map : (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[] >xs : number[] ->map : { (this: [number, number, number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U): [U, U, U, U, U]; (this: [number, number, number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [number, number, number, number, number], callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [number, number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U): [U, U, U, U]; (this: [number, number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): [U, U, U, U]; (this: [number, number, number, number], callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): [U, U, U, U]; (this: [number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U): [U, U, U]; (this: [number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): [U, U, U]; (this: [number, number, number], callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): [U, U, U]; (this: [number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U): [U, U]; (this: [number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): [U, U]; (this: [number, number], callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: number, index: number, array: number[]) => U): U[]; (callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): U[]; } +>map : (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[] >identity : (x: T) => T var v1 = map(xs, identity); // Error if not number[] @@ -72,9 +72,9 @@ var v2: number[][]; var v2 = xs.map(singleton); // Error if not number[][] >v2 : number[][] >xs.map(singleton) : number[][] ->xs.map : { (this: [number, number, number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U): [U, U, U, U, U]; (this: [number, number, number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [number, number, number, number, number], callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [number, number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U): [U, U, U, U]; (this: [number, number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): [U, U, U, U]; (this: [number, number, number, number], callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): [U, U, U, U]; (this: [number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U): [U, U, U]; (this: [number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): [U, U, U]; (this: [number, number, number], callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): [U, U, U]; (this: [number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U): [U, U]; (this: [number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): [U, U]; (this: [number, number], callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: number, index: number, array: number[]) => U): U[]; (callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): U[]; } +>xs.map : (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[] >xs : number[] ->map : { (this: [number, number, number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U): [U, U, U, U, U]; (this: [number, number, number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [number, number, number, number, number], callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [number, number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U): [U, U, U, U]; (this: [number, number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): [U, U, U, U]; (this: [number, number, number, number], callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): [U, U, U, U]; (this: [number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U): [U, U, U]; (this: [number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): [U, U, U]; (this: [number, number, number], callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): [U, U, U]; (this: [number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U): [U, U]; (this: [number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): [U, U]; (this: [number, number], callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: number, index: number, array: number[]) => U): U[]; (callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): U[]; } +>map : (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[] >singleton : (x: T) => T[] var v2 = map(xs, singleton); // Error if not number[][] diff --git a/tests/baselines/reference/contextualTypeFromJSDoc.symbols b/tests/baselines/reference/contextualTypeFromJSDoc.symbols new file mode 100644 index 00000000000..5ebe1e01ca7 --- /dev/null +++ b/tests/baselines/reference/contextualTypeFromJSDoc.symbols @@ -0,0 +1,48 @@ +=== tests/cases/conformance/types/contextualTypes/jsdoc/index.js === +/** @type {Array<[string, {x?:number, y?:number}]>} */ +const arr = [ +>arr : Symbol(arr, Decl(index.js, 1, 5)) + + ['a', { x: 1 }], +>x : Symbol(x, Decl(index.js, 2, 11)) + + ['b', { y: 2 }] +>y : Symbol(y, Decl(index.js, 3, 11)) + +]; + +/** @return {Array<[string, {x?:number, y?:number}]>} */ +function f() { +>f : Symbol(f, Decl(index.js, 4, 2)) + + return [ + ['a', { x: 1 }], +>x : Symbol(x, Decl(index.js, 9, 15)) + + ['b', { y: 2 }] +>y : Symbol(y, Decl(index.js, 10, 15)) + + ]; +} + +class C { +>C : Symbol(C, Decl(index.js, 12, 1)) + + /** @param {Array<[string, {x?:number, y?:number}]>} value */ + set x(value) { } +>x : Symbol(C.x, Decl(index.js, 14, 9), Decl(index.js, 16, 20)) +>value : Symbol(value, Decl(index.js, 16, 10)) + + get x() { +>x : Symbol(C.x, Decl(index.js, 14, 9), Decl(index.js, 16, 20)) + + return [ + ['a', { x: 1 }], +>x : Symbol(x, Decl(index.js, 19, 19)) + + ['b', { y: 2 }] +>y : Symbol(y, Decl(index.js, 20, 19)) + + ]; + } +} diff --git a/tests/baselines/reference/contextualTypeFromJSDoc.types b/tests/baselines/reference/contextualTypeFromJSDoc.types new file mode 100644 index 00000000000..f1121935d38 --- /dev/null +++ b/tests/baselines/reference/contextualTypeFromJSDoc.types @@ -0,0 +1,77 @@ +=== tests/cases/conformance/types/contextualTypes/jsdoc/index.js === +/** @type {Array<[string, {x?:number, y?:number}]>} */ +const arr = [ +>arr : [string, { x?: number; y?: number; }][] +>[ ['a', { x: 1 }], ['b', { y: 2 }]] : ([string, { x: number; }] | [string, { y: number; }])[] + + ['a', { x: 1 }], +>['a', { x: 1 }] : [string, { x: number; }] +>'a' : "a" +>{ x: 1 } : { x: number; } +>x : number +>1 : 1 + + ['b', { y: 2 }] +>['b', { y: 2 }] : [string, { y: number; }] +>'b' : "b" +>{ y: 2 } : { y: number; } +>y : number +>2 : 2 + +]; + +/** @return {Array<[string, {x?:number, y?:number}]>} */ +function f() { +>f : () => [string, { x?: number; y?: number; }][] + + return [ +>[ ['a', { x: 1 }], ['b', { y: 2 }] ] : ([string, { x: number; }] | [string, { y: number; }])[] + + ['a', { x: 1 }], +>['a', { x: 1 }] : [string, { x: number; }] +>'a' : "a" +>{ x: 1 } : { x: number; } +>x : number +>1 : 1 + + ['b', { y: 2 }] +>['b', { y: 2 }] : [string, { y: number; }] +>'b' : "b" +>{ y: 2 } : { y: number; } +>y : number +>2 : 2 + + ]; +} + +class C { +>C : C + + /** @param {Array<[string, {x?:number, y?:number}]>} value */ + set x(value) { } +>x : [string, { x?: number; y?: number; }][] +>value : [string, { x?: number; y?: number; }][] + + get x() { +>x : [string, { x?: number; y?: number; }][] + + return [ +>[ ['a', { x: 1 }], ['b', { y: 2 }] ] : ([string, { x: number; }] | [string, { y: number; }])[] + + ['a', { x: 1 }], +>['a', { x: 1 }] : [string, { x: number; }] +>'a' : "a" +>{ x: 1 } : { x: number; } +>x : number +>1 : 1 + + ['b', { y: 2 }] +>['b', { y: 2 }] : [string, { y: number; }] +>'b' : "b" +>{ y: 2 } : { y: number; } +>y : number +>2 : 2 + + ]; + } +} diff --git a/tests/baselines/reference/contextualTypingWithGenericSignature.types b/tests/baselines/reference/contextualTypingWithGenericSignature.types index 68c5f3c422d..cb70022a20b 100644 --- a/tests/baselines/reference/contextualTypingWithGenericSignature.types +++ b/tests/baselines/reference/contextualTypingWithGenericSignature.types @@ -16,10 +16,10 @@ var f2: { }; f2 = (x, y) => { return x } ->f2 = (x, y) => { return x } : (x: any, y: any) => any +>f2 = (x, y) => { return x } : (x: T, y: U) => T >f2 : (x: T, y: U) => T ->(x, y) => { return x } : (x: any, y: any) => any ->x : any ->y : any ->x : any +>(x, y) => { return x } : (x: T, y: U) => T +>x : T +>y : U +>x : T diff --git a/tests/baselines/reference/contextuallyTypedIife.symbols b/tests/baselines/reference/contextuallyTypedIife.symbols index 96e57c1f62f..b6a73764352 100644 --- a/tests/baselines/reference/contextuallyTypedIife.symbols +++ b/tests/baselines/reference/contextuallyTypedIife.symbols @@ -47,25 +47,25 @@ // rest parameters ((...numbers) => numbers.every(n => n > 0))(5,6,7); >numbers : Symbol(numbers, Decl(contextuallyTypedIife.ts, 17, 2)) ->numbers.every : Symbol(Array.every, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>numbers.every : Symbol(Array.every, Decl(lib.d.ts, --, --)) >numbers : Symbol(numbers, Decl(contextuallyTypedIife.ts, 17, 2)) ->every : Symbol(Array.every, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>every : Symbol(Array.every, Decl(lib.d.ts, --, --)) >n : Symbol(n, Decl(contextuallyTypedIife.ts, 17, 31)) >n : Symbol(n, Decl(contextuallyTypedIife.ts, 17, 31)) ((...mixed) => mixed.every(n => !!n))(5,'oops','oh no'); >mixed : Symbol(mixed, Decl(contextuallyTypedIife.ts, 18, 2)) ->mixed.every : Symbol(Array.every, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>mixed.every : Symbol(Array.every, Decl(lib.d.ts, --, --)) >mixed : Symbol(mixed, Decl(contextuallyTypedIife.ts, 18, 2)) ->every : Symbol(Array.every, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>every : Symbol(Array.every, Decl(lib.d.ts, --, --)) >n : Symbol(n, Decl(contextuallyTypedIife.ts, 18, 27)) >n : Symbol(n, Decl(contextuallyTypedIife.ts, 18, 27)) ((...noNumbers) => noNumbers.some(n => n > 0))(); >noNumbers : Symbol(noNumbers, Decl(contextuallyTypedIife.ts, 19, 2)) ->noNumbers.some : Symbol(Array.some, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>noNumbers.some : Symbol(Array.some, Decl(lib.d.ts, --, --)) >noNumbers : Symbol(noNumbers, Decl(contextuallyTypedIife.ts, 19, 2)) ->some : Symbol(Array.some, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>some : Symbol(Array.some, Decl(lib.d.ts, --, --)) >n : Symbol(n, Decl(contextuallyTypedIife.ts, 19, 34)) >n : Symbol(n, Decl(contextuallyTypedIife.ts, 19, 34)) @@ -73,9 +73,9 @@ >first : Symbol(first, Decl(contextuallyTypedIife.ts, 20, 2)) >rest : Symbol(rest, Decl(contextuallyTypedIife.ts, 20, 8)) >first : Symbol(first, Decl(contextuallyTypedIife.ts, 20, 2)) ->rest.map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>rest.map : Symbol(Array.map, Decl(lib.d.ts, --, --)) >rest : Symbol(rest, Decl(contextuallyTypedIife.ts, 20, 8)) ->map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>map : Symbol(Array.map, Decl(lib.d.ts, --, --)) >n : Symbol(n, Decl(contextuallyTypedIife.ts, 20, 43)) >n : Symbol(n, Decl(contextuallyTypedIife.ts, 20, 43)) diff --git a/tests/baselines/reference/contextuallyTypedIife.types b/tests/baselines/reference/contextuallyTypedIife.types index 77bb40df903..7b86fe1f337 100644 --- a/tests/baselines/reference/contextuallyTypedIife.types +++ b/tests/baselines/reference/contextuallyTypedIife.types @@ -105,10 +105,10 @@ >(...numbers) => numbers.every(n => n > 0) : (...numbers: number[]) => boolean >numbers : number[] >numbers.every(n => n > 0) : boolean ->numbers.every : { (callbackfn: (this: void, value: number, index: number, array: number[]) => boolean): boolean; (callbackfn: (this: void, value: number, index: number, array: number[]) => boolean, thisArg: undefined): boolean; (callbackfn: (this: Z, value: number, index: number, array: number[]) => boolean, thisArg: Z): boolean; } +>numbers.every : (callbackfn: (value: number, index: number, array: number[]) => boolean, thisArg?: any) => boolean >numbers : number[] ->every : { (callbackfn: (this: void, value: number, index: number, array: number[]) => boolean): boolean; (callbackfn: (this: void, value: number, index: number, array: number[]) => boolean, thisArg: undefined): boolean; (callbackfn: (this: Z, value: number, index: number, array: number[]) => boolean, thisArg: Z): boolean; } ->n => n > 0 : (this: void, n: number) => boolean +>every : (callbackfn: (value: number, index: number, array: number[]) => boolean, thisArg?: any) => boolean +>n => n > 0 : (n: number) => boolean >n : number >n > 0 : boolean >n : number @@ -123,10 +123,10 @@ >(...mixed) => mixed.every(n => !!n) : (...mixed: (string | number)[]) => boolean >mixed : (string | number)[] >mixed.every(n => !!n) : boolean ->mixed.every : { (callbackfn: (this: void, value: string | number, index: number, array: (string | number)[]) => boolean): boolean; (callbackfn: (this: void, value: string | number, index: number, array: (string | number)[]) => boolean, thisArg: undefined): boolean; (callbackfn: (this: Z, value: string | number, index: number, array: (string | number)[]) => boolean, thisArg: Z): boolean; } +>mixed.every : (callbackfn: (value: string | number, index: number, array: (string | number)[]) => boolean, thisArg?: any) => boolean >mixed : (string | number)[] ->every : { (callbackfn: (this: void, value: string | number, index: number, array: (string | number)[]) => boolean): boolean; (callbackfn: (this: void, value: string | number, index: number, array: (string | number)[]) => boolean, thisArg: undefined): boolean; (callbackfn: (this: Z, value: string | number, index: number, array: (string | number)[]) => boolean, thisArg: Z): boolean; } ->n => !!n : (this: void, n: string | number) => boolean +>every : (callbackfn: (value: string | number, index: number, array: (string | number)[]) => boolean, thisArg?: any) => boolean +>n => !!n : (n: string | number) => boolean >n : string | number >!!n : boolean >!n : boolean @@ -141,10 +141,10 @@ >(...noNumbers) => noNumbers.some(n => n > 0) : (...noNumbers: any[]) => boolean >noNumbers : any[] >noNumbers.some(n => n > 0) : boolean ->noNumbers.some : { (callbackfn: (this: void, value: any, index: number, array: any[]) => boolean): boolean; (callbackfn: (this: void, value: any, index: number, array: any[]) => boolean, thisArg: undefined): boolean; (callbackfn: (this: Z, value: any, index: number, array: any[]) => boolean, thisArg: Z): boolean; } +>noNumbers.some : (callbackfn: (value: any, index: number, array: any[]) => boolean, thisArg?: any) => boolean >noNumbers : any[] ->some : { (callbackfn: (this: void, value: any, index: number, array: any[]) => boolean): boolean; (callbackfn: (this: void, value: any, index: number, array: any[]) => boolean, thisArg: undefined): boolean; (callbackfn: (this: Z, value: any, index: number, array: any[]) => boolean, thisArg: Z): boolean; } ->n => n > 0 : (this: void, n: any) => boolean +>some : (callbackfn: (value: any, index: number, array: any[]) => boolean, thisArg?: any) => boolean +>n => n > 0 : (n: any) => boolean >n : any >n > 0 : boolean >n : any @@ -160,10 +160,10 @@ >first : number >[] : undefined[] >rest.map(n => n > 0) : boolean[] ->rest.map : { (this: [number, number, number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U): [U, U, U, U, U]; (this: [number, number, number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [number, number, number, number, number], callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [number, number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U): [U, U, U, U]; (this: [number, number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): [U, U, U, U]; (this: [number, number, number, number], callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): [U, U, U, U]; (this: [number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U): [U, U, U]; (this: [number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): [U, U, U]; (this: [number, number, number], callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): [U, U, U]; (this: [number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U): [U, U]; (this: [number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): [U, U]; (this: [number, number], callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: number, index: number, array: number[]) => U): U[]; (callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): U[]; } +>rest.map : (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[] >rest : number[] ->map : { (this: [number, number, number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U): [U, U, U, U, U]; (this: [number, number, number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [number, number, number, number, number], callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [number, number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U): [U, U, U, U]; (this: [number, number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): [U, U, U, U]; (this: [number, number, number, number], callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): [U, U, U, U]; (this: [number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U): [U, U, U]; (this: [number, number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): [U, U, U]; (this: [number, number, number], callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): [U, U, U]; (this: [number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U): [U, U]; (this: [number, number], callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): [U, U]; (this: [number, number], callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: number, index: number, array: number[]) => U): U[]; (callbackfn: (this: void, value: number, index: number, array: number[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: number, index: number, array: number[]) => U, thisArg: Z): U[]; } ->n => n > 0 : (this: void, n: number) => boolean +>map : (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[] +>n => n > 0 : (n: number) => boolean >n : number >n > 0 : boolean >n : number diff --git a/tests/baselines/reference/controlFlowDestructuringParameters.symbols b/tests/baselines/reference/controlFlowDestructuringParameters.symbols index 1874c16c3d3..668d346b929 100644 --- a/tests/baselines/reference/controlFlowDestructuringParameters.symbols +++ b/tests/baselines/reference/controlFlowDestructuringParameters.symbols @@ -3,9 +3,9 @@ [{ x: 1 }].map( ->[{ x: 1 }].map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>[{ x: 1 }].map : Symbol(Array.map, Decl(lib.d.ts, --, --)) >x : Symbol(x, Decl(controlFlowDestructuringParameters.ts, 3, 2)) ->map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>map : Symbol(Array.map, Decl(lib.d.ts, --, --)) ({ x }) => x >x : Symbol(x, Decl(controlFlowDestructuringParameters.ts, 4, 4)) diff --git a/tests/baselines/reference/controlFlowDestructuringParameters.types b/tests/baselines/reference/controlFlowDestructuringParameters.types index 44755dca81b..9c6c96de540 100644 --- a/tests/baselines/reference/controlFlowDestructuringParameters.types +++ b/tests/baselines/reference/controlFlowDestructuringParameters.types @@ -4,15 +4,15 @@ [{ x: 1 }].map( >[{ x: 1 }].map( ({ x }) => x) : number[] ->[{ x: 1 }].map : { (this: [{ x: number; }, { x: number; }, { x: number; }, { x: number; }, { x: number; }], callbackfn: (this: void, value: { x: number; }, index: number, array: { x: number; }[]) => U): [U, U, U, U, U]; (this: [{ x: number; }, { x: number; }, { x: number; }, { x: number; }, { x: number; }], callbackfn: (this: void, value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [{ x: number; }, { x: number; }, { x: number; }, { x: number; }, { x: number; }], callbackfn: (this: Z, value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [{ x: number; }, { x: number; }, { x: number; }, { x: number; }], callbackfn: (this: void, value: { x: number; }, index: number, array: { x: number; }[]) => U): [U, U, U, U]; (this: [{ x: number; }, { x: number; }, { x: number; }, { x: number; }], callbackfn: (this: void, value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg: undefined): [U, U, U, U]; (this: [{ x: number; }, { x: number; }, { x: number; }, { x: number; }], callbackfn: (this: Z, value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg: Z): [U, U, U, U]; (this: [{ x: number; }, { x: number; }, { x: number; }], callbackfn: (this: void, value: { x: number; }, index: number, array: { x: number; }[]) => U): [U, U, U]; (this: [{ x: number; }, { x: number; }, { x: number; }], callbackfn: (this: void, value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg: undefined): [U, U, U]; (this: [{ x: number; }, { x: number; }, { x: number; }], callbackfn: (this: Z, value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg: Z): [U, U, U]; (this: [{ x: number; }, { x: number; }], callbackfn: (this: void, value: { x: number; }, index: number, array: { x: number; }[]) => U): [U, U]; (this: [{ x: number; }, { x: number; }], callbackfn: (this: void, value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg: undefined): [U, U]; (this: [{ x: number; }, { x: number; }], callbackfn: (this: Z, value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: { x: number; }, index: number, array: { x: number; }[]) => U): U[]; (callbackfn: (this: void, value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg: Z): U[]; } +>[{ x: 1 }].map : (callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg?: any) => U[] >[{ x: 1 }] : { x: number; }[] >{ x: 1 } : { x: number; } >x : number >1 : 1 ->map : { (this: [{ x: number; }, { x: number; }, { x: number; }, { x: number; }, { x: number; }], callbackfn: (this: void, value: { x: number; }, index: number, array: { x: number; }[]) => U): [U, U, U, U, U]; (this: [{ x: number; }, { x: number; }, { x: number; }, { x: number; }, { x: number; }], callbackfn: (this: void, value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [{ x: number; }, { x: number; }, { x: number; }, { x: number; }, { x: number; }], callbackfn: (this: Z, value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [{ x: number; }, { x: number; }, { x: number; }, { x: number; }], callbackfn: (this: void, value: { x: number; }, index: number, array: { x: number; }[]) => U): [U, U, U, U]; (this: [{ x: number; }, { x: number; }, { x: number; }, { x: number; }], callbackfn: (this: void, value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg: undefined): [U, U, U, U]; (this: [{ x: number; }, { x: number; }, { x: number; }, { x: number; }], callbackfn: (this: Z, value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg: Z): [U, U, U, U]; (this: [{ x: number; }, { x: number; }, { x: number; }], callbackfn: (this: void, value: { x: number; }, index: number, array: { x: number; }[]) => U): [U, U, U]; (this: [{ x: number; }, { x: number; }, { x: number; }], callbackfn: (this: void, value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg: undefined): [U, U, U]; (this: [{ x: number; }, { x: number; }, { x: number; }], callbackfn: (this: Z, value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg: Z): [U, U, U]; (this: [{ x: number; }, { x: number; }], callbackfn: (this: void, value: { x: number; }, index: number, array: { x: number; }[]) => U): [U, U]; (this: [{ x: number; }, { x: number; }], callbackfn: (this: void, value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg: undefined): [U, U]; (this: [{ x: number; }, { x: number; }], callbackfn: (this: Z, value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: { x: number; }, index: number, array: { x: number; }[]) => U): U[]; (callbackfn: (this: void, value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg: Z): U[]; } +>map : (callbackfn: (value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg?: any) => U[] ({ x }) => x ->({ x }) => x : (this: void, { x }: { x: number; }) => number +>({ x }) => x : ({ x }: { x: number; }) => number >x : number >x : number diff --git a/tests/baselines/reference/controlFlowInstanceof.types b/tests/baselines/reference/controlFlowInstanceof.types index 16d1ec71462..5b9ea793e7d 100644 --- a/tests/baselines/reference/controlFlowInstanceof.types +++ b/tests/baselines/reference/controlFlowInstanceof.types @@ -247,7 +247,7 @@ function goo(x: X) { x.y; >x.y : string ->x : Y +>x : X & Y >y : string } x; diff --git a/tests/baselines/reference/correctlyMarkAliasAsReferences1.symbols b/tests/baselines/reference/correctlyMarkAliasAsReferences1.symbols index 3267a29050e..b0338f1c803 100644 --- a/tests/baselines/reference/correctlyMarkAliasAsReferences1.symbols +++ b/tests/baselines/reference/correctlyMarkAliasAsReferences1.symbols @@ -11,17 +11,17 @@ let buttonProps; // any let k = ; ->button : Symbol(JSX.IntrinsicElements.button, Decl(react.d.ts, 2385, 43)) +>button : Symbol(JSX.IntrinsicElements.button, Decl(react.d.ts, 2386, 43)) === tests/cases/conformance/jsx/declaration.d.ts === declare module "classnames"; diff --git a/tests/baselines/reference/correctlyMarkAliasAsReferences2.symbols b/tests/baselines/reference/correctlyMarkAliasAsReferences2.symbols index 76d9b8cdfe0..7e131bde878 100644 --- a/tests/baselines/reference/correctlyMarkAliasAsReferences2.symbols +++ b/tests/baselines/reference/correctlyMarkAliasAsReferences2.symbols @@ -12,17 +12,17 @@ let buttonProps : {[attributeName: string]: ''} let k = ; ->button : Symbol(JSX.IntrinsicElements.button, Decl(react.d.ts, 2385, 43)) +>button : Symbol(JSX.IntrinsicElements.button, Decl(react.d.ts, 2386, 43)) === tests/cases/conformance/jsx/declaration.d.ts === declare module "classnames"; diff --git a/tests/baselines/reference/correctlyMarkAliasAsReferences3.symbols b/tests/baselines/reference/correctlyMarkAliasAsReferences3.symbols index 088f553baa4..4002c29b3c6 100644 --- a/tests/baselines/reference/correctlyMarkAliasAsReferences3.symbols +++ b/tests/baselines/reference/correctlyMarkAliasAsReferences3.symbols @@ -11,17 +11,17 @@ let buttonProps; let k = ; ->button : Symbol(JSX.IntrinsicElements.button, Decl(react.d.ts, 2385, 43)) +>button : Symbol(JSX.IntrinsicElements.button, Decl(react.d.ts, 2386, 43)) === tests/cases/conformance/jsx/declaration.d.ts === declare module "classnames"; diff --git a/tests/baselines/reference/correctlyMarkAliasAsReferences4.symbols b/tests/baselines/reference/correctlyMarkAliasAsReferences4.symbols index 83b245072e9..0253e34533f 100644 --- a/tests/baselines/reference/correctlyMarkAliasAsReferences4.symbols +++ b/tests/baselines/reference/correctlyMarkAliasAsReferences4.symbols @@ -12,7 +12,7 @@ let buttonProps : {[attributeName: string]: ''} let k =