mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'master' into release-2.7
This commit is contained in:
@@ -58,6 +58,7 @@ internal/
|
||||
!tests/baselines/reference/project/nodeModules*/**/*
|
||||
.idea
|
||||
yarn.lock
|
||||
yarn-error.log
|
||||
.parallelperf.*
|
||||
tests/cases/user/*/package-lock.json
|
||||
tests/cases/user/*/node_modules/
|
||||
|
||||
+8
-1
@@ -8,7 +8,14 @@ Issues that ask questions answered in the FAQ will be closed without elaboration
|
||||
|
||||
## 2. Search for Duplicates
|
||||
|
||||
[Search the existing issues](https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93&q=is%3Aissue) before logging a new one.
|
||||
[Search the existing issues](https://github.com/Microsoft/TypeScript/search?type=Issues) before logging a new one.
|
||||
|
||||
Some search tips:
|
||||
* *Don't* restrict your search to only open issues. An issue with a title similar to yours may have been closed as a duplicate of one with a less-findable title.
|
||||
* Check for synonyms. For example, if your bug involves an interface, it likely also occurs with type aliases or classes.
|
||||
* Search for the title of the issue you're about to log. This sounds obvious but 80% of the time this is sufficient to find a duplicate when one exists.
|
||||
* Read more than the first page of results. Many bugs here use the same words so relevancy sorting is not particularly strong.
|
||||
* If you have a crash, search for the first few topmost function names shown in the call stack.
|
||||
|
||||
## 3. Do you have a question?
|
||||
|
||||
|
||||
+16
-6
@@ -151,6 +151,7 @@ const es2018LibrarySourceMap = es2018LibrarySource.map(source =>
|
||||
|
||||
const esnextLibrarySource = [
|
||||
"esnext.asynciterable.d.ts",
|
||||
"esnext.array.d.ts",
|
||||
"esnext.promise.d.ts"
|
||||
];
|
||||
|
||||
@@ -680,14 +681,14 @@ function runConsoleTests(defaultReporter: string, runInParallel: boolean, done:
|
||||
workerCount = cmdLineOptions.workers;
|
||||
}
|
||||
|
||||
if (tests || runners || light || taskConfigsFolder) {
|
||||
writeTestConfigFile(tests, runners, light, taskConfigsFolder, workerCount, stackTraceLimit);
|
||||
}
|
||||
|
||||
if (tests && tests.toLocaleLowerCase() === "rwc") {
|
||||
testTimeout = 400000;
|
||||
}
|
||||
|
||||
if (tests || runners || light || testTimeout || taskConfigsFolder) {
|
||||
writeTestConfigFile(tests, runners, light, taskConfigsFolder, workerCount, stackTraceLimit, testTimeout);
|
||||
}
|
||||
|
||||
const colors = cmdLineOptions.colors;
|
||||
const reporter = cmdLineOptions.reporter || defaultReporter;
|
||||
|
||||
@@ -872,8 +873,17 @@ function cleanTestDirs(done: (e?: any) => void) {
|
||||
}
|
||||
|
||||
// used to pass data from jake command line directly to run.js
|
||||
function writeTestConfigFile(tests: string, runners: string, light: boolean, taskConfigsFolder?: string, workerCount?: number, stackTraceLimit?: string) {
|
||||
const testConfigContents = JSON.stringify({ test: tests ? [tests] : undefined, runner: runners ? runners.split(",") : undefined, light, workerCount, stackTraceLimit, taskConfigsFolder, noColor: !cmdLineOptions.colors });
|
||||
function writeTestConfigFile(tests: string, runners: string, light: boolean, taskConfigsFolder?: string, workerCount?: number, stackTraceLimit?: string, timeout?: number) {
|
||||
const testConfigContents = JSON.stringify({
|
||||
test: tests ? [tests] : undefined,
|
||||
runner: runners ? runners.split(",") : undefined,
|
||||
light,
|
||||
workerCount,
|
||||
stackTraceLimit,
|
||||
taskConfigsFolder,
|
||||
noColor: !cmdLineOptions.colors,
|
||||
timeout,
|
||||
});
|
||||
console.log("Running tests with config: " + testConfigContents);
|
||||
fs.writeFileSync("test.config", testConfigContents);
|
||||
}
|
||||
|
||||
+9
-6
@@ -214,6 +214,7 @@ var es2018LibrarySourceMap = es2018LibrarySource.map(function (source) {
|
||||
|
||||
var esnextLibrarySource = [
|
||||
"esnext.asynciterable.d.ts",
|
||||
"esnext.array.d.ts",
|
||||
"esnext.promise.d.ts"
|
||||
];
|
||||
|
||||
@@ -858,7 +859,7 @@ function cleanTestDirs() {
|
||||
}
|
||||
|
||||
// used to pass data from jake command line directly to run.js
|
||||
function writeTestConfigFile(tests, runners, light, taskConfigsFolder, workerCount, stackTraceLimit, colors) {
|
||||
function writeTestConfigFile(tests, runners, light, taskConfigsFolder, workerCount, stackTraceLimit, colors, testTimeout) {
|
||||
var testConfigContents = JSON.stringify({
|
||||
runners: runners ? runners.split(",") : undefined,
|
||||
test: tests ? [tests] : undefined,
|
||||
@@ -866,7 +867,8 @@ function writeTestConfigFile(tests, runners, light, taskConfigsFolder, workerCou
|
||||
workerCount: workerCount,
|
||||
taskConfigsFolder: taskConfigsFolder,
|
||||
stackTraceLimit: stackTraceLimit,
|
||||
noColor: !colors
|
||||
noColor: !colors,
|
||||
timeout: testTimeout
|
||||
});
|
||||
fs.writeFileSync('test.config', testConfigContents);
|
||||
}
|
||||
@@ -908,14 +910,14 @@ function runConsoleTests(defaultReporter, runInParallel) {
|
||||
workerCount = process.env.workerCount || process.env.p || os.cpus().length;
|
||||
}
|
||||
|
||||
if (tests || runners || light || taskConfigsFolder) {
|
||||
writeTestConfigFile(tests, runners, light, taskConfigsFolder, workerCount, stackTraceLimit, colors);
|
||||
}
|
||||
|
||||
if (tests && tests.toLocaleLowerCase() === "rwc") {
|
||||
testTimeout = 800000;
|
||||
}
|
||||
|
||||
if (tests || runners || light || testTimeout || taskConfigsFolder) {
|
||||
writeTestConfigFile(tests, runners, light, taskConfigsFolder, workerCount, stackTraceLimit, colors, testTimeout);
|
||||
}
|
||||
|
||||
var colorsFlag = process.env.color || process.env.colors;
|
||||
var colors = colorsFlag !== "false" && colorsFlag !== "0";
|
||||
var reporter = process.env.reporter || process.env.r || defaultReporter;
|
||||
@@ -1202,6 +1204,7 @@ var tslintRules = [
|
||||
"debugAssertRule",
|
||||
"nextLineRule",
|
||||
"noBomRule",
|
||||
"noDoubleSpaceRule",
|
||||
"noIncrementDecrementRule",
|
||||
"noInOperatorRule",
|
||||
"noTypeAssertionWhitespaceRule",
|
||||
|
||||
@@ -15,3 +15,5 @@
|
||||
**Expected behavior:**
|
||||
|
||||
**Actual behavior:**
|
||||
|
||||
**Related:**
|
||||
|
||||
Generated
+1701
-1177
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,54 @@
|
||||
import * as Lint from "tslint/lib";
|
||||
import * as ts from "typescript";
|
||||
|
||||
export class Rule extends Lint.Rules.AbstractRule {
|
||||
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||
return this.applyWithFunction(sourceFile, walk);
|
||||
}
|
||||
}
|
||||
|
||||
function walk(ctx: Lint.WalkContext<void>): void {
|
||||
const { sourceFile } = ctx;
|
||||
const lines = sourceFile.text.split("\n");
|
||||
const strings = getLiterals(sourceFile);
|
||||
lines.forEach((line, idx) => {
|
||||
// Skip indentation.
|
||||
const firstNonSpace = /\S/.exec(line);
|
||||
if (firstNonSpace === null) {
|
||||
return;
|
||||
}
|
||||
// Allow common uses of double spaces
|
||||
// * To align `=` or `!=` signs
|
||||
// * To align comments at the end of lines
|
||||
// * To indent inside a comment
|
||||
// * To use two spaces after a period
|
||||
// * To include aligned `->` in a comment
|
||||
const rgx = /[^/*. ] [^-!/= ]/g;
|
||||
rgx.lastIndex = firstNonSpace.index;
|
||||
const doubleSpace = rgx.exec(line);
|
||||
// Also allow to align comments after `@param`
|
||||
if (doubleSpace !== null && !line.includes("@param")) {
|
||||
const pos = lines.slice(0, idx).reduce((len, line) => len + 1 + line.length, 0) + doubleSpace.index;
|
||||
if (!strings.some(s => s.getStart() <= pos && s.end > pos)) {
|
||||
ctx.addFailureAt(pos + 1, 2, "Use only one space.");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getLiterals(sourceFile: ts.SourceFile): ReadonlyArray<ts.Node> {
|
||||
const out: ts.Node[] = [];
|
||||
sourceFile.forEachChild(function cb(node) {
|
||||
switch (node.kind) {
|
||||
case ts.SyntaxKind.StringLiteral:
|
||||
case ts.SyntaxKind.TemplateHead:
|
||||
case ts.SyntaxKind.TemplateMiddle:
|
||||
case ts.SyntaxKind.TemplateTail:
|
||||
case ts.SyntaxKind.NoSubstitutionTemplateLiteral:
|
||||
case ts.SyntaxKind.RegularExpressionLiteral:
|
||||
out.push(node);
|
||||
}
|
||||
node.forEachChild(cb);
|
||||
});
|
||||
return out;
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import * as Lint from "tslint/lib";
|
||||
import * as ts from "typescript";
|
||||
|
||||
export class Rule extends Lint.Rules.AbstractRule {
|
||||
public static FAILURE_STRING = "The '|' and '&' operators must be surrounded by single spaces";
|
||||
public static FAILURE_STRING = "The '|' and '&' operators must be surrounded by spaces";
|
||||
|
||||
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||
return this.applyWithFunction(sourceFile, walk);
|
||||
@@ -11,26 +11,20 @@ export class Rule extends Lint.Rules.AbstractRule {
|
||||
|
||||
function walk(ctx: Lint.WalkContext<void>): void {
|
||||
const { sourceFile } = ctx;
|
||||
ts.forEachChild(sourceFile, recur);
|
||||
function recur(node: ts.Node): void {
|
||||
if (node.kind === ts.SyntaxKind.UnionType || node.kind === ts.SyntaxKind.IntersectionType) {
|
||||
check((node as ts.UnionOrIntersectionTypeNode).types);
|
||||
sourceFile.forEachChild(function cb(node: ts.Node): void {
|
||||
if (ts.isUnionTypeNode(node) || ts.isIntersectionTypeNode(node)) {
|
||||
check(node);
|
||||
}
|
||||
ts.forEachChild(node, recur);
|
||||
}
|
||||
node.forEachChild(cb);
|
||||
});
|
||||
|
||||
function check(types: ReadonlyArray<ts.TypeNode>): void {
|
||||
let expectedStart = types[0].end + 2; // space, | or &
|
||||
for (let i = 1; i < types.length; i++) {
|
||||
const currentType = types[i];
|
||||
if (expectedStart !== currentType.pos || currentType.getLeadingTriviaWidth() !== 1) {
|
||||
const previousTypeEndPos = sourceFile.getLineAndCharacterOfPosition(types[i - 1].end);
|
||||
const currentTypeStartPos = sourceFile.getLineAndCharacterOfPosition(currentType.pos);
|
||||
if (previousTypeEndPos.line === currentTypeStartPos.line) {
|
||||
ctx.addFailureAtNode(currentType, Rule.FAILURE_STRING);
|
||||
}
|
||||
function check(node: ts.UnionTypeNode | ts.IntersectionTypeNode): void {
|
||||
const list = node.getChildren().find(child => child.kind === ts.SyntaxKind.SyntaxList)!;
|
||||
for (const child of list.getChildren()) {
|
||||
if ((child.kind === ts.SyntaxKind.BarToken || child.kind === ts.SyntaxKind.AmpersandToken)
|
||||
&& (/\S/.test(sourceFile.text[child.getStart(sourceFile) - 1]) || /\S/.test(sourceFile.text[child.end]))) {
|
||||
ctx.addFailureAtNode(child, Rule.FAILURE_STRING);
|
||||
}
|
||||
expectedStart = currentType.end + 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,7 +303,7 @@ namespace ts {
|
||||
// without names can only come from JSDocFunctionTypes.
|
||||
Debug.assert(node.parent.kind === SyntaxKind.JSDocFunctionType);
|
||||
const functionType = <JSDocFunctionType>node.parent;
|
||||
const index = indexOf(functionType.parameters, node);
|
||||
const index = functionType.parameters.indexOf(node as ParameterDeclaration);
|
||||
return "arg" + index as __String;
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
const name = getNameOfJSDocTypedef(node as JSDocTypedefTag);
|
||||
@@ -746,11 +746,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
function isNarrowingTypeofOperands(expr1: Expression, expr2: Expression) {
|
||||
return expr1.kind === SyntaxKind.TypeOfExpression && isNarrowableOperand((<TypeOfExpression>expr1).expression) && expr2.kind === SyntaxKind.StringLiteral;
|
||||
return expr1.kind === SyntaxKind.TypeOfExpression && isNarrowableOperand((<TypeOfExpression>expr1).expression) && (expr2.kind === SyntaxKind.StringLiteral || expr2.kind === SyntaxKind.NoSubstitutionTemplateLiteral);
|
||||
}
|
||||
|
||||
function isNarrowableInOperands(left: Expression, right: Expression) {
|
||||
return left.kind === SyntaxKind.StringLiteral && isNarrowingExpression(right);
|
||||
return (left.kind === SyntaxKind.StringLiteral || left.kind === SyntaxKind.NoSubstitutionTemplateLiteral) && isNarrowingExpression(right);
|
||||
}
|
||||
|
||||
function isNarrowingBinaryExpression(expr: BinaryExpression) {
|
||||
@@ -1633,7 +1633,7 @@ namespace ts {
|
||||
// to the one we would get for: { <...>(...): T }
|
||||
//
|
||||
// We do that by making an anonymous type literal symbol, and then setting the function
|
||||
// symbol as its sole member. To the rest of the system, this symbol will be indistinguishable
|
||||
// symbol as its sole member. To the rest of the system, this symbol will be indistinguishable
|
||||
// from an actual type literal symbol you would have gotten had you used the long form.
|
||||
const symbol = createSymbol(SymbolFlags.Signature, getDeclarationName(node));
|
||||
addDeclarationToSymbol(symbol, node, SymbolFlags.Signature);
|
||||
@@ -2431,7 +2431,7 @@ namespace ts {
|
||||
if (!isPrototypeProperty && (!targetSymbol || !(targetSymbol.flags & SymbolFlags.Namespace)) && isLegalPosition) {
|
||||
Debug.assert(isIdentifier(propertyAccess.expression));
|
||||
const identifier = propertyAccess.expression as Identifier;
|
||||
const flags = SymbolFlags.Module | SymbolFlags.JSContainer;
|
||||
const flags = SymbolFlags.Module | SymbolFlags.JSContainer;
|
||||
const excludeFlags = SymbolFlags.ValueModuleExcludes & ~SymbolFlags.JSContainer;
|
||||
if (targetSymbol) {
|
||||
addDeclarationToSymbol(symbol, identifier, flags);
|
||||
@@ -2538,7 +2538,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (isBindingPattern(node.name)) {
|
||||
bindAnonymousDeclaration(node, SymbolFlags.FunctionScopedVariable, "__" + indexOf(node.parent.parameters, node) as __String);
|
||||
bindAnonymousDeclaration(node, SymbolFlags.FunctionScopedVariable, "__" + node.parent.parameters.indexOf(node) as __String);
|
||||
}
|
||||
else {
|
||||
declareSymbolAndAddToSymbolTable(node, SymbolFlags.FunctionScopedVariable, SymbolFlags.ParameterExcludes);
|
||||
|
||||
+297
-116
@@ -273,6 +273,7 @@ namespace ts {
|
||||
},
|
||||
getJsxNamespace: () => unescapeLeadingUnderscores(getJsxNamespace()),
|
||||
getAccessibleSymbolChain,
|
||||
resolveExternalModuleSymbol,
|
||||
};
|
||||
|
||||
const tupleTypes: GenericType[] = [];
|
||||
@@ -845,7 +846,7 @@ namespace ts {
|
||||
return true;
|
||||
}
|
||||
const sourceFiles = host.getSourceFiles();
|
||||
return indexOf(sourceFiles, declarationFile) <= indexOf(sourceFiles, useFile);
|
||||
return sourceFiles.indexOf(declarationFile) <= sourceFiles.indexOf(useFile);
|
||||
}
|
||||
|
||||
if (declaration.pos <= usage.pos) {
|
||||
@@ -1186,7 +1187,7 @@ namespace ts {
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (location.kind !== SyntaxKind.Block) {
|
||||
if (isNonBlockLocation(location)) {
|
||||
lastNonBlockLocation = location;
|
||||
}
|
||||
lastLocation = location;
|
||||
@@ -1194,7 +1195,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
// We just climbed up parents looking for the name, meaning that we started in a descendant node of `lastLocation`.
|
||||
// If `result === lastLocation.symbol`, that means that we are somewhere inside `lastLocation` looking up a name, and resolving to `lastLocation` itself.
|
||||
// If `result === lastNonBlockLocation.symbol`, that means that we are somewhere inside `lastNonBlockLocation` looking up a name, and resolving to `lastLocation` itself.
|
||||
// That means that this is a self-reference of `lastLocation`, and shouldn't count this when considering whether `lastLocation` is used.
|
||||
if (isUse && result && nameNotFoundMessage && noUnusedIdentifiers && result !== lastNonBlockLocation.symbol) {
|
||||
result.isReferenced = true;
|
||||
@@ -1218,7 +1219,7 @@ namespace ts {
|
||||
!checkAndReportErrorForExtendingInterface(errorLocation) &&
|
||||
!checkAndReportErrorForUsingTypeAsNamespace(errorLocation, name, meaning) &&
|
||||
!checkAndReportErrorForUsingTypeAsValue(errorLocation, name, meaning) &&
|
||||
!checkAndReportErrorForUsingNamespaceModuleAsValue(errorLocation, name, meaning)) {
|
||||
!checkAndReportErrorForUsingNamespaceModuleAsValue(errorLocation, name, meaning)) {
|
||||
let suggestion: string | undefined;
|
||||
if (suggestedNameNotFoundMessage && suggestionCount < maximumSuggestionCount) {
|
||||
suggestion = getSuggestionForNonexistentSymbol(originalLocation, name, meaning);
|
||||
@@ -1277,6 +1278,20 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
function isNonBlockLocation({ kind }: Node): boolean {
|
||||
switch (kind) {
|
||||
case SyntaxKind.Block:
|
||||
case SyntaxKind.ModuleBlock:
|
||||
case SyntaxKind.SwitchStatement:
|
||||
case SyntaxKind.CaseBlock:
|
||||
case SyntaxKind.CaseClause:
|
||||
case SyntaxKind.DefaultClause:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function diagnosticName(nameArg: __String | Identifier) {
|
||||
return isString(nameArg) ? unescapeLeadingUnderscores(nameArg as __String) : declarationNameToString(nameArg as Identifier);
|
||||
}
|
||||
@@ -1470,6 +1485,43 @@ namespace ts {
|
||||
return getSymbolOfPartOfRightHandSideOfImportEquals(<EntityName>node.moduleReference, dontResolveAlias);
|
||||
}
|
||||
|
||||
function resolveExportByName(moduleSymbol: Symbol, name: __String, dontResolveAlias: boolean) {
|
||||
const exportValue = moduleSymbol.exports.get(InternalSymbolName.ExportEquals);
|
||||
return exportValue
|
||||
? getPropertyOfType(getTypeOfSymbol(exportValue), name)
|
||||
: resolveSymbol(moduleSymbol.exports.get(name), dontResolveAlias);
|
||||
}
|
||||
|
||||
function canHaveSyntheticDefault(file: SourceFile | undefined, moduleSymbol: Symbol, dontResolveAlias: boolean) {
|
||||
if (!allowSyntheticDefaultImports) {
|
||||
return false;
|
||||
}
|
||||
// Declaration files (and ambient modules)
|
||||
if (!file || file.isDeclarationFile) {
|
||||
// Definitely cannot have a synthetic default if they have a default member specified
|
||||
if (resolveExportByName(moduleSymbol, InternalSymbolName.Default, dontResolveAlias)) {
|
||||
return false;
|
||||
}
|
||||
// It _might_ still be incorrect to assume there is no __esModule marker on the import at runtime, even if there is no `default` member
|
||||
// So we check a bit more,
|
||||
if (resolveExportByName(moduleSymbol, escapeLeadingUnderscores("__esModule"), dontResolveAlias)) {
|
||||
// If there is an `__esModule` specified in the declaration (meaning someone explicitly added it or wrote it in their code),
|
||||
// it definitely is a module and does not have a synthetic default
|
||||
return false;
|
||||
}
|
||||
// There are _many_ declaration files not written with esmodules in mind that still get compiled into a format with __esModule set
|
||||
// Meaning there may be no default at runtime - however to be on the permissive side, we allow access to a synthetic default member
|
||||
// as there is no marker to indicate if the accompanying JS has `__esModule` or not, or is even native esm
|
||||
return true;
|
||||
}
|
||||
// TypeScript files never have a synthetic default (as they are always emitted with an __esModule marker) _unless_ they contain an export= statement
|
||||
if (!isSourceFileJavaScript(file)) {
|
||||
return hasExportAssignmentSymbol(moduleSymbol);
|
||||
}
|
||||
// JS files have a synthetic default if they do not contain ES2015+ module syntax (export = is not valid in js) _and_ do not have an __esModule marker
|
||||
return !file.externalModuleIndicator && !resolveExportByName(moduleSymbol, escapeLeadingUnderscores("__esModule"), dontResolveAlias);
|
||||
}
|
||||
|
||||
function getTargetOfImportClause(node: ImportClause, dontResolveAlias: boolean): Symbol {
|
||||
const moduleSymbol = resolveExternalModuleName(node, (<ImportDeclaration>node.parent).moduleSpecifier);
|
||||
|
||||
@@ -1479,16 +1531,16 @@ namespace ts {
|
||||
exportDefaultSymbol = moduleSymbol;
|
||||
}
|
||||
else {
|
||||
const exportValue = moduleSymbol.exports.get("export=" as __String);
|
||||
exportDefaultSymbol = exportValue
|
||||
? getPropertyOfType(getTypeOfSymbol(exportValue), InternalSymbolName.Default)
|
||||
: resolveSymbol(moduleSymbol.exports.get(InternalSymbolName.Default), dontResolveAlias);
|
||||
exportDefaultSymbol = resolveExportByName(moduleSymbol, InternalSymbolName.Default, dontResolveAlias);
|
||||
}
|
||||
|
||||
if (!exportDefaultSymbol && !allowSyntheticDefaultImports) {
|
||||
const file = find(moduleSymbol.declarations, isSourceFile);
|
||||
const hasSyntheticDefault = canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias);
|
||||
if (!exportDefaultSymbol && !hasSyntheticDefault) {
|
||||
error(node.name, Diagnostics.Module_0_has_no_default_export, symbolToString(moduleSymbol));
|
||||
}
|
||||
else if (!exportDefaultSymbol && allowSyntheticDefaultImports) {
|
||||
else if (!exportDefaultSymbol && hasSyntheticDefault) {
|
||||
// per emit behavior, a synthetic default overrides a "real" .default member if `__esModule` is not present
|
||||
return resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias) || resolveSymbol(moduleSymbol, dontResolveAlias);
|
||||
}
|
||||
return exportDefaultSymbol;
|
||||
@@ -1888,8 +1940,40 @@ namespace ts {
|
||||
// combine other declarations with the module or variable (e.g. a class/module, function/module, interface/variable).
|
||||
function resolveESModuleSymbol(moduleSymbol: Symbol, moduleReferenceExpression: Expression, dontResolveAlias: boolean): Symbol {
|
||||
const symbol = resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias);
|
||||
if (!dontResolveAlias && symbol && !(symbol.flags & (SymbolFlags.Module | SymbolFlags.Variable))) {
|
||||
error(moduleReferenceExpression, Diagnostics.Module_0_resolves_to_a_non_module_entity_and_cannot_be_imported_using_this_construct, symbolToString(moduleSymbol));
|
||||
if (!dontResolveAlias && symbol) {
|
||||
if (!(symbol.flags & (SymbolFlags.Module | SymbolFlags.Variable))) {
|
||||
error(moduleReferenceExpression, Diagnostics.Module_0_resolves_to_a_non_module_entity_and_cannot_be_imported_using_this_construct, symbolToString(moduleSymbol));
|
||||
return symbol;
|
||||
}
|
||||
if (compilerOptions.esModuleInterop) {
|
||||
const referenceParent = moduleReferenceExpression.parent;
|
||||
if (
|
||||
(isImportDeclaration(referenceParent) && getNamespaceDeclarationNode(referenceParent)) ||
|
||||
isImportCall(referenceParent)
|
||||
) {
|
||||
const type = getTypeOfSymbol(symbol);
|
||||
let sigs = getSignaturesOfStructuredType(type, SignatureKind.Call);
|
||||
if (!sigs || !sigs.length) {
|
||||
sigs = getSignaturesOfStructuredType(type, SignatureKind.Construct);
|
||||
}
|
||||
if (sigs && sigs.length) {
|
||||
const moduleType = getTypeWithSyntheticDefaultImportType(type, symbol, moduleSymbol);
|
||||
// Create a new symbol which has the module's type less the call and construct signatures
|
||||
const result = createSymbol(symbol.flags, symbol.escapedName);
|
||||
result.declarations = symbol.declarations ? symbol.declarations.slice() : [];
|
||||
result.parent = symbol.parent;
|
||||
result.target = symbol;
|
||||
result.originatingImport = referenceParent;
|
||||
if (symbol.valueDeclaration) result.valueDeclaration = symbol.valueDeclaration;
|
||||
if (symbol.constEnumOnlyModule) result.constEnumOnlyModule = true;
|
||||
if (symbol.members) result.members = cloneMap(symbol.members);
|
||||
if (symbol.exports) result.exports = cloneMap(symbol.exports);
|
||||
const resolvedModuleType = resolveStructuredTypeMembers(moduleType as StructuredType); // Should already be resolved from the signature checks above
|
||||
result.type = createAnonymousType(result, resolvedModuleType.members, emptyArray, emptyArray, resolvedModuleType.stringIndexInfo, resolvedModuleType.numberIndexInfo);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return symbol;
|
||||
}
|
||||
@@ -4336,7 +4420,7 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
// Use specific property type when parent is a tuple or numeric index type when parent is an array
|
||||
const propName = "" + indexOf(pattern.elements, declaration);
|
||||
const propName = "" + pattern.elements.indexOf(declaration);
|
||||
type = isTupleLikeType(parentType)
|
||||
? getTypeOfPropertyOfType(parentType, propName as __String)
|
||||
: elementType;
|
||||
@@ -6758,7 +6842,7 @@ namespace ts {
|
||||
if (node.initializer) {
|
||||
const signatureDeclaration = <SignatureDeclaration>node.parent;
|
||||
const signature = getSignatureFromDeclaration(signatureDeclaration);
|
||||
const parameterIndex = ts.indexOf(signatureDeclaration.parameters, node);
|
||||
const parameterIndex = signatureDeclaration.parameters.indexOf(node);
|
||||
Debug.assert(parameterIndex >= 0);
|
||||
return parameterIndex >= signature.minArgumentCount;
|
||||
}
|
||||
@@ -6766,7 +6850,7 @@ namespace ts {
|
||||
if (iife) {
|
||||
return !node.type &&
|
||||
!node.dotDotDotToken &&
|
||||
indexOf((node.parent as SignatureDeclaration).parameters, node) >= iife.arguments.length;
|
||||
node.parent.parameters.indexOf(node) >= iife.arguments.length;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -8127,7 +8211,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getLiteralTypeFromPropertyName(prop: Symbol) {
|
||||
return getDeclarationModifierFlagsFromSymbol(prop) & ModifierFlags.NonPublicAccessibilityModifier || startsWith(prop.escapedName as string, "__@") ?
|
||||
return getDeclarationModifierFlagsFromSymbol(prop) & ModifierFlags.NonPublicAccessibilityModifier || isKnownSymbol(prop) ?
|
||||
neverType :
|
||||
getLiteralType(symbolName(prop));
|
||||
}
|
||||
@@ -8182,6 +8266,7 @@ namespace ts {
|
||||
const prop = getPropertyOfType(objectType, propName);
|
||||
if (prop) {
|
||||
if (accessExpression) {
|
||||
markPropertyAsReferenced(prop, accessExpression, /*isThisAccess*/ accessExpression.expression.kind === SyntaxKind.ThisKeyword);
|
||||
if (isAssignmentTarget(accessExpression) && (isReferenceToReadonlyEntity(accessExpression, prop) || isReferenceThroughNamespaceImport(accessExpression))) {
|
||||
error(accessExpression.argumentExpression, Diagnostics.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property, symbolToString(prop));
|
||||
return unknownType;
|
||||
@@ -8707,7 +8792,7 @@ namespace ts {
|
||||
* This is used during inference when instantiating type parameter defaults.
|
||||
*/
|
||||
function createBackreferenceMapper(typeParameters: TypeParameter[], index: number): TypeMapper {
|
||||
return t => indexOf(typeParameters, t) >= index ? emptyObjectType : t;
|
||||
return t => typeParameters.indexOf(t) >= index ? emptyObjectType : t;
|
||||
}
|
||||
|
||||
function isInferenceContext(mapper: TypeMapper): mapper is InferenceContext {
|
||||
@@ -9084,7 +9169,7 @@ namespace ts {
|
||||
return isTypeComparableTo(type1, type2) || isTypeComparableTo(type2, type1);
|
||||
}
|
||||
|
||||
function checkTypeAssignableTo(source: Type, target: Type, errorNode: Node, headMessage?: DiagnosticMessage, containingMessageChain?: DiagnosticMessageChain): boolean {
|
||||
function checkTypeAssignableTo(source: Type, target: Type, errorNode: Node, headMessage?: DiagnosticMessage, containingMessageChain?: () => DiagnosticMessageChain | undefined): boolean {
|
||||
return checkTypeRelatedTo(source, target, assignableRelation, errorNode, headMessage, containingMessageChain);
|
||||
}
|
||||
|
||||
@@ -9092,7 +9177,7 @@ 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 'isTypeComparableTo'.
|
||||
*/
|
||||
function checkTypeComparableTo(source: Type, target: Type, errorNode: Node, headMessage?: DiagnosticMessage, containingMessageChain?: DiagnosticMessageChain): boolean {
|
||||
function checkTypeComparableTo(source: Type, target: Type, errorNode: Node, headMessage?: DiagnosticMessage, containingMessageChain?: () => DiagnosticMessageChain | undefined): boolean {
|
||||
return checkTypeRelatedTo(source, target, comparableRelation, errorNode, headMessage, containingMessageChain);
|
||||
}
|
||||
|
||||
@@ -9426,7 +9511,7 @@ namespace ts {
|
||||
relation: Map<RelationComparisonResult>,
|
||||
errorNode: Node,
|
||||
headMessage?: DiagnosticMessage,
|
||||
containingMessageChain?: DiagnosticMessageChain): boolean {
|
||||
containingMessageChain?: () => DiagnosticMessageChain | undefined): boolean {
|
||||
|
||||
let errorInfo: DiagnosticMessageChain;
|
||||
let maybeKeys: string[];
|
||||
@@ -9446,11 +9531,25 @@ namespace ts {
|
||||
}
|
||||
else if (errorInfo) {
|
||||
if (containingMessageChain) {
|
||||
errorInfo = concatenateDiagnosticMessageChains(containingMessageChain, errorInfo);
|
||||
const chain = containingMessageChain();
|
||||
if (chain) {
|
||||
errorInfo = concatenateDiagnosticMessageChains(chain, errorInfo);
|
||||
}
|
||||
}
|
||||
|
||||
diagnostics.add(createDiagnosticForNodeFromMessageChain(errorNode, errorInfo));
|
||||
}
|
||||
// Check if we should issue an extra diagnostic to produce a quickfix for a slightly incorrect import statement
|
||||
if (headMessage && errorNode && !result && source.symbol) {
|
||||
const links = getSymbolLinks(source.symbol);
|
||||
if (links.originatingImport && !isImportCall(links.originatingImport)) {
|
||||
const helpfulRetry = checkTypeRelatedTo(getTypeOfSymbol(links.target), target, relation, /*errorNode*/ undefined);
|
||||
if (helpfulRetry) {
|
||||
// Likely an incorrect import. Issue a helpful diagnostic to produce a quickfix to change the import
|
||||
diagnostics.add(createDiagnosticForNode(links.originatingImport, Diagnostics.A_namespace_style_import_cannot_be_called_or_constructed_and_will_cause_a_failure_at_runtime));
|
||||
}
|
||||
}
|
||||
}
|
||||
return result !== Ternary.False;
|
||||
|
||||
function reportError(message: DiagnosticMessage, arg0?: string, arg1?: string, arg2?: string): void {
|
||||
@@ -9656,7 +9755,7 @@ namespace ts {
|
||||
}
|
||||
if (target.flags & TypeFlags.Union) {
|
||||
const discriminantType = findMatchingDiscriminantType(source, target as UnionType);
|
||||
if (discriminantType) {
|
||||
if (discriminantType) {
|
||||
// check excess properties against discriminant type only, not the entire union
|
||||
return hasExcessProperties(source, discriminantType, reportErrors);
|
||||
}
|
||||
@@ -10550,7 +10649,7 @@ namespace ts {
|
||||
let result = "" + type.target.id;
|
||||
for (const t of type.typeArguments) {
|
||||
if (isUnconstrainedTypeParameter(t)) {
|
||||
let index = indexOf(typeParameters, t);
|
||||
let index = typeParameters.indexOf(t);
|
||||
if (index < 0) {
|
||||
index = typeParameters.length;
|
||||
typeParameters.push(t);
|
||||
@@ -11826,7 +11925,7 @@ namespace ts {
|
||||
const container = (node as BindingElement).parent.parent;
|
||||
const key = container.kind === SyntaxKind.BindingElement ? getFlowCacheKey(container) : (container.initializer && getFlowCacheKey(container.initializer));
|
||||
const text = getBindingElementNameText(node as BindingElement);
|
||||
const result = key && text && (key + "." + text);
|
||||
const result = key && text && (key + "." + text);
|
||||
return result;
|
||||
}
|
||||
return undefined;
|
||||
@@ -12120,7 +12219,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getAssignedTypeOfArrayLiteralElement(node: ArrayLiteralExpression, element: Expression): Type {
|
||||
return getTypeOfDestructuredArrayElement(getAssignedType(node), indexOf(node.elements, element));
|
||||
return getTypeOfDestructuredArrayElement(getAssignedType(node), node.elements.indexOf(element));
|
||||
}
|
||||
|
||||
function getAssignedTypeOfSpreadExpression(node: SpreadElement): Type {
|
||||
@@ -12164,7 +12263,7 @@ namespace ts {
|
||||
const type = pattern.kind === SyntaxKind.ObjectBindingPattern ?
|
||||
getTypeOfDestructuredProperty(parentType, node.propertyName || <Identifier>node.name) :
|
||||
!node.dotDotDotToken ?
|
||||
getTypeOfDestructuredArrayElement(parentType, indexOf(pattern.elements, node)) :
|
||||
getTypeOfDestructuredArrayElement(parentType, pattern.elements.indexOf(node)) :
|
||||
getTypeOfDestructuredSpreadExpression(parentType);
|
||||
return getTypeWithDefault(type, node.initializer);
|
||||
}
|
||||
@@ -12749,7 +12848,7 @@ namespace ts {
|
||||
firstAntecedentType = flowType;
|
||||
}
|
||||
const type = getTypeFromFlowType(flowType);
|
||||
// If we see a value appear in the cache it is a sign that control flow analysis
|
||||
// If we see a value appear in the cache it is a sign that control flow analysis
|
||||
// was restarted and completed by checkExpressionCached. We can simply pick up
|
||||
// the resulting type and bail out.
|
||||
const cached = cache.get(key);
|
||||
@@ -12837,10 +12936,10 @@ namespace ts {
|
||||
const operator = expr.operatorToken.kind;
|
||||
const left = getReferenceCandidate(expr.left);
|
||||
const right = getReferenceCandidate(expr.right);
|
||||
if (left.kind === SyntaxKind.TypeOfExpression && right.kind === SyntaxKind.StringLiteral) {
|
||||
if (left.kind === SyntaxKind.TypeOfExpression && (right.kind === SyntaxKind.StringLiteral || right.kind === SyntaxKind.NoSubstitutionTemplateLiteral)) {
|
||||
return narrowTypeByTypeof(type, <TypeOfExpression>left, operator, <LiteralExpression>right, assumeTrue);
|
||||
}
|
||||
if (right.kind === SyntaxKind.TypeOfExpression && left.kind === SyntaxKind.StringLiteral) {
|
||||
if (right.kind === SyntaxKind.TypeOfExpression && (left.kind === SyntaxKind.StringLiteral || left.kind === SyntaxKind.NoSubstitutionTemplateLiteral)) {
|
||||
return narrowTypeByTypeof(type, <TypeOfExpression>right, operator, <LiteralExpression>left, assumeTrue);
|
||||
}
|
||||
if (isMatchingReference(reference, left)) {
|
||||
@@ -12863,7 +12962,7 @@ namespace ts {
|
||||
return narrowTypeByInstanceof(type, expr, assumeTrue);
|
||||
case SyntaxKind.InKeyword:
|
||||
const target = getReferenceCandidate(expr.right);
|
||||
if (expr.left.kind === SyntaxKind.StringLiteral && isMatchingReference(reference, target)) {
|
||||
if ((expr.left.kind === SyntaxKind.StringLiteral || expr.left.kind === SyntaxKind.NoSubstitutionTemplateLiteral) && isMatchingReference(reference, target)) {
|
||||
return narrowByInKeyword(type, <LiteralExpression>expr.left, assumeTrue);
|
||||
}
|
||||
break;
|
||||
@@ -13332,6 +13431,7 @@ namespace ts {
|
||||
const declarationContainer = getControlFlowContainer(declaration);
|
||||
let flowContainer = getControlFlowContainer(node);
|
||||
const isOuterVariable = flowContainer !== declarationContainer;
|
||||
const isSpreadDestructuringAsignmentTarget = node.parent && node.parent.parent && isSpreadAssignment(node.parent) && isDestructuringAssignmentTarget(node.parent.parent);
|
||||
// When the control flow originates in a function expression or arrow function and we are referencing
|
||||
// a const variable or parameter from an outer function, we extend the origin of the control flow
|
||||
// analysis to include the immediately enclosing function.
|
||||
@@ -13343,7 +13443,7 @@ namespace ts {
|
||||
// We only look for uninitialized variables in strict null checking mode, and only when we can analyze
|
||||
// the entire control flow graph from the variable's declaration (i.e. when the flow container and
|
||||
// declaration container are the same).
|
||||
const assumeInitialized = isParameter || isAlias || isOuterVariable ||
|
||||
const assumeInitialized = isParameter || isAlias || isOuterVariable || isSpreadDestructuringAsignmentTarget ||
|
||||
type !== autoType && type !== autoArrayType && (!strictNullChecks || (type.flags & TypeFlags.Any) !== 0 ||
|
||||
isInTypeQuery(node) || node.parent.kind === SyntaxKind.ExportSpecifier) ||
|
||||
node.parent.kind === SyntaxKind.NonNullExpression ||
|
||||
@@ -13462,7 +13562,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function findFirstSuperCall(n: Node): Node {
|
||||
function findFirstSuperCall(n: Node): SuperCall | undefined {
|
||||
if (isSuperCall(n)) {
|
||||
return n;
|
||||
}
|
||||
@@ -13478,12 +13578,12 @@ namespace ts {
|
||||
*
|
||||
* @param constructor constructor-function to look for super statement
|
||||
*/
|
||||
function getSuperCallInConstructor(constructor: ConstructorDeclaration): ExpressionStatement {
|
||||
function getSuperCallInConstructor(constructor: ConstructorDeclaration): SuperCall | undefined {
|
||||
const links = getNodeLinks(constructor);
|
||||
|
||||
// Only trying to find super-call if we haven't yet tried to find one. Once we try, we will record the result
|
||||
if (links.hasSuperCall === undefined) {
|
||||
links.superCall = <ExpressionStatement>findFirstSuperCall(constructor.body);
|
||||
links.superCall = findFirstSuperCall(constructor.body);
|
||||
links.hasSuperCall = links.superCall ? true : false;
|
||||
}
|
||||
return links.superCall;
|
||||
@@ -13918,7 +14018,7 @@ namespace ts {
|
||||
if (isContextSensitiveFunctionOrObjectLiteralMethod(func)) {
|
||||
const iife = getImmediatelyInvokedFunctionExpression(func);
|
||||
if (iife && iife.arguments) {
|
||||
const indexOfParameter = indexOf(func.parameters, parameter);
|
||||
const indexOfParameter = func.parameters.indexOf(parameter);
|
||||
if (parameter.dotDotDotToken) {
|
||||
const restTypes: Type[] = [];
|
||||
for (let i = indexOfParameter; i < iife.arguments.length; i++) {
|
||||
@@ -13939,7 +14039,7 @@ namespace ts {
|
||||
if (contextualSignature) {
|
||||
const funcHasRestParameters = hasRestParameter(func);
|
||||
const len = func.parameters.length - (funcHasRestParameters ? 1 : 0);
|
||||
let indexOfParameter = indexOf(func.parameters, parameter);
|
||||
let indexOfParameter = func.parameters.indexOf(parameter);
|
||||
if (getThisParameter(func) !== undefined && !contextualSignature.thisParameter) {
|
||||
Debug.assert(indexOfParameter !== 0); // Otherwise we should not have called `getContextuallyTypedParameterType`.
|
||||
indexOfParameter -= 1;
|
||||
@@ -14070,7 +14170,7 @@ namespace ts {
|
||||
// In a typed function call, an argument or substitution expression is contextually typed by the type of the corresponding parameter.
|
||||
function getContextualTypeForArgument(callTarget: CallLikeExpression, arg: Expression): Type {
|
||||
const args = getEffectiveCallArguments(callTarget);
|
||||
const argIndex = indexOf(args, arg);
|
||||
const argIndex = args.indexOf(arg);
|
||||
if (argIndex >= 0) {
|
||||
// If we're already in the process of resolving the given signature, don't resolve again as
|
||||
// that could cause infinite recursion. Instead, return anySignature.
|
||||
@@ -14522,7 +14622,7 @@ namespace ts {
|
||||
if (patternElement.kind !== SyntaxKind.OmittedExpression) {
|
||||
error(patternElement, Diagnostics.Initializer_provides_no_value_for_this_binding_element_and_the_binding_element_has_no_default_value);
|
||||
}
|
||||
elementTypes.push(unknownType);
|
||||
elementTypes.push(strictNullChecks ? implicitNeverType : undefinedWideningType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15762,17 +15862,35 @@ namespace ts {
|
||||
});
|
||||
}
|
||||
|
||||
function checkNonNullExpression(node: Expression | QualifiedName) {
|
||||
return checkNonNullType(checkExpression(node), node);
|
||||
function checkNonNullExpression(
|
||||
node: Expression | QualifiedName,
|
||||
nullDiagnostic?: DiagnosticMessage,
|
||||
undefinedDiagnostic?: DiagnosticMessage,
|
||||
nullOrUndefinedDiagnostic?: DiagnosticMessage,
|
||||
) {
|
||||
return checkNonNullType(
|
||||
checkExpression(node),
|
||||
node,
|
||||
nullDiagnostic,
|
||||
undefinedDiagnostic,
|
||||
nullOrUndefinedDiagnostic
|
||||
);
|
||||
}
|
||||
|
||||
function checkNonNullType(type: Type, errorNode: Node): Type {
|
||||
function checkNonNullType(
|
||||
type: Type,
|
||||
node: Node,
|
||||
nullDiagnostic?: DiagnosticMessage,
|
||||
undefinedDiagnostic?: DiagnosticMessage,
|
||||
nullOrUndefinedDiagnostic?: DiagnosticMessage
|
||||
): Type {
|
||||
const kind = (strictNullChecks ? getFalsyFlags(type) : type.flags) & TypeFlags.Nullable;
|
||||
if (kind) {
|
||||
error(errorNode, kind & TypeFlags.Undefined ? kind & TypeFlags.Null ?
|
||||
Diagnostics.Object_is_possibly_null_or_undefined :
|
||||
Diagnostics.Object_is_possibly_undefined :
|
||||
Diagnostics.Object_is_possibly_null);
|
||||
error(node, kind & TypeFlags.Undefined ? kind & TypeFlags.Null ?
|
||||
(nullOrUndefinedDiagnostic || Diagnostics.Object_is_possibly_null_or_undefined) :
|
||||
(undefinedDiagnostic || Diagnostics.Object_is_possibly_undefined) :
|
||||
(nullDiagnostic || Diagnostics.Object_is_possibly_null)
|
||||
);
|
||||
const t = getNonNullableType(type);
|
||||
return t.flags & (TypeFlags.Nullable | TypeFlags.Never) ? unknownType : t;
|
||||
}
|
||||
@@ -16560,7 +16678,7 @@ namespace ts {
|
||||
const constraint = getConstraintOfTypeParameter(typeParameters[i]);
|
||||
if (!constraint) continue;
|
||||
|
||||
const errorInfo = reportErrors && headMessage && chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Type_0_does_not_satisfy_the_constraint_1);
|
||||
const errorInfo = reportErrors && headMessage && (() => chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Type_0_does_not_satisfy_the_constraint_1));
|
||||
const typeArgumentHeadMessage = headMessage || Diagnostics.Type_0_does_not_satisfy_the_constraint_1;
|
||||
if (!mapper) {
|
||||
mapper = createTypeMapper(typeParameters, typeArgumentTypes);
|
||||
@@ -17236,7 +17354,7 @@ namespace ts {
|
||||
}
|
||||
excludeCount--;
|
||||
if (excludeCount > 0) {
|
||||
excludeArgument[indexOf(excludeArgument, /*value*/ true)] = false;
|
||||
excludeArgument[excludeArgument.indexOf(/*value*/ true)] = false;
|
||||
}
|
||||
else {
|
||||
excludeArgument = undefined;
|
||||
@@ -17281,7 +17399,13 @@ namespace ts {
|
||||
return resolveUntypedCall(node);
|
||||
}
|
||||
|
||||
const funcType = checkNonNullExpression(node.expression);
|
||||
const funcType = checkNonNullExpression(
|
||||
node.expression,
|
||||
Diagnostics.Cannot_invoke_an_object_which_is_possibly_null,
|
||||
Diagnostics.Cannot_invoke_an_object_which_is_possibly_undefined,
|
||||
Diagnostics.Cannot_invoke_an_object_which_is_possibly_null_or_undefined
|
||||
);
|
||||
|
||||
if (funcType === silentNeverType) {
|
||||
return silentNeverSignature;
|
||||
}
|
||||
@@ -17318,7 +17442,7 @@ namespace ts {
|
||||
error(node, Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType));
|
||||
}
|
||||
else {
|
||||
error(node, Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, typeToString(apparentType));
|
||||
invocationError(node, apparentType, SignatureKind.Call);
|
||||
}
|
||||
return resolveErrorCall(node);
|
||||
}
|
||||
@@ -17408,7 +17532,7 @@ namespace ts {
|
||||
return signature;
|
||||
}
|
||||
|
||||
error(node, Diagnostics.Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature);
|
||||
invocationError(node, expressionType, SignatureKind.Construct);
|
||||
return resolveErrorCall(node);
|
||||
}
|
||||
|
||||
@@ -17455,6 +17579,28 @@ namespace ts {
|
||||
return true;
|
||||
}
|
||||
|
||||
function invocationError(node: Node, apparentType: Type, kind: SignatureKind) {
|
||||
error(node, kind === SignatureKind.Call
|
||||
? Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures
|
||||
: Diagnostics.Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature
|
||||
, typeToString(apparentType));
|
||||
invocationErrorRecovery(apparentType, kind);
|
||||
}
|
||||
|
||||
function invocationErrorRecovery(apparentType: Type, kind: SignatureKind) {
|
||||
if (!apparentType.symbol) {
|
||||
return;
|
||||
}
|
||||
const importNode = getSymbolLinks(apparentType.symbol).originatingImport;
|
||||
// Create a diagnostic on the originating import if possible onto which we can attach a quickfix
|
||||
// An import call expression cannot be rewritten into another form to correct the error - the only solution is to use `.default` at the use-site
|
||||
if (importNode && !isImportCall(importNode)) {
|
||||
const sigs = getSignaturesOfType(getTypeOfSymbol(getSymbolLinks(apparentType.symbol).target), kind);
|
||||
if (!sigs || !sigs.length) return;
|
||||
error(importNode, Diagnostics.A_namespace_style_import_cannot_be_called_or_constructed_and_will_cause_a_failure_at_runtime);
|
||||
}
|
||||
}
|
||||
|
||||
function resolveTaggedTemplateExpression(node: TaggedTemplateExpression, candidatesOutArray: Signature[]): Signature {
|
||||
const tagType = checkExpression(node.tag);
|
||||
const apparentType = getApparentType(tagType);
|
||||
@@ -17472,7 +17618,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (!callSignatures.length) {
|
||||
error(node, Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, typeToString(apparentType));
|
||||
invocationError(node, apparentType, SignatureKind.Call);
|
||||
return resolveErrorCall(node);
|
||||
}
|
||||
|
||||
@@ -17529,6 +17675,7 @@ namespace ts {
|
||||
errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, typeToString(apparentType));
|
||||
errorInfo = chainDiagnosticMessages(errorInfo, headMessage);
|
||||
diagnostics.add(createDiagnosticForNodeFromMessageChain(node, errorInfo));
|
||||
invocationErrorRecovery(apparentType, SignatureKind.Call);
|
||||
return resolveErrorCall(node);
|
||||
}
|
||||
|
||||
@@ -17783,17 +17930,19 @@ namespace ts {
|
||||
if (moduleSymbol) {
|
||||
const esModuleSymbol = resolveESModuleSymbol(moduleSymbol, specifier, /*dontRecursivelyResolve*/ true);
|
||||
if (esModuleSymbol) {
|
||||
return createPromiseReturnType(node, getTypeWithSyntheticDefaultImportType(getTypeOfSymbol(esModuleSymbol), esModuleSymbol));
|
||||
return createPromiseReturnType(node, getTypeWithSyntheticDefaultImportType(getTypeOfSymbol(esModuleSymbol), esModuleSymbol, moduleSymbol));
|
||||
}
|
||||
}
|
||||
return createPromiseReturnType(node, anyType);
|
||||
}
|
||||
|
||||
function getTypeWithSyntheticDefaultImportType(type: Type, symbol: Symbol): Type {
|
||||
function getTypeWithSyntheticDefaultImportType(type: Type, symbol: Symbol, originalSymbol: Symbol): Type {
|
||||
if (allowSyntheticDefaultImports && type && type !== unknownType) {
|
||||
const synthType = type as SyntheticDefaultModuleType;
|
||||
if (!synthType.syntheticType) {
|
||||
if (!getPropertyOfType(type, InternalSymbolName.Default)) {
|
||||
const file = find(originalSymbol.declarations, isSourceFile);
|
||||
const hasSyntheticDefault = canHaveSyntheticDefault(file, originalSymbol, /*dontResolveAlias*/ false);
|
||||
if (hasSyntheticDefault) {
|
||||
const memberTable = createSymbolTable();
|
||||
const newSymbol = createSymbol(SymbolFlags.Alias, InternalSymbolName.Default);
|
||||
newSymbol.target = resolveSymbol(symbol);
|
||||
@@ -17801,7 +17950,7 @@ namespace ts {
|
||||
const anonymousSymbol = createSymbol(SymbolFlags.TypeLiteral, InternalSymbolName.Type);
|
||||
const defaultContainingObject = createAnonymousType(anonymousSymbol, memberTable, emptyArray, emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined);
|
||||
anonymousSymbol.type = defaultContainingObject;
|
||||
synthType.syntheticType = getIntersectionType([type, defaultContainingObject]);
|
||||
synthType.syntheticType = (type.flags & TypeFlags.StructuredType && type.symbol.flags & (SymbolFlags.Module | SymbolFlags.Variable)) ? getSpreadType(type, defaultContainingObject, anonymousSymbol, /*propegatedFlags*/ 0) : defaultContainingObject;
|
||||
}
|
||||
else {
|
||||
synthType.syntheticType = type;
|
||||
@@ -19342,10 +19491,11 @@ namespace ts {
|
||||
const ok =
|
||||
(node.parent.kind === SyntaxKind.PropertyAccessExpression && (<PropertyAccessExpression>node.parent).expression === node) ||
|
||||
(node.parent.kind === SyntaxKind.ElementAccessExpression && (<ElementAccessExpression>node.parent).expression === node) ||
|
||||
((node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.QualifiedName) && isInRightSideOfImportOrExportAssignment(<Identifier>node));
|
||||
((node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.QualifiedName) && isInRightSideOfImportOrExportAssignment(<Identifier>node) ||
|
||||
(node.parent.kind === SyntaxKind.TypeQuery && (<TypeQueryNode>node.parent).exprName === node));
|
||||
|
||||
if (!ok) {
|
||||
error(node, Diagnostics.const_enums_can_only_be_used_in_property_or_index_access_expressions_or_the_right_hand_side_of_an_import_declaration_or_export_assignment);
|
||||
error(node, Diagnostics.const_enums_can_only_be_used_in_property_or_index_access_expressions_or_the_right_hand_side_of_an_import_declaration_or_export_assignment_or_type_query);
|
||||
}
|
||||
}
|
||||
return type;
|
||||
@@ -19497,7 +19647,7 @@ namespace ts {
|
||||
error(node, Diagnostics.A_binding_pattern_parameter_cannot_be_optional_in_an_implementation_signature);
|
||||
}
|
||||
if (node.name && isIdentifier(node.name) && (node.name.escapedText === "this" || node.name.escapedText === "new")) {
|
||||
if (indexOf(func.parameters, node) !== 0) {
|
||||
if (func.parameters.indexOf(node) !== 0) {
|
||||
error(node, Diagnostics.A_0_parameter_must_be_the_first_parameter, node.name.escapedText as string);
|
||||
}
|
||||
if (func.kind === SyntaxKind.Constructor || func.kind === SyntaxKind.ConstructSignature || func.kind === SyntaxKind.ConstructorType) {
|
||||
@@ -19550,7 +19700,7 @@ namespace ts {
|
||||
Diagnostics.A_type_predicate_cannot_reference_a_rest_parameter);
|
||||
}
|
||||
else {
|
||||
const leadingError = chainDiagnosticMessages(/*details*/ undefined, Diagnostics.A_type_predicate_s_type_must_be_assignable_to_its_parameter_s_type);
|
||||
const leadingError = () => chainDiagnosticMessages(/*details*/ undefined, Diagnostics.A_type_predicate_s_type_must_be_assignable_to_its_parameter_s_type);
|
||||
checkTypeAssignableTo(typePredicate.type,
|
||||
getTypeOfNode(parent.parameters[typePredicate.parameterIndex]),
|
||||
node.type,
|
||||
@@ -19918,24 +20068,6 @@ namespace ts {
|
||||
return;
|
||||
}
|
||||
|
||||
function containsSuperCallAsComputedPropertyName(n: Declaration): boolean {
|
||||
const name = getNameOfDeclaration(n);
|
||||
return name && containsSuperCall(name);
|
||||
}
|
||||
|
||||
function containsSuperCall(n: Node): boolean {
|
||||
if (isSuperCall(n)) {
|
||||
return true;
|
||||
}
|
||||
else if (isFunctionLike(n)) {
|
||||
return false;
|
||||
}
|
||||
else if (isClassLike(n)) {
|
||||
return forEach((<ClassLikeDeclaration>n).members, containsSuperCallAsComputedPropertyName);
|
||||
}
|
||||
return forEachChild(n, containsSuperCall);
|
||||
}
|
||||
|
||||
function isInstancePropertyWithInitializer(n: Node): boolean {
|
||||
return n.kind === SyntaxKind.PropertyDeclaration &&
|
||||
!hasModifier(n, ModifierFlags.Static) &&
|
||||
@@ -20622,7 +20754,7 @@ namespace ts {
|
||||
|
||||
const promisedType = getPromisedTypeOfPromise(type);
|
||||
if (promisedType) {
|
||||
if (type.id === promisedType.id || indexOf(awaitedTypeStack, promisedType.id) >= 0) {
|
||||
if (type.id === promisedType.id || awaitedTypeStack.indexOf(promisedType.id) >= 0) {
|
||||
// Verify that we don't have a bad actor in the form of a promise whose
|
||||
// promised type is the same as the promise type, or a mutually recursive
|
||||
// promise. If so, we return undefined as we cannot guess the shape. If this
|
||||
@@ -20855,7 +20987,7 @@ namespace ts {
|
||||
expectedReturnType,
|
||||
node,
|
||||
headMessage,
|
||||
errorInfo);
|
||||
() => errorInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -21257,34 +21389,33 @@ namespace ts {
|
||||
|
||||
function checkUnusedClassMembers(node: ClassDeclaration | ClassExpression): void {
|
||||
if (compilerOptions.noUnusedLocals && !(node.flags & NodeFlags.Ambient)) {
|
||||
if (node.members) {
|
||||
for (const member of node.members) {
|
||||
switch (member.kind) {
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
if (member.kind === SyntaxKind.SetAccessor && member.symbol.flags & SymbolFlags.GetAccessor) {
|
||||
// Already would have reported an error on the getter.
|
||||
break;
|
||||
}
|
||||
if (!member.symbol.isReferenced && hasModifier(member, ModifierFlags.Private)) {
|
||||
error(member.name, Diagnostics._0_is_declared_but_its_value_is_never_read, symbolName(member.symbol));
|
||||
}
|
||||
for (const member of node.members) {
|
||||
switch (member.kind) {
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
if (member.kind === SyntaxKind.SetAccessor && member.symbol.flags & SymbolFlags.GetAccessor) {
|
||||
// Already would have reported an error on the getter.
|
||||
break;
|
||||
case SyntaxKind.Constructor:
|
||||
for (const parameter of (<ConstructorDeclaration>member).parameters) {
|
||||
if (!parameter.symbol.isReferenced && hasModifier(parameter, ModifierFlags.Private)) {
|
||||
error(parameter.name, Diagnostics.Property_0_is_declared_but_its_value_is_never_read, symbolName(parameter.symbol));
|
||||
}
|
||||
}
|
||||
const symbol = getSymbolOfNode(member);
|
||||
if (!symbol.isReferenced && hasModifier(member, ModifierFlags.Private)) {
|
||||
error(member.name, Diagnostics._0_is_declared_but_its_value_is_never_read, symbolToString(symbol));
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.Constructor:
|
||||
for (const parameter of (<ConstructorDeclaration>member).parameters) {
|
||||
if (!parameter.symbol.isReferenced && hasModifier(parameter, ModifierFlags.Private)) {
|
||||
error(parameter.name, Diagnostics.Property_0_is_declared_but_its_value_is_never_read, symbolName(parameter.symbol));
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.IndexSignature:
|
||||
// Can't be private
|
||||
break;
|
||||
default:
|
||||
Debug.fail();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.IndexSignature:
|
||||
// Can't be private
|
||||
break;
|
||||
default:
|
||||
Debug.fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21931,7 +22062,7 @@ namespace ts {
|
||||
checkGrammarForInOrForOfStatement(node);
|
||||
|
||||
const rightType = checkNonNullExpression(node.expression);
|
||||
// TypeScript 1.0 spec (April 2014): 5.4
|
||||
// TypeScript 1.0 spec (April 2014): 5.4
|
||||
// In a 'for-in' statement of the form
|
||||
// for (let VarDecl in Expr) Statement
|
||||
// VarDecl must be a variable declaration without a type annotation that declares a variable of type Any,
|
||||
@@ -22779,7 +22910,10 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
}
|
||||
checkTypeAssignableTo(typeWithThis, getTypeWithThisArgument(baseType, type.thisType), node.name || node, Diagnostics.Class_0_incorrectly_extends_base_class_1);
|
||||
const baseWithThis = getTypeWithThisArgument(baseType, type.thisType);
|
||||
if (!checkTypeAssignableTo(typeWithThis, baseWithThis, /*errorNode*/ undefined)) {
|
||||
issueMemberSpecificError(node, typeWithThis, baseWithThis, Diagnostics.Class_0_incorrectly_extends_base_class_1);
|
||||
}
|
||||
checkTypeAssignableTo(staticType, getTypeWithoutSignatures(staticBaseType), node.name || node,
|
||||
Diagnostics.Class_static_side_0_incorrectly_extends_base_class_static_side_1);
|
||||
if (baseConstructorType.flags & TypeFlags.TypeVariable && !isMixinConstructorType(staticType)) {
|
||||
@@ -22811,12 +22945,13 @@ namespace ts {
|
||||
const t = getTypeFromTypeNode(typeRefNode);
|
||||
if (t !== unknownType) {
|
||||
if (isValidBaseType(t)) {
|
||||
checkTypeAssignableTo(typeWithThis,
|
||||
getTypeWithThisArgument(t, type.thisType),
|
||||
node.name || node,
|
||||
t.symbol && t.symbol.flags & SymbolFlags.Class ?
|
||||
Diagnostics.Class_0_incorrectly_implements_class_1_Did_you_mean_to_extend_1_and_inherit_its_members_as_a_subclass :
|
||||
Diagnostics.Class_0_incorrectly_implements_interface_1);
|
||||
const genericDiag = t.symbol && t.symbol.flags & SymbolFlags.Class ?
|
||||
Diagnostics.Class_0_incorrectly_implements_class_1_Did_you_mean_to_extend_1_and_inherit_its_members_as_a_subclass :
|
||||
Diagnostics.Class_0_incorrectly_implements_interface_1;
|
||||
const baseWithThis = getTypeWithThisArgument(t, type.thisType);
|
||||
if (!checkTypeAssignableTo(typeWithThis, baseWithThis, /*errorNode*/ undefined)) {
|
||||
issueMemberSpecificError(node, typeWithThis, baseWithThis, genericDiag);
|
||||
}
|
||||
}
|
||||
else {
|
||||
error(typeRefNode, Diagnostics.A_class_may_only_implement_another_class_or_interface);
|
||||
@@ -22833,6 +22968,37 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function issueMemberSpecificError(node: ClassLikeDeclaration, typeWithThis: Type, baseWithThis: Type, broadDiag: DiagnosticMessage) {
|
||||
// iterate over all implemented properties and issue errors on each one which isn't compatible, rather than the class as a whole, if possible
|
||||
let issuedMemberError = false;
|
||||
for (const member of node.members) {
|
||||
if (hasStaticModifier(member)) {
|
||||
continue;
|
||||
}
|
||||
const declaredProp = member.name && getSymbolAtLocation(member.name) || getSymbolAtLocation(member);
|
||||
if (declaredProp) {
|
||||
const prop = getPropertyOfType(typeWithThis, declaredProp.escapedName);
|
||||
const baseProp = getPropertyOfType(baseWithThis, declaredProp.escapedName);
|
||||
if (prop && baseProp) {
|
||||
const rootChain = () => chainDiagnosticMessages(
|
||||
/*details*/ undefined,
|
||||
Diagnostics.Property_0_in_type_1_is_not_assignable_to_the_same_property_in_base_type_2,
|
||||
unescapeLeadingUnderscores(declaredProp.escapedName),
|
||||
typeToString(typeWithThis),
|
||||
typeToString(getTypeOfSymbol(baseProp))
|
||||
);
|
||||
if (!checkTypeAssignableTo(getTypeOfSymbol(prop), getTypeOfSymbol(baseProp), member.name || member, /*message*/ undefined, rootChain)) {
|
||||
issuedMemberError = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!issuedMemberError) {
|
||||
// check again with diagnostics to generate a less-specific error
|
||||
checkTypeAssignableTo(typeWithThis, baseWithThis, node.name || node, broadDiag);
|
||||
}
|
||||
}
|
||||
|
||||
function checkBaseTypeAccessibility(type: Type, node: ExpressionWithTypeArguments) {
|
||||
const signatures = getSignaturesOfType(type, SignatureKind.Construct);
|
||||
if (signatures.length) {
|
||||
@@ -24669,7 +24835,7 @@ namespace ts {
|
||||
const typeOfArrayLiteral = getTypeOfArrayLiteralOrObjectLiteralDestructuringAssignment(<Expression>expr.parent);
|
||||
const elementType = checkIteratedTypeOrElementType(typeOfArrayLiteral || unknownType, expr.parent, /*allowStringInput*/ false, /*allowAsyncIterables*/ false) || unknownType;
|
||||
return checkArrayLiteralDestructuringElementAssignment(<ArrayLiteralExpression>expr.parent, typeOfArrayLiteral,
|
||||
indexOf((<ArrayLiteralExpression>expr.parent).elements, expr), elementType || unknownType);
|
||||
(<ArrayLiteralExpression>expr.parent).elements.indexOf(expr), elementType || unknownType);
|
||||
}
|
||||
|
||||
// Gets the property symbol corresponding to the property in destructuring assignment
|
||||
@@ -24864,7 +25030,7 @@ namespace ts {
|
||||
// AND
|
||||
// - binding is not declared in loop, should be renamed to avoid name reuse across siblings
|
||||
// let a, b
|
||||
// { let x = 1; a = () => x; }
|
||||
// { let x = 1; a = () => x; }
|
||||
// { let x = 100; b = () => x; }
|
||||
// console.log(a()); // should print '1'
|
||||
// console.log(b()); // should print '100'
|
||||
@@ -25325,7 +25491,7 @@ namespace ts {
|
||||
|
||||
// walk the parent chain for symbols to make sure that top level parent symbol is in the global scope
|
||||
// external modules cannot define or contribute to type declaration files
|
||||
let current = symbol;
|
||||
let current = symbol;
|
||||
while (true) {
|
||||
const parent = getParentOfSymbol(current);
|
||||
if (parent) {
|
||||
@@ -25882,6 +26048,21 @@ namespace ts {
|
||||
return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_parameter_must_have_a_type_annotation);
|
||||
}
|
||||
if (parameter.type.kind !== SyntaxKind.StringKeyword && parameter.type.kind !== SyntaxKind.NumberKeyword) {
|
||||
const type = getTypeFromTypeNode(parameter.type);
|
||||
|
||||
if (type.flags & TypeFlags.String || type.flags & TypeFlags.Number) {
|
||||
return grammarErrorOnNode(parameter.name,
|
||||
Diagnostics.An_index_signature_parameter_type_cannot_be_a_type_alias_Consider_writing_0_Colon_1_Colon_2_instead,
|
||||
getTextOfNode(parameter.name),
|
||||
typeToString(type),
|
||||
typeToString(getTypeFromTypeNode(node.type)));
|
||||
}
|
||||
|
||||
if (allTypesAssignableToKind(type, TypeFlags.StringLiteral, /*strict*/ true)) {
|
||||
return grammarErrorOnNode(parameter.name,
|
||||
Diagnostics.An_index_signature_parameter_type_cannot_be_a_union_type_Consider_using_a_mapped_object_type_instead);
|
||||
}
|
||||
|
||||
return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_parameter_type_must_be_string_or_number);
|
||||
}
|
||||
if (!node.type) {
|
||||
|
||||
@@ -144,6 +144,7 @@ namespace ts {
|
||||
"es2017.string": "lib.es2017.string.d.ts",
|
||||
"es2017.intl": "lib.es2017.intl.d.ts",
|
||||
"es2017.typedarrays": "lib.es2017.typedarrays.d.ts",
|
||||
"esnext.array": "lib.esnext.array.d.ts",
|
||||
"esnext.asynciterable": "lib.esnext.asynciterable.d.ts",
|
||||
"esnext.promise": "lib.esnext.promise.d.ts",
|
||||
}),
|
||||
@@ -401,6 +402,13 @@ namespace ts {
|
||||
category: Diagnostics.Module_Resolution_Options,
|
||||
description: Diagnostics.Allow_default_imports_from_modules_with_no_default_export_This_does_not_affect_code_emit_just_typechecking
|
||||
},
|
||||
{
|
||||
name: "esModuleInterop",
|
||||
type: "boolean",
|
||||
showInSimplifiedHelpView: true,
|
||||
category: Diagnostics.Module_Resolution_Options,
|
||||
description: Diagnostics.Enables_emit_interoperability_between_CommonJS_and_ES_Modules_via_creation_of_namespace_objects_for_all_imports_Implies_allowSyntheticDefaultImports
|
||||
},
|
||||
{
|
||||
name: "preserveSymlinks",
|
||||
type: "boolean",
|
||||
@@ -703,7 +711,8 @@ namespace ts {
|
||||
export const defaultInitCompilerOptions: CompilerOptions = {
|
||||
module: ModuleKind.CommonJS,
|
||||
target: ScriptTarget.ES5,
|
||||
strict: true
|
||||
strict: true,
|
||||
esModuleInterop: true
|
||||
};
|
||||
|
||||
let optionNameMapCache: OptionNameMap;
|
||||
@@ -1864,7 +1873,7 @@ namespace ts {
|
||||
return normalizeNonListOptionValue(option, basePath, value);
|
||||
}
|
||||
|
||||
function normalizeNonListOptionValue(option: CommandLineOption, basePath: string, value: any): CompilerOptionsValue {
|
||||
function normalizeNonListOptionValue(option: CommandLineOption, basePath: string, value: any): CompilerOptionsValue {
|
||||
if (option.isFilePath) {
|
||||
value = normalizePath(combinePaths(basePath, value));
|
||||
if (value === "") {
|
||||
|
||||
+6
-15
@@ -335,17 +335,6 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
export function indexOf<T>(array: ReadonlyArray<T>, value: T): number {
|
||||
if (array) {
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
if (array[i] === value) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
export function indexOfAnyCharCode(text: string, charCodes: ReadonlyArray<number>, start?: number): number {
|
||||
for (let i = start || 0; i < text.length; i++) {
|
||||
if (contains(charCodes, text.charCodeAt(i))) {
|
||||
@@ -2016,7 +2005,9 @@ namespace ts {
|
||||
const moduleKind = getEmitModuleKind(compilerOptions);
|
||||
return compilerOptions.allowSyntheticDefaultImports !== undefined
|
||||
? compilerOptions.allowSyntheticDefaultImports
|
||||
: moduleKind === ModuleKind.System;
|
||||
: compilerOptions.esModuleInterop
|
||||
? moduleKind !== ModuleKind.None && moduleKind < ModuleKind.ES2015
|
||||
: moduleKind === ModuleKind.System;
|
||||
}
|
||||
|
||||
export type StrictOptionName = "noImplicitAny" | "noImplicitThis" | "strictNullChecks" | "strictFunctionTypes" | "strictPropertyInitialization" | "alwaysStrict";
|
||||
@@ -2080,7 +2071,7 @@ namespace ts {
|
||||
|
||||
function getNormalizedPathComponentsOfUrl(url: string) {
|
||||
// Get root length of http://www.website.com/folder1/folder2/
|
||||
// In this example the root is: http://www.website.com/
|
||||
// In this example the root is: http://www.website.com/
|
||||
// normalized path components should be ["http://www.website.com/", "folder1", "folder2"]
|
||||
|
||||
const urlLength = url.length;
|
||||
@@ -2113,7 +2104,7 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
// Can't find the host assume the rest of the string as component
|
||||
// but make sure we append "/" to it as root is not joined using "/"
|
||||
// but make sure we append "/" to it as root is not joined using "/"
|
||||
// eg. if url passed in was http://website.com we want to use root as [http://website.com/]
|
||||
// so that other path manipulations will be correct and it can be merged with relative paths correctly
|
||||
return [url + directorySeparator];
|
||||
@@ -2134,7 +2125,7 @@ namespace ts {
|
||||
const directoryComponents = getNormalizedPathOrUrlComponents(directoryPathOrUrl, currentDirectory);
|
||||
if (directoryComponents.length > 1 && lastOrUndefined(directoryComponents) === "") {
|
||||
// If the directory path given was of type test/cases/ then we really need components of directory to be only till its name
|
||||
// that is ["test", "cases", ""] needs to be actually ["test", "cases"]
|
||||
// that is ["test", "cases", ""] needs to be actually ["test", "cases"]
|
||||
directoryComponents.pop();
|
||||
}
|
||||
|
||||
|
||||
@@ -148,8 +148,8 @@ namespace ts {
|
||||
moduleElementDeclarationEmitInfo = [];
|
||||
}
|
||||
|
||||
if (!isBundledEmit && isExternalModule(sourceFile) && sourceFile.moduleAugmentations.length && !resultHasExternalModuleIndicator) {
|
||||
// if file was external module with augmentations - this fact should be preserved in .d.ts as well.
|
||||
if (!isBundledEmit && isExternalModule(sourceFile) && !resultHasExternalModuleIndicator) {
|
||||
// if file was external module this fact should be preserved in .d.ts as well.
|
||||
// in case if we didn't write any external module specifiers in .d.ts we need to emit something
|
||||
// that will force compiler to think that this file is an external module - 'export {}' is a reasonable choice here.
|
||||
write("export {};");
|
||||
@@ -651,6 +651,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
function emitExportAssignment(node: ExportAssignment) {
|
||||
if (isSourceFile(node.parent)) {
|
||||
resultHasExternalModuleIndicator = true; // Top-level exports are external module indicators
|
||||
}
|
||||
if (node.expression.kind === SyntaxKind.Identifier) {
|
||||
write(node.isExportEquals ? "export = " : "export default ");
|
||||
writeTextOfNode(currentText, node.expression);
|
||||
@@ -745,6 +748,7 @@ namespace ts {
|
||||
const modifiers = getModifierFlags(node);
|
||||
// If the node is exported
|
||||
if (modifiers & ModifierFlags.Export) {
|
||||
resultHasExternalModuleIndicator = true; // Top-level exports are external module indicators
|
||||
write("export ");
|
||||
}
|
||||
|
||||
@@ -901,6 +905,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function emitExportDeclaration(node: ExportDeclaration) {
|
||||
resultHasExternalModuleIndicator = true; // Top-level exports are external module indicators
|
||||
emitJsDocComments(node);
|
||||
write("export ");
|
||||
if (node.exportClause) {
|
||||
@@ -1199,7 +1204,7 @@ namespace ts {
|
||||
write(">");
|
||||
}
|
||||
}
|
||||
else {
|
||||
else {
|
||||
emitHeritageClause([baseTypeNode], /*isImplementsList*/ false);
|
||||
}
|
||||
}
|
||||
@@ -1866,6 +1871,7 @@ namespace ts {
|
||||
// it allows emitSeparatedList to write separator appropriately)
|
||||
// Example:
|
||||
// original: function foo([, x, ,]) {}
|
||||
// tslint:disable-next-line no-double-space
|
||||
// emit : function foo([ , x, , ]) {}
|
||||
write(" ");
|
||||
}
|
||||
|
||||
@@ -939,6 +939,14 @@
|
||||
"category": "Error",
|
||||
"code": 1335
|
||||
},
|
||||
"An index signature parameter type cannot be a type alias. Consider writing '[{0}: {1}]: {2}' instead.": {
|
||||
"category": "Error",
|
||||
"code": 1336
|
||||
},
|
||||
"An index signature parameter type cannot be a union type. Consider using a mapped object type instead.": {
|
||||
"category": "Error",
|
||||
"code": 1337
|
||||
},
|
||||
|
||||
"Duplicate identifier '{0}'.": {
|
||||
"category": "Error",
|
||||
@@ -1396,6 +1404,10 @@
|
||||
"category": "Error",
|
||||
"code": 2415
|
||||
},
|
||||
"Property '{0}' in type '{1}' is not assignable to the same property in base type '{2}'.": {
|
||||
"category": "Error",
|
||||
"code": 2416
|
||||
},
|
||||
"Class static side '{0}' incorrectly extends base class static side '{1}'.": {
|
||||
"category": "Error",
|
||||
"code": 2417
|
||||
@@ -1612,7 +1624,7 @@
|
||||
"category": "Error",
|
||||
"code": 2474
|
||||
},
|
||||
"'const' enums can only be used in property or index access expressions or the right hand side of an import declaration or export assignment.": {
|
||||
"'const' enums can only be used in property or index access expressions or the right hand side of an import declaration or export assignment or type query.": {
|
||||
"category": "Error",
|
||||
"code": 2475
|
||||
},
|
||||
@@ -2280,7 +2292,18 @@
|
||||
"category": "Error",
|
||||
"code": 2720
|
||||
},
|
||||
|
||||
"Cannot invoke an object which is possibly 'null'.": {
|
||||
"category": "Error",
|
||||
"code": 2721
|
||||
},
|
||||
"Cannot invoke an object which is possibly 'undefined'.": {
|
||||
"category": "Error",
|
||||
"code": 2722
|
||||
},
|
||||
"Cannot invoke an object which is possibly 'null' or 'undefined'.": {
|
||||
"category": "Error",
|
||||
"code": 2723
|
||||
},
|
||||
"Import declaration '{0}' is using private name '{1}'.": {
|
||||
"category": "Error",
|
||||
"code": 4000
|
||||
@@ -3540,6 +3563,14 @@
|
||||
"category": "Error",
|
||||
"code": 7036
|
||||
},
|
||||
"Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'.": {
|
||||
"category": "Message",
|
||||
"code": 7037
|
||||
},
|
||||
"A namespace-style import cannot be called or constructed, and will cause a failure at runtime.": {
|
||||
"category": "Error",
|
||||
"code": 7038
|
||||
},
|
||||
|
||||
"You cannot rename this element.": {
|
||||
"category": "Error",
|
||||
@@ -3898,5 +3929,13 @@
|
||||
"Install '{0}'": {
|
||||
"category": "Message",
|
||||
"code": 95014
|
||||
},
|
||||
"Replace import with '{0}'.": {
|
||||
"category": "Message",
|
||||
"code": 95015
|
||||
},
|
||||
"Use synthetic 'default' member.": {
|
||||
"category": "Message",
|
||||
"code": 95016
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3831,13 +3831,13 @@ namespace ts {
|
||||
if (isLeftSideOfBinary) {
|
||||
// No need to parenthesize the left operand when the binary operator is
|
||||
// left associative:
|
||||
// (a*b)/x -> a*b/x
|
||||
// (a**b)/x -> a**b/x
|
||||
// (a*b)/x -> a*b/x
|
||||
// (a**b)/x -> a**b/x
|
||||
//
|
||||
// Parentheses are needed for the left operand when the binary operator is
|
||||
// right associative:
|
||||
// (a/b)**x -> (a/b)**x
|
||||
// (a**b)**x -> (a**b)**x
|
||||
// (a/b)**x -> (a/b)**x
|
||||
// (a**b)**x -> (a**b)**x
|
||||
return binaryOperatorAssociativity === Associativity.Right;
|
||||
}
|
||||
else {
|
||||
|
||||
+48
-38
@@ -585,7 +585,7 @@ namespace ts {
|
||||
// 'disallow-in' set to 'false'. Otherwise, if we had 'allowsIn' set to 'true', then almost
|
||||
// all nodes would need extra state on them to store this info.
|
||||
//
|
||||
// Note: 'allowIn' and 'allowYield' track 1:1 with the [in] and [yield] concepts in the ES6
|
||||
// Note: 'allowIn' and 'allowYield' track 1:1 with the [in] and [yield] concepts in the ES6
|
||||
// grammar specification.
|
||||
//
|
||||
// An important thing about these context concepts. By default they are effectively inherited
|
||||
@@ -701,7 +701,7 @@ namespace ts {
|
||||
|
||||
function getLanguageVariant(scriptKind: ScriptKind) {
|
||||
// .tsx and .jsx files are treated as jsx language variant.
|
||||
return scriptKind === ScriptKind.TSX || scriptKind === ScriptKind.JSX || scriptKind === ScriptKind.JS || scriptKind === ScriptKind.JSON ? LanguageVariant.JSX : LanguageVariant.Standard;
|
||||
return scriptKind === ScriptKind.TSX || scriptKind === ScriptKind.JSX || scriptKind === ScriptKind.JS || scriptKind === ScriptKind.JSON ? LanguageVariant.JSX : LanguageVariant.Standard;
|
||||
}
|
||||
|
||||
function initializeState(_sourceText: string, languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor, scriptKind: ScriptKind) {
|
||||
@@ -1429,9 +1429,13 @@ namespace ts {
|
||||
return token() === SyntaxKind.CommaToken || token() === SyntaxKind.DotDotDotToken || isIdentifierOrPattern();
|
||||
case ParsingContext.TypeParameters:
|
||||
return isIdentifier();
|
||||
case ParsingContext.ArgumentExpressions:
|
||||
case ParsingContext.ArrayLiteralMembers:
|
||||
return token() === SyntaxKind.CommaToken || token() === SyntaxKind.DotDotDotToken || isStartOfExpression();
|
||||
if (token() === SyntaxKind.CommaToken) {
|
||||
return true;
|
||||
}
|
||||
// falls through
|
||||
case ParsingContext.ArgumentExpressions:
|
||||
return token() === SyntaxKind.DotDotDotToken || isStartOfExpression();
|
||||
case ParsingContext.Parameters:
|
||||
return isStartOfParameter();
|
||||
case ParsingContext.TypeArguments:
|
||||
@@ -1453,7 +1457,7 @@ namespace ts {
|
||||
function isValidHeritageClauseObjectLiteral() {
|
||||
Debug.assert(token() === SyntaxKind.OpenBraceToken);
|
||||
if (nextToken() === SyntaxKind.CloseBraceToken) {
|
||||
// if we see "extends {}" then only treat the {} as what we're extending (and not
|
||||
// if we see "extends {}" then only treat the {} as what we're extending (and not
|
||||
// the class body) if we have:
|
||||
//
|
||||
// extends {} {
|
||||
@@ -1549,7 +1553,7 @@ namespace ts {
|
||||
|
||||
function isVariableDeclaratorListTerminator(): boolean {
|
||||
// If we can consume a semicolon (either explicitly, or with ASI), then consider us done
|
||||
// with parsing the list of variable declarators.
|
||||
// with parsing the list of variable declarators.
|
||||
if (canParseSemicolon()) {
|
||||
return true;
|
||||
}
|
||||
@@ -1675,6 +1679,11 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if ((node as JSDocContainer).jsDocCache) {
|
||||
// jsDocCache may include tags from parent nodes, which might have been modified.
|
||||
(node as JSDocContainer).jsDocCache = undefined;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -2269,7 +2278,7 @@ namespace ts {
|
||||
//
|
||||
// <T extends "">
|
||||
//
|
||||
// We do *not* want to consume the > as we're consuming the expression for "".
|
||||
// We do *not* want to consume the `>` as we're consuming the expression for "".
|
||||
node.expression = parseUnaryExpressionOrHigher();
|
||||
}
|
||||
}
|
||||
@@ -3089,7 +3098,7 @@ namespace ts {
|
||||
// And production (2) is parsed in "tryParseParenthesizedArrowFunctionExpression".
|
||||
//
|
||||
// If we do successfully parse arrow-function, we must *not* recurse for productions 1, 2 or 3. An ArrowFunction is
|
||||
// not a LeftHandSideExpression, nor does it start a ConditionalExpression. So we are done
|
||||
// not a LeftHandSideExpression, nor does it start a ConditionalExpression. So we are done
|
||||
// with AssignmentExpression if we see one.
|
||||
const arrowExpression = tryParseParenthesizedArrowFunctionExpression() || tryParseAsyncSimpleArrowFunctionExpression();
|
||||
if (arrowExpression) {
|
||||
@@ -3119,7 +3128,7 @@ namespace ts {
|
||||
// we're in '2' or '3'. Consume the assignment and return.
|
||||
//
|
||||
// Note: we call reScanGreaterToken so that we get an appropriately merged token
|
||||
// for cases like > > = becoming >>=
|
||||
// for cases like `> > =` becoming `>>=`
|
||||
if (isLeftHandSideExpression(expr) && isAssignmentOperator(reScanGreaterToken())) {
|
||||
return makeBinaryExpression(expr, <BinaryOperatorToken>parseTokenNode(), parseAssignmentExpressionOrHigher());
|
||||
}
|
||||
@@ -3275,7 +3284,7 @@ namespace ts {
|
||||
|
||||
if (first === SyntaxKind.OpenParenToken) {
|
||||
if (second === SyntaxKind.CloseParenToken) {
|
||||
// Simple cases: "() =>", "(): ", and "() {".
|
||||
// Simple cases: "() =>", "(): ", and "() {".
|
||||
// This is an arrow function with no parameters.
|
||||
// The last one is not actually an arrow function,
|
||||
// but this is probably what the user intended.
|
||||
@@ -3500,7 +3509,9 @@ namespace ts {
|
||||
node.whenTrue = doOutsideOfContext(disallowInAndDecoratorContext, parseAssignmentExpressionOrHigher);
|
||||
node.colonToken = parseExpectedToken(SyntaxKind.ColonToken, /*reportAtCurrentPosition*/ false,
|
||||
Diagnostics._0_expected, tokenToString(SyntaxKind.ColonToken));
|
||||
node.whenFalse = parseAssignmentExpressionOrHigher();
|
||||
node.whenFalse = nodeIsPresent(node.colonToken)
|
||||
? parseAssignmentExpressionOrHigher()
|
||||
: createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ false, Diagnostics._0_expected, tokenToString(SyntaxKind.ColonToken));
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
@@ -3895,7 +3906,8 @@ namespace ts {
|
||||
// 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
|
||||
// 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<PrimaryExpression>();
|
||||
}
|
||||
@@ -3945,7 +3957,7 @@ namespace ts {
|
||||
// treated as the invocation of "new Foo". We disambiguate that in code (to match
|
||||
// the original grammar) by making sure that if we see an ObjectCreationExpression
|
||||
// we always consume arguments if they are there. So we treat "new Foo()" as an
|
||||
// object creation only, and not at all as an invocation) Another way to think
|
||||
// object creation only, and not at all as an invocation. Another way to think
|
||||
// about this is that for every "new" that we see, we will consume an argument list if
|
||||
// it is there as part of the *associated* object creation node. Any additional
|
||||
// argument lists we see, will become invocation expressions.
|
||||
@@ -4361,7 +4373,7 @@ namespace ts {
|
||||
|
||||
const typeArguments = parseDelimitedList(ParsingContext.TypeArguments, parseType);
|
||||
if (!parseExpected(SyntaxKind.GreaterThanToken)) {
|
||||
// If it doesn't have the closing > then it's definitely not an type argument list.
|
||||
// If it doesn't have the closing `>` then it's definitely not an type argument list.
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -5394,8 +5406,8 @@ namespace ts {
|
||||
// off. The grammar would look something like this:
|
||||
//
|
||||
// MemberVariableDeclaration[Yield]:
|
||||
// AccessibilityModifier_opt PropertyName TypeAnnotation_opt Initializer_opt[In];
|
||||
// AccessibilityModifier_opt static_opt PropertyName TypeAnnotation_opt Initializer_opt[In, ?Yield];
|
||||
// AccessibilityModifier_opt PropertyName TypeAnnotation_opt Initializer_opt[In];
|
||||
// AccessibilityModifier_opt static_opt PropertyName TypeAnnotation_opt Initializer_opt[In, ?Yield];
|
||||
//
|
||||
// The checker may still error in the static case to explicitly disallow the yield expression.
|
||||
node.initializer = hasModifier(node, ModifierFlags.Static)
|
||||
@@ -6269,17 +6281,17 @@ namespace ts {
|
||||
indent += text.length;
|
||||
}
|
||||
|
||||
nextJSDocToken();
|
||||
while (token() === SyntaxKind.WhitespaceTrivia) {
|
||||
nextJSDocToken();
|
||||
let t = nextJSDocToken();
|
||||
while (t === SyntaxKind.WhitespaceTrivia) {
|
||||
t = nextJSDocToken();
|
||||
}
|
||||
if (token() === SyntaxKind.NewLineTrivia) {
|
||||
if (t === SyntaxKind.NewLineTrivia) {
|
||||
state = JSDocState.BeginningOfLine;
|
||||
indent = 0;
|
||||
nextJSDocToken();
|
||||
t = nextJSDocToken();
|
||||
}
|
||||
while (token() !== SyntaxKind.EndOfFileToken) {
|
||||
switch (token()) {
|
||||
loop: while (true) {
|
||||
switch (t) {
|
||||
case SyntaxKind.AtToken:
|
||||
if (state === JSDocState.BeginningOfLine || state === JSDocState.SawAsterisk) {
|
||||
removeTrailingNewlines(comments);
|
||||
@@ -6333,7 +6345,7 @@ namespace ts {
|
||||
indent += whitespace.length;
|
||||
break;
|
||||
case SyntaxKind.EndOfFileToken:
|
||||
break;
|
||||
break loop;
|
||||
default:
|
||||
// anything other than whitespace or asterisk at the beginning of the line starts the comment text
|
||||
state = JSDocState.SavingComments;
|
||||
@@ -6341,10 +6353,11 @@ namespace ts {
|
||||
break;
|
||||
}
|
||||
if (advanceToken) {
|
||||
nextJSDocToken();
|
||||
t = nextJSDocToken();
|
||||
}
|
||||
else {
|
||||
advanceToken = true;
|
||||
t = currentToken as JsDocSyntaxKind;
|
||||
}
|
||||
}
|
||||
removeLeadingNewlines(comments);
|
||||
@@ -6455,8 +6468,9 @@ namespace ts {
|
||||
comments.push(text);
|
||||
indent += text.length;
|
||||
}
|
||||
while (token() !== SyntaxKind.AtToken && token() !== SyntaxKind.EndOfFileToken) {
|
||||
switch (token()) {
|
||||
let tok = token() as JsDocSyntaxKind;
|
||||
loop: while (true) {
|
||||
switch (tok) {
|
||||
case SyntaxKind.NewLineTrivia:
|
||||
if (state >= JSDocState.SawAsterisk) {
|
||||
state = JSDocState.BeginningOfLine;
|
||||
@@ -6465,8 +6479,9 @@ namespace ts {
|
||||
indent = 0;
|
||||
break;
|
||||
case SyntaxKind.AtToken:
|
||||
case SyntaxKind.EndOfFileToken:
|
||||
// Done
|
||||
break;
|
||||
break loop;
|
||||
case SyntaxKind.WhitespaceTrivia:
|
||||
if (state === JSDocState.SavingComments) {
|
||||
pushComment(scanner.getTokenText());
|
||||
@@ -6494,11 +6509,7 @@ namespace ts {
|
||||
pushComment(scanner.getTokenText());
|
||||
break;
|
||||
}
|
||||
if (token() === SyntaxKind.AtToken) {
|
||||
// Done
|
||||
break;
|
||||
}
|
||||
nextJSDocToken();
|
||||
tok = nextJSDocToken();
|
||||
}
|
||||
|
||||
removeLeadingNewlines(comments);
|
||||
@@ -6776,8 +6787,7 @@ namespace ts {
|
||||
let canParseTag = true;
|
||||
let seenAsterisk = false;
|
||||
while (true) {
|
||||
nextJSDocToken();
|
||||
switch (token()) {
|
||||
switch (nextJSDocToken()) {
|
||||
case SyntaxKind.AtToken:
|
||||
if (canParseTag) {
|
||||
const child = tryParseChildTag(target);
|
||||
@@ -6873,7 +6883,7 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
function nextJSDocToken(): SyntaxKind {
|
||||
function nextJSDocToken(): JsDocSyntaxKind {
|
||||
return currentToken = scanner.scanJSDocToken();
|
||||
}
|
||||
|
||||
@@ -7077,7 +7087,7 @@ namespace ts {
|
||||
|
||||
// If the 'pos' is before the start of the change, then we don't need to touch it.
|
||||
// If it isn't, then the 'pos' must be inside the change. How we update it will
|
||||
// depend if delta is positive or negative. If delta is positive then we have
|
||||
// depend if delta is positive or negative. If delta is positive then we have
|
||||
// something like:
|
||||
//
|
||||
// -------------------AAA-----------------
|
||||
@@ -7102,7 +7112,7 @@ namespace ts {
|
||||
|
||||
// If the 'end' is after the change range, then we always adjust it by the delta
|
||||
// amount. However, if the end is in the change range, then how we adjust it
|
||||
// will depend on if delta is positive or negative. If delta is positive then we
|
||||
// will depend on if delta is positive or negative. If delta is positive then we
|
||||
// have something like:
|
||||
//
|
||||
// -------------------AAA-----------------
|
||||
|
||||
@@ -1601,6 +1601,7 @@ namespace ts {
|
||||
// synthesize 'import "tslib"' declaration
|
||||
const externalHelpersModuleReference = createLiteral(externalHelpersModuleNameText);
|
||||
const importDecl = createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*importClause*/ undefined);
|
||||
addEmitFlags(importDecl, EmitFlags.NeverApplyImportHelper);
|
||||
externalHelpersModuleReference.parent = importDecl;
|
||||
importDecl.parent = file;
|
||||
imports = [externalHelpersModuleReference];
|
||||
|
||||
+10
-34
@@ -35,7 +35,7 @@ namespace ts {
|
||||
scanJsxAttributeValue(): SyntaxKind;
|
||||
reScanJsxToken(): SyntaxKind;
|
||||
scanJsxToken(): SyntaxKind;
|
||||
scanJSDocToken(): SyntaxKind;
|
||||
scanJSDocToken(): JsDocSyntaxKind;
|
||||
scan(): SyntaxKind;
|
||||
getText(): string;
|
||||
// Sets the text for the scanner to scan. An optional subrange starting point and length
|
||||
@@ -193,7 +193,7 @@ namespace ts {
|
||||
/*
|
||||
As per ECMAScript Language Specification 3th Edition, Section 7.6: Identifiers
|
||||
IdentifierStart ::
|
||||
Can contain Unicode 3.0.0 categories:
|
||||
Can contain Unicode 3.0.0 categories:
|
||||
Uppercase letter (Lu),
|
||||
Lowercase letter (Ll),
|
||||
Titlecase letter (Lt),
|
||||
@@ -201,7 +201,7 @@ namespace ts {
|
||||
Other letter (Lo), or
|
||||
Letter number (Nl).
|
||||
IdentifierPart :: =
|
||||
Can contain IdentifierStart + Unicode 3.0.0 categories:
|
||||
Can contain IdentifierStart + Unicode 3.0.0 categories:
|
||||
Non-spacing mark (Mn),
|
||||
Combining spacing mark (Mc),
|
||||
Decimal number (Nd), or
|
||||
@@ -216,7 +216,7 @@ namespace ts {
|
||||
/*
|
||||
As per ECMAScript Language Specification 5th Edition, Section 7.6: ISyntaxToken Names and Identifiers
|
||||
IdentifierStart ::
|
||||
Can contain Unicode 6.2 categories:
|
||||
Can contain Unicode 6.2 categories:
|
||||
Uppercase letter (Lu),
|
||||
Lowercase letter (Ll),
|
||||
Titlecase letter (Lt),
|
||||
@@ -224,7 +224,7 @@ namespace ts {
|
||||
Other letter (Lo), or
|
||||
Letter number (Nl).
|
||||
IdentifierPart ::
|
||||
Can contain IdentifierStart + Unicode 6.2 categories:
|
||||
Can contain IdentifierStart + Unicode 6.2 categories:
|
||||
Non-spacing mark (Mn),
|
||||
Combining spacing mark (Mc),
|
||||
Decimal number (Nd),
|
||||
@@ -1594,7 +1594,7 @@ namespace ts {
|
||||
return token = SyntaxKind.NumericLiteral;
|
||||
case CharacterCodes.colon:
|
||||
pos++;
|
||||
return token = SyntaxKind.ColonToken;
|
||||
return token = SyntaxKind.ColonToken;
|
||||
case CharacterCodes.semicolon:
|
||||
pos++;
|
||||
return token = SyntaxKind.SemicolonToken;
|
||||
@@ -1905,7 +1905,7 @@ namespace ts {
|
||||
break;
|
||||
}
|
||||
}
|
||||
tokenValue += text.substr(firstCharPosition, pos - firstCharPosition);
|
||||
tokenValue += text.substring(firstCharPosition, pos);
|
||||
}
|
||||
return token;
|
||||
}
|
||||
@@ -1924,7 +1924,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function scanJSDocToken(): SyntaxKind {
|
||||
function scanJSDocToken(): JsDocSyntaxKind {
|
||||
if (pos >= end) {
|
||||
return token = SyntaxKind.EndOfFileToken;
|
||||
}
|
||||
@@ -1933,6 +1933,7 @@ namespace ts {
|
||||
tokenPos = pos;
|
||||
|
||||
const ch = text.charCodeAt(pos);
|
||||
pos++;
|
||||
switch (ch) {
|
||||
case CharacterCodes.tab:
|
||||
case CharacterCodes.verticalTab:
|
||||
@@ -1943,56 +1944,31 @@ namespace ts {
|
||||
}
|
||||
return token = SyntaxKind.WhitespaceTrivia;
|
||||
case CharacterCodes.at:
|
||||
pos++;
|
||||
return token = SyntaxKind.AtToken;
|
||||
case CharacterCodes.lineFeed:
|
||||
case CharacterCodes.carriageReturn:
|
||||
pos++;
|
||||
return token = SyntaxKind.NewLineTrivia;
|
||||
case CharacterCodes.asterisk:
|
||||
pos++;
|
||||
return token = SyntaxKind.AsteriskToken;
|
||||
case CharacterCodes.openBrace:
|
||||
pos++;
|
||||
return token = SyntaxKind.OpenBraceToken;
|
||||
case CharacterCodes.closeBrace:
|
||||
pos++;
|
||||
return token = SyntaxKind.CloseBraceToken;
|
||||
case CharacterCodes.openBracket:
|
||||
pos++;
|
||||
return token = SyntaxKind.OpenBracketToken;
|
||||
case CharacterCodes.closeBracket:
|
||||
pos++;
|
||||
return token = SyntaxKind.CloseBracketToken;
|
||||
case CharacterCodes.lessThan:
|
||||
pos++;
|
||||
return token = SyntaxKind.LessThanToken;
|
||||
case CharacterCodes.greaterThan:
|
||||
pos++;
|
||||
return token = SyntaxKind.GreaterThanToken;
|
||||
case CharacterCodes.equals:
|
||||
pos++;
|
||||
return token = SyntaxKind.EqualsToken;
|
||||
case CharacterCodes.comma:
|
||||
pos++;
|
||||
return token = SyntaxKind.CommaToken;
|
||||
case CharacterCodes.dot:
|
||||
pos++;
|
||||
if (text.substr(tokenPos, pos + 2) === "...") {
|
||||
pos += 2;
|
||||
return token = SyntaxKind.DotDotDotToken;
|
||||
}
|
||||
return token = SyntaxKind.DotToken;
|
||||
case CharacterCodes.exclamation:
|
||||
pos++;
|
||||
return token = SyntaxKind.ExclamationToken;
|
||||
case CharacterCodes.question:
|
||||
pos++;
|
||||
return token = SyntaxKind.QuestionToken;
|
||||
}
|
||||
|
||||
if (isIdentifierStart(ch, ScriptTarget.Latest)) {
|
||||
pos++;
|
||||
while (isIdentifierPart(text.charCodeAt(pos), ScriptTarget.Latest) && pos < end) {
|
||||
pos++;
|
||||
}
|
||||
@@ -2000,7 +1976,7 @@ namespace ts {
|
||||
return token = SyntaxKind.Identifier;
|
||||
}
|
||||
else {
|
||||
return pos += 1, token = SyntaxKind.Unknown;
|
||||
return token = SyntaxKind.Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -420,7 +420,7 @@ namespace ts {
|
||||
host.getCanonicalFileName,
|
||||
/*isAbsolutePathAnUrl*/ true);
|
||||
|
||||
sourceMapSourceIndex = indexOf(sourceMapData.sourceMapSources, source);
|
||||
sourceMapSourceIndex = sourceMapData.sourceMapSources.indexOf(source);
|
||||
if (sourceMapSourceIndex === -1) {
|
||||
sourceMapSourceIndex = sourceMapData.sourceMapSources.length;
|
||||
sourceMapData.sourceMapSources.push(source);
|
||||
|
||||
@@ -859,7 +859,7 @@ namespace ts {
|
||||
statements.push(
|
||||
setTextRange(
|
||||
createStatement(
|
||||
createExtendsHelper(context, getLocalName(node))
|
||||
createExtendsHelper(context, getInternalName(node))
|
||||
),
|
||||
/*location*/ extendsClauseElement
|
||||
)
|
||||
|
||||
@@ -3190,8 +3190,8 @@ namespace ts {
|
||||
// `throw` methods that step through the generator when invoked.
|
||||
//
|
||||
// parameters:
|
||||
// thisArg The value to use as the `this` binding for the transformed generator body.
|
||||
// body A function that acts as the transformed generator body.
|
||||
// @param thisArg The value to use as the `this` binding for the transformed generator body.
|
||||
// @param body A function that acts as the transformed generator body.
|
||||
//
|
||||
// variables:
|
||||
// _ Persistent state for the generator that is shared between the helper and the
|
||||
|
||||
@@ -25,14 +25,14 @@ namespace ts {
|
||||
if (externalHelpersModuleName) {
|
||||
const statements: Statement[] = [];
|
||||
const statementOffset = addPrologue(statements, node.statements);
|
||||
append(statements,
|
||||
createImportDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
createImportClause(/*name*/ undefined, createNamespaceImport(externalHelpersModuleName)),
|
||||
createLiteral(externalHelpersModuleNameText)
|
||||
)
|
||||
const tslibImport = createImportDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
createImportClause(/*name*/ undefined, createNamespaceImport(externalHelpersModuleName)),
|
||||
createLiteral(externalHelpersModuleNameText)
|
||||
);
|
||||
addEmitFlags(tslibImport, EmitFlags.NeverApplyImportHelper);
|
||||
append(statements, tslibImport);
|
||||
|
||||
addRange(statements, visitNodes(node.statements, visitor, isStatement, statementOffset));
|
||||
return updateSourceFileNode(
|
||||
|
||||
@@ -148,7 +148,7 @@ namespace ts {
|
||||
// Create an updated SourceFile:
|
||||
//
|
||||
// define(moduleName?, ["module1", "module2"], function ...
|
||||
return updateSourceFileNode(node,
|
||||
const updated = updateSourceFileNode(node,
|
||||
setTextRange(
|
||||
createNodeArray([
|
||||
createStatement(
|
||||
@@ -192,6 +192,9 @@ namespace ts {
|
||||
/*location*/ node.statements
|
||||
)
|
||||
);
|
||||
|
||||
addEmitHelpers(updated, context.readEmitHelpers());
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -296,7 +299,7 @@ namespace ts {
|
||||
// }
|
||||
// })(function ...)
|
||||
|
||||
return updateSourceFileNode(
|
||||
const updated = updateSourceFileNode(
|
||||
node,
|
||||
setTextRange(
|
||||
createNodeArray([
|
||||
@@ -328,6 +331,9 @@ namespace ts {
|
||||
/*location*/ node.statements
|
||||
)
|
||||
);
|
||||
|
||||
addEmitHelpers(updated, context.readEmitHelpers());
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -385,6 +391,18 @@ namespace ts {
|
||||
return { aliasedModuleNames, unaliasedModuleNames, importAliasNames };
|
||||
}
|
||||
|
||||
function getAMDImportExpressionForImport(node: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration) {
|
||||
if (isImportEqualsDeclaration(node) || isExportDeclaration(node) || !getExternalModuleNameLiteral(node, currentSourceFile, host, resolver, compilerOptions)) {
|
||||
return undefined;
|
||||
}
|
||||
const name = getLocalNameForExternalImport(node, currentSourceFile);
|
||||
const expr = getHelperExpressionForImport(node, name);
|
||||
if (expr === name) {
|
||||
return undefined;
|
||||
}
|
||||
return createStatement(createAssignment(name, expr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a SourceFile into an AMD or UMD module body.
|
||||
*
|
||||
@@ -402,6 +420,9 @@ namespace ts {
|
||||
|
||||
// Visit each statement of the module body.
|
||||
append(statements, visitNode(currentModuleInfo.externalHelpersImportDeclaration, sourceElementVisitor, isStatement));
|
||||
if (moduleKind === ModuleKind.AMD) {
|
||||
addRange(statements, mapDefined(currentModuleInfo.externalImports, getAMDImportExpressionForImport));
|
||||
}
|
||||
addRange(statements, visitNodes(node.statements, sourceElementVisitor, isStatement, statementOffset));
|
||||
|
||||
// Append the 'export =' statement if provided.
|
||||
@@ -617,7 +638,12 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
return createNew(createIdentifier("Promise"), /*typeArguments*/ undefined, [func]);
|
||||
const promise = createNew(createIdentifier("Promise"), /*typeArguments*/ undefined, [func]);
|
||||
if (compilerOptions.esModuleInterop) {
|
||||
context.requestEmitHelper(importStarHelper);
|
||||
return createCall(createPropertyAccess(promise, createIdentifier("then")), /*typeArguments*/ undefined, [getHelperName("__importStar")]);
|
||||
}
|
||||
return promise;
|
||||
}
|
||||
|
||||
function createImportCallExpressionCommonJS(arg: Expression | undefined, containsLexicalThis: boolean): Expression {
|
||||
@@ -627,7 +653,11 @@ namespace ts {
|
||||
// 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
|
||||
const promiseResolveCall = createCall(createPropertyAccess(createIdentifier("Promise"), "resolve"), /*typeArguments*/ undefined, /*argumentsArray*/ []);
|
||||
const requireCall = createCall(createIdentifier("require"), /*typeArguments*/ undefined, arg ? [arg] : []);
|
||||
let requireCall = createCall(createIdentifier("require"), /*typeArguments*/ undefined, arg ? [arg] : []);
|
||||
if (compilerOptions.esModuleInterop) {
|
||||
context.requestEmitHelper(importStarHelper);
|
||||
requireCall = createCall(getHelperName("__importStar"), /*typeArguments*/ undefined, [requireCall]);
|
||||
}
|
||||
|
||||
let func: FunctionExpression | ArrowFunction;
|
||||
if (languageVersion >= ScriptTarget.ES2015) {
|
||||
@@ -660,6 +690,22 @@ namespace ts {
|
||||
return createCall(createPropertyAccess(promiseResolveCall, "then"), /*typeArguments*/ undefined, [func]);
|
||||
}
|
||||
|
||||
|
||||
function getHelperExpressionForImport(node: ImportDeclaration, innerExpr: Expression) {
|
||||
if (!compilerOptions.esModuleInterop || getEmitFlags(node) & EmitFlags.NeverApplyImportHelper) {
|
||||
return innerExpr;
|
||||
}
|
||||
if (getNamespaceDeclarationNode(node)) {
|
||||
context.requestEmitHelper(importStarHelper);
|
||||
return createCall(getHelperName("__importStar"), /*typeArguments*/ undefined, [innerExpr]);
|
||||
}
|
||||
if (isDefaultImport(node)) {
|
||||
context.requestEmitHelper(importDefaultHelper);
|
||||
return createCall(getHelperName("__importDefault"), /*typeArguments*/ undefined, [innerExpr]);
|
||||
}
|
||||
return innerExpr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits an ImportDeclaration node.
|
||||
*
|
||||
@@ -681,7 +727,7 @@ namespace ts {
|
||||
createVariableDeclaration(
|
||||
getSynthesizedClone(namespaceDeclaration.name),
|
||||
/*type*/ undefined,
|
||||
createRequireCall(node)
|
||||
getHelperExpressionForImport(node, createRequireCall(node))
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -694,7 +740,7 @@ namespace ts {
|
||||
createVariableDeclaration(
|
||||
getGeneratedNameForNode(node),
|
||||
/*type*/ undefined,
|
||||
createRequireCall(node)
|
||||
getHelperExpressionForImport(node, createRequireCall(node))
|
||||
)
|
||||
);
|
||||
|
||||
@@ -1671,4 +1717,28 @@ namespace ts {
|
||||
text: `
|
||||
var __syncRequire = typeof module === "object" && typeof module.exports === "object";`
|
||||
};
|
||||
|
||||
// emit helper for `import * as Name from "foo"`
|
||||
const importStarHelper: EmitHelper = {
|
||||
name: "typescript:commonjsimportstar",
|
||||
scoped: false,
|
||||
text: `
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||
result["default"] = mod;
|
||||
return result;
|
||||
}`
|
||||
};
|
||||
|
||||
// emit helper for `import Name from "foo"`
|
||||
const importDefaultHelper: EmitHelper = {
|
||||
name: "typescript:commonjsimportdefault",
|
||||
scoped: false,
|
||||
text: `
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
}`
|
||||
};
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ namespace ts {
|
||||
let classAliases: Identifier[];
|
||||
|
||||
/**
|
||||
* Keeps track of whether we are within any containing namespaces when performing
|
||||
* Keeps track of whether we are within any containing namespaces when performing
|
||||
* just-in-time substitution while printing an expression identifier.
|
||||
*/
|
||||
let applicableSubstitutions: TypeScriptSubstitutionFlags;
|
||||
|
||||
@@ -143,6 +143,7 @@ namespace ts {
|
||||
createLiteral(externalHelpersModuleNameText));
|
||||
|
||||
if (externalHelpersImportDeclaration) {
|
||||
addEmitFlags(externalHelpersImportDeclaration, EmitFlags.NeverApplyImportHelper);
|
||||
externalImports.unshift(externalHelpersImportDeclaration);
|
||||
}
|
||||
|
||||
|
||||
+44
-22
@@ -58,6 +58,23 @@ namespace ts {
|
||||
end: number;
|
||||
}
|
||||
|
||||
export type JsDocSyntaxKind =
|
||||
| SyntaxKind.EndOfFileToken
|
||||
| SyntaxKind.WhitespaceTrivia
|
||||
| SyntaxKind.AtToken
|
||||
| SyntaxKind.NewLineTrivia
|
||||
| SyntaxKind.AsteriskToken
|
||||
| SyntaxKind.OpenBraceToken
|
||||
| SyntaxKind.CloseBraceToken
|
||||
| SyntaxKind.LessThanToken
|
||||
| SyntaxKind.OpenBracketToken
|
||||
| SyntaxKind.CloseBracketToken
|
||||
| SyntaxKind.EqualsToken
|
||||
| SyntaxKind.CommaToken
|
||||
| SyntaxKind.DotToken
|
||||
| SyntaxKind.Identifier
|
||||
| SyntaxKind.Unknown;
|
||||
|
||||
// token > SyntaxKind.Identifer => token is a keyword
|
||||
// Also, If you add a new SyntaxKind be sure to keep the `Markers` section at the bottom in sync
|
||||
export const enum SyntaxKind {
|
||||
@@ -438,24 +455,24 @@ namespace ts {
|
||||
}
|
||||
|
||||
export const enum NodeFlags {
|
||||
None = 0,
|
||||
Let = 1 << 0, // Variable declaration
|
||||
Const = 1 << 1, // Variable declaration
|
||||
NestedNamespace = 1 << 2, // Namespace declaration
|
||||
Synthesized = 1 << 3, // Node was synthesized during transformation
|
||||
Namespace = 1 << 4, // Namespace declaration
|
||||
ExportContext = 1 << 5, // Export context (initialized by binding)
|
||||
ContainsThis = 1 << 6, // Interface contains references to "this"
|
||||
HasImplicitReturn = 1 << 7, // If function implicitly returns on one of codepaths (initialized by binding)
|
||||
HasExplicitReturn = 1 << 8, // If function has explicit reachable return on one of codepaths (initialized by binding)
|
||||
None = 0,
|
||||
Let = 1 << 0, // Variable declaration
|
||||
Const = 1 << 1, // Variable declaration
|
||||
NestedNamespace = 1 << 2, // Namespace declaration
|
||||
Synthesized = 1 << 3, // Node was synthesized during transformation
|
||||
Namespace = 1 << 4, // Namespace declaration
|
||||
ExportContext = 1 << 5, // Export context (initialized by binding)
|
||||
ContainsThis = 1 << 6, // Interface contains references to "this"
|
||||
HasImplicitReturn = 1 << 7, // If function implicitly returns on one of codepaths (initialized by binding)
|
||||
HasExplicitReturn = 1 << 8, // If function has explicit reachable return on one of codepaths (initialized by binding)
|
||||
GlobalAugmentation = 1 << 9, // Set if module declaration is an augmentation for the global scope
|
||||
HasAsyncFunctions = 1 << 10, // If the file has async functions (initialized by binding)
|
||||
DisallowInContext = 1 << 11, // If node was parsed in a context where 'in-expressions' are not allowed
|
||||
YieldContext = 1 << 12, // If node was parsed in the 'yield' context created when parsing a generator
|
||||
DecoratorContext = 1 << 13, // If node was parsed as part of a decorator
|
||||
AwaitContext = 1 << 14, // If node was parsed in the 'await' context created when parsing an async function
|
||||
ThisNodeHasError = 1 << 15, // If the parser encountered an error when parsing the code that created this node
|
||||
JavaScriptFile = 1 << 16, // If node was parsed in a JavaScript
|
||||
HasAsyncFunctions = 1 << 10, // If the file has async functions (initialized by binding)
|
||||
DisallowInContext = 1 << 11, // If node was parsed in a context where 'in-expressions' are not allowed
|
||||
YieldContext = 1 << 12, // If node was parsed in the 'yield' context created when parsing a generator
|
||||
DecoratorContext = 1 << 13, // If node was parsed as part of a decorator
|
||||
AwaitContext = 1 << 14, // If node was parsed in the 'await' context created when parsing an async function
|
||||
ThisNodeHasError = 1 << 15, // If the parser encountered an error when parsing the code that created this node
|
||||
JavaScriptFile = 1 << 16, // If node was parsed in a JavaScript
|
||||
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
|
||||
|
||||
@@ -1394,7 +1411,7 @@ namespace ts {
|
||||
|
||||
export type BinaryOperatorToken = Token<BinaryOperator>;
|
||||
|
||||
export interface BinaryExpression extends Expression, Declaration {
|
||||
export interface BinaryExpression extends Expression, Declaration {
|
||||
kind: SyntaxKind.BinaryExpression;
|
||||
left: Expression;
|
||||
operatorToken: BinaryOperatorToken;
|
||||
@@ -2874,6 +2891,8 @@ namespace ts {
|
||||
* This should be called in a loop climbing parents of the symbol, so we'll get `N`.
|
||||
*/
|
||||
/* @internal */ getAccessibleSymbolChain(symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags, useOnlyExternalAliasing: boolean): Symbol[] | undefined;
|
||||
|
||||
/* @internal */ resolveExternalModuleSymbol(symbol: Symbol): Symbol;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
@@ -2977,9 +2996,9 @@ namespace ts {
|
||||
None = 0x00000000,
|
||||
|
||||
// Write symbols's type argument if it is instantiated symbol
|
||||
// eg. class C<T> { p: T } <-- Show p as C<T>.p here
|
||||
// eg. class C<T> { p: T } <-- Show p as C<T>.p here
|
||||
// var a: C<number>;
|
||||
// var p = a.p; <--- Here p is property of C<number> so show it as C<number>.p instead of just C.p
|
||||
// var p = a.p; <--- Here p is property of C<number> so show it as C<number>.p instead of just C.p
|
||||
WriteTypeParametersOrArguments = 0x00000001,
|
||||
|
||||
// Use only external alias information to get the symbol name in the given context
|
||||
@@ -3229,6 +3248,7 @@ namespace ts {
|
||||
bindingElement?: BindingElement; // Binding element associated with property symbol
|
||||
exportsSomeValue?: boolean; // True if module exports some value (not just types)
|
||||
enumKind?: EnumKind; // Enum declaration classification
|
||||
originatingImport?: ImportDeclaration | ImportCall; // Import declaration which produced the symbol, present if the symbol is marked as uncallable but had call signatures in `resolveESModuleSymbol`
|
||||
lateSymbol?: Symbol; // Late-bound symbol for a computed property
|
||||
}
|
||||
|
||||
@@ -3372,7 +3392,7 @@ namespace ts {
|
||||
resolvedJsxElementAttributesType?: Type; // resolved element attributes type of a JSX openinglike element
|
||||
resolvedJsxElementAllAttributesType?: Type; // resolved all element attributes type of a JSX openinglike element
|
||||
hasSuperCall?: boolean; // recorded result when we try to find super-call. We only try to find one if this flag is undefined, indicating that we haven't made an attempt.
|
||||
superCall?: ExpressionStatement; // Cached first super-call found in the constructor. Used in checking whether super is called before this-accessing
|
||||
superCall?: SuperCall; // Cached first super-call found in the constructor. Used in checking whether super is called before this-accessing
|
||||
switchTypes?: Type[]; // Cached array of switch case expression types
|
||||
}
|
||||
|
||||
@@ -3628,7 +3648,7 @@ namespace ts {
|
||||
|
||||
/* @internal */
|
||||
// Object literals are initially marked fresh. Freshness disappears following an assignment,
|
||||
// before a type assertion, or when an object literal's type is widened. The regular
|
||||
// before a type assertion, or when an object literal's type is widened. The regular
|
||||
// version of a fresh type is identical except for the TypeFlags.FreshObjectLiteral flag.
|
||||
export interface FreshObjectLiteralType extends ResolvedType {
|
||||
regularType: ResolvedType; // Regular version of fresh type
|
||||
@@ -3959,6 +3979,7 @@ namespace ts {
|
||||
typeRoots?: string[];
|
||||
/*@internal*/ version?: boolean;
|
||||
/*@internal*/ watch?: boolean;
|
||||
esModuleInterop?: boolean;
|
||||
|
||||
[option: string]: CompilerOptionsValue | JsonSourceFile | undefined;
|
||||
}
|
||||
@@ -4526,6 +4547,7 @@ namespace ts {
|
||||
Iterator = 1 << 23, // The expression to a `yield*` should be treated as an Iterator when down-leveling, not an Iterable.
|
||||
NoAsciiEscaping = 1 << 24, // When synthesizing nodes that lack an original node or textSourceNode, we want to write the text on the node with ASCII escaping substitutions.
|
||||
/*@internal*/ TypeScriptClassWrapper = 1 << 25, // The node is an IIFE class wrapper created by the ts transform.
|
||||
/*@internal*/ NeverApplyImportHelper = 1 << 26, // Indicates the node should never be wrapped with an import star helper (because, for example, it imports tslib itself)
|
||||
}
|
||||
|
||||
export interface EmitHelper {
|
||||
|
||||
@@ -803,7 +803,7 @@ namespace ts {
|
||||
return node === (<TypeAssertion>parent).type;
|
||||
case SyntaxKind.CallExpression:
|
||||
case SyntaxKind.NewExpression:
|
||||
return (<CallExpression>parent).typeArguments && indexOf((<CallExpression>parent).typeArguments, node) >= 0;
|
||||
return contains((<CallExpression>parent).typeArguments, node);
|
||||
case SyntaxKind.TaggedTemplateExpression:
|
||||
// TODO (drosen): TaggedTemplateExpressions may eventually support type arguments.
|
||||
return false;
|
||||
@@ -2119,6 +2119,10 @@ namespace ts {
|
||||
return "__@" + symbolName as __String;
|
||||
}
|
||||
|
||||
export function isKnownSymbol(symbol: Symbol): boolean {
|
||||
return startsWith(symbol.escapedName as string, "__@");
|
||||
}
|
||||
|
||||
/**
|
||||
* Includes the word "Symbol" with unicode escapes
|
||||
*/
|
||||
@@ -3917,8 +3921,8 @@ namespace ts {
|
||||
//
|
||||
// {
|
||||
// oldStart3: Min(oldStart1, oldStart2),
|
||||
// oldEnd3 : Max(oldEnd1, oldEnd1 + (oldEnd2 - newEnd1)),
|
||||
// newEnd3 : Max(newEnd2, newEnd2 + (newEnd1 - oldEnd2))
|
||||
// oldEnd3: Max(oldEnd1, oldEnd1 + (oldEnd2 - newEnd1)),
|
||||
// newEnd3: Max(newEnd2, newEnd2 + (newEnd1 - oldEnd2))
|
||||
// }
|
||||
|
||||
const oldStart1 = oldStartN;
|
||||
@@ -5843,4 +5847,19 @@ namespace ts {
|
||||
export function hasOnlyExpressionInitializer(node: Node): node is HasExpressionInitializer {
|
||||
return hasInitializer(node) && !isForStatement(node) && !isForInStatement(node) && !isForOfStatement(node) && !isJsxAttribute(node);
|
||||
}
|
||||
|
||||
export function isObjectLiteralElement(node: Node): node is ObjectLiteralElement {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.JsxAttribute:
|
||||
case SyntaxKind.JsxSpreadAttribute:
|
||||
case SyntaxKind.PropertyAssignment:
|
||||
case SyntaxKind.ShorthandPropertyAssignment:
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -622,7 +622,7 @@ namespace ts {
|
||||
|
||||
case SyntaxKind.ForOfStatement:
|
||||
return updateForOf(<ForOfStatement>node,
|
||||
(<ForOfStatement>node).awaitModifier,
|
||||
visitNode((<ForOfStatement>node).awaitModifier, visitor, isToken),
|
||||
visitNode((<ForOfStatement>node).initializer, visitor, isForInitializer),
|
||||
visitNode((<ForOfStatement>node).expression, visitor, isExpression),
|
||||
visitNode((<ForOfStatement>node).statement, visitor, isStatement, liftToBlock));
|
||||
|
||||
+31
-14
@@ -265,7 +265,7 @@ namespace FourSlash {
|
||||
ts.forEach(testData.files, file => {
|
||||
// Create map between fileName and its content for easily looking up when resolveReference flag is specified
|
||||
this.inputFiles.set(file.fileName, file.content);
|
||||
if (ts.getBaseFileName(file.fileName).toLowerCase() === "tsconfig.json") {
|
||||
if (isTsconfig(file)) {
|
||||
const configJson = ts.parseConfigFileTextToJson(file.fileName, file.content);
|
||||
if (configJson.config === undefined) {
|
||||
throw new Error(`Failed to parse test tsconfig.json: ${configJson.error.messageText}`);
|
||||
@@ -381,6 +381,7 @@ namespace FourSlash {
|
||||
insertSpaceAfterTypeAssertion: false,
|
||||
placeOpenBraceOnNewLineForFunctions: false,
|
||||
placeOpenBraceOnNewLineForControlBlocks: false,
|
||||
insertSpaceBeforeTypeAnnotation: false
|
||||
};
|
||||
|
||||
// Open the first file by default
|
||||
@@ -510,7 +511,7 @@ namespace FourSlash {
|
||||
}
|
||||
}
|
||||
|
||||
private raiseError(message: string) {
|
||||
private raiseError(message: string): never {
|
||||
throw new Error(this.messageAtLastKnownMarker(message));
|
||||
}
|
||||
|
||||
@@ -847,10 +848,10 @@ namespace FourSlash {
|
||||
}
|
||||
}
|
||||
|
||||
public verifyCompletionsAt(markerName: string, expected: string[], options?: FourSlashInterface.CompletionsAtOptions) {
|
||||
public verifyCompletionsAt(markerName: string, expected: ReadonlyArray<FourSlashInterface.ExpectedCompletionEntry>, options?: FourSlashInterface.CompletionsAtOptions) {
|
||||
this.goToMarker(markerName);
|
||||
|
||||
const actualCompletions = this.getCompletionListAtCaret();
|
||||
const actualCompletions = this.getCompletionListAtCaret(options);
|
||||
if (!actualCompletions) {
|
||||
this.raiseError(`No completions at position '${this.currentCaretPosition}'.`);
|
||||
}
|
||||
@@ -866,9 +867,20 @@ namespace FourSlash {
|
||||
}
|
||||
|
||||
ts.zipWith(actual, expected, (completion, expectedCompletion, index) => {
|
||||
if (completion.name !== expectedCompletion) {
|
||||
const { name, insertText, replacementSpan } = typeof expectedCompletion === "string" ? { name: expectedCompletion, insertText: undefined, replacementSpan: undefined } : expectedCompletion;
|
||||
if (completion.name !== name) {
|
||||
this.raiseError(`Expected completion at index ${index} to be ${expectedCompletion}, got ${completion.name}`);
|
||||
}
|
||||
if (completion.insertText !== insertText) {
|
||||
this.raiseError(`Expected completion insert text at index ${index} to be ${insertText}, got ${completion.insertText}`);
|
||||
}
|
||||
const convertedReplacementSpan = replacementSpan && textSpanFromRange(replacementSpan);
|
||||
try {
|
||||
assert.deepEqual(completion.replacementSpan, convertedReplacementSpan);
|
||||
}
|
||||
catch {
|
||||
this.raiseError(`Expected completion replacementSpan at index ${index} to be ${stringify(convertedReplacementSpan)}, got ${stringify(completion.replacementSpan)}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1807,7 +1819,7 @@ Actual: ${stringify(fullActual)}`);
|
||||
}
|
||||
else if (prevChar === " " && /A-Za-z_/.test(ch)) {
|
||||
/* Completions */
|
||||
this.languageService.getCompletionsAtPosition(this.activeFile.fileName, offset, { includeExternalModuleExports: false });
|
||||
this.languageService.getCompletionsAtPosition(this.activeFile.fileName, offset, { includeExternalModuleExports: false, includeInsertTextCompletions: false });
|
||||
}
|
||||
|
||||
if (i % checkCadence === 0) {
|
||||
@@ -2382,7 +2394,8 @@ Actual: ${stringify(fullActual)}`);
|
||||
public applyCodeActionFromCompletion(markerName: string, options: FourSlashInterface.VerifyCompletionActionOptions) {
|
||||
this.goToMarker(markerName);
|
||||
|
||||
const actualCompletion = this.getCompletionListAtCaret({ includeExternalModuleExports: true }).entries.find(e => e.name === options.name && e.source === options.source);
|
||||
const actualCompletion = this.getCompletionListAtCaret({ includeExternalModuleExports: true, includeInsertTextCompletions: false }).entries.find(e =>
|
||||
e.name === options.name && e.source === options.source);
|
||||
|
||||
if (!actualCompletion.hasAction) {
|
||||
this.raiseError(`Completion for ${options.name} does not have an associated action.`);
|
||||
@@ -3194,8 +3207,7 @@ Actual: ${stringify(fullActual)}`);
|
||||
private getTextSpanForRangeAtIndex(index: number): ts.TextSpan {
|
||||
const ranges = this.getRanges();
|
||||
if (ranges && ranges.length > index) {
|
||||
const range = ranges[index];
|
||||
return { start: range.start, length: range.end - range.start };
|
||||
return textSpanFromRange(ranges[index]);
|
||||
}
|
||||
else {
|
||||
this.raiseError("Supplied span index: " + index + " does not exist in range list of size: " + (ranges ? 0 : ranges.length));
|
||||
@@ -3225,6 +3237,10 @@ Actual: ${stringify(fullActual)}`);
|
||||
}
|
||||
}
|
||||
|
||||
function textSpanFromRange(range: FourSlash.Range): ts.TextSpan {
|
||||
return ts.createTextSpanFromBounds(range.start, range.end);
|
||||
}
|
||||
|
||||
export function runFourSlashTest(basePath: string, testType: FourSlashTestType, fileName: string) {
|
||||
const content = Harness.IO.readFile(fileName);
|
||||
runFourSlashTestContent(basePath, testType, content, fileName);
|
||||
@@ -3384,7 +3400,7 @@ ${code}
|
||||
}
|
||||
|
||||
// @Filename is the only directive that can be used in a test that contains tsconfig.json file.
|
||||
if (containTSConfigJson(files)) {
|
||||
if (files.some(isTsconfig)) {
|
||||
let directive = getNonFileNameOptionInFileList(files);
|
||||
if (!directive) {
|
||||
directive = getNonFileNameOptionInObject(globalOptions);
|
||||
@@ -3403,8 +3419,8 @@ ${code}
|
||||
};
|
||||
}
|
||||
|
||||
function containTSConfigJson(files: FourSlashFile[]): boolean {
|
||||
return ts.forEach(files, f => f.fileOptions.Filename === "tsconfig.json");
|
||||
function isTsconfig(file: FourSlashFile): boolean {
|
||||
return ts.getBaseFileName(file.fileName).toLowerCase() === "tsconfig.json";
|
||||
}
|
||||
|
||||
function getNonFileNameOptionInFileList(files: FourSlashFile[]): string {
|
||||
@@ -3777,7 +3793,7 @@ namespace FourSlashInterface {
|
||||
|
||||
public eachMarker(markers: ReadonlyArray<string>, action: (marker: FourSlash.Marker, index: number) => void): void;
|
||||
public eachMarker(action: (marker: FourSlash.Marker, index: number) => void): void;
|
||||
public eachMarker(a: ReadonlyArray<string> | ((marker: FourSlash.Marker, index: number) => void), b?: (marker: FourSlash.Marker, index: number) => void): void {
|
||||
public eachMarker(a: ReadonlyArray<string> | ((marker: FourSlash.Marker, index: number) => void), b?: (marker: FourSlash.Marker, index: number) => void): void {
|
||||
const markers = typeof a === "function" ? this.state.getMarkers() : a.map(m => this.state.getMarkerByName(m));
|
||||
this.state.goToEachMarker(markers, typeof a === "function" ? a : b);
|
||||
}
|
||||
@@ -3966,7 +3982,7 @@ namespace FourSlashInterface {
|
||||
super(state);
|
||||
}
|
||||
|
||||
public completionsAt(markerName: string, completions: string[], options?: CompletionsAtOptions) {
|
||||
public completionsAt(markerName: string, completions: ReadonlyArray<ExpectedCompletionEntry>, options?: CompletionsAtOptions) {
|
||||
this.state.verifyCompletionsAt(markerName, completions, options);
|
||||
}
|
||||
|
||||
@@ -4590,6 +4606,7 @@ namespace FourSlashInterface {
|
||||
newContent: string;
|
||||
}
|
||||
|
||||
export type ExpectedCompletionEntry = string | { name: string, insertText?: string, replacementSpan?: FourSlash.Range };
|
||||
export interface CompletionsAtOptions extends ts.GetCompletionsAtPositionOptions {
|
||||
isNewIdentifierLocation?: boolean;
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ declare var window: {};
|
||||
declare var XMLHttpRequest: {
|
||||
new(): XMLHttpRequest;
|
||||
};
|
||||
interface XMLHttpRequest {
|
||||
interface XMLHttpRequest {
|
||||
readonly readyState: number;
|
||||
readonly responseText: string;
|
||||
readonly status: number;
|
||||
@@ -874,7 +874,7 @@ namespace Harness {
|
||||
// Cache of lib files from "built/local"
|
||||
let libFileNameSourceFileMap: ts.Map<ts.SourceFile> | undefined;
|
||||
|
||||
// Cache of lib files from "tests/lib/"
|
||||
// Cache of lib files from "tests/lib/"
|
||||
const testLibFileNameSourceFileMap = ts.createMap<ts.SourceFile>();
|
||||
const es6TestLibFileNameSourceFileMap = ts.createMap<ts.SourceFile>();
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@ namespace Harness.Parallel.Host {
|
||||
on(event: "error", listener: (err: Error) => void): this;
|
||||
on(event: "exit", listener: (code: number, signal: string) => void): this;
|
||||
on(event: "message", listener: (message: ParallelClientMessage) => void): this;
|
||||
kill(signal?: string): void;
|
||||
currentTasks?: {file: string}[]; // Custom monkeypatch onto child process handle
|
||||
}
|
||||
|
||||
interface ProgressBarsOptions {
|
||||
@@ -134,6 +136,11 @@ namespace Harness.Parallel.Host {
|
||||
const newPerfData: {[testHash: string]: number} = {};
|
||||
|
||||
const workers: ChildProcessPartial[] = [];
|
||||
const defaultTimeout = globalTimeout !== undefined
|
||||
? globalTimeout
|
||||
: mocha && mocha.suite && mocha.suite._timeout
|
||||
? mocha.suite._timeout
|
||||
: 20000; // 20 seconds
|
||||
let closedWorkers = 0;
|
||||
for (let i = 0; i < workerCount; i++) {
|
||||
// TODO: Just send the config over the IPC channel or in the command line arguments
|
||||
@@ -141,6 +148,14 @@ namespace Harness.Parallel.Host {
|
||||
const configPath = ts.combinePaths(taskConfigsFolder, `task-config${i}.json`);
|
||||
Harness.IO.writeFile(configPath, JSON.stringify(config));
|
||||
const child = fork(__filename, [`--config="${configPath}"`]);
|
||||
let currentTimeout = defaultTimeout;
|
||||
const killChild = () => {
|
||||
child.kill();
|
||||
console.error(`Worker exceeded ${currentTimeout}ms timeout ${child.currentTasks && child.currentTasks.length ? `while running test '${child.currentTasks[0].file}'.` : `during test setup.`}`);
|
||||
return process.exit(2);
|
||||
};
|
||||
let timer = setTimeout(killChild, currentTimeout);
|
||||
const timeoutStack: number[] = [];
|
||||
child.on("error", err => {
|
||||
console.error("Unexpected error in child process:");
|
||||
console.error(err);
|
||||
@@ -160,8 +175,25 @@ namespace Harness.Parallel.Host {
|
||||
Stack: ${data.payload.stack}`);
|
||||
return process.exit(2);
|
||||
}
|
||||
case "timeout": {
|
||||
clearTimeout(timer);
|
||||
if (data.payload.duration === "reset") {
|
||||
currentTimeout = timeoutStack.pop() || defaultTimeout;
|
||||
}
|
||||
else {
|
||||
timeoutStack.push(currentTimeout);
|
||||
currentTimeout = data.payload.duration;
|
||||
}
|
||||
timer = setTimeout(killChild, currentTimeout); // Reset timeout on timeout update, for when a timeout changes while a suite is executing
|
||||
break;
|
||||
}
|
||||
case "progress":
|
||||
case "result": {
|
||||
clearTimeout(timer);
|
||||
timer = setTimeout(killChild, currentTimeout);
|
||||
if (child.currentTasks) {
|
||||
child.currentTasks.shift();
|
||||
}
|
||||
totalPassing += data.payload.passing;
|
||||
if (data.payload.errors.length) {
|
||||
errorResults = errorResults.concat(data.payload.errors);
|
||||
@@ -195,6 +227,7 @@ namespace Harness.Parallel.Host {
|
||||
while (tasks.length && taskList.reduce((p, c) => p + c.size, 0) < chunkSize) {
|
||||
taskList.push(tasks.pop());
|
||||
}
|
||||
child.currentTasks = taskList;
|
||||
if (taskList.length === 1) {
|
||||
child.send({ type: "test", payload: taskList[0] });
|
||||
}
|
||||
@@ -252,18 +285,22 @@ namespace Harness.Parallel.Host {
|
||||
for (const worker of workers) {
|
||||
const payload = batches.pop();
|
||||
if (payload) {
|
||||
worker.currentTasks = payload;
|
||||
worker.send({ type: "batch", payload });
|
||||
}
|
||||
else { // Out of batches, send off just one test
|
||||
const payload = tasks.pop();
|
||||
ts.Debug.assert(!!payload); // The reserve kept above should ensure there is always an initial task available, even in suboptimal scenarios
|
||||
worker.currentTasks = [payload];
|
||||
worker.send({ type: "test", payload });
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (let i = 0; i < workerCount; i++) {
|
||||
workers[i].send({ type: "test", payload: tasks.pop() });
|
||||
const task = tasks.pop();
|
||||
workers[i].currentTasks = [task];
|
||||
workers[i].send({ type: "test", payload: task });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,5 +10,6 @@ namespace Harness.Parallel {
|
||||
export type ErrorInfo = ParallelErrorMessage["payload"] & { name: string[] };
|
||||
export type ParallelResultMessage = { type: "result", payload: { passing: number, errors: ErrorInfo[], duration: number, runner: TestRunnerKind | "unittest", file: string } } | never;
|
||||
export type ParallelBatchProgressMessage = { type: "progress", payload: ParallelResultMessage["payload"] } | never;
|
||||
export type ParallelClientMessage = ParallelErrorMessage | ParallelResultMessage | ParallelBatchProgressMessage;
|
||||
export type ParallelTimeoutChangeMessage = { type: "timeout", payload: { duration: number | "reset" } } | never;
|
||||
export type ParallelClientMessage = ParallelErrorMessage | ParallelResultMessage | ParallelBatchProgressMessage | ParallelTimeoutChangeMessage;
|
||||
}
|
||||
@@ -36,11 +36,28 @@ namespace Harness.Parallel.Worker {
|
||||
}) as Mocha.ITestDefinition;
|
||||
}
|
||||
|
||||
function setTimeoutAndExecute(timeout: number | undefined, f: () => void) {
|
||||
if (timeout !== undefined) {
|
||||
const timeoutMsg: ParallelTimeoutChangeMessage = { type: "timeout", payload: { duration: timeout } };
|
||||
process.send(timeoutMsg);
|
||||
}
|
||||
f();
|
||||
if (timeout !== undefined) {
|
||||
// Reset timeout
|
||||
const timeoutMsg: ParallelTimeoutChangeMessage = { type: "timeout", payload: { duration: "reset" } };
|
||||
process.send(timeoutMsg);
|
||||
}
|
||||
}
|
||||
|
||||
function executeSuiteCallback(name: string, callback: MochaCallback) {
|
||||
let timeout: number;
|
||||
const fakeContext: Mocha.ISuiteCallbackContext = {
|
||||
retries() { return this; },
|
||||
slow() { return this; },
|
||||
timeout() { return this; },
|
||||
timeout(n) {
|
||||
timeout = n as number;
|
||||
return this;
|
||||
},
|
||||
};
|
||||
namestack.push(name);
|
||||
let beforeFunc: Callable;
|
||||
@@ -71,7 +88,10 @@ namespace Harness.Parallel.Worker {
|
||||
finally {
|
||||
beforeFunc = undefined;
|
||||
}
|
||||
testList.forEach(({ name, callback, kind }) => executeCallback(name, callback, kind));
|
||||
|
||||
setTimeoutAndExecute(timeout, () => {
|
||||
testList.forEach(({ name, callback, kind }) => executeCallback(name, callback, kind));
|
||||
});
|
||||
|
||||
try {
|
||||
if (afterFunc) {
|
||||
@@ -103,9 +123,15 @@ namespace Harness.Parallel.Worker {
|
||||
}
|
||||
|
||||
function executeTestCallback(name: string, callback: MochaCallback) {
|
||||
let timeout: number;
|
||||
const fakeContext: Mocha.ITestCallbackContext = {
|
||||
skip() { return this; },
|
||||
timeout() { return this; },
|
||||
timeout(n) {
|
||||
timeout = n as number;
|
||||
const timeoutMsg: ParallelTimeoutChangeMessage = { type: "timeout", payload: { duration: timeout } };
|
||||
process.send(timeoutMsg);
|
||||
return this;
|
||||
},
|
||||
retries() { return this; },
|
||||
slow() { return this; },
|
||||
};
|
||||
@@ -131,6 +157,10 @@ namespace Harness.Parallel.Worker {
|
||||
}
|
||||
finally {
|
||||
namestack.pop();
|
||||
if (timeout !== undefined) {
|
||||
const timeoutMsg: ParallelTimeoutChangeMessage = { type: "timeout", payload: { duration: "reset" } };
|
||||
process.send(timeoutMsg);
|
||||
}
|
||||
}
|
||||
passing++;
|
||||
}
|
||||
@@ -157,6 +187,10 @@ namespace Harness.Parallel.Worker {
|
||||
}
|
||||
finally {
|
||||
namestack.pop();
|
||||
if (timeout !== undefined) {
|
||||
const timeoutMsg: ParallelTimeoutChangeMessage = { type: "timeout", payload: { duration: "reset" } };
|
||||
process.send(timeoutMsg);
|
||||
}
|
||||
}
|
||||
if (!completed) {
|
||||
errors.push({ error: "Test completes asynchronously, which is unsupported by the parallel harness", stack: "", name: [...namestack] });
|
||||
|
||||
@@ -186,7 +186,7 @@ class ProjectRunner extends RunnerBase {
|
||||
getCanonicalFileName: Harness.Compiler.getCanonicalFileName,
|
||||
useCaseSensitiveFileNames: () => Harness.IO.useCaseSensitiveFileNames(),
|
||||
getNewLine: () => Harness.IO.newLine(),
|
||||
fileExists: fileName => fileName === Harness.Compiler.defaultLibFileName || getSourceFileText(fileName) !== undefined,
|
||||
fileExists: fileName => fileName === Harness.Compiler.defaultLibFileName || getSourceFileText(fileName) !== undefined,
|
||||
readFile: fileName => Harness.IO.readFile(fileName),
|
||||
getDirectories: path => Harness.IO.getDirectories(path)
|
||||
};
|
||||
|
||||
@@ -100,6 +100,7 @@ interface TestConfig {
|
||||
runners?: string[];
|
||||
runUnitTests?: boolean;
|
||||
noColors?: boolean;
|
||||
timeout?: number;
|
||||
}
|
||||
|
||||
interface TaskSet {
|
||||
@@ -108,12 +109,16 @@ interface TaskSet {
|
||||
}
|
||||
|
||||
let configOption: string;
|
||||
let globalTimeout: number;
|
||||
function handleTestConfig() {
|
||||
if (testConfigContent !== "") {
|
||||
const testConfig = <TestConfig>JSON.parse(testConfigContent);
|
||||
if (testConfig.light) {
|
||||
Harness.lightMode = true;
|
||||
}
|
||||
if (testConfig.timeout) {
|
||||
globalTimeout = testConfig.timeout;
|
||||
}
|
||||
runUnitTests = testConfig.runUnitTests;
|
||||
if (testConfig.workerCount) {
|
||||
workerCount = +testConfig.workerCount;
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace ts {
|
||||
});
|
||||
});
|
||||
|
||||
function makeAssertChanges(getProgram: () => Program): (fileNames: ReadonlyArray<string>) => void {
|
||||
function makeAssertChanges(getProgram: () => Program): (fileNames: ReadonlyArray<string>) => void {
|
||||
const builder = createBuilder({
|
||||
getCanonicalFileName: identity,
|
||||
computeHash: identity
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace ts {
|
||||
assertParseResult(["--lib", "es5,invalidOption", "0.ts"],
|
||||
{
|
||||
errors: [{
|
||||
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'esnext.asynciterable', 'esnext.promise'.",
|
||||
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'esnext.array', 'esnext.asynciterable', 'esnext.promise'.",
|
||||
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
|
||||
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
|
||||
|
||||
@@ -263,7 +263,7 @@ namespace ts {
|
||||
assertParseResult(["--lib", "es5,", "es7", "0.ts"],
|
||||
{
|
||||
errors: [{
|
||||
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'esnext.asynciterable', 'esnext.promise'.",
|
||||
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'esnext.array', 'esnext.asynciterable', 'esnext.promise'.",
|
||||
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
|
||||
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
|
||||
|
||||
@@ -283,7 +283,7 @@ namespace ts {
|
||||
assertParseResult(["--lib", "es5, ", "es7", "0.ts"],
|
||||
{
|
||||
errors: [{
|
||||
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'esnext.asynciterable', 'esnext.promise'.",
|
||||
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'esnext.array', 'esnext.asynciterable', 'esnext.promise'.",
|
||||
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
|
||||
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
|
||||
|
||||
|
||||
@@ -266,7 +266,7 @@ namespace ts {
|
||||
file: undefined,
|
||||
start: 0,
|
||||
length: 0,
|
||||
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'esnext.asynciterable', 'esnext.promise'.",
|
||||
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'esnext.array', 'esnext.asynciterable', 'esnext.promise'.",
|
||||
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
|
||||
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
|
||||
}]
|
||||
@@ -297,7 +297,7 @@ namespace ts {
|
||||
file: undefined,
|
||||
start: 0,
|
||||
length: 0,
|
||||
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'esnext.asynciterable', 'esnext.promise'.",
|
||||
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'esnext.array', 'esnext.asynciterable', 'esnext.promise'.",
|
||||
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
|
||||
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
|
||||
}]
|
||||
@@ -328,7 +328,7 @@ namespace ts {
|
||||
file: undefined,
|
||||
start: 0,
|
||||
length: 0,
|
||||
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'esnext.asynciterable', 'esnext.promise'.",
|
||||
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'esnext.array', 'esnext.asynciterable', 'esnext.promise'.",
|
||||
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
|
||||
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
|
||||
}]
|
||||
@@ -359,7 +359,7 @@ namespace ts {
|
||||
file: undefined,
|
||||
start: 0,
|
||||
length: 0,
|
||||
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'esnext.asynciterable', 'esnext.promise'.",
|
||||
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'esnext.array', 'esnext.asynciterable', 'esnext.promise'.",
|
||||
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
|
||||
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
|
||||
}]
|
||||
|
||||
@@ -441,7 +441,7 @@ export = C;
|
||||
"/a/b/c.ts": `/// <reference path="d.ts"/>`,
|
||||
"/a/b/d.ts": "var x"
|
||||
});
|
||||
test(files, { module: ts.ModuleKind.AMD }, "/a/b", /*useCaseSensitiveFileNames*/ false, ["c.ts", "/a/b/d.ts"], []);
|
||||
test(files, { module: ts.ModuleKind.AMD }, "/a/b", /*useCaseSensitiveFileNames*/ false, ["c.ts", "/a/b/d.ts"], []);
|
||||
});
|
||||
|
||||
it("should fail when two files used in program differ only in casing (tripleslash references)", () => {
|
||||
@@ -449,7 +449,7 @@ export = C;
|
||||
"/a/b/c.ts": `/// <reference path="D.ts"/>`,
|
||||
"/a/b/d.ts": "var x"
|
||||
});
|
||||
test(files, { module: ts.ModuleKind.AMD, forceConsistentCasingInFileNames: true }, "/a/b", /*useCaseSensitiveFileNames*/ false, ["c.ts", "d.ts"], [1149]);
|
||||
test(files, { module: ts.ModuleKind.AMD, forceConsistentCasingInFileNames: true }, "/a/b", /*useCaseSensitiveFileNames*/ false, ["c.ts", "d.ts"], [1149]);
|
||||
});
|
||||
|
||||
it("should fail when two files used in program differ only in casing (imports)", () => {
|
||||
@@ -457,7 +457,7 @@ export = C;
|
||||
"/a/b/c.ts": `import {x} from "D"`,
|
||||
"/a/b/d.ts": "export var x"
|
||||
});
|
||||
test(files, { module: ts.ModuleKind.AMD, forceConsistentCasingInFileNames: true }, "/a/b", /*useCaseSensitiveFileNames*/ false, ["c.ts", "d.ts"], [1149]);
|
||||
test(files, { module: ts.ModuleKind.AMD, forceConsistentCasingInFileNames: true }, "/a/b", /*useCaseSensitiveFileNames*/ false, ["c.ts", "d.ts"], [1149]);
|
||||
});
|
||||
|
||||
it("should fail when two files used in program differ only in casing (imports, relative module names)", () => {
|
||||
@@ -465,7 +465,7 @@ export = C;
|
||||
"moduleA.ts": `import {x} from "./ModuleB"`,
|
||||
"moduleB.ts": "export var x"
|
||||
});
|
||||
test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "", /*useCaseSensitiveFileNames*/ false, ["moduleA.ts", "moduleB.ts"], [1149]);
|
||||
test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "", /*useCaseSensitiveFileNames*/ false, ["moduleA.ts", "moduleB.ts"], [1149]);
|
||||
});
|
||||
|
||||
it("should fail when two files exist on disk that differs only in casing", () => {
|
||||
@@ -474,7 +474,7 @@ export = C;
|
||||
"/a/b/D.ts": "export var x",
|
||||
"/a/b/d.ts": "export var y"
|
||||
});
|
||||
test(files, { module: ts.ModuleKind.AMD }, "/a/b", /*useCaseSensitiveFileNames*/ true, ["c.ts", "d.ts"], [1149]);
|
||||
test(files, { module: ts.ModuleKind.AMD }, "/a/b", /*useCaseSensitiveFileNames*/ true, ["c.ts", "d.ts"], [1149]);
|
||||
});
|
||||
|
||||
it("should fail when module name in 'require' calls has inconsistent casing", () => {
|
||||
@@ -483,7 +483,7 @@ export = C;
|
||||
"moduleB.ts": `import a = require("./moduleC")`,
|
||||
"moduleC.ts": "export var x"
|
||||
});
|
||||
test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "", /*useCaseSensitiveFileNames*/ false, ["moduleA.ts", "moduleB.ts", "moduleC.ts"], [1149, 1149]);
|
||||
test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "", /*useCaseSensitiveFileNames*/ false, ["moduleA.ts", "moduleB.ts", "moduleC.ts"], [1149, 1149]);
|
||||
});
|
||||
|
||||
it("should fail when module names in 'require' calls has inconsistent casing and current directory has uppercase chars", () => {
|
||||
@@ -496,7 +496,7 @@ import a = require("./moduleA");
|
||||
import b = require("./moduleB");
|
||||
`
|
||||
});
|
||||
test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "/a/B/c", /*useCaseSensitiveFileNames*/ false, ["moduleD.ts"], [1149]);
|
||||
test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "/a/B/c", /*useCaseSensitiveFileNames*/ false, ["moduleD.ts"], [1149]);
|
||||
});
|
||||
it("should not fail when module names in 'require' calls has consistent casing and current directory has uppercase chars", () => {
|
||||
const files = createMapFromTemplate({
|
||||
@@ -508,7 +508,7 @@ import a = require("./moduleA");
|
||||
import b = require("./moduleB");
|
||||
`
|
||||
});
|
||||
test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "/a/B/c", /*useCaseSensitiveFileNames*/ false, ["moduleD.ts"], []);
|
||||
test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "/a/B/c", /*useCaseSensitiveFileNames*/ false, ["moduleD.ts"], []);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1302,13 +1302,13 @@ namespace ts.projectSystem {
|
||||
service.checkNumberOfProjects({ externalProjects: 1 });
|
||||
checkProjectActualFiles(service.externalProjects[0], [f1.path, f2.path, libFile.path]);
|
||||
|
||||
const completions1 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 2, { includeExternalModuleExports: false });
|
||||
const completions1 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 2, { includeExternalModuleExports: false, includeInsertTextCompletions: false });
|
||||
// should contain completions for string
|
||||
assert.isTrue(completions1.entries.some(e => e.name === "charAt"), "should contain 'charAt'");
|
||||
assert.isFalse(completions1.entries.some(e => e.name === "toExponential"), "should not contain 'toExponential'");
|
||||
|
||||
service.closeClientFile(f2.path);
|
||||
const completions2 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 2, { includeExternalModuleExports: false });
|
||||
const completions2 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 2, { includeExternalModuleExports: false, includeInsertTextCompletions: false });
|
||||
// should contain completions for string
|
||||
assert.isFalse(completions2.entries.some(e => e.name === "charAt"), "should not contain 'charAt'");
|
||||
assert.isTrue(completions2.entries.some(e => e.name === "toExponential"), "should contain 'toExponential'");
|
||||
@@ -1334,11 +1334,11 @@ namespace ts.projectSystem {
|
||||
service.checkNumberOfProjects({ externalProjects: 1 });
|
||||
checkProjectActualFiles(service.externalProjects[0], [f1.path, f2.path, libFile.path]);
|
||||
|
||||
const completions1 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 0, { includeExternalModuleExports: false });
|
||||
const completions1 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 0, { includeExternalModuleExports: false, includeInsertTextCompletions: false });
|
||||
assert.isTrue(completions1.entries.some(e => e.name === "somelongname"), "should contain 'somelongname'");
|
||||
|
||||
service.closeClientFile(f2.path);
|
||||
const completions2 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 0, { includeExternalModuleExports: false });
|
||||
const completions2 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 0, { includeExternalModuleExports: false, includeInsertTextCompletions: false });
|
||||
assert.isFalse(completions2.entries.some(e => e.name === "somelongname"), "should not contain 'somelongname'");
|
||||
const sf2 = service.externalProjects[0].getLanguageService().getProgram().getSourceFile(f2.path);
|
||||
assert.equal(sf2.text, "");
|
||||
@@ -1943,7 +1943,7 @@ namespace ts.projectSystem {
|
||||
|
||||
// Check identifiers defined in HTML content are available in .ts file
|
||||
const project = configuredProjectAt(projectService, 0);
|
||||
let completions = project.getLanguageService().getCompletionsAtPosition(file1.path, 1, { includeExternalModuleExports: false });
|
||||
let completions = project.getLanguageService().getCompletionsAtPosition(file1.path, 1, { includeExternalModuleExports: false, includeInsertTextCompletions: false });
|
||||
assert(completions && completions.entries[0].name === "hello", `expected entry hello to be in completion list`);
|
||||
|
||||
// Close HTML file
|
||||
@@ -1957,7 +1957,7 @@ namespace ts.projectSystem {
|
||||
checkProjectActualFiles(configuredProjectAt(projectService, 0), [file1.path, file2.path, config.path]);
|
||||
|
||||
// Check identifiers defined in HTML content are not available in .ts file
|
||||
completions = project.getLanguageService().getCompletionsAtPosition(file1.path, 5, { includeExternalModuleExports: false });
|
||||
completions = project.getLanguageService().getCompletionsAtPosition(file1.path, 5, { includeExternalModuleExports: false, includeInsertTextCompletions: false });
|
||||
assert(completions && completions.entries[0].name !== "hello", `unexpected hello entry in completion list`);
|
||||
});
|
||||
|
||||
|
||||
@@ -162,7 +162,7 @@ namespace Utils {
|
||||
/**
|
||||
* Reads the directory at the given path and retrieves a list of file names and a list
|
||||
* of directory names within it. Suitable for use with ts.matchFiles()
|
||||
* @param path The path to the directory to be read
|
||||
* @param path The path to the directory to be read
|
||||
*/
|
||||
getAccessibleFileSystemEntries(path: string) {
|
||||
const entry = this.traversePath(path);
|
||||
|
||||
Vendored
+110
-25
@@ -761,7 +761,7 @@ interface ProgressEventInit extends EventInit {
|
||||
}
|
||||
|
||||
interface PushSubscriptionOptionsInit {
|
||||
applicationServerKey?: any;
|
||||
applicationServerKey?: BufferSource | null;
|
||||
userVisibleOnly?: boolean;
|
||||
}
|
||||
|
||||
@@ -770,7 +770,8 @@ interface RegistrationOptions {
|
||||
}
|
||||
|
||||
interface RequestInit {
|
||||
body?: any;
|
||||
signal?: AbortSignal;
|
||||
body?: Blob | BufferSource | FormData | string | null;
|
||||
cache?: RequestCache;
|
||||
credentials?: RequestCredentials;
|
||||
headers?: HeadersInit;
|
||||
@@ -1088,7 +1089,7 @@ interface RTCTransportStats extends RTCStats {
|
||||
}
|
||||
|
||||
interface ScopedCredentialDescriptor {
|
||||
id: any;
|
||||
id: BufferSource;
|
||||
transports?: Transport[];
|
||||
type: ScopedCredentialType;
|
||||
}
|
||||
@@ -3596,11 +3597,11 @@ interface Element extends Node, GlobalEventHandlers, ElementTraversal, NodeSelec
|
||||
slot: string;
|
||||
readonly shadowRoot: ShadowRoot | null;
|
||||
getAttribute(name: string): string | null;
|
||||
getAttributeNode(name: string): Attr;
|
||||
getAttributeNodeNS(namespaceURI: string, localName: string): Attr;
|
||||
getAttributeNode(name: string): Attr | null;
|
||||
getAttributeNodeNS(namespaceURI: string, localName: string): Attr | null;
|
||||
getAttributeNS(namespaceURI: string, localName: string): string;
|
||||
getBoundingClientRect(): ClientRect;
|
||||
getClientRects(): ClientRectList;
|
||||
getBoundingClientRect(): ClientRect | DOMRect;
|
||||
getClientRects(): ClientRectList | DOMRectList;
|
||||
getElementsByTagName<K extends keyof HTMLElementTagNameMap>(name: K): NodeListOf<HTMLElementTagNameMap[K]>;
|
||||
getElementsByTagName<K extends keyof SVGElementTagNameMap>(name: K): NodeListOf<SVGElementTagNameMap[K]>;
|
||||
getElementsByTagName(name: string): NodeListOf<Element>;
|
||||
@@ -3757,9 +3758,10 @@ declare var External: {
|
||||
};
|
||||
|
||||
interface File extends Blob {
|
||||
readonly lastModifiedDate: any;
|
||||
readonly lastModifiedDate: Date;
|
||||
readonly name: string;
|
||||
readonly webkitRelativePath: string;
|
||||
readonly lastModified: number;
|
||||
}
|
||||
|
||||
declare var File: {
|
||||
@@ -4897,6 +4899,7 @@ interface HTMLFormElement extends HTMLElement {
|
||||
*/
|
||||
submit(): void;
|
||||
reportValidity(): boolean;
|
||||
reportValidity(): boolean;
|
||||
addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLFormElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
|
||||
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
|
||||
removeEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLFormElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
|
||||
@@ -5200,6 +5203,10 @@ interface HTMLIFrameElement extends HTMLElement, GetSVGDocument {
|
||||
* Sets or retrieves the width of the object.
|
||||
*/
|
||||
width: string;
|
||||
/**
|
||||
* Sets or retrives the content of the page that is to contain.
|
||||
*/
|
||||
srcdoc: string;
|
||||
addEventListener<K extends keyof HTMLIFrameElementEventMap>(type: K, listener: (this: HTMLIFrameElement, ev: HTMLIFrameElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
|
||||
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
|
||||
removeEventListener<K extends keyof HTMLIFrameElementEventMap>(type: K, listener: (this: HTMLIFrameElement, ev: HTMLIFrameElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
|
||||
@@ -5495,8 +5502,9 @@ interface HTMLInputElement extends HTMLElement {
|
||||
* Sets the start and end positions of a selection in a text field.
|
||||
* @param start The offset into the text field for the start of the selection.
|
||||
* @param end The offset into the text field for the end of the selection.
|
||||
* @param direction The direction in which the selection is performed.
|
||||
*/
|
||||
setSelectionRange(start?: number, end?: number, direction?: string): void;
|
||||
setSelectionRange(start: number, end: number, direction?: "forward" | "backward" | "none"): void;
|
||||
/**
|
||||
* Decrements a range input control's value by the value given by the Step attribute. If the optional parameter is used, it will decrement the input control's step value multiplied by the parameter's value.
|
||||
* @param n Value to decrement the value by.
|
||||
@@ -6057,6 +6065,7 @@ interface HTMLObjectElement extends HTMLElement, GetSVGDocument {
|
||||
* Returns whether an element will successfully validate based on forms validation rules and constraints.
|
||||
*/
|
||||
readonly willValidate: boolean;
|
||||
typemustmatch: boolean;
|
||||
/**
|
||||
* Returns whether a form will validate when it is submitted, without having to submit it.
|
||||
*/
|
||||
@@ -6958,8 +6967,9 @@ interface HTMLTextAreaElement extends HTMLElement {
|
||||
* Sets the start and end positions of a selection in a text field.
|
||||
* @param start The offset into the text field for the start of the selection.
|
||||
* @param end The offset into the text field for the end of the selection.
|
||||
* @param direction The direction in which the selection is performed.
|
||||
*/
|
||||
setSelectionRange(start: number, end: number): void;
|
||||
setSelectionRange(start: number, end: number, direction?: "forward" | "backward" | "none"): void;
|
||||
addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLTextAreaElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
|
||||
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
|
||||
removeEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLTextAreaElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
|
||||
@@ -7362,10 +7372,10 @@ declare var IntersectionObserver: {
|
||||
};
|
||||
|
||||
interface IntersectionObserverEntry {
|
||||
readonly boundingClientRect: ClientRect;
|
||||
readonly boundingClientRect: ClientRect | DOMRect;
|
||||
readonly intersectionRatio: number;
|
||||
readonly intersectionRect: ClientRect;
|
||||
readonly rootBounds: ClientRect;
|
||||
readonly intersectionRect: ClientRect | DOMRect;
|
||||
readonly rootBounds: ClientRect | DOMRect;
|
||||
readonly target: Element;
|
||||
readonly time: number;
|
||||
readonly isIntersecting: boolean;
|
||||
@@ -7534,7 +7544,7 @@ declare var MediaKeyMessageEvent: {
|
||||
|
||||
interface MediaKeys {
|
||||
createSession(sessionType?: MediaKeySessionType): MediaKeySession;
|
||||
setServerCertificate(serverCertificate: any): Promise<void>;
|
||||
setServerCertificate(serverCertificate: BufferSource): Promise<void>;
|
||||
}
|
||||
|
||||
declare var MediaKeys: {
|
||||
@@ -7548,10 +7558,10 @@ interface MediaKeySession extends EventTarget {
|
||||
readonly keyStatuses: MediaKeyStatusMap;
|
||||
readonly sessionId: string;
|
||||
close(): Promise<void>;
|
||||
generateRequest(initDataType: string, initData: any): Promise<void>;
|
||||
generateRequest(initDataType: string, initData: BufferSource): Promise<void>;
|
||||
load(sessionId: string): Promise<boolean>;
|
||||
remove(): Promise<void>;
|
||||
update(response: any): Promise<void>;
|
||||
update(response: BufferSource): Promise<void>;
|
||||
}
|
||||
|
||||
declare var MediaKeySession: {
|
||||
@@ -7562,8 +7572,8 @@ declare var MediaKeySession: {
|
||||
interface MediaKeyStatusMap {
|
||||
readonly size: number;
|
||||
forEach(callback: ForEachCallback): void;
|
||||
get(keyId: any): MediaKeyStatus;
|
||||
has(keyId: any): boolean;
|
||||
get(keyId: BufferSource): MediaKeyStatus;
|
||||
has(keyId: BufferSource): boolean;
|
||||
}
|
||||
|
||||
declare var MediaKeyStatusMap: {
|
||||
@@ -9163,8 +9173,8 @@ interface Range {
|
||||
detach(): void;
|
||||
expand(Unit: ExpandGranularity): boolean;
|
||||
extractContents(): DocumentFragment;
|
||||
getBoundingClientRect(): ClientRect;
|
||||
getClientRects(): ClientRectList;
|
||||
getBoundingClientRect(): ClientRect | DOMRect;
|
||||
getClientRects(): ClientRectList | DOMRectList;
|
||||
insertNode(newNode: Node): void;
|
||||
selectNode(refNode: Node): void;
|
||||
selectNodeContents(refNode: Node): void;
|
||||
@@ -9227,6 +9237,7 @@ interface Request extends Object, Body {
|
||||
readonly referrerPolicy: ReferrerPolicy;
|
||||
readonly type: RequestType;
|
||||
readonly url: string;
|
||||
readonly signal: AbortSignal;
|
||||
clone(): Request;
|
||||
}
|
||||
|
||||
@@ -12213,7 +12224,7 @@ interface URL {
|
||||
|
||||
declare var URL: {
|
||||
prototype: URL;
|
||||
new(url: string, base?: string): URL;
|
||||
new(url: string, base?: string | URL): URL;
|
||||
createObjectURL(object: any, options?: ObjectURLOptions): string;
|
||||
revokeObjectURL(url: string): void;
|
||||
};
|
||||
@@ -12301,8 +12312,8 @@ declare var WaveShaperNode: {
|
||||
};
|
||||
|
||||
interface WebAuthentication {
|
||||
getAssertion(assertionChallenge: any, options?: AssertionOptions): Promise<WebAuthnAssertion>;
|
||||
makeCredential(accountInformation: Account, cryptoParameters: ScopedCredentialParameters[], attestationChallenge: any, options?: ScopedCredentialOptions): Promise<ScopedCredentialInfo>;
|
||||
getAssertion(assertionChallenge: BufferSource, options?: AssertionOptions): Promise<WebAuthnAssertion>;
|
||||
makeCredential(accountInformation: Account, cryptoParameters: ScopedCredentialParameters[], attestationChallenge: BufferSource, options?: ScopedCredentialOptions): Promise<ScopedCredentialInfo>;
|
||||
}
|
||||
|
||||
declare var WebAuthentication: {
|
||||
@@ -14657,6 +14668,23 @@ declare var HTMLSummaryElement: {
|
||||
new(): HTMLSummaryElement;
|
||||
};
|
||||
|
||||
interface DOMRectReadOnly {
|
||||
readonly bottom: number;
|
||||
readonly height: number;
|
||||
readonly left: number;
|
||||
readonly right: number;
|
||||
readonly top: number;
|
||||
readonly width: number;
|
||||
readonly x: number;
|
||||
readonly y: number;
|
||||
}
|
||||
|
||||
declare var DOMRectReadOnly: {
|
||||
prototype: DOMRectReadOnly;
|
||||
new (x?: number, y?: number, width?: number, height?: number): DOMRectReadOnly;
|
||||
fromRect(rectangle?: DOMRectInit): DOMRectReadOnly;
|
||||
};
|
||||
|
||||
interface EXT_blend_minmax {
|
||||
readonly MIN_EXT: number;
|
||||
readonly MAX_EXT: number;
|
||||
@@ -14675,6 +14703,25 @@ interface EXT_sRGB {
|
||||
readonly FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT: number;
|
||||
}
|
||||
|
||||
interface DOMRect extends DOMRectReadOnly {
|
||||
height: number;
|
||||
width: number;
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
|
||||
declare var DOMRect: {
|
||||
prototype: DOMRect;
|
||||
new (x?: number, y?: number, width?: number, height?: number): DOMRect;
|
||||
fromRect(rectangle?: DOMRectInit): DOMRect;
|
||||
};
|
||||
|
||||
interface DOMRectList {
|
||||
readonly length: number;
|
||||
item(index: number): DOMRect | null;
|
||||
[index: number]: DOMRect;
|
||||
}
|
||||
|
||||
interface OES_vertex_array_object {
|
||||
readonly VERTEX_ARRAY_BINDING_OES: number;
|
||||
createVertexArrayOES(): WebGLVertexArrayObjectOES;
|
||||
@@ -14779,6 +14826,43 @@ interface WEBGL_lose_context {
|
||||
restoreContext(): void;
|
||||
}
|
||||
|
||||
interface AbortController {
|
||||
readonly signal: AbortSignal;
|
||||
abort(): void;
|
||||
}
|
||||
|
||||
declare var AbortController: {
|
||||
prototype: AbortController;
|
||||
new(): AbortController;
|
||||
};
|
||||
|
||||
interface AbortSignal extends EventTarget {
|
||||
readonly aborted: boolean;
|
||||
onabort: (ev: Event) => any;
|
||||
}
|
||||
|
||||
interface EventSource extends EventTarget {
|
||||
readonly url: string;
|
||||
readonly withCredentials: boolean;
|
||||
readonly CONNECTING: number;
|
||||
readonly OPEN: number;
|
||||
readonly CLOSED: number;
|
||||
readonly readyState: number;
|
||||
onopen: (evt: MessageEvent) => any;
|
||||
onmessage: (evt: MessageEvent) => any;
|
||||
onerror: (evt: MessageEvent) => any;
|
||||
close(): void;
|
||||
}
|
||||
|
||||
declare var EventSource: {
|
||||
prototype: EventSource;
|
||||
new(url: string, eventSourceInitDict?: EventSourceInit): EventSource;
|
||||
};
|
||||
|
||||
interface EventSourceInit {
|
||||
readonly withCredentials: boolean;
|
||||
}
|
||||
|
||||
declare type EventListenerOrEventListenerObject = EventListener | EventListenerObject;
|
||||
|
||||
interface DecodeErrorCallback {
|
||||
@@ -14791,7 +14875,7 @@ interface ErrorEventHandler {
|
||||
(message: string, filename?: string, lineno?: number, colno?: number, error?: Error): void;
|
||||
}
|
||||
interface ForEachCallback {
|
||||
(keyId: any, status: MediaKeyStatus): void;
|
||||
(keyId: BufferSource, status: MediaKeyStatus): void;
|
||||
}
|
||||
interface FrameRequestCallback {
|
||||
(time: number): void;
|
||||
@@ -15029,6 +15113,7 @@ interface SVGElementTagNameMap {
|
||||
"view": SVGViewElement;
|
||||
}
|
||||
|
||||
/** @deprecated Directly use HTMLElementTagNameMap or SVGElementTagNameMap as appropriate, instead. */
|
||||
interface ElementTagNameMap extends HTMLElementTagNameMap, SVGElementTagNameMap { }
|
||||
|
||||
declare var Audio: { new(src?: string): HTMLAudioElement; };
|
||||
@@ -15246,7 +15331,7 @@ declare function removeEventListener<K extends keyof WindowEventMap>(type: K, li
|
||||
declare function removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
|
||||
type AAGUID = string;
|
||||
type AlgorithmIdentifier = string | Algorithm;
|
||||
type BodyInit = any;
|
||||
type BodyInit = Blob | BufferSource | FormData | string;
|
||||
type ByteString = string;
|
||||
type ConstrainBoolean = boolean | ConstrainBooleanParameters;
|
||||
type ConstrainDOMString = string | string[] | ConstrainDOMStringParameters;
|
||||
|
||||
Vendored
+4
-4
@@ -10,7 +10,7 @@ interface Map<K, V> {
|
||||
|
||||
interface MapConstructor {
|
||||
new (): Map<any, any>;
|
||||
new <K, V>(entries?: [K, V][]): Map<K, V>;
|
||||
new <K, V>(entries?: ReadonlyArray<[K, V]>): Map<K, V>;
|
||||
readonly prototype: Map<any, any>;
|
||||
}
|
||||
declare var Map: MapConstructor;
|
||||
@@ -31,7 +31,7 @@ interface WeakMap<K extends object, V> {
|
||||
|
||||
interface WeakMapConstructor {
|
||||
new (): WeakMap<object, any>;
|
||||
new <K extends object, V>(entries?: [K, V][]): WeakMap<K, V>;
|
||||
new <K extends object, V>(entries?: ReadonlyArray<[K, V]>): WeakMap<K, V>;
|
||||
readonly prototype: WeakMap<object, any>;
|
||||
}
|
||||
declare var WeakMap: WeakMapConstructor;
|
||||
@@ -47,7 +47,7 @@ interface Set<T> {
|
||||
|
||||
interface SetConstructor {
|
||||
new (): Set<any>;
|
||||
new <T>(values?: T[]): Set<T>;
|
||||
new <T>(values?: ReadonlyArray<T>): Set<T>;
|
||||
readonly prototype: Set<any>;
|
||||
}
|
||||
declare var Set: SetConstructor;
|
||||
@@ -66,7 +66,7 @@ interface WeakSet<T> {
|
||||
|
||||
interface WeakSetConstructor {
|
||||
new (): WeakSet<object>;
|
||||
new <T extends object>(values?: T[]): WeakSet<T>;
|
||||
new <T extends object>(values?: ReadonlyArray<T>): WeakSet<T>;
|
||||
readonly prototype: WeakSet<object>;
|
||||
}
|
||||
declare var WeakSet: WeakSetConstructor;
|
||||
|
||||
Vendored
+3
-2
@@ -118,8 +118,9 @@ interface Math {
|
||||
log1p(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the result of (e^x - 1) of x (e raised to the power of x, where e is the base of
|
||||
* the natural logarithms).
|
||||
* Returns the result of (e^x - 1), which is an implementation-dependent approximation to
|
||||
* subtracting 1 from the exponential function of x (e raised to the power of x, where e
|
||||
* is the base of the natural logarithms).
|
||||
* @param x A numeric expression.
|
||||
*/
|
||||
expm1(x: number): number;
|
||||
|
||||
Vendored
+2
-2
@@ -9,7 +9,7 @@ interface ObjectConstructor {
|
||||
* Returns an array of values of the enumerable properties of an object
|
||||
* @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
|
||||
*/
|
||||
values(o: any): any[];
|
||||
values(o: {}): any[];
|
||||
|
||||
/**
|
||||
* Returns an array of key/values of the enumerable properties of an object
|
||||
@@ -21,7 +21,7 @@ interface ObjectConstructor {
|
||||
* Returns an array of key/values of the enumerable properties of an object
|
||||
* @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
|
||||
*/
|
||||
entries(o: any): [string, any][];
|
||||
entries(o: {}): [string, any][];
|
||||
|
||||
/**
|
||||
* Returns an object containing all own property descriptors of an object
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
/// <reference path="lib.es2017.d.ts" />
|
||||
/// <reference path="lib.es2017.d.ts" />
|
||||
|
||||
Vendored
+203
@@ -0,0 +1,203 @@
|
||||
interface ReadonlyArray<T> {
|
||||
|
||||
/**
|
||||
* Calls a defined callback function on each element of an array. Then, flattens the result into
|
||||
* a new array.
|
||||
* This is identical to a map followed by a flatten of depth 1.
|
||||
*
|
||||
* @param callback A function that accepts up to three arguments. The flatMap method calls the
|
||||
* callback function one time for each element in the array.
|
||||
* @param thisArg An object to which the this keyword can refer in the callback function. If
|
||||
* thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
flatMap<U, This = undefined> (
|
||||
callback: (this: This, value: T, index: number, array: T[]) => U|U[],
|
||||
thisArg?: This
|
||||
): U[]
|
||||
|
||||
|
||||
/**
|
||||
* Returns a new array with all sub-array elements concatenated into it recursively up to the
|
||||
* specified depth.
|
||||
*
|
||||
* @param depth The maximum recursion depth
|
||||
*/
|
||||
flatten<U>(this:
|
||||
ReadonlyArray<U[][][][]> |
|
||||
|
||||
ReadonlyArray<ReadonlyArray<U[][][]>> |
|
||||
ReadonlyArray<ReadonlyArray<U[][]>[]> |
|
||||
ReadonlyArray<ReadonlyArray<U[]>[][]> |
|
||||
ReadonlyArray<ReadonlyArray<U>[][][]> |
|
||||
|
||||
ReadonlyArray<ReadonlyArray<ReadonlyArray<U[][]>>> |
|
||||
ReadonlyArray<ReadonlyArray<ReadonlyArray<U>[][]>> |
|
||||
ReadonlyArray<ReadonlyArray<ReadonlyArray<U>>[][]> |
|
||||
ReadonlyArray<ReadonlyArray<ReadonlyArray<U>[]>[]> |
|
||||
ReadonlyArray<ReadonlyArray<ReadonlyArray<U[]>>[]> |
|
||||
ReadonlyArray<ReadonlyArray<ReadonlyArray<U[]>[]>> |
|
||||
|
||||
ReadonlyArray<ReadonlyArray<ReadonlyArray<ReadonlyArray<U[]>>>> |
|
||||
ReadonlyArray<ReadonlyArray<ReadonlyArray<ReadonlyArray<U>[]>>> |
|
||||
ReadonlyArray<ReadonlyArray<ReadonlyArray<ReadonlyArray<U>>[]>> |
|
||||
ReadonlyArray<ReadonlyArray<ReadonlyArray<ReadonlyArray<U>>>[]> |
|
||||
|
||||
ReadonlyArray<ReadonlyArray<ReadonlyArray<ReadonlyArray<ReadonlyArray<U>>>>>,
|
||||
depth: 4): U[];
|
||||
|
||||
/**
|
||||
* Returns a new array with all sub-array elements concatenated into it recursively up to the
|
||||
* specified depth.
|
||||
*
|
||||
* @param depth The maximum recursion depth
|
||||
*/
|
||||
flatten<U>(this:
|
||||
ReadonlyArray<U[][][]> |
|
||||
|
||||
ReadonlyArray<ReadonlyArray<U>[][]> |
|
||||
ReadonlyArray<ReadonlyArray<U[]>[]> |
|
||||
ReadonlyArray<ReadonlyArray<U[][]>> |
|
||||
|
||||
ReadonlyArray<ReadonlyArray<ReadonlyArray<U[]>>> |
|
||||
ReadonlyArray<ReadonlyArray<ReadonlyArray<U>[]>> |
|
||||
ReadonlyArray<ReadonlyArray<ReadonlyArray<U>>[]> |
|
||||
|
||||
ReadonlyArray<ReadonlyArray<ReadonlyArray<ReadonlyArray<U>>>>,
|
||||
depth: 3): U[];
|
||||
|
||||
/**
|
||||
* Returns a new array with all sub-array elements concatenated into it recursively up to the
|
||||
* specified depth.
|
||||
*
|
||||
* @param depth The maximum recursion depth
|
||||
*/
|
||||
flatten<U>(this:
|
||||
ReadonlyArray<U[][]> |
|
||||
|
||||
ReadonlyArray<ReadonlyArray<U[]>> |
|
||||
ReadonlyArray<ReadonlyArray<U>[]> |
|
||||
|
||||
ReadonlyArray<ReadonlyArray<ReadonlyArray<U>>>,
|
||||
depth: 2): U[];
|
||||
|
||||
/**
|
||||
* Returns a new array with all sub-array elements concatenated into it recursively up to the
|
||||
* specified depth.
|
||||
*
|
||||
* @param depth The maximum recursion depth
|
||||
*/
|
||||
flatten<U>(this:
|
||||
ReadonlyArray<U[]> |
|
||||
ReadonlyArray<ReadonlyArray<U>>,
|
||||
depth?: 1
|
||||
): U[];
|
||||
|
||||
/**
|
||||
* Returns a new array with all sub-array elements concatenated into it recursively up to the
|
||||
* specified depth.
|
||||
*
|
||||
* @param depth The maximum recursion depth
|
||||
*/
|
||||
flatten<U>(this:
|
||||
ReadonlyArray<U>,
|
||||
depth: 0
|
||||
): U[];
|
||||
|
||||
/**
|
||||
* Returns a new array with all sub-array elements concatenated into it recursively up to the
|
||||
* specified depth. If no depth is provided, flatten method defaults to the depth of 1.
|
||||
*
|
||||
* @param depth The maximum recursion depth
|
||||
*/
|
||||
flatten<U>(depth?: number): any[];
|
||||
}
|
||||
|
||||
interface Array<T> {
|
||||
|
||||
/**
|
||||
* Calls a defined callback function on each element of an array. Then, flattens the result into
|
||||
* a new array.
|
||||
* This is identical to a map followed by a flatten of depth 1.
|
||||
*
|
||||
* @param callback A function that accepts up to three arguments. The flatMap method calls the
|
||||
* callback function one time for each element in the array.
|
||||
* @param thisArg An object to which the this keyword can refer in the callback function. If
|
||||
* thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
flatMap<U, This = undefined> (
|
||||
callback: (this: This, value: T, index: number, array: T[]) => U|U[],
|
||||
thisArg?: This
|
||||
): U[]
|
||||
|
||||
/**
|
||||
* Returns a new array with all sub-array elements concatenated into it recursively up to the
|
||||
* specified depth.
|
||||
*
|
||||
* @param depth The maximum recursion depth
|
||||
*/
|
||||
flatten<U>(this: U[][][][][][][][], depth: 7): U[];
|
||||
|
||||
/**
|
||||
* Returns a new array with all sub-array elements concatenated into it recursively up to the
|
||||
* specified depth.
|
||||
*
|
||||
* @param depth The maximum recursion depth
|
||||
*/
|
||||
flatten<U>(this: U[][][][][][][], depth: 6): U[];
|
||||
|
||||
/**
|
||||
* Returns a new array with all sub-array elements concatenated into it recursively up to the
|
||||
* specified depth.
|
||||
*
|
||||
* @param depth The maximum recursion depth
|
||||
*/
|
||||
flatten<U>(this: U[][][][][][], depth: 5): U[];
|
||||
|
||||
/**
|
||||
* Returns a new array with all sub-array elements concatenated into it recursively up to the
|
||||
* specified depth.
|
||||
*
|
||||
* @param depth The maximum recursion depth
|
||||
*/
|
||||
flatten<U>(this: U[][][][][], depth: 4): U[];
|
||||
|
||||
/**
|
||||
* Returns a new array with all sub-array elements concatenated into it recursively up to the
|
||||
* specified depth.
|
||||
*
|
||||
* @param depth The maximum recursion depth
|
||||
*/
|
||||
flatten<U>(this: U[][][][], depth: 3): U[];
|
||||
|
||||
/**
|
||||
* Returns a new array with all sub-array elements concatenated into it recursively up to the
|
||||
* specified depth.
|
||||
*
|
||||
* @param depth The maximum recursion depth
|
||||
*/
|
||||
flatten<U>(this: U[][][], depth: 2): U[];
|
||||
|
||||
/**
|
||||
* Returns a new array with all sub-array elements concatenated into it recursively up to the
|
||||
* specified depth.
|
||||
*
|
||||
* @param depth The maximum recursion depth
|
||||
*/
|
||||
flatten<U>(this: U[][], depth?: 1): U[];
|
||||
|
||||
/**
|
||||
* Returns a new array with all sub-array elements concatenated into it recursively up to the
|
||||
* specified depth.
|
||||
*
|
||||
* @param depth The maximum recursion depth
|
||||
*/
|
||||
flatten<U>(this: U[], depth: 0): U[];
|
||||
|
||||
/**
|
||||
* Returns a new array with all sub-array elements concatenated into it recursively up to the
|
||||
* specified depth. If no depth is provided, flatten method defaults to the depth of 1.
|
||||
*
|
||||
* @param depth The maximum recursion depth
|
||||
*/
|
||||
flatten<U>(depth?: number): any[];
|
||||
}
|
||||
Vendored
+1
@@ -1,3 +1,4 @@
|
||||
/// <reference path="lib.es2018.d.ts" />
|
||||
/// <reference path="lib.esnext.asynciterable.d.ts" />
|
||||
/// <reference path="lib.esnext.array.d.ts" />
|
||||
/// <reference path="lib.esnext.promise.d.ts" />
|
||||
|
||||
Vendored
+47
-7
@@ -66,12 +66,13 @@ interface ObjectURLOptions {
|
||||
}
|
||||
|
||||
interface PushSubscriptionOptionsInit {
|
||||
applicationServerKey?: any;
|
||||
applicationServerKey?: BufferSource | null;
|
||||
userVisibleOnly?: boolean;
|
||||
}
|
||||
|
||||
interface RequestInit {
|
||||
body?: any;
|
||||
signal?: AbortSignal;
|
||||
body?: Blob | BufferSource | FormData | string | null;
|
||||
cache?: RequestCache;
|
||||
credentials?: RequestCredentials;
|
||||
headers?: HeadersInit;
|
||||
@@ -119,7 +120,7 @@ interface NotificationEventInit extends ExtendableEventInit {
|
||||
}
|
||||
|
||||
interface PushEventInit extends ExtendableEventInit {
|
||||
data?: any;
|
||||
data?: BufferSource | USVString;
|
||||
}
|
||||
|
||||
interface SyncEventInit extends ExtendableEventInit {
|
||||
@@ -414,9 +415,10 @@ declare var EventTarget: {
|
||||
};
|
||||
|
||||
interface File extends Blob {
|
||||
readonly lastModifiedDate: any;
|
||||
readonly lastModifiedDate: Date;
|
||||
readonly name: string;
|
||||
readonly webkitRelativePath: string;
|
||||
readonly lastModified: number;
|
||||
}
|
||||
|
||||
declare var File: {
|
||||
@@ -959,6 +961,7 @@ interface Request extends Object, Body {
|
||||
readonly referrerPolicy: ReferrerPolicy;
|
||||
readonly type: RequestType;
|
||||
readonly url: string;
|
||||
readonly signal: AbortSignal;
|
||||
clone(): Request;
|
||||
}
|
||||
|
||||
@@ -1061,7 +1064,7 @@ interface URL {
|
||||
|
||||
declare var URL: {
|
||||
prototype: URL;
|
||||
new(url: string, base?: string): URL;
|
||||
new(url: string, base?: string | URL): URL;
|
||||
createObjectURL(object: any, options?: ObjectURLOptions): string;
|
||||
revokeObjectURL(url: string): void;
|
||||
};
|
||||
@@ -1821,6 +1824,43 @@ interface AddEventListenerOptions extends EventListenerOptions {
|
||||
once?: boolean;
|
||||
}
|
||||
|
||||
interface AbortController {
|
||||
readonly signal: AbortSignal;
|
||||
abort(): void;
|
||||
}
|
||||
|
||||
declare var AbortController: {
|
||||
prototype: AbortController;
|
||||
new(): AbortController;
|
||||
};
|
||||
|
||||
interface AbortSignal extends EventTarget {
|
||||
readonly aborted: boolean;
|
||||
onabort: (ev: Event) => any;
|
||||
}
|
||||
|
||||
interface EventSource extends EventTarget {
|
||||
readonly url: string;
|
||||
readonly withCredentials: boolean;
|
||||
readonly CONNECTING: number;
|
||||
readonly OPEN: number;
|
||||
readonly CLOSED: number;
|
||||
readonly readyState: number;
|
||||
onopen: (evt: MessageEvent) => any;
|
||||
onmessage: (evt: MessageEvent) => any;
|
||||
onerror: (evt: MessageEvent) => any;
|
||||
close(): void;
|
||||
}
|
||||
|
||||
declare var EventSource: {
|
||||
prototype: EventSource;
|
||||
new(url: string, eventSourceInitDict?: EventSourceInit): EventSource;
|
||||
};
|
||||
|
||||
interface EventSourceInit {
|
||||
readonly withCredentials: boolean;
|
||||
}
|
||||
|
||||
declare type EventListenerOrEventListenerObject = EventListener | EventListenerObject;
|
||||
|
||||
interface DecodeErrorCallback {
|
||||
@@ -1833,7 +1873,7 @@ interface ErrorEventHandler {
|
||||
(message: string, filename?: string, lineno?: number, colno?: number, error?: Error): void;
|
||||
}
|
||||
interface ForEachCallback {
|
||||
(keyId: any, status: MediaKeyStatus): void;
|
||||
(keyId: BufferSource, status: MediaKeyStatus): void;
|
||||
}
|
||||
interface FunctionStringCallback {
|
||||
(data: string): void;
|
||||
@@ -1883,7 +1923,7 @@ declare function addEventListener(type: string, listener: EventListenerOrEventLi
|
||||
declare function removeEventListener<K extends keyof DedicatedWorkerGlobalScopeEventMap>(type: K, listener: (this: DedicatedWorkerGlobalScope, ev: DedicatedWorkerGlobalScopeEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
|
||||
declare function removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
|
||||
type AlgorithmIdentifier = string | Algorithm;
|
||||
type BodyInit = any;
|
||||
type BodyInit = Blob | BufferSource | FormData | string;
|
||||
type IDBKeyPath = string;
|
||||
type RequestInfo = Request | string;
|
||||
type USVString = string;
|
||||
|
||||
@@ -2082,6 +2082,9 @@
|
||||
<Item ItemId=";Class_0_incorrectly_implements_class_1_Did_you_mean_to_extend_1_and_inherit_its_members_as_a_subclas_2720" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Class '{0}' incorrectly implements class '{1}'. Did you mean to extend '{1}' and inherit its members as a subclass?]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[La clase "{0}" no implementa correctamente la clase "{1}". ¿Pretendía extender "{1}" y heredar sus miembros como una subclase?]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
|
||||
@@ -46,7 +46,7 @@ function createCancellationToken(args: string[]): ServerCancellationToken {
|
||||
let perRequestPipeName: string;
|
||||
let currentRequestId: number;
|
||||
return {
|
||||
isCancellationRequested: () => perRequestPipeName !== undefined && pipeExists(perRequestPipeName),
|
||||
isCancellationRequested: () => perRequestPipeName !== undefined && pipeExists(perRequestPipeName),
|
||||
setRequest(requestId: number) {
|
||||
currentRequestId = requestId;
|
||||
perRequestPipeName = namePrefix + requestId;
|
||||
|
||||
+13
-1
@@ -566,7 +566,7 @@ namespace ts.server.protocol {
|
||||
|
||||
// TODO: GH#20538
|
||||
/* @internal */
|
||||
export interface GetCombinedCodeFixResponse extends Response {
|
||||
export interface GetCombinedCodeFixResponse extends Response {
|
||||
body: CombinedCodeActions;
|
||||
}
|
||||
|
||||
@@ -1693,6 +1693,11 @@ namespace ts.server.protocol {
|
||||
* This affects lone identifier completions but not completions on the right hand side of `obj.`.
|
||||
*/
|
||||
includeExternalModuleExports: boolean;
|
||||
/**
|
||||
* If enabled, the completion list will include completions with invalid identifier names.
|
||||
* For those entries, The `insertText` and `replacementSpan` properties will be set to change from `.x` property access to `["x"]`.
|
||||
*/
|
||||
includeInsertTextCompletions: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1768,6 +1773,12 @@ namespace ts.server.protocol {
|
||||
* is often the same as the name but may be different in certain circumstances.
|
||||
*/
|
||||
sortText: string;
|
||||
/**
|
||||
* Text to insert instead of `name`.
|
||||
* This is used to support bracketed completions; If `name` might be "a-b" but `insertText` would be `["a-b"]`,
|
||||
* coupled with `replacementSpan` to replace a dotted access with a bracket access.
|
||||
*/
|
||||
insertText?: string;
|
||||
/**
|
||||
* An optional span that indicates the text to be replaced by this completion item.
|
||||
* If present, this span should be used instead of the default one.
|
||||
@@ -2556,6 +2567,7 @@ namespace ts.server.protocol {
|
||||
insertSpaceBeforeFunctionParenthesis?: boolean;
|
||||
placeOpenBraceOnNewLineForFunctions?: boolean;
|
||||
placeOpenBraceOnNewLineForControlBlocks?: boolean;
|
||||
insertSpaceBeforeTypeAnnotation?: boolean;
|
||||
}
|
||||
|
||||
export interface CompilerOptions {
|
||||
|
||||
@@ -257,7 +257,7 @@ namespace ts.server {
|
||||
export class ScriptVersionCache {
|
||||
private changes: TextChange[] = [];
|
||||
private readonly versions: LineIndexSnapshot[] = new Array<LineIndexSnapshot>(ScriptVersionCache.maxVersions);
|
||||
private minVersion = 0; // no versions earlier than min version will maintain change history
|
||||
private minVersion = 0; // no versions earlier than min version will maintain change history
|
||||
|
||||
private currentVersion = 0;
|
||||
|
||||
|
||||
@@ -1207,10 +1207,10 @@ namespace ts.server {
|
||||
if (simplifiedResult) {
|
||||
return mapDefined<CompletionEntry, protocol.CompletionEntry>(completions && completions.entries, entry => {
|
||||
if (completions.isMemberCompletion || startsWith(entry.name.toLowerCase(), prefix.toLowerCase())) {
|
||||
const { name, kind, kindModifiers, sortText, replacementSpan, hasAction, source, isRecommended } = entry;
|
||||
const { name, kind, kindModifiers, sortText, insertText, replacementSpan, hasAction, source, isRecommended } = entry;
|
||||
const convertedSpan = replacementSpan ? this.toLocationTextSpan(replacementSpan, scriptInfo) : undefined;
|
||||
// Use `hasAction || undefined` to avoid serializing `false`.
|
||||
return { name, kind, kindModifiers, sortText, replacementSpan: convertedSpan, hasAction: hasAction || undefined, source, isRecommended };
|
||||
return { name, kind, kindModifiers, sortText, insertText, replacementSpan: convertedSpan, hasAction: hasAction || undefined, source, isRecommended };
|
||||
}
|
||||
}).sort((a, b) => compareStringsCaseSensitiveUI(a.name, b.name));
|
||||
}
|
||||
|
||||
@@ -262,8 +262,8 @@ namespace ts.BreakpointResolver {
|
||||
}
|
||||
|
||||
// Set breakpoint on identifier element of destructuring pattern
|
||||
// a or ...c or d: x from
|
||||
// [a, b, ...c] or { a, b } or { d: x } from destructuring pattern
|
||||
// `a` or `...c` or `d: x` from
|
||||
// `[a, b, ...c]` or `{ a, b }` or `{ d: x }` from destructuring pattern
|
||||
if ((node.kind === SyntaxKind.Identifier ||
|
||||
node.kind === SyntaxKind.SpreadElement ||
|
||||
node.kind === SyntaxKind.PropertyAssignment ||
|
||||
@@ -427,8 +427,9 @@ namespace ts.BreakpointResolver {
|
||||
}
|
||||
else {
|
||||
const functionDeclaration = <FunctionLikeDeclaration>parameter.parent;
|
||||
const indexOfParameter = indexOf(functionDeclaration.parameters, parameter);
|
||||
if (indexOfParameter) {
|
||||
const indexOfParameter = functionDeclaration.parameters.indexOf(parameter);
|
||||
Debug.assert(indexOfParameter !== -1);
|
||||
if (indexOfParameter !== 0) {
|
||||
// Not a first parameter, go to previous parameter
|
||||
return spanInParameterDeclaration(functionDeclaration.parameters[indexOfParameter - 1]);
|
||||
}
|
||||
|
||||
@@ -837,7 +837,7 @@ namespace ts {
|
||||
return ClassificationType.keyword;
|
||||
}
|
||||
|
||||
// Special case < and > If they appear in a generic context they are punctuation,
|
||||
// Special case `<` and `>`: If they appear in a generic context they are punctuation,
|
||||
// not operators.
|
||||
if (tokenKind === SyntaxKind.LessThanToken || tokenKind === SyntaxKind.GreaterThanToken) {
|
||||
// If the node owning the token has a type argument list or type parameter list, then
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/* @internal */
|
||||
namespace ts.codefix {
|
||||
registerCodeFix({
|
||||
errorCodes: [Diagnostics.A_namespace_style_import_cannot_be_called_or_constructed_and_will_cause_a_failure_at_runtime.code],
|
||||
getCodeActions: getActionsForInvalidImport
|
||||
});
|
||||
|
||||
function getActionsForInvalidImport(context: CodeFixContext): CodeAction[] | undefined {
|
||||
const sourceFile = context.sourceFile;
|
||||
|
||||
// This is the whole import statement, eg:
|
||||
// import * as Bluebird from 'bluebird';
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
const node = getTokenAtPosition(sourceFile, context.span.start, /*includeJsDocComment*/ false).parent as ImportDeclaration;
|
||||
if (!isImportDeclaration(node)) {
|
||||
// No import quick fix for import calls
|
||||
return [];
|
||||
}
|
||||
return getCodeFixesForImportDeclaration(context, node);
|
||||
}
|
||||
|
||||
function getCodeFixesForImportDeclaration(context: CodeFixContext, node: ImportDeclaration) {
|
||||
const sourceFile = getSourceFileOfNode(node);
|
||||
const namespace = getNamespaceDeclarationNode(node) as NamespaceImport;
|
||||
const opts = context.program.getCompilerOptions();
|
||||
const variations: CodeAction[] = [];
|
||||
|
||||
// import Bluebird from "bluebird";
|
||||
const replacement = createImportDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
createImportClause(namespace.name, /*namedBindings*/ undefined),
|
||||
node.moduleSpecifier
|
||||
);
|
||||
const changeTracker = textChanges.ChangeTracker.fromContext(context);
|
||||
changeTracker.replaceNode(sourceFile, node, replacement, { useNonAdjustedEndPosition: true });
|
||||
const changes = changeTracker.getChanges();
|
||||
variations.push({
|
||||
description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Replace_import_with_0), [changes[0].textChanges[0].newText]),
|
||||
changes
|
||||
});
|
||||
|
||||
if (getEmitModuleKind(opts) === ModuleKind.CommonJS) {
|
||||
// import Bluebird = require("bluebird");
|
||||
const replacement = createImportEqualsDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
namespace.name,
|
||||
createExternalModuleReference(node.moduleSpecifier)
|
||||
);
|
||||
const changeTracker = textChanges.ChangeTracker.fromContext(context);
|
||||
changeTracker.replaceNode(sourceFile, node, replacement, { useNonAdjustedEndPosition: true });
|
||||
const changes = changeTracker.getChanges();
|
||||
variations.push({
|
||||
description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Replace_import_with_0), [changes[0].textChanges[0].newText]),
|
||||
changes
|
||||
});
|
||||
}
|
||||
|
||||
return variations;
|
||||
}
|
||||
|
||||
registerCodeFix({
|
||||
errorCodes: [
|
||||
Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures.code,
|
||||
Diagnostics.Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature.code,
|
||||
],
|
||||
getCodeActions: getActionsForUsageOfInvalidImport
|
||||
});
|
||||
|
||||
function getActionsForUsageOfInvalidImport(context: CodeFixContext): CodeAction[] | undefined {
|
||||
const sourceFile = context.sourceFile;
|
||||
const targetKind = Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures.code === context.errorCode ? SyntaxKind.CallExpression : SyntaxKind.NewExpression;
|
||||
const node = findAncestor(getTokenAtPosition(sourceFile, context.span.start, /*includeJsDocComment*/ false), a => a.kind === targetKind && a.getStart() === context.span.start && a.getEnd() === (context.span.start + context.span.length)) as CallExpression | NewExpression;
|
||||
if (!node) {
|
||||
return [];
|
||||
}
|
||||
const expr = node.expression;
|
||||
const type = context.program.getTypeChecker().getTypeAtLocation(expr);
|
||||
if (!(type.symbol && (type.symbol as TransientSymbol).originatingImport)) {
|
||||
return [];
|
||||
}
|
||||
const fixes: CodeAction[] = [];
|
||||
const relatedImport = (type.symbol as TransientSymbol).originatingImport;
|
||||
if (!isImportCall(relatedImport)) {
|
||||
addRange(fixes, getCodeFixesForImportDeclaration(context, relatedImport));
|
||||
}
|
||||
const propertyAccess = createPropertyAccess(expr, "default");
|
||||
const changeTracker = textChanges.ChangeTracker.fromContext(context);
|
||||
changeTracker.replaceNode(sourceFile, expr, propertyAccess, {});
|
||||
const changes = changeTracker.getChanges();
|
||||
fixes.push({
|
||||
description: getLocaleSpecificMessage(Diagnostics.Use_synthetic_default_member),
|
||||
changes
|
||||
});
|
||||
return fixes;
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ namespace ts.codefix {
|
||||
errorCodes,
|
||||
getCodeActions(context) {
|
||||
const { sourceFile } = context;
|
||||
const info = getInfo(sourceFile, context.span.start, context.program.getTypeChecker());
|
||||
const info = getInfo(sourceFile, context.span.start, context.program.getTypeChecker());
|
||||
if (!info) return undefined;
|
||||
const { node, suggestion } = info;
|
||||
const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, node, suggestion));
|
||||
|
||||
@@ -15,3 +15,5 @@
|
||||
/// <reference path='disableJsDiagnostics.ts' />
|
||||
/// <reference path='helpers.ts' />
|
||||
/// <reference path='inferFromUsage.ts' />
|
||||
/// <reference path="fixInvalidImportSyntax.ts" />
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ namespace ts.codefix {
|
||||
createStubbedMethodBody());
|
||||
}
|
||||
|
||||
function createDummyParameters(argCount: number, names: string[] | undefined, minArgumentCount: number | undefined, inJs: boolean): ParameterDeclaration[] {
|
||||
function createDummyParameters(argCount: number, names: string[] | undefined, minArgumentCount: number | undefined, inJs: boolean): ParameterDeclaration[] {
|
||||
const parameters: ParameterDeclaration[] = [];
|
||||
for (let i = 0; i < argCount; i++) {
|
||||
const newParameter = createParameter(
|
||||
|
||||
@@ -363,6 +363,10 @@ namespace ts.codefix {
|
||||
}
|
||||
}
|
||||
|
||||
if (isPathRelativeToParent(relativeToBaseUrl)) {
|
||||
return [relativePath];
|
||||
}
|
||||
|
||||
/*
|
||||
Prefer a relative import over a baseUrl import if it doesn't traverse up to baseUrl.
|
||||
|
||||
@@ -424,9 +428,10 @@ namespace ts.codefix {
|
||||
}
|
||||
}
|
||||
|
||||
function tryGetModuleNameFromPaths(relativeNameWithIndex: string, relativeName: string, paths: MapLike<ReadonlyArray<string>>): string | undefined {
|
||||
function tryGetModuleNameFromPaths(relativeToBaseUrlWithIndex: string, relativeToBaseUrl: string, paths: MapLike<ReadonlyArray<string>>): string | undefined {
|
||||
for (const key in paths) {
|
||||
for (const pattern of paths[key]) {
|
||||
for (const patternText of paths[key]) {
|
||||
const pattern = removeFileExtension(normalizePath(patternText));
|
||||
const indexOfStar = pattern.indexOf("*");
|
||||
if (indexOfStar === 0 && pattern.length === 1) {
|
||||
continue;
|
||||
@@ -434,14 +439,14 @@ namespace ts.codefix {
|
||||
else if (indexOfStar !== -1) {
|
||||
const prefix = pattern.substr(0, indexOfStar);
|
||||
const suffix = pattern.substr(indexOfStar + 1);
|
||||
if (relativeName.length >= prefix.length + suffix.length &&
|
||||
startsWith(relativeName, prefix) &&
|
||||
endsWith(relativeName, suffix)) {
|
||||
const matchedStar = relativeName.substr(prefix.length, relativeName.length - suffix.length);
|
||||
return key.replace("\*", matchedStar);
|
||||
if (relativeToBaseUrl.length >= prefix.length + suffix.length &&
|
||||
startsWith(relativeToBaseUrl, prefix) &&
|
||||
endsWith(relativeToBaseUrl, suffix)) {
|
||||
const matchedStar = relativeToBaseUrl.substr(prefix.length, relativeToBaseUrl.length - suffix.length);
|
||||
return key.replace("*", matchedStar);
|
||||
}
|
||||
}
|
||||
else if (pattern === relativeName || pattern === relativeNameWithIndex) {
|
||||
else if (pattern === relativeToBaseUrl || pattern === relativeToBaseUrlWithIndex) {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
@@ -601,7 +606,10 @@ namespace ts.codefix {
|
||||
}
|
||||
|
||||
function getPathRelativeToRootDirs(path: string, rootDirs: ReadonlyArray<string>, getCanonicalFileName: GetCanonicalFileName): string | undefined {
|
||||
return firstDefined(rootDirs, rootDir => getRelativePathIfInDirectory(path, rootDir, getCanonicalFileName));
|
||||
return firstDefined(rootDirs, rootDir => {
|
||||
const relativePath = getRelativePathIfInDirectory(path, rootDir, getCanonicalFileName);
|
||||
return isPathRelativeToParent(relativePath) ? undefined : relativePath;
|
||||
});
|
||||
}
|
||||
|
||||
function removeExtensionAndIndexPostFix(fileName: string, options: CompilerOptions, addJsExtension: boolean): string {
|
||||
@@ -615,7 +623,11 @@ namespace ts.codefix {
|
||||
|
||||
function getRelativePathIfInDirectory(path: string, directoryPath: string, getCanonicalFileName: GetCanonicalFileName): string | undefined {
|
||||
const relativePath = getRelativePathToDirectoryOrUrl(directoryPath, path, directoryPath, getCanonicalFileName, /*isAbsolutePathAnUrl*/ false);
|
||||
return isRootedDiskPath(relativePath) || startsWith(relativePath, "..") ? undefined : relativePath;
|
||||
return isRootedDiskPath(relativePath) ? undefined : relativePath;
|
||||
}
|
||||
|
||||
function isPathRelativeToParent(path: string): boolean {
|
||||
return startsWith(path, "..");
|
||||
}
|
||||
|
||||
function getRelativePath(path: string, directoryPath: string, getCanonicalFileName: GetCanonicalFileName) {
|
||||
@@ -780,8 +792,11 @@ namespace ts.codefix {
|
||||
const defaultExport = checker.tryGetMemberInModuleExports(InternalSymbolName.Default, moduleSymbol);
|
||||
if (defaultExport) {
|
||||
const localSymbol = getLocalSymbolForExportDefault(defaultExport);
|
||||
if ((localSymbol && localSymbol.escapedName === symbolName || moduleSymbolToValidIdentifier(moduleSymbol, context.compilerOptions.target) === symbolName)
|
||||
&& checkSymbolHasMeaning(localSymbol || defaultExport, currentTokenMeaning)) {
|
||||
if ((
|
||||
localSymbol && localSymbol.escapedName === symbolName ||
|
||||
getEscapedNameForExportDefault(defaultExport) === symbolName ||
|
||||
moduleSymbolToValidIdentifier(moduleSymbol, context.compilerOptions.target) === symbolName
|
||||
) && checkSymbolHasMeaning(localSymbol || defaultExport, currentTokenMeaning)) {
|
||||
// check if this symbol is already used
|
||||
const symbolId = getUniqueSymbolId(localSymbol || defaultExport, checker);
|
||||
symbolIdActionMap.addActions(symbolId, getCodeActionForImport(moduleSymbol, { ...context, kind: ImportKind.Default }));
|
||||
@@ -794,6 +809,22 @@ namespace ts.codefix {
|
||||
const symbolId = getUniqueSymbolId(exportSymbolWithIdenticalName, checker);
|
||||
symbolIdActionMap.addActions(symbolId, getCodeActionForImport(moduleSymbol, { ...context, kind: ImportKind.Named }));
|
||||
}
|
||||
|
||||
function getEscapedNameForExportDefault(symbol: Symbol): __String | undefined {
|
||||
return firstDefined(symbol.declarations, declaration => {
|
||||
if (isExportAssignment(declaration)) {
|
||||
if (isIdentifier(declaration.expression)) {
|
||||
return declaration.expression.escapedText;
|
||||
}
|
||||
}
|
||||
else if (isExportSpecifier(declaration)) {
|
||||
Debug.assert(declaration.name.escapedText === InternalSymbolName.Default);
|
||||
if (declaration.propertyName) {
|
||||
return declaration.propertyName.escapedText;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return symbolIdActionMap.getAllActions();
|
||||
|
||||
+228
-193
@@ -50,39 +50,49 @@ namespace ts.Completions {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const { symbols, isGlobalCompletion, isMemberCompletion, allowStringLiteral, isNewIdentifierLocation, location, request, keywordFilters, symbolToOriginInfoMap, recommendedCompletion } = completionData;
|
||||
switch (completionData.kind) {
|
||||
case CompletionDataKind.Data:
|
||||
return completionInfoFromData(sourceFile, typeChecker, compilerOptions, log, completionData, options.includeInsertTextCompletions);
|
||||
case CompletionDataKind.JsDocTagName:
|
||||
// If the current position is a jsDoc tag name, only tag names should be provided for completion
|
||||
return jsdocCompletionInfo(JsDoc.getJSDocTagNameCompletions());
|
||||
case CompletionDataKind.JsDocTag:
|
||||
// If the current position is a jsDoc tag, only tags should be provided for completion
|
||||
return jsdocCompletionInfo(JsDoc.getJSDocTagCompletions());
|
||||
case CompletionDataKind.JsDocParameterName:
|
||||
return jsdocCompletionInfo(JsDoc.getJSDocParameterNameCompletions(completionData.tag));
|
||||
default:
|
||||
throw Debug.assertNever(completionData);
|
||||
}
|
||||
}
|
||||
|
||||
if (sourceFile.languageVariant === LanguageVariant.JSX &&
|
||||
location && location.parent && location.parent.kind === SyntaxKind.JsxClosingElement) {
|
||||
function jsdocCompletionInfo(entries: CompletionEntry[]): CompletionInfo {
|
||||
return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, entries };
|
||||
}
|
||||
|
||||
function completionInfoFromData(sourceFile: SourceFile, typeChecker: TypeChecker, compilerOptions: CompilerOptions, log: Log, completionData: CompletionData, includeInsertTextCompletions: boolean): CompletionInfo {
|
||||
const { symbols, completionKind, isNewIdentifierLocation, location, propertyAccessToConvert, keywordFilters, symbolToOriginInfoMap, recommendedCompletion } = completionData;
|
||||
|
||||
if (sourceFile.languageVariant === LanguageVariant.JSX && location && location.parent && isJsxClosingElement(location.parent)) {
|
||||
// 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 = <div> </ /*1*/> completion list at "1" will contain "div" with type any
|
||||
const tagName = (<JsxElement>location.parent.parent).openingElement.tagName;
|
||||
// var x = <div> </ /*1*/>
|
||||
// The 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: (<JsxTagNameExpression>tagName).getFullText(),
|
||||
name: tagName.getFullText(),
|
||||
kind: ScriptElementKind.classElement,
|
||||
kindModifiers: undefined,
|
||||
sortText: "0",
|
||||
}]};
|
||||
}
|
||||
|
||||
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[] = [];
|
||||
|
||||
if (isSourceFileJavaScript(sourceFile)) {
|
||||
const uniqueNames = getCompletionEntriesFromSymbols(symbols, entries, location, /*performCharacterChecks*/ true, typeChecker, compilerOptions.target, log, allowStringLiteral, recommendedCompletion, symbolToOriginInfoMap);
|
||||
const uniqueNames = getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target, log, completionKind, includeInsertTextCompletions, propertyAccessToConvert, recommendedCompletion, symbolToOriginInfoMap);
|
||||
getJavaScriptCompletionEntries(sourceFile, location.pos, uniqueNames, compilerOptions.target, entries);
|
||||
}
|
||||
else {
|
||||
@@ -90,7 +100,7 @@ namespace ts.Completions {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
getCompletionEntriesFromSymbols(symbols, entries, location, /*performCharacterChecks*/ true, typeChecker, compilerOptions.target, log, allowStringLiteral, recommendedCompletion, symbolToOriginInfoMap);
|
||||
getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target, log, completionKind, includeInsertTextCompletions, propertyAccessToConvert, recommendedCompletion, symbolToOriginInfoMap);
|
||||
}
|
||||
|
||||
// TODO add filter for keyword based on type/value/namespace and also location
|
||||
@@ -98,17 +108,29 @@ namespace ts.Completions {
|
||||
// Add all keywords if
|
||||
// - this is not a member completion list (all the keywords)
|
||||
// - other filters are enabled in required scenario so add those keywords
|
||||
const isMemberCompletion = isMemberCompletionKind(completionKind);
|
||||
if (keywordFilters !== KeywordCompletionFilters.None || !isMemberCompletion) {
|
||||
addRange(entries, getKeywordCompletions(keywordFilters));
|
||||
}
|
||||
|
||||
return { isGlobalCompletion, isMemberCompletion, isNewIdentifierLocation, entries };
|
||||
return { isGlobalCompletion: completionKind === CompletionKind.Global, isMemberCompletion, isNewIdentifierLocation, entries };
|
||||
}
|
||||
|
||||
function isMemberCompletionKind(kind: CompletionKind): boolean {
|
||||
switch (kind) {
|
||||
case CompletionKind.ObjectPropertyDeclaration:
|
||||
case CompletionKind.MemberLike:
|
||||
case CompletionKind.PropertyAccess:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function getJavaScriptCompletionEntries(
|
||||
sourceFile: SourceFile,
|
||||
position: number,
|
||||
uniqueNames: Map<{}>,
|
||||
uniqueNames: Map<true>,
|
||||
target: ScriptTarget,
|
||||
entries: Push<CompletionEntry>): void {
|
||||
getNameTable(sourceFile).forEach((pos, name) => {
|
||||
@@ -117,16 +139,9 @@ namespace ts.Completions {
|
||||
return;
|
||||
}
|
||||
const realName = unescapeLeadingUnderscores(name);
|
||||
|
||||
if (uniqueNames.has(realName) || isStringANonContextualKeyword(realName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
uniqueNames.set(realName, true);
|
||||
const displayName = getCompletionEntryDisplayName(realName, target, /*performCharacterChecks*/ true, /*allowStringLiteral*/ false);
|
||||
if (displayName) {
|
||||
if (addToSeen(uniqueNames, realName) && isIdentifierText(realName, target) && !isStringANonContextualKeyword(realName)) {
|
||||
entries.push({
|
||||
name: displayName,
|
||||
name: realName,
|
||||
kind: ScriptElementKind.warning,
|
||||
kindModifiers: "",
|
||||
sortText: "1"
|
||||
@@ -138,18 +153,22 @@ namespace ts.Completions {
|
||||
function createCompletionEntry(
|
||||
symbol: Symbol,
|
||||
location: Node,
|
||||
performCharacterChecks: boolean,
|
||||
sourceFile: SourceFile,
|
||||
typeChecker: TypeChecker,
|
||||
target: ScriptTarget,
|
||||
allowStringLiteral: boolean,
|
||||
kind: CompletionKind,
|
||||
origin: SymbolOriginInfo | undefined,
|
||||
recommendedCompletion: Symbol | undefined,
|
||||
propertyAccessToConvert: PropertyAccessExpression | undefined,
|
||||
includeInsertTextCompletions: boolean,
|
||||
): CompletionEntry | undefined {
|
||||
// Try to get a valid display name for this symbol, if we could not find one, then ignore it.
|
||||
// We would like to only show things that can be added after a dot, so for instance numeric properties can
|
||||
// not be accessed with a dot (a.1 <- invalid)
|
||||
const displayName = getCompletionEntryDisplayNameForSymbol(symbol, target, performCharacterChecks, allowStringLiteral, origin);
|
||||
if (!displayName) {
|
||||
const info = getCompletionEntryDisplayNameForSymbol(symbol, target, origin, kind);
|
||||
if (!info) {
|
||||
return undefined;
|
||||
}
|
||||
const { name, needsConvertPropertyAccess } = info;
|
||||
Debug.assert(!(needsConvertPropertyAccess && !propertyAccessToConvert));
|
||||
if (needsConvertPropertyAccess && !includeInsertTextCompletions) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -162,16 +181,22 @@ namespace ts.Completions {
|
||||
// Use a 'sortText' of 0' so that all symbol completion entries come before any other
|
||||
// entries (like JavaScript identifier entries).
|
||||
return {
|
||||
name: displayName,
|
||||
name,
|
||||
kind: SymbolDisplay.getSymbolKind(typeChecker, symbol, location),
|
||||
kindModifiers: SymbolDisplay.getSymbolModifiers(symbol),
|
||||
sortText: "0",
|
||||
source: getSourceFromOrigin(origin),
|
||||
hasAction: trueOrUndefined(origin !== undefined),
|
||||
// TODO: GH#20619 Use configured quote style
|
||||
insertText: needsConvertPropertyAccess ? `["${name}"]` : undefined,
|
||||
replacementSpan: needsConvertPropertyAccess
|
||||
? createTextSpanFromBounds(findChildOfKind(propertyAccessToConvert, SyntaxKind.DotToken, sourceFile)!.getStart(sourceFile), propertyAccessToConvert.name.end)
|
||||
: undefined,
|
||||
hasAction: trueOrUndefined(needsConvertPropertyAccess || origin !== undefined),
|
||||
isRecommended: trueOrUndefined(isRecommendedCompletionMatch(symbol, recommendedCompletion, typeChecker)),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function isRecommendedCompletionMatch(localSymbol: Symbol, recommendedCompletion: Symbol, checker: TypeChecker): boolean {
|
||||
return localSymbol === recommendedCompletion ||
|
||||
!!(localSymbol.flags & SymbolFlags.ExportValue) && checker.getExportSymbolOfSymbol(localSymbol) === recommendedCompletion;
|
||||
@@ -189,11 +214,13 @@ namespace ts.Completions {
|
||||
symbols: ReadonlyArray<Symbol>,
|
||||
entries: Push<CompletionEntry>,
|
||||
location: Node,
|
||||
performCharacterChecks: boolean,
|
||||
sourceFile: SourceFile,
|
||||
typeChecker: TypeChecker,
|
||||
target: ScriptTarget,
|
||||
log: Log,
|
||||
allowStringLiteral: boolean,
|
||||
kind: CompletionKind,
|
||||
includeInsertTextCompletions?: boolean,
|
||||
propertyAccessToConvert?: PropertyAccessExpression | undefined,
|
||||
recommendedCompletion?: Symbol,
|
||||
symbolToOriginInfoMap?: SymbolOriginInfoMap,
|
||||
): Map<true> {
|
||||
@@ -205,7 +232,7 @@ namespace ts.Completions {
|
||||
const uniques = createMap<true>();
|
||||
for (const symbol of symbols) {
|
||||
const origin = symbolToOriginInfoMap ? symbolToOriginInfoMap[getSymbolId(symbol)] : undefined;
|
||||
const entry = createCompletionEntry(symbol, location, performCharacterChecks, typeChecker, target, allowStringLiteral, origin, recommendedCompletion);
|
||||
const entry = createCompletionEntry(symbol, location, sourceFile, typeChecker, target, kind, origin, recommendedCompletion, propertyAccessToConvert, includeInsertTextCompletions);
|
||||
if (!entry) {
|
||||
continue;
|
||||
}
|
||||
@@ -255,7 +282,7 @@ namespace ts.Completions {
|
||||
// foo({
|
||||
// '/*completion position*/'
|
||||
// });
|
||||
return getStringLiteralCompletionEntriesFromPropertyAssignment(<ObjectLiteralElement>node.parent, typeChecker, compilerOptions.target, log);
|
||||
return getStringLiteralCompletionEntriesFromPropertyAssignment(<ObjectLiteralElement>node.parent, sourceFile, typeChecker, compilerOptions.target, log);
|
||||
}
|
||||
else if (isElementAccessExpression(node.parent) && node.parent.argumentExpression === node) {
|
||||
// Get all names of properties on the expression
|
||||
@@ -265,7 +292,7 @@ namespace ts.Completions {
|
||||
// let a: A;
|
||||
// a['/*completion position*/']
|
||||
const type = typeChecker.getTypeAtLocation(node.parent.expression);
|
||||
return getStringLiteralCompletionEntriesFromElementAccessOrIndexedAccess(node, type, typeChecker, compilerOptions.target, log);
|
||||
return getStringLiteralCompletionEntriesFromElementAccessOrIndexedAccess(node, sourceFile, type, typeChecker, compilerOptions.target, log);
|
||||
}
|
||||
else if (node.parent.kind === SyntaxKind.ImportDeclaration || node.parent.kind === SyntaxKind.ExportDeclaration
|
||||
|| isRequireCall(node.parent, /*checkArgumentIsStringLiteral*/ false) || isImportCall(node.parent)
|
||||
@@ -276,7 +303,7 @@ namespace ts.Completions {
|
||||
// import x = require("/*completion position*/");
|
||||
// var y = require("/*completion position*/");
|
||||
// export * from "/*completion position*/";
|
||||
const entries = PathCompletions.getStringLiteralCompletionsFromModuleNames(node, compilerOptions, host, typeChecker);
|
||||
const entries = PathCompletions.getStringLiteralCompletionsFromModuleNames(sourceFile, node, compilerOptions, host, typeChecker);
|
||||
return pathCompletionsInfo(entries);
|
||||
}
|
||||
else if (isIndexedAccessTypeNode(node.parent.parent)) {
|
||||
@@ -287,7 +314,7 @@ namespace ts.Completions {
|
||||
// }
|
||||
// let x: Foo["/*completion position*/"]
|
||||
const type = typeChecker.getTypeFromTypeNode(node.parent.parent.objectType);
|
||||
return getStringLiteralCompletionEntriesFromElementAccessOrIndexedAccess(node, type, typeChecker, compilerOptions.target, log);
|
||||
return getStringLiteralCompletionEntriesFromElementAccessOrIndexedAccess(node, sourceFile, type, typeChecker, compilerOptions.target, log);
|
||||
}
|
||||
else {
|
||||
const argumentInfo = SignatureHelp.getImmediatelyContainingArgumentInfo(node, position, sourceFile);
|
||||
@@ -316,11 +343,11 @@ namespace ts.Completions {
|
||||
};
|
||||
}
|
||||
|
||||
function getStringLiteralCompletionEntriesFromPropertyAssignment(element: ObjectLiteralElement, typeChecker: TypeChecker, target: ScriptTarget, log: Log): CompletionInfo | undefined {
|
||||
function getStringLiteralCompletionEntriesFromPropertyAssignment(element: ObjectLiteralElement, sourceFile: SourceFile, typeChecker: TypeChecker, target: ScriptTarget, log: Log): CompletionInfo | undefined {
|
||||
const type = typeChecker.getContextualType((<ObjectLiteralExpression>element.parent));
|
||||
const entries: CompletionEntry[] = [];
|
||||
if (type) {
|
||||
getCompletionEntriesFromSymbols(type.getApparentProperties(), entries, element, /*performCharacterChecks*/ false, typeChecker, target, log, /*allowStringLiteral*/ true);
|
||||
getCompletionEntriesFromSymbols(type.getApparentProperties(), entries, element, sourceFile, typeChecker, target, log, CompletionKind.String);
|
||||
if (entries.length) {
|
||||
return { isGlobalCompletion: false, isMemberCompletion: true, isNewIdentifierLocation: true, entries };
|
||||
}
|
||||
@@ -345,10 +372,10 @@ namespace ts.Completions {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getStringLiteralCompletionEntriesFromElementAccessOrIndexedAccess(stringLiteralNode: StringLiteral | NoSubstitutionTemplateLiteral, type: Type, typeChecker: TypeChecker, target: ScriptTarget, log: Log): CompletionInfo | undefined {
|
||||
function getStringLiteralCompletionEntriesFromElementAccessOrIndexedAccess(stringLiteralNode: StringLiteral | NoSubstitutionTemplateLiteral, sourceFile: SourceFile, type: Type, typeChecker: TypeChecker, target: ScriptTarget, log: Log): CompletionInfo | undefined {
|
||||
const entries: CompletionEntry[] = [];
|
||||
if (type) {
|
||||
getCompletionEntriesFromSymbols(type.getApparentProperties(), entries, stringLiteralNode, /*performCharacterChecks*/ false, typeChecker, target, log, /*allowStringLiteral*/ true);
|
||||
getCompletionEntriesFromSymbols(type.getApparentProperties(), entries, stringLiteralNode, sourceFile, typeChecker, target, log, CompletionKind.String);
|
||||
if (entries.length) {
|
||||
return { isGlobalCompletion: false, isMemberCompletion: true, isNewIdentifierLocation: true, entries };
|
||||
}
|
||||
@@ -419,6 +446,13 @@ namespace ts.Completions {
|
||||
}
|
||||
}
|
||||
|
||||
interface SymbolCompletion {
|
||||
type: "symbol";
|
||||
symbol: Symbol;
|
||||
location: Node;
|
||||
symbolToOriginInfoMap: SymbolOriginInfoMap;
|
||||
previousToken: Node;
|
||||
}
|
||||
function getSymbolCompletionFromEntryId(
|
||||
typeChecker: TypeChecker,
|
||||
log: (message: string) => void,
|
||||
@@ -427,27 +461,26 @@ namespace ts.Completions {
|
||||
position: number,
|
||||
{ name, source }: CompletionEntryIdentifier,
|
||||
allSourceFiles: ReadonlyArray<SourceFile>,
|
||||
): { type: "symbol", symbol: Symbol, location: Node, symbolToOriginInfoMap: SymbolOriginInfoMap, previousToken: Node } | { type: "request", request: Request } | { type: "none" } {
|
||||
const completionData = getCompletionData(typeChecker, log, sourceFile, position, allSourceFiles, { includeExternalModuleExports: true }, compilerOptions.target);
|
||||
): SymbolCompletion | { type: "request", request: Request } | { type: "none" } {
|
||||
const completionData = getCompletionData(typeChecker, log, sourceFile, position, allSourceFiles, { includeExternalModuleExports: true, includeInsertTextCompletions: true }, compilerOptions.target);
|
||||
if (!completionData) {
|
||||
return { type: "none" };
|
||||
}
|
||||
|
||||
const { symbols, location, allowStringLiteral, symbolToOriginInfoMap, request, previousToken } = completionData;
|
||||
if (request) {
|
||||
return { type: "request", request };
|
||||
if (completionData.kind !== CompletionDataKind.Data) {
|
||||
return { type: "request", request: completionData };
|
||||
}
|
||||
|
||||
const { symbols, location, completionKind, symbolToOriginInfoMap, previousToken } = completionData;
|
||||
|
||||
// Find the symbol with the matching entry name.
|
||||
// We don't need to perform character checks here because we're only comparing the
|
||||
// name against 'entryName' (which is known to be good), not building a new
|
||||
// completion entry.
|
||||
const symbol = find(symbols, s => {
|
||||
const origin = symbolToOriginInfoMap[getSymbolId(s)];
|
||||
return getCompletionEntryDisplayNameForSymbol(s, compilerOptions.target, /*performCharacterChecks*/ false, allowStringLiteral, origin) === name
|
||||
&& getSourceFromOrigin(origin) === source;
|
||||
});
|
||||
return symbol ? { type: "symbol", symbol, location, symbolToOriginInfoMap, previousToken } : { type: "none" };
|
||||
return firstDefined<Symbol, SymbolCompletion>(symbols, (symbol): SymbolCompletion => { // TODO: Shouldn't need return type annotation (GH#12632)
|
||||
const origin = symbolToOriginInfoMap[getSymbolId(symbol)];
|
||||
const info = getCompletionEntryDisplayNameForSymbol(symbol, compilerOptions.target, origin, completionKind);
|
||||
return info && info.name === name && getSourceFromOrigin(origin) === source ? { type: "symbol" as "symbol", symbol, location, symbolToOriginInfoMap, previousToken } : undefined;
|
||||
}) || { type: "none" };
|
||||
}
|
||||
|
||||
function getSymbolName(symbol: Symbol, origin: SymbolOriginInfo | undefined, target: ScriptTarget): string {
|
||||
@@ -483,11 +516,11 @@ namespace ts.Completions {
|
||||
case "request": {
|
||||
const { request } = symbolCompletion;
|
||||
switch (request.kind) {
|
||||
case "JsDocTagName":
|
||||
case CompletionDataKind.JsDocTagName:
|
||||
return JsDoc.getJSDocTagNameCompletionDetails(name);
|
||||
case "JsDocTag":
|
||||
case CompletionDataKind.JsDocTag:
|
||||
return JsDoc.getJSDocTagCompletionDetails(name);
|
||||
case "JsDocParameterName":
|
||||
case CompletionDataKind.JsDocParameterName:
|
||||
return JsDoc.getJSDocParameterNameCompletionDetails(name);
|
||||
default:
|
||||
return Debug.assertNever(request);
|
||||
@@ -519,6 +552,10 @@ namespace ts.Completions {
|
||||
}
|
||||
}
|
||||
|
||||
interface CodeActionsAndSourceDisplay {
|
||||
readonly codeActions: CodeAction[] | undefined;
|
||||
readonly sourceDisplay: SymbolDisplayPart[] | undefined;
|
||||
}
|
||||
function getCompletionEntryCodeActionsAndSourceDisplay(
|
||||
symbolToOriginInfoMap: SymbolOriginInfoMap,
|
||||
symbol: Symbol,
|
||||
@@ -531,12 +568,26 @@ namespace ts.Completions {
|
||||
formatContext: formatting.FormatContext,
|
||||
getCanonicalFileName: GetCanonicalFileName,
|
||||
allSourceFiles: ReadonlyArray<SourceFile>,
|
||||
): { codeActions: CodeAction[] | undefined, sourceDisplay: SymbolDisplayPart[] | undefined } {
|
||||
): CodeActionsAndSourceDisplay {
|
||||
const symbolOriginInfo = symbolToOriginInfoMap[getSymbolId(symbol)];
|
||||
if (!symbolOriginInfo) {
|
||||
return { codeActions: undefined, sourceDisplay: undefined };
|
||||
}
|
||||
return symbolOriginInfo
|
||||
? getCodeActionsAndSourceDisplayForImport(symbolOriginInfo, symbol, program, checker, host, compilerOptions, sourceFile, previousToken, formatContext, getCanonicalFileName, allSourceFiles)
|
||||
: { codeActions: undefined, sourceDisplay: undefined };
|
||||
}
|
||||
|
||||
function getCodeActionsAndSourceDisplayForImport(
|
||||
symbolOriginInfo: SymbolOriginInfo,
|
||||
symbol: Symbol,
|
||||
program: Program,
|
||||
checker: TypeChecker,
|
||||
host: LanguageServiceHost,
|
||||
compilerOptions: CompilerOptions,
|
||||
sourceFile: SourceFile,
|
||||
previousToken: Node,
|
||||
formatContext: formatting.FormatContext,
|
||||
getCanonicalFileName: GetCanonicalFileName,
|
||||
allSourceFiles: ReadonlyArray<SourceFile>
|
||||
): CodeActionsAndSourceDisplay {
|
||||
const { moduleSymbol, isDefaultExport } = symbolOriginInfo;
|
||||
const exportedSymbol = skipAlias(symbol.exportSymbol || symbol, checker);
|
||||
const moduleSymbols = getAllReExportingModules(exportedSymbol, checker, allSourceFiles);
|
||||
@@ -584,21 +635,30 @@ namespace ts.Completions {
|
||||
return completion.type === "symbol" ? completion.symbol : undefined;
|
||||
}
|
||||
|
||||
const enum CompletionDataKind { Data, JsDocTagName, JsDocTag, JsDocParameterName }
|
||||
interface CompletionData {
|
||||
symbols: ReadonlyArray<Symbol>;
|
||||
isGlobalCompletion: boolean;
|
||||
isMemberCompletion: boolean;
|
||||
allowStringLiteral: boolean;
|
||||
isNewIdentifierLocation: boolean;
|
||||
location: Node | undefined;
|
||||
isRightOfDot: boolean;
|
||||
request?: Request;
|
||||
keywordFilters: KeywordCompletionFilters;
|
||||
symbolToOriginInfoMap: SymbolOriginInfoMap;
|
||||
recommendedCompletion: Symbol | undefined;
|
||||
previousToken: Node;
|
||||
readonly kind: CompletionDataKind.Data;
|
||||
readonly symbols: ReadonlyArray<Symbol>;
|
||||
readonly completionKind: CompletionKind;
|
||||
/** Note that the presence of this alone doesn't mean that we need a conversion. Only do that if the completion is not an ordinary identifier. */
|
||||
readonly propertyAccessToConvert: PropertyAccessExpression | undefined;
|
||||
readonly isNewIdentifierLocation: boolean;
|
||||
readonly location: Node | undefined;
|
||||
readonly keywordFilters: KeywordCompletionFilters;
|
||||
readonly symbolToOriginInfoMap: SymbolOriginInfoMap;
|
||||
readonly recommendedCompletion: Symbol | undefined;
|
||||
readonly previousToken: Node | undefined;
|
||||
}
|
||||
type Request = { readonly kind: CompletionDataKind.JsDocTagName | CompletionDataKind.JsDocTag } | { readonly kind: CompletionDataKind.JsDocParameterName, tag: JSDocParameterTag };
|
||||
|
||||
const enum CompletionKind {
|
||||
ObjectPropertyDeclaration,
|
||||
Global,
|
||||
PropertyAccess,
|
||||
MemberLike,
|
||||
String,
|
||||
None,
|
||||
}
|
||||
type Request = { kind: "JsDocTagName" } | { kind: "JsDocTag" } | { kind: "JsDocParameterName", tag: JSDocParameterTag };
|
||||
|
||||
function getRecommendedCompletion(currentToken: Node, checker: TypeChecker): Symbol | undefined {
|
||||
const ty = getContextualType(currentToken, checker);
|
||||
@@ -669,9 +729,7 @@ namespace ts.Completions {
|
||||
allSourceFiles: ReadonlyArray<SourceFile>,
|
||||
options: GetCompletionsAtPositionOptions,
|
||||
target: ScriptTarget,
|
||||
): CompletionData | undefined {
|
||||
let request: Request | undefined;
|
||||
|
||||
): CompletionData | 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.)
|
||||
@@ -689,7 +747,7 @@ namespace ts.Completions {
|
||||
if (sourceFile.text.charCodeAt(position - 1) === CharacterCodes.at) {
|
||||
// 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" };
|
||||
return { kind: CompletionDataKind.JsDocTagName };
|
||||
}
|
||||
else {
|
||||
// When completion is requested without "@", we will have check to make sure that
|
||||
@@ -710,7 +768,7 @@ namespace ts.Completions {
|
||||
// */
|
||||
const lineStart = getLineStartPositionForPosition(position, sourceFile);
|
||||
if (!(sourceFile.text.substring(lineStart, position).match(/[^\*|\s|(/\*\*)]/))) {
|
||||
request = { kind: "JsDocTag" };
|
||||
return { kind: CompletionDataKind.JsDocTag };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -721,7 +779,7 @@ namespace ts.Completions {
|
||||
const tag = getJsDocTagAtPosition(currentToken, position);
|
||||
if (tag) {
|
||||
if (tag.tagName.pos <= position && position <= tag.tagName.end) {
|
||||
request = { kind: "JsDocTagName" };
|
||||
return { kind: CompletionDataKind.JsDocTagName };
|
||||
}
|
||||
if (isTagWithTypeExpression(tag) && tag.typeExpression && tag.typeExpression.kind === SyntaxKind.JSDocTypeExpression) {
|
||||
currentToken = getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ true);
|
||||
@@ -734,27 +792,10 @@ namespace ts.Completions {
|
||||
}
|
||||
}
|
||||
if (isJSDocParameterTag(tag) && (nodeIsMissing(tag.name) || tag.name.pos <= position && position <= tag.name.end)) {
|
||||
request = { kind: "JsDocParameterName", tag };
|
||||
return { kind: CompletionDataKind.JsDocParameterName, tag };
|
||||
}
|
||||
}
|
||||
|
||||
if (request) {
|
||||
return {
|
||||
symbols: emptyArray,
|
||||
isGlobalCompletion: false,
|
||||
isMemberCompletion: false,
|
||||
allowStringLiteral: false,
|
||||
isNewIdentifierLocation: false,
|
||||
location: undefined,
|
||||
isRightOfDot: false,
|
||||
request,
|
||||
keywordFilters: KeywordCompletionFilters.None,
|
||||
symbolToOriginInfoMap: undefined,
|
||||
recommendedCompletion: undefined,
|
||||
previousToken: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
if (!insideJsDocTagTypeExpression) {
|
||||
// Proceed if the current position is in jsDoc tag expression; otherwise it is a normal
|
||||
// comment or the plain text part of a jsDoc comment, so no completion should be available
|
||||
@@ -783,6 +824,7 @@ namespace ts.Completions {
|
||||
// Also determine whether we are trying to complete with members of that node
|
||||
// or attributes of a JSX tag.
|
||||
let node = currentToken;
|
||||
let propertyAccessToConvert: PropertyAccessExpression | undefined;
|
||||
let isRightOfDot = false;
|
||||
let isRightOfOpenTag = false;
|
||||
let isStartingCloseTag = false;
|
||||
@@ -797,18 +839,19 @@ namespace ts.Completions {
|
||||
|
||||
let parent = contextToken.parent;
|
||||
if (contextToken.kind === SyntaxKind.DotToken) {
|
||||
if (parent.kind === SyntaxKind.PropertyAccessExpression) {
|
||||
node = (<PropertyAccessExpression>contextToken.parent).expression;
|
||||
isRightOfDot = true;
|
||||
}
|
||||
else if (parent.kind === SyntaxKind.QualifiedName) {
|
||||
node = (<QualifiedName>contextToken.parent).left;
|
||||
isRightOfDot = true;
|
||||
}
|
||||
else {
|
||||
// There is nothing that precedes the dot, so this likely just a stray character
|
||||
// or leading into a '...' token. Just bail out instead.
|
||||
return undefined;
|
||||
isRightOfDot = true;
|
||||
switch (parent.kind) {
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
propertyAccessToConvert = parent as PropertyAccessExpression;
|
||||
node = propertyAccessToConvert.expression;
|
||||
break;
|
||||
case SyntaxKind.QualifiedName:
|
||||
node = (parent as QualifiedName).left;
|
||||
break;
|
||||
default:
|
||||
// There is nothing that precedes the dot, so this likely just a stray character
|
||||
// or leading into a '...' token. Just bail out instead.
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
else if (sourceFile.languageVariant === LanguageVariant.JSX) {
|
||||
@@ -848,10 +891,8 @@ namespace ts.Completions {
|
||||
}
|
||||
|
||||
const semanticStart = timestamp();
|
||||
let isGlobalCompletion = false;
|
||||
let isMemberCompletion: boolean;
|
||||
let allowStringLiteral = false;
|
||||
let isNewIdentifierLocation: boolean;
|
||||
let completionKind = CompletionKind.None;
|
||||
let isNewIdentifierLocation = false;
|
||||
let keywordFilters = KeywordCompletionFilters.None;
|
||||
let symbols: Symbol[] = [];
|
||||
const symbolToOriginInfoMap: SymbolOriginInfoMap = [];
|
||||
@@ -867,8 +908,7 @@ namespace ts.Completions {
|
||||
else {
|
||||
symbols = tagSymbols;
|
||||
}
|
||||
isMemberCompletion = true;
|
||||
isNewIdentifierLocation = false;
|
||||
completionKind = CompletionKind.MemberLike;
|
||||
}
|
||||
else if (isStartingCloseTag) {
|
||||
const tagName = (<JsxElement>contextToken.parent.parent).openingElement.tagName;
|
||||
@@ -877,8 +917,7 @@ namespace ts.Completions {
|
||||
if (!typeChecker.isUnknownSymbol(tagSymbol)) {
|
||||
symbols = [tagSymbol];
|
||||
}
|
||||
isMemberCompletion = true;
|
||||
isNewIdentifierLocation = false;
|
||||
completionKind = CompletionKind.MemberLike;
|
||||
}
|
||||
else {
|
||||
// For JavaScript or TypeScript, if we're not after a dot, then just try to get the
|
||||
@@ -892,7 +931,7 @@ namespace ts.Completions {
|
||||
log("getCompletionData: Semantic work: " + (timestamp() - semanticStart));
|
||||
|
||||
const recommendedCompletion = previousToken && getRecommendedCompletion(previousToken, typeChecker);
|
||||
return { symbols, isGlobalCompletion, isMemberCompletion, allowStringLiteral, isNewIdentifierLocation, location, isRightOfDot: (isRightOfDot || isRightOfOpenTag), request, keywordFilters, symbolToOriginInfoMap, recommendedCompletion, previousToken };
|
||||
return { kind: CompletionDataKind.Data, symbols, completionKind, propertyAccessToConvert, isNewIdentifierLocation, location, keywordFilters, symbolToOriginInfoMap, recommendedCompletion, previousToken };
|
||||
|
||||
type JSDocTagWithTypeExpression = JSDocParameterTag | JSDocPropertyTag | JSDocReturnTag | JSDocTypeTag | JSDocTypedefTag;
|
||||
|
||||
@@ -909,9 +948,7 @@ namespace ts.Completions {
|
||||
|
||||
function getTypeScriptMemberSymbols(): void {
|
||||
// Right of dot member completion list
|
||||
isGlobalCompletion = false;
|
||||
isMemberCompletion = true;
|
||||
isNewIdentifierLocation = false;
|
||||
completionKind = CompletionKind.PropertyAccess;
|
||||
|
||||
// Since this is qualified name check its a type node location
|
||||
const isTypeLocation = insideJsDocTagTypeExpression || isPartOfTypeNode(node.parent);
|
||||
@@ -987,7 +1024,7 @@ namespace ts.Completions {
|
||||
|
||||
if (tryGetConstructorLikeCompletionContainer(contextToken)) {
|
||||
// no members, only keywords
|
||||
isMemberCompletion = false;
|
||||
completionKind = CompletionKind.None;
|
||||
// Declaring new property/method/accessor
|
||||
isNewIdentifierLocation = true;
|
||||
// Has keywords for constructor parameter
|
||||
@@ -1009,7 +1046,7 @@ namespace ts.Completions {
|
||||
|
||||
if (attrsType) {
|
||||
symbols = filterJsxAttributes(typeChecker.getPropertiesOfType(attrsType), (<JsxOpeningLikeElement>jsxContainer).attributes.properties);
|
||||
isMemberCompletion = true;
|
||||
completionKind = CompletionKind.MemberLike;
|
||||
isNewIdentifierLocation = false;
|
||||
return true;
|
||||
}
|
||||
@@ -1017,7 +1054,7 @@ namespace ts.Completions {
|
||||
}
|
||||
|
||||
// Get all entities in the current scope.
|
||||
isMemberCompletion = false;
|
||||
completionKind = CompletionKind.None;
|
||||
isNewIdentifierLocation = isNewIdentifierDefinitionLocation(contextToken);
|
||||
|
||||
if (previousToken !== contextToken) {
|
||||
@@ -1053,13 +1090,8 @@ namespace ts.Completions {
|
||||
position;
|
||||
|
||||
const scopeNode = getScopeNode(contextToken, adjustedPosition, sourceFile) || sourceFile;
|
||||
if (scopeNode) {
|
||||
isGlobalCompletion =
|
||||
scopeNode.kind === SyntaxKind.SourceFile ||
|
||||
scopeNode.kind === SyntaxKind.TemplateExpression ||
|
||||
scopeNode.kind === SyntaxKind.JsxExpression ||
|
||||
scopeNode.kind === SyntaxKind.Block || // Some blocks aren't statements, but all get global completions
|
||||
isStatement(scopeNode);
|
||||
if (isGlobalCompletionScope(scopeNode)) {
|
||||
completionKind = CompletionKind.Global;
|
||||
}
|
||||
|
||||
const symbolMeanings = SymbolFlags.Type | SymbolFlags.Value | SymbolFlags.Namespace | SymbolFlags.Alias;
|
||||
@@ -1073,6 +1105,18 @@ namespace ts.Completions {
|
||||
return true;
|
||||
}
|
||||
|
||||
function isGlobalCompletionScope(scopeNode: Node): boolean {
|
||||
switch (scopeNode.kind) {
|
||||
case SyntaxKind.SourceFile:
|
||||
case SyntaxKind.TemplateExpression:
|
||||
case SyntaxKind.JsxExpression:
|
||||
case SyntaxKind.Block:
|
||||
return true;
|
||||
default:
|
||||
return isStatement(scopeNode);
|
||||
}
|
||||
}
|
||||
|
||||
function filterGlobalCompletion(symbols: Symbol[]): void {
|
||||
filterMutate(symbols, symbol => {
|
||||
if (!isSourceFile(location)) {
|
||||
@@ -1154,9 +1198,10 @@ namespace ts.Completions {
|
||||
codefix.forEachExternalModuleToImportFrom(typeChecker, sourceFile, allSourceFiles, moduleSymbol => {
|
||||
for (let symbol of typeChecker.getExportsOfModule(moduleSymbol)) {
|
||||
// Don't add a completion for a re-export, only for the original.
|
||||
// If `symbol.parent !== moduleSymbol`, this comes from an `export * from "foo"` re-export. Those don't create new symbols.
|
||||
// If `symbol.parent !== ...`, this comes from an `export * from "foo"` re-export. Those don't create new symbols.
|
||||
// If `some(...)`, this comes from an `export { foo } from "foo"` re-export, which creates a new symbol (thus isn't caught by the first check).
|
||||
if (symbol.parent !== moduleSymbol || some(symbol.declarations, d => isExportSpecifier(d) && !!d.parent.parent.moduleSpecifier)) {
|
||||
if (symbol.parent !== typeChecker.resolveExternalModuleSymbol(moduleSymbol)
|
||||
|| some(symbol.declarations, d => isExportSpecifier(d) && !!d.parent.parent.moduleSpecifier)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1331,8 +1376,7 @@ namespace ts.Completions {
|
||||
*/
|
||||
function tryGetObjectLikeCompletionSymbols(objectLikeContainer: ObjectLiteralExpression | ObjectBindingPattern): boolean {
|
||||
// We're looking up possible property names from contextual/inferred/declared type.
|
||||
isMemberCompletion = true;
|
||||
allowStringLiteral = true;
|
||||
completionKind = CompletionKind.ObjectPropertyDeclaration;
|
||||
|
||||
let typeMembers: Symbol[];
|
||||
let existingMembers: ReadonlyArray<Declaration>;
|
||||
@@ -1410,7 +1454,7 @@ namespace ts.Completions {
|
||||
return false;
|
||||
}
|
||||
|
||||
isMemberCompletion = true;
|
||||
completionKind = CompletionKind.MemberLike;
|
||||
isNewIdentifierLocation = false;
|
||||
|
||||
const moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(moduleSpecifier);
|
||||
@@ -1430,7 +1474,7 @@ namespace ts.Completions {
|
||||
*/
|
||||
function getGetClassLikeCompletionSymbols(classLikeDeclaration: ClassLikeDeclaration) {
|
||||
// We're looking up possible property names from parent type.
|
||||
isMemberCompletion = true;
|
||||
completionKind = CompletionKind.MemberLike;
|
||||
// Declaring new property/method/accessor
|
||||
isNewIdentifierLocation = true;
|
||||
// Has keywords for class elements
|
||||
@@ -1984,55 +2028,44 @@ namespace ts.Completions {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name to be display in completion from a given symbol.
|
||||
*
|
||||
* @return undefined if the name is of external module
|
||||
*/
|
||||
function getCompletionEntryDisplayNameForSymbol(symbol: Symbol, target: ScriptTarget, performCharacterChecks: boolean, allowStringLiteral: boolean, origin: SymbolOriginInfo | undefined): string | undefined {
|
||||
const name = getSymbolName(symbol, origin, target);
|
||||
if (!name) return undefined;
|
||||
|
||||
// First check of the displayName is not external module; if it is an external module, it is not valid entry
|
||||
if (symbol.flags & SymbolFlags.Namespace) {
|
||||
const firstCharCode = name.charCodeAt(0);
|
||||
if (isSingleOrDoubleQuote(firstCharCode)) {
|
||||
// If the symbol is external module, don't show it in the completion list
|
||||
// (i.e declare module "http" { const x; } | // <= request completion here, "http" should not be there)
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
// If the symbol is for a member of an object type and is the internal name of an ES
|
||||
// symbol, it is not a valid entry. Internal names for ES symbols start with "__@"
|
||||
if (symbol.flags & SymbolFlags.ClassMember) {
|
||||
const escapedName = symbol.escapedName as string;
|
||||
if (escapedName.length >= 3 &&
|
||||
escapedName.charCodeAt(0) === CharacterCodes._ &&
|
||||
escapedName.charCodeAt(1) === CharacterCodes._ &&
|
||||
escapedName.charCodeAt(2) === CharacterCodes.at) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
return getCompletionEntryDisplayName(name, target, performCharacterChecks, allowStringLiteral);
|
||||
interface CompletionEntryDisplayNameForSymbol {
|
||||
readonly name: string;
|
||||
readonly needsConvertPropertyAccess: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a displayName from a given for completion list, performing any necessary quotes stripping
|
||||
* and checking whether the name is valid identifier name.
|
||||
*/
|
||||
function getCompletionEntryDisplayName(name: string, target: ScriptTarget, performCharacterChecks: boolean, allowStringLiteral: boolean): string {
|
||||
// If the user entered name for the symbol was quoted, removing the quotes is not enough, as the name could be an
|
||||
// invalid identifier name. We need to check if whatever was inside the quotes is actually a valid identifier name.
|
||||
// e.g "b a" is valid quoted name but when we strip off the quotes, it is invalid.
|
||||
// We, thus, need to check if whatever was inside the quotes is actually a valid identifier name.
|
||||
if (performCharacterChecks && !isIdentifierText(name, target)) {
|
||||
// TODO: GH#18169
|
||||
return allowStringLiteral ? JSON.stringify(name) : undefined;
|
||||
function getCompletionEntryDisplayNameForSymbol(
|
||||
symbol: Symbol,
|
||||
target: ScriptTarget,
|
||||
origin: SymbolOriginInfo | undefined,
|
||||
kind: CompletionKind,
|
||||
): CompletionEntryDisplayNameForSymbol | undefined {
|
||||
const name = getSymbolName(symbol, origin, target);
|
||||
if (name === undefined
|
||||
// If the symbol is external module, don't show it in the completion list
|
||||
// (i.e declare module "http" { const x; } | // <= request completion here, "http" should not be there)
|
||||
|| symbol.flags & SymbolFlags.Module && startsWithQuote(name)
|
||||
// If the symbol is the internal name of an ES symbol, it is not a valid entry. Internal names for ES symbols start with "__@"
|
||||
|| isKnownSymbol(symbol)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return name;
|
||||
const validIdentiferResult: CompletionEntryDisplayNameForSymbol = { name, needsConvertPropertyAccess: false };
|
||||
if (isIdentifierText(name, target)) return validIdentiferResult;
|
||||
switch (kind) {
|
||||
case CompletionKind.None:
|
||||
case CompletionKind.Global:
|
||||
case CompletionKind.MemberLike:
|
||||
return undefined;
|
||||
case CompletionKind.ObjectPropertyDeclaration:
|
||||
// TODO: GH#18169
|
||||
return { name: JSON.stringify(name), needsConvertPropertyAccess: false };
|
||||
case CompletionKind.PropertyAccess:
|
||||
// Don't add a completion for a name starting with a space. See https://github.com/Microsoft/TypeScript/pull/20547
|
||||
return name.charCodeAt(0) === CharacterCodes.space ? undefined : { name, needsConvertPropertyAccess: true };
|
||||
case CompletionKind.String:
|
||||
return validIdentiferResult;
|
||||
default:
|
||||
Debug.assertNever(kind);
|
||||
}
|
||||
}
|
||||
|
||||
// A cache of completion entries for keywords, these do not change between sessions
|
||||
@@ -2045,7 +2078,7 @@ namespace ts.Completions {
|
||||
return _keywordCompletions[keywordFilter] = generateKeywordCompletions(keywordFilter);
|
||||
|
||||
type FilterKeywordCompletions = (entryName: string) => boolean;
|
||||
function generateKeywordCompletions(keywordFilter: KeywordCompletionFilters) {
|
||||
function generateKeywordCompletions(keywordFilter: KeywordCompletionFilters): CompletionEntry[] {
|
||||
switch (keywordFilter) {
|
||||
case KeywordCompletionFilters.None:
|
||||
return getAllKeywordCompletions();
|
||||
@@ -2053,6 +2086,8 @@ namespace ts.Completions {
|
||||
return getFilteredKeywordCompletions(isClassMemberCompletionKeywordText);
|
||||
case KeywordCompletionFilters.ConstructorParameterKeywords:
|
||||
return getFilteredKeywordCompletions(isConstructorParameterCompletionKeywordText);
|
||||
default:
|
||||
Debug.assertNever(keywordFilter);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,19 +2,15 @@
|
||||
namespace ts.DocumentHighlights {
|
||||
export function getDocumentHighlights(program: Program, cancellationToken: CancellationToken, sourceFile: SourceFile, position: number, sourceFilesToSearch: SourceFile[]): DocumentHighlights[] | undefined {
|
||||
const node = getTouchingWord(sourceFile, position, /*includeJsDocComment*/ true);
|
||||
// Note that getTouchingWord indicates failure by returning the sourceFile node.
|
||||
if (node === sourceFile) return undefined;
|
||||
|
||||
Debug.assert(node.parent !== undefined);
|
||||
|
||||
if (isJsxOpeningElement(node.parent) && node.parent.tagName === node || isJsxClosingElement(node.parent)) {
|
||||
if (node.parent && (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);
|
||||
return getSemanticDocumentHighlights(position, node, program, cancellationToken, sourceFilesToSearch) || getSyntacticDocumentHighlights(node, sourceFile);
|
||||
}
|
||||
|
||||
function getHighlightSpanForNode(node: Node, sourceFile: SourceFile): HighlightSpan {
|
||||
@@ -25,8 +21,8 @@ namespace ts.DocumentHighlights {
|
||||
};
|
||||
}
|
||||
|
||||
function getSemanticDocumentHighlights(node: Node, program: Program, cancellationToken: CancellationToken, sourceFilesToSearch: SourceFile[]): DocumentHighlights[] {
|
||||
const referenceEntries = FindAllReferences.getReferenceEntriesForNode(node, program, sourceFilesToSearch, cancellationToken);
|
||||
function getSemanticDocumentHighlights(position: number, node: Node, program: Program, cancellationToken: CancellationToken, sourceFilesToSearch: SourceFile[]): DocumentHighlights[] {
|
||||
const referenceEntries = FindAllReferences.getReferenceEntriesForNode(position, node, program, sourceFilesToSearch, cancellationToken);
|
||||
return referenceEntries && convertReferencedSymbols(referenceEntries);
|
||||
}
|
||||
|
||||
|
||||
@@ -52,12 +52,12 @@ namespace ts.FindAllReferences {
|
||||
export function getImplementationsAtPosition(program: Program, cancellationToken: CancellationToken, sourceFiles: ReadonlyArray<SourceFile>, sourceFile: SourceFile, position: number): ImplementationLocation[] {
|
||||
// A node in a JSDoc comment can't have an implementation anyway.
|
||||
const node = getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ false);
|
||||
const referenceEntries = getImplementationReferenceEntries(program, cancellationToken, sourceFiles, node);
|
||||
const referenceEntries = getImplementationReferenceEntries(program, cancellationToken, sourceFiles, node, position);
|
||||
const checker = program.getTypeChecker();
|
||||
return map(referenceEntries, entry => toImplementationLocation(entry, checker));
|
||||
}
|
||||
|
||||
function getImplementationReferenceEntries(program: Program, cancellationToken: CancellationToken, sourceFiles: ReadonlyArray<SourceFile>, node: Node): Entry[] | undefined {
|
||||
function getImplementationReferenceEntries(program: Program, cancellationToken: CancellationToken, sourceFiles: ReadonlyArray<SourceFile>, node: Node, position: number): Entry[] | undefined {
|
||||
if (node.kind === SyntaxKind.SourceFile) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -78,7 +78,7 @@ namespace ts.FindAllReferences {
|
||||
}
|
||||
else {
|
||||
// Perform "Find all References" and retrieve only those that are implementations
|
||||
return getReferenceEntriesForNode(node, program, sourceFiles, cancellationToken, { implementations: true });
|
||||
return getReferenceEntriesForNode(position, node, program, sourceFiles, cancellationToken, { implementations: true });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,13 +87,13 @@ namespace ts.FindAllReferences {
|
||||
return map(x, toReferenceEntry);
|
||||
}
|
||||
|
||||
export function getReferenceEntriesForNode(node: Node, program: Program, sourceFiles: ReadonlyArray<SourceFile>, cancellationToken: CancellationToken, options: Options = {}): Entry[] | undefined {
|
||||
return flattenEntries(Core.getReferencedSymbolsForNode(node, program, sourceFiles, cancellationToken, options));
|
||||
export function getReferenceEntriesForNode(position: number, node: Node, program: Program, sourceFiles: ReadonlyArray<SourceFile>, cancellationToken: CancellationToken, options: Options = {}): Entry[] | undefined {
|
||||
return flattenEntries(Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options));
|
||||
}
|
||||
|
||||
function findAllReferencedSymbols(program: Program, cancellationToken: CancellationToken, sourceFiles: ReadonlyArray<SourceFile>, sourceFile: SourceFile, position: number, options?: Options): SymbolAndEntries[] | undefined {
|
||||
const node = getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true);
|
||||
return Core.getReferencedSymbolsForNode(node, program, sourceFiles, cancellationToken, options);
|
||||
return Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options);
|
||||
}
|
||||
|
||||
function flattenEntries(referenceSymbols: SymbolAndEntries[]): Entry[] {
|
||||
@@ -242,9 +242,10 @@ namespace ts.FindAllReferences {
|
||||
/* @internal */
|
||||
namespace ts.FindAllReferences.Core {
|
||||
/** Core find-all-references algorithm. Handles special cases before delegating to `getReferencedSymbolsForSymbol`. */
|
||||
export function getReferencedSymbolsForNode(node: Node, program: Program, sourceFiles: ReadonlyArray<SourceFile>, cancellationToken: CancellationToken, options: Options = {}): SymbolAndEntries[] | undefined {
|
||||
if (node.kind === ts.SyntaxKind.SourceFile) {
|
||||
return undefined;
|
||||
export function getReferencedSymbolsForNode(position: number, node: Node, program: Program, sourceFiles: ReadonlyArray<SourceFile>, cancellationToken: CancellationToken, options: Options = {}): SymbolAndEntries[] | undefined {
|
||||
if (isSourceFile(node)) {
|
||||
const reference = GoToDefinition.getReferenceAtPosition(node, position, program);
|
||||
return reference && getReferencedSymbolsForModule(program, program.getTypeChecker().getMergedSymbol(reference.file.symbol), sourceFiles);
|
||||
}
|
||||
|
||||
if (!options.implementations) {
|
||||
@@ -260,11 +261,7 @@ namespace ts.FindAllReferences.Core {
|
||||
// Could not find a symbol e.g. unknown identifier
|
||||
if (!symbol) {
|
||||
// String literal might be a property (and thus have a symbol), so do this here rather than in getReferencedSymbolsSpecial.
|
||||
if (!options.implementations && node.kind === SyntaxKind.StringLiteral) {
|
||||
return getReferencesForStringLiteral(<StringLiteral>node, sourceFiles, cancellationToken);
|
||||
}
|
||||
// Can't have references to something that we have no symbol for.
|
||||
return undefined;
|
||||
return !options.implementations && isStringLiteral(node) ? getReferencesForStringLiteral(node, sourceFiles, cancellationToken) : undefined;
|
||||
}
|
||||
|
||||
if (symbol.flags & SymbolFlags.Module && isModuleReferenceLocation(node)) {
|
||||
@@ -499,6 +496,9 @@ namespace ts.FindAllReferences.Core {
|
||||
/** @param allSearchSymbols set of additinal symbols for use by `includes`. */
|
||||
createSearch(location: Node, symbol: Symbol, comingFrom: ImportExport | undefined, searchOptions: { text?: string, allSearchSymbols?: Symbol[] } = {}): Search {
|
||||
// Note: if this is an external module symbol, the name doesn't include quotes.
|
||||
// Note: getLocalSymbolForExportDefault handles `export default class C {}`, but not `export default C` or `export { C as default }`.
|
||||
// The other two forms seem to be handled downstream (e.g. in `skipPastExportOrImportSpecifier`), so special-casing the first form
|
||||
// here appears to be intentional).
|
||||
const {
|
||||
text = stripQuotes(unescapeLeadingUnderscores((getLocalSymbolForExportDefault(symbol) || symbol).escapedName)),
|
||||
allSearchSymbols = undefined,
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace ts.formatting {
|
||||
rule("IgnoreBeforeComment", anyToken, comments, anyContext, RuleAction.Ignore),
|
||||
rule("IgnoreAfterLineComment", SyntaxKind.SingleLineCommentTrivia, anyToken, anyContext, RuleAction.Ignore),
|
||||
|
||||
rule("NoSpaceBeforeColon", anyToken, SyntaxKind.ColonToken, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], RuleAction.Delete),
|
||||
rule("NotSpaceBeforeColon", anyToken, SyntaxKind.ColonToken, [isNonJsxSameLineTokenContext, isNotBinaryOpContext, isNotTypeAnnotationContext], RuleAction.Delete),
|
||||
rule("SpaceAfterColon", SyntaxKind.ColonToken, anyToken, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], RuleAction.Space),
|
||||
rule("NoSpaceBeforeQuestionMark", anyToken, SyntaxKind.QuestionToken, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], RuleAction.Delete),
|
||||
// insert space after '?' only when it is used in conditional operator
|
||||
@@ -69,10 +69,10 @@ namespace ts.formatting {
|
||||
rule("NoSpaceBeforeUnaryPostdecrementOperator", unaryPostdecrementExpressions, SyntaxKind.MinusMinusToken, [isNonJsxSameLineTokenContext], RuleAction.Delete),
|
||||
|
||||
// More unary operator special-casing.
|
||||
// DevDiv 181814: Be careful when removing leading whitespace
|
||||
// DevDiv 181814: Be careful when removing leading whitespace
|
||||
// around unary operators. Examples:
|
||||
// 1 - -2 --X--> 1--2
|
||||
// a + ++b --X--> a+++b
|
||||
// 1 - -2 --X--> 1--2
|
||||
// a + ++b --X--> a+++b
|
||||
rule("SpaceAfterPostincrementWhenFollowedByAdd", SyntaxKind.PlusPlusToken, SyntaxKind.PlusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.Space),
|
||||
rule("SpaceAfterAddWhenFollowedByUnaryPlus", SyntaxKind.PlusToken, SyntaxKind.PlusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.Space),
|
||||
rule("SpaceAfterAddWhenFollowedByPreincrement", SyntaxKind.PlusToken, SyntaxKind.PlusPlusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.Space),
|
||||
@@ -300,6 +300,9 @@ namespace ts.formatting {
|
||||
|
||||
rule("SpaceAfterTypeAssertion", SyntaxKind.GreaterThanToken, anyToken, [isOptionEnabled("insertSpaceAfterTypeAssertion"), isNonJsxSameLineTokenContext, isTypeAssertionContext], RuleAction.Space),
|
||||
rule("NoSpaceAfterTypeAssertion", SyntaxKind.GreaterThanToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterTypeAssertion"), isNonJsxSameLineTokenContext, isTypeAssertionContext], RuleAction.Delete),
|
||||
|
||||
rule("SpaceBeforeTypeAnnotation", anyToken, SyntaxKind.ColonToken, [isOptionEnabled("insertSpaceBeforeTypeAnnotation"), isNonJsxSameLineTokenContext, isTypeAnnotationContext], RuleAction.Space),
|
||||
rule("NoSpaceBeforeTypeAnnotation", anyToken, SyntaxKind.ColonToken, [isOptionDisabledOrUndefined("insertSpaceBeforeTypeAnnotation"), isNonJsxSameLineTokenContext, isTypeAnnotationContext], RuleAction.Delete),
|
||||
];
|
||||
|
||||
// These rules are lower in priority than user-configurable. Rules earlier in this list have priority over rules later in the list.
|
||||
@@ -441,6 +444,19 @@ namespace ts.formatting {
|
||||
return !isBinaryOpContext(context);
|
||||
}
|
||||
|
||||
function isNotTypeAnnotationContext(context: FormattingContext): boolean {
|
||||
return !isTypeAnnotationContext(context);
|
||||
}
|
||||
|
||||
function isTypeAnnotationContext(context: FormattingContext): boolean {
|
||||
const contextKind = context.contextNode.kind;
|
||||
return contextKind === SyntaxKind.PropertyDeclaration ||
|
||||
contextKind === SyntaxKind.PropertySignature ||
|
||||
contextKind === SyntaxKind.Parameter ||
|
||||
contextKind === SyntaxKind.VariableDeclaration ||
|
||||
isFunctionLikeKind(contextKind);
|
||||
}
|
||||
|
||||
function isConditionalOperatorContext(context: FormattingContext): boolean {
|
||||
return context.contextNode.kind === SyntaxKind.ConditionalExpression;
|
||||
}
|
||||
|
||||
@@ -367,12 +367,13 @@ namespace ts.formatting {
|
||||
|
||||
function getActualIndentationForListItem(node: Node, sourceFile: SourceFile, options: EditorSettings): number {
|
||||
const containingList = getContainingList(node, sourceFile);
|
||||
return containingList ? getActualIndentationFromList(containingList) : Value.Unknown;
|
||||
|
||||
function getActualIndentationFromList(list: ReadonlyArray<Node>): number {
|
||||
const index = indexOf(list, node);
|
||||
return index !== -1 ? deriveActualIndentationFromList(list, index, sourceFile, options) : Value.Unknown;
|
||||
if (containingList) {
|
||||
const index = containingList.indexOf(node);
|
||||
if (index !== -1) {
|
||||
return deriveActualIndentationFromList(containingList, index, sourceFile, options);
|
||||
}
|
||||
}
|
||||
return Value.Unknown;
|
||||
}
|
||||
|
||||
function getLineIndentationWhenExpressionIsInMultiLine(node: Node, sourceFile: SourceFile, options: EditorSettings): number {
|
||||
|
||||
@@ -1,22 +1,9 @@
|
||||
/* @internal */
|
||||
namespace ts.GoToDefinition {
|
||||
export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile, position: number): DefinitionInfo[] {
|
||||
/// Triple slash reference comments
|
||||
const comment = findReferenceInPosition(sourceFile.referencedFiles, position);
|
||||
if (comment) {
|
||||
const referenceFile = tryResolveScriptReference(program, sourceFile, comment);
|
||||
if (referenceFile) {
|
||||
return [getDefinitionInfoForFileReference(comment.fileName, referenceFile.fileName)];
|
||||
}
|
||||
// Might still be on jsdoc, so keep looking.
|
||||
}
|
||||
|
||||
// Type reference directives
|
||||
const typeReferenceDirective = findReferenceInPosition(sourceFile.typeReferenceDirectives, position);
|
||||
if (typeReferenceDirective) {
|
||||
const referenceFile = program.getResolvedTypeReferenceDirectives().get(typeReferenceDirective.fileName);
|
||||
return referenceFile && referenceFile.resolvedFileName &&
|
||||
[getDefinitionInfoForFileReference(typeReferenceDirective.fileName, referenceFile.resolvedFileName)];
|
||||
const reference = getReferenceAtPosition(sourceFile, position, program);
|
||||
if (reference) {
|
||||
return [getDefinitionInfoForFileReference(reference.fileName, reference.file.fileName)];
|
||||
}
|
||||
|
||||
const node = getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true);
|
||||
@@ -115,6 +102,23 @@ namespace ts.GoToDefinition {
|
||||
return getDefinitionFromSymbol(typeChecker, symbol, node);
|
||||
}
|
||||
|
||||
export function getReferenceAtPosition(sourceFile: SourceFile, position: number, program: Program): { fileName: string, file: SourceFile } | undefined {
|
||||
const referencePath = findReferenceInPosition(sourceFile.referencedFiles, position);
|
||||
if (referencePath) {
|
||||
const file = tryResolveScriptReference(program, sourceFile, referencePath);
|
||||
return file && { fileName: referencePath.fileName, file };
|
||||
}
|
||||
|
||||
const typeReferenceDirective = findReferenceInPosition(sourceFile.typeReferenceDirectives, position);
|
||||
if (typeReferenceDirective) {
|
||||
const reference = program.getResolvedTypeReferenceDirectives().get(typeReferenceDirective.fileName);
|
||||
const file = reference && program.getSourceFile(reference.resolvedFileName);
|
||||
return file && { fileName: typeReferenceDirective.fileName, file };
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/// Goto type
|
||||
export function getTypeDefinitionAtPosition(typeChecker: TypeChecker, sourceFile: SourceFile, position: number): DefinitionInfo[] {
|
||||
const node = getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true);
|
||||
@@ -301,7 +305,7 @@ namespace ts.GoToDefinition {
|
||||
return createDefinitionInfo(decl, symbolKind, symbolName, containerName);
|
||||
}
|
||||
|
||||
function findReferenceInPosition(refs: ReadonlyArray<FileReference>, pos: number): FileReference {
|
||||
export function findReferenceInPosition(refs: ReadonlyArray<FileReference>, pos: number): FileReference {
|
||||
for (const ref of refs) {
|
||||
if (ref.pos <= pos && pos <= ref.end) {
|
||||
return ref;
|
||||
|
||||
@@ -616,7 +616,7 @@ 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.
|
||||
// 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) {
|
||||
|
||||
@@ -112,7 +112,7 @@ namespace ts.JsDoc {
|
||||
function forEachUnique<T, U>(array: T[], callback: (element: T, index: number) => U): U {
|
||||
if (array) {
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
if (indexOf(array, array[i]) === i) {
|
||||
if (array.indexOf(array[i]) === i) {
|
||||
const result = callback(array[i], i);
|
||||
if (result) {
|
||||
return result;
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace ts.NavigateTo {
|
||||
continue;
|
||||
}
|
||||
|
||||
// It was a match! If the pattern has dots in it, then also see if the
|
||||
// It was a match! If the pattern has dots in it, then also see if the
|
||||
// declaration container matches as well.
|
||||
let containerMatches = matches;
|
||||
if (patternMatcher.patternContainsDots) {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/* @internal */
|
||||
namespace ts.Completions.PathCompletions {
|
||||
export function getStringLiteralCompletionsFromModuleNames(node: LiteralExpression, compilerOptions: CompilerOptions, host: LanguageServiceHost, typeChecker: TypeChecker): CompletionEntry[] {
|
||||
export function getStringLiteralCompletionsFromModuleNames(sourceFile: SourceFile, node: LiteralExpression, compilerOptions: CompilerOptions, host: LanguageServiceHost, typeChecker: TypeChecker): CompletionEntry[] {
|
||||
const literalValue = normalizeSlashes(node.text);
|
||||
|
||||
const scriptPath = node.getSourceFile().path;
|
||||
const scriptDirectory = getDirectoryPath(scriptPath);
|
||||
|
||||
const span = getDirectoryFragmentTextSpan((<StringLiteral>node).text, node.getStart() + 1);
|
||||
const span = getDirectoryFragmentTextSpan((<StringLiteral>node).text, node.getStart(sourceFile) + 1);
|
||||
if (isPathRelativeToScript(literalValue) || isRootedDiskPath(literalValue)) {
|
||||
const extensions = getSupportedExtensions(compilerOptions);
|
||||
if (compilerOptions.rootDirs) {
|
||||
@@ -147,25 +147,15 @@ namespace ts.Completions.PathCompletions {
|
||||
getCompletionEntriesForDirectoryFragment(fragment, normalizePath(absolute), fileExtensions, /*includeExtensions*/ false, span, host, /*exclude*/ undefined, result);
|
||||
|
||||
for (const path in paths) {
|
||||
if (!paths.hasOwnProperty(path)) continue;
|
||||
const patterns = paths[path];
|
||||
if (!patterns) continue;
|
||||
|
||||
if (path === "*") {
|
||||
for (const pattern of patterns) {
|
||||
for (const match of getModulesForPathsPattern(fragment, baseUrl, pattern, fileExtensions, host)) {
|
||||
// Path mappings may provide a duplicate way to get to something we've already added, so don't add again.
|
||||
if (result.some(entry => entry.name === match)) continue;
|
||||
result.push(createCompletionEntryForModule(match, ScriptElementKind.externalModuleName, span));
|
||||
if (paths.hasOwnProperty(path) && patterns) {
|
||||
for (const pathCompletion of getCompletionsForPathMapping(path, patterns, fragment, baseUrl, fileExtensions, host)) {
|
||||
// Path mappings may provide a duplicate way to get to something we've already added, so don't add again.
|
||||
if (!result.some(entry => entry.name === pathCompletion)) {
|
||||
result.push(createCompletionEntryForModule(pathCompletion, ScriptElementKind.externalModuleName, span));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (startsWith(path, fragment)) {
|
||||
if (patterns.length === 1) {
|
||||
if (result.some(entry => entry.name === path)) continue;
|
||||
result.push(createCompletionEntryForModule(path, ScriptElementKind.externalModuleName, span));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,52 +177,66 @@ namespace ts.Completions.PathCompletions {
|
||||
return result;
|
||||
}
|
||||
|
||||
function getModulesForPathsPattern(fragment: string, baseUrl: string, pattern: string, fileExtensions: ReadonlyArray<string>, host: LanguageServiceHost): string[] {
|
||||
if (host.readDirectory) {
|
||||
const parsed = hasZeroOrOneAsteriskCharacter(pattern) ? tryParsePattern(pattern) : undefined;
|
||||
if (parsed) {
|
||||
// The prefix has two effective parts: the directory path and the base component after the filepath that is not a
|
||||
// full directory component. For example: directory/path/of/prefix/base*
|
||||
const normalizedPrefix = normalizeAndPreserveTrailingSlash(parsed.prefix);
|
||||
const normalizedPrefixDirectory = getDirectoryPath(normalizedPrefix);
|
||||
const normalizedPrefixBase = getBaseFileName(normalizedPrefix);
|
||||
|
||||
const fragmentHasPath = stringContains(fragment, directorySeparator);
|
||||
|
||||
// Try and expand the prefix to include any path from the fragment so that we can limit the readDirectory call
|
||||
const expandedPrefixDirectory = fragmentHasPath ? combinePaths(normalizedPrefixDirectory, normalizedPrefixBase + getDirectoryPath(fragment)) : normalizedPrefixDirectory;
|
||||
|
||||
const normalizedSuffix = normalizePath(parsed.suffix);
|
||||
const baseDirectory = combinePaths(baseUrl, expandedPrefixDirectory);
|
||||
const completePrefix = fragmentHasPath ? baseDirectory : ensureTrailingDirectorySeparator(baseDirectory) + normalizedPrefixBase;
|
||||
|
||||
// If we have a suffix, then we need to read the directory all the way down. We could create a glob
|
||||
// that encodes the suffix, but we would have to escape the character "?" which readDirectory
|
||||
// doesn't support. For now, this is safer but slower
|
||||
const includeGlob = normalizedSuffix ? "**/*" : "./*";
|
||||
|
||||
const matches = tryReadDirectory(host, baseDirectory, fileExtensions, /*exclude*/ undefined, [includeGlob]);
|
||||
if (matches) {
|
||||
const result: string[] = [];
|
||||
|
||||
// Trim away prefix and suffix
|
||||
for (const match of matches) {
|
||||
const normalizedMatch = normalizePath(match);
|
||||
if (!endsWith(normalizedMatch, normalizedSuffix) || !startsWith(normalizedMatch, completePrefix)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const start = completePrefix.length;
|
||||
const length = normalizedMatch.length - start - normalizedSuffix.length;
|
||||
|
||||
result.push(removeFileExtension(normalizedMatch.substr(start, length)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
function getCompletionsForPathMapping(
|
||||
path: string, patterns: ReadonlyArray<string>, fragment: string, baseUrl: string, fileExtensions: ReadonlyArray<string>, host: LanguageServiceHost,
|
||||
): string[] {
|
||||
if (!endsWith(path, "*")) {
|
||||
// For a path mapping "foo": ["/x/y/z.ts"], add "foo" itself as a completion.
|
||||
return !stringContains(path, "*") && startsWith(path, fragment) ? [path] : emptyArray;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
const pathPrefix = path.slice(0, path.length - 1);
|
||||
if (!startsWith(fragment, pathPrefix)) {
|
||||
return emptyArray;
|
||||
}
|
||||
|
||||
const remainingFragment = fragment.slice(pathPrefix.length);
|
||||
return flatMap(patterns, pattern => getModulesForPathsPattern(remainingFragment, baseUrl, pattern, fileExtensions, host));
|
||||
}
|
||||
|
||||
function getModulesForPathsPattern(fragment: string, baseUrl: string, pattern: string, fileExtensions: ReadonlyArray<string>, host: LanguageServiceHost): string[] | undefined {
|
||||
if (!host.readDirectory) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const parsed = hasZeroOrOneAsteriskCharacter(pattern) ? tryParsePattern(pattern) : undefined;
|
||||
if (!parsed) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// The prefix has two effective parts: the directory path and the base component after the filepath that is not a
|
||||
// full directory component. For example: directory/path/of/prefix/base*
|
||||
const normalizedPrefix = normalizeAndPreserveTrailingSlash(parsed.prefix);
|
||||
const normalizedPrefixDirectory = getDirectoryPath(normalizedPrefix);
|
||||
const normalizedPrefixBase = getBaseFileName(normalizedPrefix);
|
||||
|
||||
const fragmentHasPath = stringContains(fragment, directorySeparator);
|
||||
|
||||
// Try and expand the prefix to include any path from the fragment so that we can limit the readDirectory call
|
||||
const expandedPrefixDirectory = fragmentHasPath ? combinePaths(normalizedPrefixDirectory, normalizedPrefixBase + getDirectoryPath(fragment)) : normalizedPrefixDirectory;
|
||||
|
||||
const normalizedSuffix = normalizePath(parsed.suffix);
|
||||
// Need to normalize after combining: If we combinePaths("a", "../b"), we want "b" and not "a/../b".
|
||||
const baseDirectory = normalizePath(combinePaths(baseUrl, expandedPrefixDirectory));
|
||||
const completePrefix = fragmentHasPath ? baseDirectory : ensureTrailingDirectorySeparator(baseDirectory) + normalizedPrefixBase;
|
||||
|
||||
// If we have a suffix, then we need to read the directory all the way down. We could create a glob
|
||||
// that encodes the suffix, but we would have to escape the character "?" which readDirectory
|
||||
// doesn't support. For now, this is safer but slower
|
||||
const includeGlob = normalizedSuffix ? "**/*" : "./*";
|
||||
|
||||
const matches = tryReadDirectory(host, baseDirectory, fileExtensions, /*exclude*/ undefined, [includeGlob]);
|
||||
// Trim away prefix and suffix
|
||||
return mapDefined(matches, match => {
|
||||
const normalizedMatch = normalizePath(match);
|
||||
if (!endsWith(normalizedMatch, normalizedSuffix) || !startsWith(normalizedMatch, completePrefix)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const start = completePrefix.length;
|
||||
const length = normalizedMatch.length - start - normalizedSuffix.length;
|
||||
return removeFileExtension(normalizedMatch.substr(start, length));
|
||||
});
|
||||
}
|
||||
|
||||
function enumeratePotentialNonRelativeModules(fragment: string, scriptPath: string, options: CompilerOptions, typeChecker: TypeChecker, host: LanguageServiceHost): string[] {
|
||||
|
||||
@@ -295,7 +295,7 @@ namespace ts {
|
||||
// import "mod";
|
||||
// import d from "mod"
|
||||
// import {a as A } from "mod";
|
||||
// import * as NS from "mod"
|
||||
// import * as NS from "mod"
|
||||
// import d, {a, b as B} from "mod"
|
||||
// import i = require("mod");
|
||||
// import("mod");
|
||||
|
||||
+10
-2
@@ -38,9 +38,17 @@ namespace ts.Rename {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const displayName = stripQuotes(getDeclaredName(typeChecker, symbol, node));
|
||||
const kind = SymbolDisplay.getSymbolKind(typeChecker, symbol, node);
|
||||
return kind ? getRenameInfoSuccess(displayName, typeChecker.getFullyQualifiedName(symbol), kind, SymbolDisplay.getSymbolModifiers(symbol), node, sourceFile) : undefined;
|
||||
if (!kind) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const specifierName = (isImportOrExportSpecifierName(node) || isStringOrNumericLiteral(node) && node.parent.kind === SyntaxKind.ComputedPropertyName)
|
||||
? stripQuotes(getTextOfIdentifierOrLiteral(node))
|
||||
: undefined;
|
||||
const displayName = specifierName || typeChecker.symbolToString(symbol);
|
||||
const fullDisplayName = specifierName || typeChecker.getFullyQualifiedName(symbol);
|
||||
return getRenameInfoSuccess(displayName, fullDisplayName, kind, SymbolDisplay.getSymbolModifiers(symbol), node, sourceFile);
|
||||
}
|
||||
}
|
||||
else if (node.kind === SyntaxKind.StringLiteral) {
|
||||
|
||||
@@ -1432,7 +1432,7 @@ namespace ts {
|
||||
return [...program.getOptionsDiagnostics(cancellationToken), ...program.getGlobalDiagnostics(cancellationToken)];
|
||||
}
|
||||
|
||||
function getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions = { includeExternalModuleExports: false }): CompletionInfo {
|
||||
function getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions = { includeExternalModuleExports: false, includeInsertTextCompletions: false }): CompletionInfo {
|
||||
synchronizeHostData();
|
||||
return Completions.getCompletionsAtPosition(
|
||||
host,
|
||||
@@ -2053,7 +2053,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getTodoCommentsRegExp(): RegExp {
|
||||
// NOTE: ?: means 'non-capture group'. It allows us to have groups without having to
|
||||
// NOTE: `?:` means 'non-capture group'. It allows us to have groups without having to
|
||||
// filter them out later in the final result array.
|
||||
|
||||
// TODO comments can appear in one of the following forms:
|
||||
@@ -2251,20 +2251,6 @@ namespace ts {
|
||||
isLiteralComputedPropertyDeclarationName(node);
|
||||
}
|
||||
|
||||
function isObjectLiteralElement(node: Node): node is ObjectLiteralElement {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.JsxAttribute:
|
||||
case SyntaxKind.JsxSpreadAttribute:
|
||||
case SyntaxKind.PropertyAssignment:
|
||||
case SyntaxKind.ShorthandPropertyAssignment:
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the containing object literal property declaration given a possible name node, e.g. "a" in x = { "a": 1 }
|
||||
*/
|
||||
|
||||
@@ -141,7 +141,6 @@ namespace ts {
|
||||
getEncodedSemanticClassifications(fileName: string, start: number, length: number): string;
|
||||
|
||||
getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions | undefined): string;
|
||||
// tslint:disable-next-line type-operator-spacing (false positive)
|
||||
getCompletionEntryDetails(fileName: string, position: number, entryName: string, options: string/*Services.FormatCodeOptions*/ | undefined, source: string | undefined): string;
|
||||
|
||||
getQuickInfoAtPosition(fileName: string, position: number): string;
|
||||
@@ -907,7 +906,6 @@ namespace ts {
|
||||
}
|
||||
|
||||
/** Get a string based representation of a completion list entry details */
|
||||
// tslint:disable-next-line type-operator-spacing (false positive)
|
||||
public getCompletionEntryDetails(fileName: string, position: number, entryName: string, options: string/*Services.FormatCodeOptions*/ | undefined, source: string | undefined) {
|
||||
return this.forwardJSONCall(
|
||||
`getCompletionEntryDetails('${fileName}', ${position}, '${entryName}')`,
|
||||
|
||||
@@ -197,7 +197,7 @@ namespace ts.SignatureHelp {
|
||||
function getArgumentIndex(argumentsList: Node, node: Node) {
|
||||
// The list we got back can include commas. In the presence of errors it may
|
||||
// also just have nodes without commas. For example "Foo(a b c)" will have 3
|
||||
// args without commas. We want to find what index we're at. So we count
|
||||
// args without commas. We want to find what index we're at. So we count
|
||||
// forward until we hit ourselves, only incrementing the index if it isn't a
|
||||
// comma.
|
||||
//
|
||||
@@ -224,12 +224,12 @@ namespace ts.SignatureHelp {
|
||||
// The argument count for a list is normally the number of non-comma children it has.
|
||||
// For example, if you have "Foo(a,b)" then there will be three children of the arg
|
||||
// list 'a' '<comma>' 'b'. So, in this case the arg count will be 2. However, there
|
||||
// is a small subtlety. If you have "Foo(a,)", then the child list will just have
|
||||
// is a small subtlety. If you have "Foo(a,)", then the child list will just have
|
||||
// 'a' '<comma>'. So, in the case where the last child is a comma, we increase the
|
||||
// arg count by one to compensate.
|
||||
//
|
||||
// Note: this subtlety only applies to the last comma. If you had "Foo(a,," then
|
||||
// we'll have: 'a' '<comma>' '<missing>'
|
||||
// Note: this subtlety only applies to the last comma. If you had "Foo(a,," then
|
||||
// we'll have: 'a' '<comma>' '<missing>'
|
||||
// That will give us 2 non-commas. We then add one for the last comma, giving us an
|
||||
// arg count of 3.
|
||||
const listChildren = argumentsList.getChildren();
|
||||
@@ -253,9 +253,11 @@ namespace ts.SignatureHelp {
|
||||
// not enough to put us in the substitution expression; we should consider ourselves part of
|
||||
// the *next* span's expression by offsetting the index (argIndex = (spanIndex + 1) + 1).
|
||||
//
|
||||
// tslint:disable no-double-space
|
||||
// Example: f `# abcd $#{# 1 + 1# }# efghi ${ #"#hello"# } # `
|
||||
// ^ ^ ^ ^ ^ ^ ^ ^ ^
|
||||
// Case: 1 1 3 2 1 3 2 2 1
|
||||
// tslint:enable no-double-space
|
||||
Debug.assert(position >= node.getStart(), "Assumed 'position' could not occur before node.");
|
||||
if (isTemplateLiteralKind(node.kind)) {
|
||||
if (isInsideTemplateLiteral(<LiteralExpression>node, position)) {
|
||||
@@ -307,9 +309,8 @@ namespace ts.SignatureHelp {
|
||||
// Otherwise, we will not show signature help past the expression.
|
||||
// For example,
|
||||
//
|
||||
// ` ${ 1 + 1 foo(10)
|
||||
// | |
|
||||
//
|
||||
// ` ${ 1 + 1 foo(10)
|
||||
// | |
|
||||
// This is because a Missing node has no width. However, what we actually want is to include trivia
|
||||
// leading up to the next token in case the user is about to type in a TemplateMiddle or TemplateTail.
|
||||
if (template.kind === SyntaxKind.TemplateExpression) {
|
||||
|
||||
@@ -110,7 +110,7 @@ namespace ts.SymbolDisplay {
|
||||
|
||||
// TODO(drosen): Currently completion entry details passes the SemanticMeaning.All instead of using semanticMeaning of location
|
||||
export function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker: TypeChecker, symbol: Symbol, sourceFile: SourceFile, enclosingDeclaration: Node,
|
||||
location: Node, semanticMeaning = getMeaningFromLocation(location)): SymbolDisplayPartsDocumentationAndSymbolKind {
|
||||
location: Node, semanticMeaning = getMeaningFromLocation(location), alias?: Symbol): SymbolDisplayPartsDocumentationAndSymbolKind {
|
||||
|
||||
const displayParts: SymbolDisplayPart[] = [];
|
||||
let documentation: SymbolDisplayPart[];
|
||||
@@ -120,6 +120,7 @@ namespace ts.SymbolDisplay {
|
||||
let hasAddedSymbolInfo: boolean;
|
||||
const isThisExpression = location.kind === SyntaxKind.ThisKeyword && isExpression(location);
|
||||
let type: Type;
|
||||
let documentationFromAlias: SymbolDisplayPart[];
|
||||
|
||||
// Class at constructor site need to be shown as constructor apart from property,method, vars
|
||||
if (symbolKind !== ScriptElementKind.unknown || symbolFlags & SymbolFlags.Class || symbolFlags & SymbolFlags.Alias) {
|
||||
@@ -248,6 +249,7 @@ namespace ts.SymbolDisplay {
|
||||
}
|
||||
}
|
||||
if (symbolFlags & SymbolFlags.Class && !hasAddedSymbolInfo && !isThisExpression) {
|
||||
addAliasPrefixIfNecessary();
|
||||
if (getDeclarationOfKind(symbol, SyntaxKind.ClassExpression)) {
|
||||
// Special case for class expressions because we would like to indicate that
|
||||
// the class name is local to the class body (similar to function expression)
|
||||
@@ -263,14 +265,14 @@ namespace ts.SymbolDisplay {
|
||||
writeTypeParametersOfSymbol(symbol, sourceFile);
|
||||
}
|
||||
if ((symbolFlags & SymbolFlags.Interface) && (semanticMeaning & SemanticMeaning.Type)) {
|
||||
addNewLineIfDisplayPartsExist();
|
||||
prefixNextMeaning();
|
||||
displayParts.push(keywordPart(SyntaxKind.InterfaceKeyword));
|
||||
displayParts.push(spacePart());
|
||||
addFullSymbolName(symbol);
|
||||
writeTypeParametersOfSymbol(symbol, sourceFile);
|
||||
}
|
||||
if (symbolFlags & SymbolFlags.TypeAlias) {
|
||||
addNewLineIfDisplayPartsExist();
|
||||
prefixNextMeaning();
|
||||
displayParts.push(keywordPart(SyntaxKind.TypeKeyword));
|
||||
displayParts.push(spacePart());
|
||||
addFullSymbolName(symbol);
|
||||
@@ -281,7 +283,7 @@ namespace ts.SymbolDisplay {
|
||||
addRange(displayParts, typeToDisplayParts(typeChecker, typeChecker.getDeclaredTypeOfSymbol(symbol), enclosingDeclaration, TypeFormatFlags.InTypeAlias));
|
||||
}
|
||||
if (symbolFlags & SymbolFlags.Enum) {
|
||||
addNewLineIfDisplayPartsExist();
|
||||
prefixNextMeaning();
|
||||
if (forEach(symbol.declarations, isConstEnumDeclaration)) {
|
||||
displayParts.push(keywordPart(SyntaxKind.ConstKeyword));
|
||||
displayParts.push(spacePart());
|
||||
@@ -291,7 +293,7 @@ namespace ts.SymbolDisplay {
|
||||
addFullSymbolName(symbol);
|
||||
}
|
||||
if (symbolFlags & SymbolFlags.Module) {
|
||||
addNewLineIfDisplayPartsExist();
|
||||
prefixNextMeaning();
|
||||
const declaration = getDeclarationOfKind<ModuleDeclaration>(symbol, SyntaxKind.ModuleDeclaration);
|
||||
const isNamespace = declaration && declaration.name && declaration.name.kind === SyntaxKind.Identifier;
|
||||
displayParts.push(keywordPart(isNamespace ? SyntaxKind.NamespaceKeyword : SyntaxKind.ModuleKeyword));
|
||||
@@ -299,7 +301,7 @@ namespace ts.SymbolDisplay {
|
||||
addFullSymbolName(symbol);
|
||||
}
|
||||
if ((symbolFlags & SymbolFlags.TypeParameter) && (semanticMeaning & SemanticMeaning.Type)) {
|
||||
addNewLineIfDisplayPartsExist();
|
||||
prefixNextMeaning();
|
||||
displayParts.push(punctuationPart(SyntaxKind.OpenParenToken));
|
||||
displayParts.push(textPart("type parameter"));
|
||||
displayParts.push(punctuationPart(SyntaxKind.CloseParenToken));
|
||||
@@ -333,7 +335,7 @@ namespace ts.SymbolDisplay {
|
||||
else if (declaration.kind === SyntaxKind.TypeAliasDeclaration) {
|
||||
// Type alias type parameter
|
||||
// For example
|
||||
// type list<T> = T[]; // Both T will go through same code path
|
||||
// type list<T> = T[]; // Both T will go through same code path
|
||||
addInPrefix();
|
||||
displayParts.push(keywordPart(SyntaxKind.TypeKeyword));
|
||||
displayParts.push(spacePart());
|
||||
@@ -359,7 +361,32 @@ namespace ts.SymbolDisplay {
|
||||
}
|
||||
}
|
||||
if (symbolFlags & SymbolFlags.Alias) {
|
||||
addNewLineIfDisplayPartsExist();
|
||||
prefixNextMeaning();
|
||||
if (!hasAddedSymbolInfo) {
|
||||
const resolvedSymbol = typeChecker.getAliasedSymbol(symbol);
|
||||
if (resolvedSymbol !== symbol && resolvedSymbol.declarations && resolvedSymbol.declarations.length > 0) {
|
||||
const resolvedNode = resolvedSymbol.declarations[0];
|
||||
const declarationName = ts.getNameOfDeclaration(resolvedNode);
|
||||
if (declarationName) {
|
||||
const isExternalModuleDeclaration =
|
||||
ts.isModuleWithStringLiteralName(resolvedNode) &&
|
||||
ts.hasModifier(resolvedNode, ModifierFlags.Ambient);
|
||||
const shouldUseAliasName = symbol.name !== "default" && !isExternalModuleDeclaration;
|
||||
const resolvedInfo = getSymbolDisplayPartsDocumentationAndSymbolKind(
|
||||
typeChecker,
|
||||
resolvedSymbol,
|
||||
ts.getSourceFileOfNode(resolvedNode),
|
||||
resolvedNode,
|
||||
declarationName,
|
||||
semanticMeaning,
|
||||
shouldUseAliasName ? symbol : resolvedSymbol);
|
||||
displayParts.push(...resolvedInfo.displayParts);
|
||||
displayParts.push(lineBreakPart());
|
||||
documentationFromAlias = resolvedInfo.documentation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (symbol.declarations[0].kind) {
|
||||
case SyntaxKind.NamespaceExportDeclaration:
|
||||
displayParts.push(keywordPart(SyntaxKind.ExportKeyword));
|
||||
@@ -405,7 +432,7 @@ namespace ts.SymbolDisplay {
|
||||
if (symbolKind !== ScriptElementKind.unknown) {
|
||||
if (type) {
|
||||
if (isThisExpression) {
|
||||
addNewLineIfDisplayPartsExist();
|
||||
prefixNextMeaning();
|
||||
displayParts.push(keywordPart(SyntaxKind.ThisKeyword));
|
||||
}
|
||||
else {
|
||||
@@ -477,12 +504,24 @@ namespace ts.SymbolDisplay {
|
||||
}
|
||||
}
|
||||
|
||||
if (documentation.length === 0 && documentationFromAlias) {
|
||||
documentation = documentationFromAlias;
|
||||
}
|
||||
|
||||
return { displayParts, documentation, symbolKind, tags };
|
||||
|
||||
function addNewLineIfDisplayPartsExist() {
|
||||
function prefixNextMeaning() {
|
||||
if (displayParts.length) {
|
||||
displayParts.push(lineBreakPart());
|
||||
}
|
||||
addAliasPrefixIfNecessary();
|
||||
}
|
||||
|
||||
function addAliasPrefixIfNecessary() {
|
||||
if (alias) {
|
||||
pushTypePart(ScriptElementKind.alias);
|
||||
displayParts.push(spacePart());
|
||||
}
|
||||
}
|
||||
|
||||
function addInPrefix() {
|
||||
@@ -491,14 +530,17 @@ namespace ts.SymbolDisplay {
|
||||
displayParts.push(spacePart());
|
||||
}
|
||||
|
||||
function addFullSymbolName(symbol: Symbol, enclosingDeclaration?: Node) {
|
||||
const fullSymbolDisplayParts = symbolToDisplayParts(typeChecker, symbol, enclosingDeclaration || sourceFile, /*meaning*/ undefined,
|
||||
function addFullSymbolName(symbolToDisplay: Symbol, enclosingDeclaration?: Node) {
|
||||
if (alias && symbolToDisplay === symbol) {
|
||||
symbolToDisplay = alias;
|
||||
}
|
||||
const fullSymbolDisplayParts = symbolToDisplayParts(typeChecker, symbolToDisplay, enclosingDeclaration || sourceFile, /*meaning*/ undefined,
|
||||
SymbolFormatFlags.WriteTypeParametersOrArguments | SymbolFormatFlags.UseOnlyExternalAliasing);
|
||||
addRange(displayParts, fullSymbolDisplayParts);
|
||||
}
|
||||
|
||||
function addPrefixForAnyFunctionOrVar(symbol: Symbol, symbolKind: string) {
|
||||
addNewLineIfDisplayPartsExist();
|
||||
prefixNextMeaning();
|
||||
if (symbolKind) {
|
||||
pushTypePart(symbolKind);
|
||||
if (symbol && !some(symbol.declarations, d => isArrowFunction(d) || (isFunctionExpression(d) || isClassExpression(d)) && !d.name)) {
|
||||
|
||||
@@ -333,6 +333,7 @@ namespace ts {
|
||||
|
||||
export interface GetCompletionsAtPositionOptions {
|
||||
includeExternalModuleExports: boolean;
|
||||
includeInsertTextCompletions: boolean;
|
||||
}
|
||||
|
||||
export interface ApplyCodeActionCommandResult {
|
||||
@@ -597,6 +598,7 @@ namespace ts {
|
||||
InsertSpaceBeforeFunctionParenthesis?: boolean;
|
||||
PlaceOpenBraceOnNewLineForFunctions: boolean;
|
||||
PlaceOpenBraceOnNewLineForControlBlocks: boolean;
|
||||
insertSpaceBeforeTypeAnnotation?: boolean;
|
||||
}
|
||||
|
||||
export interface FormatCodeSettings extends EditorSettings {
|
||||
@@ -615,6 +617,7 @@ namespace ts {
|
||||
insertSpaceBeforeFunctionParenthesis?: boolean;
|
||||
placeOpenBraceOnNewLineForFunctions?: boolean;
|
||||
placeOpenBraceOnNewLineForControlBlocks?: boolean;
|
||||
insertSpaceBeforeTypeAnnotation?: boolean;
|
||||
}
|
||||
|
||||
export interface DefinitionInfo {
|
||||
@@ -746,6 +749,7 @@ namespace ts {
|
||||
kind: ScriptElementKind;
|
||||
kindModifiers: string; // see ScriptElementKindModifier, comma separated
|
||||
sortText: string;
|
||||
insertText?: string;
|
||||
/**
|
||||
* An optional span that indicates the text to be replaced by this completion item.
|
||||
* If present, this span should be used instead of the default one.
|
||||
|
||||
@@ -1274,19 +1274,6 @@ namespace ts {
|
||||
});
|
||||
}
|
||||
|
||||
export function getDeclaredName(typeChecker: TypeChecker, symbol: Symbol, location: Node): string {
|
||||
// If this is an export or import specifier it could have been renamed using the 'as' syntax.
|
||||
// If so we want to search for whatever is under the cursor.
|
||||
if (isImportOrExportSpecifierName(location) || isStringOrNumericLiteral(location) && location.parent.kind === SyntaxKind.ComputedPropertyName) {
|
||||
return getTextOfIdentifierOrLiteral(location);
|
||||
}
|
||||
|
||||
// Try to get the local symbol if we're dealing with an 'export default'
|
||||
// since that symbol has the "true" name.
|
||||
const localExportDefaultSymbol = getLocalSymbolForExportDefault(symbol);
|
||||
return typeChecker.symbolToString(localExportDefaultSymbol || symbol);
|
||||
}
|
||||
|
||||
export function isImportOrExportSpecifierName(location: Node): location is Identifier {
|
||||
return location.parent &&
|
||||
(location.parent.kind === SyntaxKind.ImportSpecifier || location.parent.kind === SyntaxKind.ExportSpecifier) &&
|
||||
@@ -1300,12 +1287,16 @@ namespace ts {
|
||||
*/
|
||||
export function stripQuotes(name: string) {
|
||||
const length = name.length;
|
||||
if (length >= 2 && name.charCodeAt(0) === name.charCodeAt(length - 1) && isSingleOrDoubleQuote(name.charCodeAt(0))) {
|
||||
if (length >= 2 && name.charCodeAt(0) === name.charCodeAt(length - 1) && startsWithQuote(name)) {
|
||||
return name.substring(1, length - 1);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
export function startsWithQuote(name: string): boolean {
|
||||
return isSingleOrDoubleQuote(name.charCodeAt(0));
|
||||
}
|
||||
|
||||
export function scriptKindIs(fileName: string, host: LanguageServiceHost, ...scriptKinds: ScriptKind[]): boolean {
|
||||
const scriptKind = getScriptKind(fileName, host);
|
||||
return forEach(scriptKinds, k => k === scriptKind);
|
||||
|
||||
@@ -7,15 +7,12 @@ tests/cases/compiler/abstractPropertyNegative.ts(13,7): error TS2515: Non-abstra
|
||||
tests/cases/compiler/abstractPropertyNegative.ts(15,5): error TS1244: Abstract methods can only appear within an abstract class.
|
||||
tests/cases/compiler/abstractPropertyNegative.ts(16,37): error TS1005: '{' expected.
|
||||
tests/cases/compiler/abstractPropertyNegative.ts(19,3): error TS2540: Cannot assign to 'ro' because it is a constant or a read-only property.
|
||||
tests/cases/compiler/abstractPropertyNegative.ts(24,7): error TS2415: Class 'WrongTypePropertyImpl' incorrectly extends base class 'WrongTypeProperty'.
|
||||
Types of property 'num' are incompatible.
|
||||
Type 'string' is not assignable to type 'number'.
|
||||
tests/cases/compiler/abstractPropertyNegative.ts(30,7): error TS2415: Class 'WrongTypeAccessorImpl' incorrectly extends base class 'WrongTypeAccessor'.
|
||||
Types of property 'num' are incompatible.
|
||||
Type 'string' is not assignable to type 'number'.
|
||||
tests/cases/compiler/abstractPropertyNegative.ts(33,7): error TS2415: Class 'WrongTypeAccessorImpl2' incorrectly extends base class 'WrongTypeAccessor'.
|
||||
Types of property 'num' are incompatible.
|
||||
Type 'string' is not assignable to type 'number'.
|
||||
tests/cases/compiler/abstractPropertyNegative.ts(25,5): error TS2416: Property 'num' in type 'WrongTypePropertyImpl' is not assignable to the same property in base type 'number'.
|
||||
Type 'string' is not assignable to type 'number'.
|
||||
tests/cases/compiler/abstractPropertyNegative.ts(31,9): error TS2416: Property 'num' in type 'WrongTypeAccessorImpl' is not assignable to the same property in base type 'number'.
|
||||
Type 'string' is not assignable to type 'number'.
|
||||
tests/cases/compiler/abstractPropertyNegative.ts(34,5): error TS2416: Property 'num' in type 'WrongTypeAccessorImpl2' is not assignable to the same property in base type 'number'.
|
||||
Type 'string' is not assignable to type 'number'.
|
||||
tests/cases/compiler/abstractPropertyNegative.ts(38,18): error TS2676: Accessors must both be abstract or non-abstract.
|
||||
tests/cases/compiler/abstractPropertyNegative.ts(39,9): error TS2676: Accessors must both be abstract or non-abstract.
|
||||
tests/cases/compiler/abstractPropertyNegative.ts(40,9): error TS2676: Accessors must both be abstract or non-abstract.
|
||||
@@ -65,28 +62,25 @@ tests/cases/compiler/abstractPropertyNegative.ts(41,18): error TS2676: Accessors
|
||||
abstract num: number;
|
||||
}
|
||||
class WrongTypePropertyImpl extends WrongTypeProperty {
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2415: Class 'WrongTypePropertyImpl' incorrectly extends base class 'WrongTypeProperty'.
|
||||
!!! error TS2415: Types of property 'num' are incompatible.
|
||||
!!! error TS2415: Type 'string' is not assignable to type 'number'.
|
||||
num = "nope, wrong";
|
||||
~~~
|
||||
!!! error TS2416: Property 'num' in type 'WrongTypePropertyImpl' is not assignable to the same property in base type 'number'.
|
||||
!!! error TS2416: Type 'string' is not assignable to type 'number'.
|
||||
}
|
||||
abstract class WrongTypeAccessor {
|
||||
abstract get num(): number;
|
||||
}
|
||||
class WrongTypeAccessorImpl extends WrongTypeAccessor {
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2415: Class 'WrongTypeAccessorImpl' incorrectly extends base class 'WrongTypeAccessor'.
|
||||
!!! error TS2415: Types of property 'num' are incompatible.
|
||||
!!! error TS2415: Type 'string' is not assignable to type 'number'.
|
||||
get num() { return "nope, wrong"; }
|
||||
~~~
|
||||
!!! error TS2416: Property 'num' in type 'WrongTypeAccessorImpl' is not assignable to the same property in base type 'number'.
|
||||
!!! error TS2416: Type 'string' is not assignable to type 'number'.
|
||||
}
|
||||
class WrongTypeAccessorImpl2 extends WrongTypeAccessor {
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2415: Class 'WrongTypeAccessorImpl2' incorrectly extends base class 'WrongTypeAccessor'.
|
||||
!!! error TS2415: Types of property 'num' are incompatible.
|
||||
!!! error TS2415: Type 'string' is not assignable to type 'number'.
|
||||
num = "nope, wrong";
|
||||
~~~
|
||||
!!! error TS2416: Property 'num' in type 'WrongTypeAccessorImpl2' is not assignable to the same property in base type 'number'.
|
||||
!!! error TS2416: Type 'string' is not assignable to type 'number'.
|
||||
}
|
||||
|
||||
abstract class AbstractAccessorMismatch {
|
||||
|
||||
@@ -4,21 +4,12 @@
|
||||
import Namespace from "./b";
|
||||
export var x = new Namespace.Foo();
|
||||
|
||||
//// [b.ts]
|
||||
//// [b.d.ts]
|
||||
export class Foo {
|
||||
member: string;
|
||||
}
|
||||
|
||||
|
||||
//// [b.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var Foo = /** @class */ (function () {
|
||||
function Foo() {
|
||||
}
|
||||
return Foo;
|
||||
}());
|
||||
exports.Foo = Foo;
|
||||
//// [a.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
|
||||
@@ -4,15 +4,15 @@ import Namespace from "./b";
|
||||
|
||||
export var x = new Namespace.Foo();
|
||||
>x : Symbol(x, Decl(a.ts, 1, 10))
|
||||
>Namespace.Foo : Symbol(Namespace.Foo, Decl(b.ts, 0, 0))
|
||||
>Namespace.Foo : Symbol(Namespace.Foo, Decl(b.d.ts, 0, 0))
|
||||
>Namespace : Symbol(Namespace, Decl(a.ts, 0, 6))
|
||||
>Foo : Symbol(Namespace.Foo, Decl(b.ts, 0, 0))
|
||||
>Foo : Symbol(Namespace.Foo, Decl(b.d.ts, 0, 0))
|
||||
|
||||
=== tests/cases/compiler/b.ts ===
|
||||
=== tests/cases/compiler/b.d.ts ===
|
||||
export class Foo {
|
||||
>Foo : Symbol(Foo, Decl(b.ts, 0, 0))
|
||||
>Foo : Symbol(Foo, Decl(b.d.ts, 0, 0))
|
||||
|
||||
member: string;
|
||||
>member : Symbol(Foo.member, Decl(b.ts, 0, 18))
|
||||
>member : Symbol(Foo.member, Decl(b.d.ts, 0, 18))
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ export var x = new Namespace.Foo();
|
||||
>Namespace : typeof Namespace
|
||||
>Foo : typeof Namespace.Foo
|
||||
|
||||
=== tests/cases/compiler/b.ts ===
|
||||
=== tests/cases/compiler/b.d.ts ===
|
||||
export class Foo {
|
||||
>Foo : Foo
|
||||
|
||||
|
||||
@@ -4,28 +4,11 @@
|
||||
import Namespace from "./b";
|
||||
export var x = new Namespace.Foo();
|
||||
|
||||
//// [b.ts]
|
||||
//// [b.d.ts]
|
||||
export class Foo {
|
||||
member: string;
|
||||
}
|
||||
|
||||
//// [b.js]
|
||||
System.register([], function (exports_1, context_1) {
|
||||
"use strict";
|
||||
var __moduleName = context_1 && context_1.id;
|
||||
var Foo;
|
||||
return {
|
||||
setters: [],
|
||||
execute: function () {
|
||||
Foo = /** @class */ (function () {
|
||||
function Foo() {
|
||||
}
|
||||
return Foo;
|
||||
}());
|
||||
exports_1("Foo", Foo);
|
||||
}
|
||||
};
|
||||
});
|
||||
//// [a.js]
|
||||
System.register(["./b"], function (exports_1, context_1) {
|
||||
"use strict";
|
||||
|
||||
@@ -4,14 +4,14 @@ import Namespace from "./b";
|
||||
|
||||
export var x = new Namespace.Foo();
|
||||
>x : Symbol(x, Decl(a.ts, 1, 10))
|
||||
>Namespace.Foo : Symbol(Namespace.Foo, Decl(b.ts, 0, 0))
|
||||
>Namespace.Foo : Symbol(Namespace.Foo, Decl(b.d.ts, 0, 0))
|
||||
>Namespace : Symbol(Namespace, Decl(a.ts, 0, 6))
|
||||
>Foo : Symbol(Namespace.Foo, Decl(b.ts, 0, 0))
|
||||
>Foo : Symbol(Namespace.Foo, Decl(b.d.ts, 0, 0))
|
||||
|
||||
=== tests/cases/compiler/b.ts ===
|
||||
=== tests/cases/compiler/b.d.ts ===
|
||||
export class Foo {
|
||||
>Foo : Symbol(Foo, Decl(b.ts, 0, 0))
|
||||
>Foo : Symbol(Foo, Decl(b.d.ts, 0, 0))
|
||||
|
||||
member: string;
|
||||
>member : Symbol(Foo.member, Decl(b.ts, 0, 18))
|
||||
>member : Symbol(Foo.member, Decl(b.d.ts, 0, 18))
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ export var x = new Namespace.Foo();
|
||||
>Namespace : typeof Namespace
|
||||
>Foo : typeof Namespace.Foo
|
||||
|
||||
=== tests/cases/compiler/b.ts ===
|
||||
=== tests/cases/compiler/b.d.ts ===
|
||||
export class Foo {
|
||||
>Foo : Foo
|
||||
|
||||
|
||||
+20
-1
@@ -59,6 +59,7 @@ declare namespace ts {
|
||||
pos: number;
|
||||
end: number;
|
||||
}
|
||||
type JsDocSyntaxKind = SyntaxKind.EndOfFileToken | SyntaxKind.WhitespaceTrivia | SyntaxKind.AtToken | SyntaxKind.NewLineTrivia | SyntaxKind.AsteriskToken | SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.LessThanToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.EqualsToken | SyntaxKind.CommaToken | SyntaxKind.DotToken | SyntaxKind.Identifier | SyntaxKind.Unknown;
|
||||
enum SyntaxKind {
|
||||
Unknown = 0,
|
||||
EndOfFileToken = 1,
|
||||
@@ -2295,6 +2296,7 @@ declare namespace ts {
|
||||
types?: string[];
|
||||
/** Paths used to compute primary types search locations */
|
||||
typeRoots?: string[];
|
||||
esModuleInterop?: boolean;
|
||||
[option: string]: CompilerOptionsValue | JsonSourceFile | undefined;
|
||||
}
|
||||
interface TypeAcquisition {
|
||||
@@ -3104,6 +3106,7 @@ declare namespace ts {
|
||||
function isJSDocCommentContainingNode(node: Node): boolean;
|
||||
function isSetAccessor(node: Node): node is SetAccessorDeclaration;
|
||||
function isGetAccessor(node: Node): node is GetAccessorDeclaration;
|
||||
function isObjectLiteralElement(node: Node): node is ObjectLiteralElement;
|
||||
}
|
||||
declare namespace ts {
|
||||
type ErrorCallback = (message: DiagnosticMessage, length: number) => void;
|
||||
@@ -3126,7 +3129,7 @@ declare namespace ts {
|
||||
scanJsxAttributeValue(): SyntaxKind;
|
||||
reScanJsxToken(): SyntaxKind;
|
||||
scanJsxToken(): SyntaxKind;
|
||||
scanJSDocToken(): SyntaxKind;
|
||||
scanJSDocToken(): JsDocSyntaxKind;
|
||||
scan(): SyntaxKind;
|
||||
getText(): string;
|
||||
setText(text: string, start?: number, length?: number): void;
|
||||
@@ -3998,6 +4001,7 @@ declare namespace ts {
|
||||
}
|
||||
interface GetCompletionsAtPositionOptions {
|
||||
includeExternalModuleExports: boolean;
|
||||
includeInsertTextCompletions: boolean;
|
||||
}
|
||||
interface ApplyCodeActionCommandResult {
|
||||
successMessage: string;
|
||||
@@ -4208,6 +4212,7 @@ declare namespace ts {
|
||||
InsertSpaceBeforeFunctionParenthesis?: boolean;
|
||||
PlaceOpenBraceOnNewLineForFunctions: boolean;
|
||||
PlaceOpenBraceOnNewLineForControlBlocks: boolean;
|
||||
insertSpaceBeforeTypeAnnotation?: boolean;
|
||||
}
|
||||
interface FormatCodeSettings extends EditorSettings {
|
||||
insertSpaceAfterCommaDelimiter?: boolean;
|
||||
@@ -4225,6 +4230,7 @@ declare namespace ts {
|
||||
insertSpaceBeforeFunctionParenthesis?: boolean;
|
||||
placeOpenBraceOnNewLineForFunctions?: boolean;
|
||||
placeOpenBraceOnNewLineForControlBlocks?: boolean;
|
||||
insertSpaceBeforeTypeAnnotation?: boolean;
|
||||
}
|
||||
interface DefinitionInfo {
|
||||
fileName: string;
|
||||
@@ -4340,6 +4346,7 @@ declare namespace ts {
|
||||
kind: ScriptElementKind;
|
||||
kindModifiers: string;
|
||||
sortText: string;
|
||||
insertText?: string;
|
||||
/**
|
||||
* An optional span that indicates the text to be replaced by this completion item.
|
||||
* If present, this span should be used instead of the default one.
|
||||
@@ -6103,6 +6110,11 @@ declare namespace ts.server.protocol {
|
||||
* This affects lone identifier completions but not completions on the right hand side of `obj.`.
|
||||
*/
|
||||
includeExternalModuleExports: boolean;
|
||||
/**
|
||||
* If enabled, the completion list will include completions with invalid identifier names.
|
||||
* For those entries, The `insertText` and `replacementSpan` properties will be set to change from `.x` property access to `["x"]`.
|
||||
*/
|
||||
includeInsertTextCompletions: boolean;
|
||||
}
|
||||
/**
|
||||
* Completions request; value of command field is "completions".
|
||||
@@ -6171,6 +6183,12 @@ declare namespace ts.server.protocol {
|
||||
* is often the same as the name but may be different in certain circumstances.
|
||||
*/
|
||||
sortText: string;
|
||||
/**
|
||||
* Text to insert instead of `name`.
|
||||
* This is used to support bracketed completions; If `name` might be "a-b" but `insertText` would be `["a-b"]`,
|
||||
* coupled with `replacementSpan` to replace a dotted access with a bracket access.
|
||||
*/
|
||||
insertText?: string;
|
||||
/**
|
||||
* An optional span that indicates the text to be replaced by this completion item.
|
||||
* If present, this span should be used instead of the default one.
|
||||
@@ -6844,6 +6862,7 @@ declare namespace ts.server.protocol {
|
||||
insertSpaceBeforeFunctionParenthesis?: boolean;
|
||||
placeOpenBraceOnNewLineForFunctions?: boolean;
|
||||
placeOpenBraceOnNewLineForControlBlocks?: boolean;
|
||||
insertSpaceBeforeTypeAnnotation?: boolean;
|
||||
}
|
||||
interface CompilerOptions {
|
||||
allowJs?: boolean;
|
||||
|
||||
+8
-1
@@ -59,6 +59,7 @@ declare namespace ts {
|
||||
pos: number;
|
||||
end: number;
|
||||
}
|
||||
type JsDocSyntaxKind = SyntaxKind.EndOfFileToken | SyntaxKind.WhitespaceTrivia | SyntaxKind.AtToken | SyntaxKind.NewLineTrivia | SyntaxKind.AsteriskToken | SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.LessThanToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.EqualsToken | SyntaxKind.CommaToken | SyntaxKind.DotToken | SyntaxKind.Identifier | SyntaxKind.Unknown;
|
||||
enum SyntaxKind {
|
||||
Unknown = 0,
|
||||
EndOfFileToken = 1,
|
||||
@@ -2295,6 +2296,7 @@ declare namespace ts {
|
||||
types?: string[];
|
||||
/** Paths used to compute primary types search locations */
|
||||
typeRoots?: string[];
|
||||
esModuleInterop?: boolean;
|
||||
[option: string]: CompilerOptionsValue | JsonSourceFile | undefined;
|
||||
}
|
||||
interface TypeAcquisition {
|
||||
@@ -2788,7 +2790,7 @@ declare namespace ts {
|
||||
scanJsxAttributeValue(): SyntaxKind;
|
||||
reScanJsxToken(): SyntaxKind;
|
||||
scanJsxToken(): SyntaxKind;
|
||||
scanJSDocToken(): SyntaxKind;
|
||||
scanJSDocToken(): JsDocSyntaxKind;
|
||||
scan(): SyntaxKind;
|
||||
getText(): string;
|
||||
setText(text: string, start?: number, length?: number): void;
|
||||
@@ -3157,6 +3159,7 @@ declare namespace ts {
|
||||
function isJSDocCommentContainingNode(node: Node): boolean;
|
||||
function isSetAccessor(node: Node): node is SetAccessorDeclaration;
|
||||
function isGetAccessor(node: Node): node is GetAccessorDeclaration;
|
||||
function isObjectLiteralElement(node: Node): node is ObjectLiteralElement;
|
||||
}
|
||||
declare namespace ts {
|
||||
function createNode(kind: SyntaxKind, pos?: number, end?: number): Node;
|
||||
@@ -3998,6 +4001,7 @@ declare namespace ts {
|
||||
}
|
||||
interface GetCompletionsAtPositionOptions {
|
||||
includeExternalModuleExports: boolean;
|
||||
includeInsertTextCompletions: boolean;
|
||||
}
|
||||
interface ApplyCodeActionCommandResult {
|
||||
successMessage: string;
|
||||
@@ -4208,6 +4212,7 @@ declare namespace ts {
|
||||
InsertSpaceBeforeFunctionParenthesis?: boolean;
|
||||
PlaceOpenBraceOnNewLineForFunctions: boolean;
|
||||
PlaceOpenBraceOnNewLineForControlBlocks: boolean;
|
||||
insertSpaceBeforeTypeAnnotation?: boolean;
|
||||
}
|
||||
interface FormatCodeSettings extends EditorSettings {
|
||||
insertSpaceAfterCommaDelimiter?: boolean;
|
||||
@@ -4225,6 +4230,7 @@ declare namespace ts {
|
||||
insertSpaceBeforeFunctionParenthesis?: boolean;
|
||||
placeOpenBraceOnNewLineForFunctions?: boolean;
|
||||
placeOpenBraceOnNewLineForControlBlocks?: boolean;
|
||||
insertSpaceBeforeTypeAnnotation?: boolean;
|
||||
}
|
||||
interface DefinitionInfo {
|
||||
fileName: string;
|
||||
@@ -4340,6 +4346,7 @@ declare namespace ts {
|
||||
kind: ScriptElementKind;
|
||||
kindModifiers: string;
|
||||
sortText: string;
|
||||
insertText?: string;
|
||||
/**
|
||||
* An optional span that indicates the text to be replaced by this completion item.
|
||||
* If present, this span should be used instead of the default one.
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
tests/cases/conformance/types/typeRelationships/apparentType/apparentTypeSubtyping.ts(9,7): error TS2415: Class 'Derived<U>' incorrectly extends base class 'Base<string>'.
|
||||
Types of property 'x' are incompatible.
|
||||
Type 'String' is not assignable to type 'string'.
|
||||
'string' is a primitive, but 'String' is a wrapper object. Prefer using 'string' when possible.
|
||||
tests/cases/conformance/types/typeRelationships/apparentType/apparentTypeSubtyping.ts(10,5): error TS2416: Property 'x' in type 'Derived<U>' is not assignable to the same property in base type 'string'.
|
||||
Type 'String' is not assignable to type 'string'.
|
||||
'string' is a primitive, but 'String' is a wrapper object. Prefer using 'string' when possible.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/typeRelationships/apparentType/apparentTypeSubtyping.ts (1 errors) ====
|
||||
@@ -14,12 +13,11 @@ tests/cases/conformance/types/typeRelationships/apparentType/apparentTypeSubtypi
|
||||
|
||||
// is String (S) a subtype of U extends String (T)? Would only be true if we used the apparent type of U (T)
|
||||
class Derived<U> extends Base<string> { // error
|
||||
~~~~~~~
|
||||
!!! error TS2415: Class 'Derived<U>' incorrectly extends base class 'Base<string>'.
|
||||
!!! error TS2415: Types of property 'x' are incompatible.
|
||||
!!! error TS2415: Type 'String' is not assignable to type 'string'.
|
||||
!!! error TS2415: 'string' is a primitive, but 'String' is a wrapper object. Prefer using 'string' when possible.
|
||||
x: String;
|
||||
~
|
||||
!!! error TS2416: Property 'x' in type 'Derived<U>' is not assignable to the same property in base type 'string'.
|
||||
!!! error TS2416: Type 'String' is not assignable to type 'string'.
|
||||
!!! error TS2416: 'string' is a primitive, but 'String' is a wrapper object. Prefer using 'string' when possible.
|
||||
}
|
||||
|
||||
class Base2 {
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
tests/cases/conformance/types/typeRelationships/apparentType/apparentTypeSupertype.ts(9,7): error TS2415: Class 'Derived<U>' incorrectly extends base class 'Base'.
|
||||
Types of property 'x' are incompatible.
|
||||
Type 'U' is not assignable to type 'string'.
|
||||
Type 'String' is not assignable to type 'string'.
|
||||
'string' is a primitive, but 'String' is a wrapper object. Prefer using 'string' when possible.
|
||||
tests/cases/conformance/types/typeRelationships/apparentType/apparentTypeSupertype.ts(10,5): error TS2416: Property 'x' in type 'Derived<U>' is not assignable to the same property in base type 'string'.
|
||||
Type 'U' is not assignable to type 'string'.
|
||||
Type 'String' is not assignable to type 'string'.
|
||||
'string' is a primitive, but 'String' is a wrapper object. Prefer using 'string' when possible.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/typeRelationships/apparentType/apparentTypeSupertype.ts (1 errors) ====
|
||||
@@ -15,11 +14,10 @@ tests/cases/conformance/types/typeRelationships/apparentType/apparentTypeSuperty
|
||||
|
||||
// is String (S) a subtype of U extends String (T)? Would only be true if we used the apparent type of U (T)
|
||||
class Derived<U extends String> extends Base { // error
|
||||
~~~~~~~
|
||||
!!! error TS2415: Class 'Derived<U>' incorrectly extends base class 'Base'.
|
||||
!!! error TS2415: Types of property 'x' are incompatible.
|
||||
!!! error TS2415: Type 'U' is not assignable to type 'string'.
|
||||
!!! error TS2415: Type 'String' is not assignable to type 'string'.
|
||||
!!! error TS2415: 'string' is a primitive, but 'String' is a wrapper object. Prefer using 'string' when possible.
|
||||
x: U;
|
||||
~
|
||||
!!! error TS2416: Property 'x' in type 'Derived<U>' is not assignable to the same property in base type 'string'.
|
||||
!!! error TS2416: Type 'U' is not assignable to type 'string'.
|
||||
!!! error TS2416: Type 'String' is not assignable to type 'string'.
|
||||
!!! error TS2416: 'string' is a primitive, but 'String' is a wrapper object. Prefer using 'string' when possible.
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
tests/cases/compiler/baseClassImprovedMismatchErrors.ts(8,5): error TS2416: Property 'n' in type 'Derived' is not assignable to the same property in base type 'string | Base'.
|
||||
Type 'string | Derived' is not assignable to type 'string | Base'.
|
||||
Type 'Derived' is not assignable to type 'string | Base'.
|
||||
Type 'Derived' is not assignable to type 'Base'.
|
||||
Types of property 'n' are incompatible.
|
||||
Type 'string | Derived' is not assignable to type 'string | Base'.
|
||||
Type 'Derived' is not assignable to type 'string | Base'.
|
||||
Type 'Derived' is not assignable to type 'Base'.
|
||||
tests/cases/compiler/baseClassImprovedMismatchErrors.ts(9,5): error TS2416: Property 'fn' in type 'Derived' is not assignable to the same property in base type '() => number'.
|
||||
Type '() => string | number' is not assignable to type '() => number'.
|
||||
Type 'string | number' is not assignable to type 'number'.
|
||||
Type 'string' is not assignable to type 'number'.
|
||||
tests/cases/compiler/baseClassImprovedMismatchErrors.ts(14,5): error TS2416: Property 'n' in type 'DerivedInterface' is not assignable to the same property in base type 'string | Base'.
|
||||
Type 'string | DerivedInterface' is not assignable to type 'string | Base'.
|
||||
Type 'DerivedInterface' is not assignable to type 'string | Base'.
|
||||
Type 'DerivedInterface' is not assignable to type 'Base'.
|
||||
Types of property 'n' are incompatible.
|
||||
Type 'string | DerivedInterface' is not assignable to type 'string | Base'.
|
||||
Type 'DerivedInterface' is not assignable to type 'string | Base'.
|
||||
Type 'DerivedInterface' is not assignable to type 'Base'.
|
||||
tests/cases/compiler/baseClassImprovedMismatchErrors.ts(15,5): error TS2416: Property 'fn' in type 'DerivedInterface' is not assignable to the same property in base type '() => number'.
|
||||
Type '() => string | number' is not assignable to type '() => number'.
|
||||
Type 'string | number' is not assignable to type 'number'.
|
||||
Type 'string' is not assignable to type 'number'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/baseClassImprovedMismatchErrors.ts (4 errors) ====
|
||||
class Base {
|
||||
n: Base | string;
|
||||
fn() {
|
||||
return 10;
|
||||
}
|
||||
}
|
||||
class Derived extends Base {
|
||||
n: Derived | string;
|
||||
~
|
||||
!!! error TS2416: Property 'n' in type 'Derived' is not assignable to the same property in base type 'string | Base'.
|
||||
!!! error TS2416: Type 'string | Derived' is not assignable to type 'string | Base'.
|
||||
!!! error TS2416: Type 'Derived' is not assignable to type 'string | Base'.
|
||||
!!! error TS2416: Type 'Derived' is not assignable to type 'Base'.
|
||||
!!! error TS2416: Types of property 'n' are incompatible.
|
||||
!!! error TS2416: Type 'string | Derived' is not assignable to type 'string | Base'.
|
||||
!!! error TS2416: Type 'Derived' is not assignable to type 'string | Base'.
|
||||
!!! error TS2416: Type 'Derived' is not assignable to type 'Base'.
|
||||
fn() {
|
||||
~~
|
||||
!!! error TS2416: Property 'fn' in type 'Derived' is not assignable to the same property in base type '() => number'.
|
||||
!!! error TS2416: Type '() => string | number' is not assignable to type '() => number'.
|
||||
!!! error TS2416: Type 'string | number' is not assignable to type 'number'.
|
||||
!!! error TS2416: Type 'string' is not assignable to type 'number'.
|
||||
return 10 as number | string;
|
||||
}
|
||||
}
|
||||
class DerivedInterface implements Base {
|
||||
n: DerivedInterface | string;
|
||||
~
|
||||
!!! error TS2416: Property 'n' in type 'DerivedInterface' is not assignable to the same property in base type 'string | Base'.
|
||||
!!! error TS2416: Type 'string | DerivedInterface' is not assignable to type 'string | Base'.
|
||||
!!! error TS2416: Type 'DerivedInterface' is not assignable to type 'string | Base'.
|
||||
!!! error TS2416: Type 'DerivedInterface' is not assignable to type 'Base'.
|
||||
!!! error TS2416: Types of property 'n' are incompatible.
|
||||
!!! error TS2416: Type 'string | DerivedInterface' is not assignable to type 'string | Base'.
|
||||
!!! error TS2416: Type 'DerivedInterface' is not assignable to type 'string | Base'.
|
||||
!!! error TS2416: Type 'DerivedInterface' is not assignable to type 'Base'.
|
||||
fn() {
|
||||
~~
|
||||
!!! error TS2416: Property 'fn' in type 'DerivedInterface' is not assignable to the same property in base type '() => number'.
|
||||
!!! error TS2416: Type '() => string | number' is not assignable to type '() => number'.
|
||||
!!! error TS2416: Type 'string | number' is not assignable to type 'number'.
|
||||
!!! error TS2416: Type 'string' is not assignable to type 'number'.
|
||||
return 10 as number | string;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
//// [baseClassImprovedMismatchErrors.ts]
|
||||
class Base {
|
||||
n: Base | string;
|
||||
fn() {
|
||||
return 10;
|
||||
}
|
||||
}
|
||||
class Derived extends Base {
|
||||
n: Derived | string;
|
||||
fn() {
|
||||
return 10 as number | string;
|
||||
}
|
||||
}
|
||||
class DerivedInterface implements Base {
|
||||
n: DerivedInterface | string;
|
||||
fn() {
|
||||
return 10 as number | string;
|
||||
}
|
||||
}
|
||||
|
||||
//// [baseClassImprovedMismatchErrors.js]
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
var Base = /** @class */ (function () {
|
||||
function Base() {
|
||||
}
|
||||
Base.prototype.fn = function () {
|
||||
return 10;
|
||||
};
|
||||
return Base;
|
||||
}());
|
||||
var Derived = /** @class */ (function (_super) {
|
||||
__extends(Derived, _super);
|
||||
function Derived() {
|
||||
return _super !== null && _super.apply(this, arguments) || this;
|
||||
}
|
||||
Derived.prototype.fn = function () {
|
||||
return 10;
|
||||
};
|
||||
return Derived;
|
||||
}(Base));
|
||||
var DerivedInterface = /** @class */ (function () {
|
||||
function DerivedInterface() {
|
||||
}
|
||||
DerivedInterface.prototype.fn = function () {
|
||||
return 10;
|
||||
};
|
||||
return DerivedInterface;
|
||||
}());
|
||||
@@ -0,0 +1,42 @@
|
||||
=== tests/cases/compiler/baseClassImprovedMismatchErrors.ts ===
|
||||
class Base {
|
||||
>Base : Symbol(Base, Decl(baseClassImprovedMismatchErrors.ts, 0, 0))
|
||||
|
||||
n: Base | string;
|
||||
>n : Symbol(Base.n, Decl(baseClassImprovedMismatchErrors.ts, 0, 12))
|
||||
>Base : Symbol(Base, Decl(baseClassImprovedMismatchErrors.ts, 0, 0))
|
||||
|
||||
fn() {
|
||||
>fn : Symbol(Base.fn, Decl(baseClassImprovedMismatchErrors.ts, 1, 21))
|
||||
|
||||
return 10;
|
||||
}
|
||||
}
|
||||
class Derived extends Base {
|
||||
>Derived : Symbol(Derived, Decl(baseClassImprovedMismatchErrors.ts, 5, 1))
|
||||
>Base : Symbol(Base, Decl(baseClassImprovedMismatchErrors.ts, 0, 0))
|
||||
|
||||
n: Derived | string;
|
||||
>n : Symbol(Derived.n, Decl(baseClassImprovedMismatchErrors.ts, 6, 28))
|
||||
>Derived : Symbol(Derived, Decl(baseClassImprovedMismatchErrors.ts, 5, 1))
|
||||
|
||||
fn() {
|
||||
>fn : Symbol(Derived.fn, Decl(baseClassImprovedMismatchErrors.ts, 7, 24))
|
||||
|
||||
return 10 as number | string;
|
||||
}
|
||||
}
|
||||
class DerivedInterface implements Base {
|
||||
>DerivedInterface : Symbol(DerivedInterface, Decl(baseClassImprovedMismatchErrors.ts, 11, 1))
|
||||
>Base : Symbol(Base, Decl(baseClassImprovedMismatchErrors.ts, 0, 0))
|
||||
|
||||
n: DerivedInterface | string;
|
||||
>n : Symbol(DerivedInterface.n, Decl(baseClassImprovedMismatchErrors.ts, 12, 40))
|
||||
>DerivedInterface : Symbol(DerivedInterface, Decl(baseClassImprovedMismatchErrors.ts, 11, 1))
|
||||
|
||||
fn() {
|
||||
>fn : Symbol(DerivedInterface.fn, Decl(baseClassImprovedMismatchErrors.ts, 13, 33))
|
||||
|
||||
return 10 as number | string;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
=== tests/cases/compiler/baseClassImprovedMismatchErrors.ts ===
|
||||
class Base {
|
||||
>Base : Base
|
||||
|
||||
n: Base | string;
|
||||
>n : string | Base
|
||||
>Base : Base
|
||||
|
||||
fn() {
|
||||
>fn : () => number
|
||||
|
||||
return 10;
|
||||
>10 : 10
|
||||
}
|
||||
}
|
||||
class Derived extends Base {
|
||||
>Derived : Derived
|
||||
>Base : Base
|
||||
|
||||
n: Derived | string;
|
||||
>n : string | Derived
|
||||
>Derived : Derived
|
||||
|
||||
fn() {
|
||||
>fn : () => string | number
|
||||
|
||||
return 10 as number | string;
|
||||
>10 as number | string : string | number
|
||||
>10 : 10
|
||||
}
|
||||
}
|
||||
class DerivedInterface implements Base {
|
||||
>DerivedInterface : DerivedInterface
|
||||
>Base : Base
|
||||
|
||||
n: DerivedInterface | string;
|
||||
>n : string | DerivedInterface
|
||||
>DerivedInterface : DerivedInterface
|
||||
|
||||
fn() {
|
||||
>fn : () => string | number
|
||||
|
||||
return 10 as number | string;
|
||||
>10 as number | string : string | number
|
||||
>10 : 10
|
||||
}
|
||||
}
|
||||
@@ -9,3 +9,4 @@ var _b, _c, _d, _e;
|
||||
|
||||
|
||||
//// [bindingPatternOmittedExpressionNesting.d.ts]
|
||||
export {};
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
//// [classExtensionNameOutput.ts]
|
||||
class A {}
|
||||
if (true) {
|
||||
class B extends A {}
|
||||
|
||||
const foo = function () {
|
||||
new B();
|
||||
}
|
||||
}
|
||||
|
||||
//// [classExtensionNameOutput.js]
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
var A = /** @class */ (function () {
|
||||
function A() {
|
||||
}
|
||||
return A;
|
||||
}());
|
||||
if (true) {
|
||||
var B_1 = /** @class */ (function (_super) {
|
||||
__extends(B, _super);
|
||||
function B() {
|
||||
return _super !== null && _super.apply(this, arguments) || this;
|
||||
}
|
||||
return B;
|
||||
}(A));
|
||||
var foo = function () {
|
||||
new B_1();
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
=== tests/cases/compiler/classExtensionNameOutput.ts ===
|
||||
class A {}
|
||||
>A : Symbol(A, Decl(classExtensionNameOutput.ts, 0, 0))
|
||||
|
||||
if (true) {
|
||||
class B extends A {}
|
||||
>B : Symbol(B, Decl(classExtensionNameOutput.ts, 1, 11))
|
||||
>A : Symbol(A, Decl(classExtensionNameOutput.ts, 0, 0))
|
||||
|
||||
const foo = function () {
|
||||
>foo : Symbol(foo, Decl(classExtensionNameOutput.ts, 4, 7))
|
||||
|
||||
new B();
|
||||
>B : Symbol(B, Decl(classExtensionNameOutput.ts, 1, 11))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
=== tests/cases/compiler/classExtensionNameOutput.ts ===
|
||||
class A {}
|
||||
>A : A
|
||||
|
||||
if (true) {
|
||||
>true : true
|
||||
|
||||
class B extends A {}
|
||||
>B : B
|
||||
>A : A
|
||||
|
||||
const foo = function () {
|
||||
>foo : () => void
|
||||
>function () { new B(); } : () => void
|
||||
|
||||
new B();
|
||||
>new B() : B
|
||||
>B : typeof B
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
tests/cases/conformance/classes/classDeclarations/classHeritageSpecification/classIsSubtypeOfBaseType.ts(11,7): error TS2415: Class 'Derived2' incorrectly extends base class 'Base<{ bar: string; }>'.
|
||||
Types of property 'foo' are incompatible.
|
||||
Type '{ bar?: string; }' is not assignable to type '{ bar: string; }'.
|
||||
Property 'bar' is optional in type '{ bar?: string; }' but required in type '{ bar: string; }'.
|
||||
tests/cases/conformance/classes/classDeclarations/classHeritageSpecification/classIsSubtypeOfBaseType.ts(12,5): error TS2416: Property 'foo' in type 'Derived2' is not assignable to the same property in base type '{ bar: string; }'.
|
||||
Type '{ bar?: string; }' is not assignable to type '{ bar: string; }'.
|
||||
Property 'bar' is optional in type '{ bar?: string; }' but required in type '{ bar: string; }'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/classes/classDeclarations/classHeritageSpecification/classIsSubtypeOfBaseType.ts (1 errors) ====
|
||||
@@ -16,12 +15,11 @@ tests/cases/conformance/classes/classDeclarations/classHeritageSpecification/cla
|
||||
}
|
||||
|
||||
class Derived2 extends Base<{ bar: string; }> {
|
||||
~~~~~~~~
|
||||
!!! error TS2415: Class 'Derived2' incorrectly extends base class 'Base<{ bar: string; }>'.
|
||||
!!! error TS2415: Types of property 'foo' are incompatible.
|
||||
!!! error TS2415: Type '{ bar?: string; }' is not assignable to type '{ bar: string; }'.
|
||||
!!! error TS2415: Property 'bar' is optional in type '{ bar?: string; }' but required in type '{ bar: string; }'.
|
||||
foo: {
|
||||
~~~
|
||||
!!! error TS2416: Property 'foo' in type 'Derived2' is not assignable to the same property in base type '{ bar: string; }'.
|
||||
!!! error TS2416: Type '{ bar?: string; }' is not assignable to type '{ bar: string; }'.
|
||||
!!! error TS2416: Property 'bar' is optional in type '{ bar?: string; }' but required in type '{ bar: string; }'.
|
||||
bar?: string; // error
|
||||
}
|
||||
}
|
||||
@@ -169,3 +169,4 @@ export declare module m4 {
|
||||
function fooExport(): number;
|
||||
}
|
||||
//// [commentsExternalModules_1.d.ts]
|
||||
export {};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user