diff --git a/scripts/authors.ts b/scripts/authors.ts
index b52898244b6..f92511ed6ef 100644
--- a/scripts/authors.ts
+++ b/scripts/authors.ts
@@ -15,8 +15,8 @@ type Command = {
description?: string;
};
-const mailMapPath = path.resolve("../.mailmap");
-const authorsPath = path.resolve("../AUTHORS.md");
+const mailMapPath = path.resolve(__dirname, "../.mailmap");
+const authorsPath = path.resolve(__dirname, "../AUTHORS.md");
function getKnownAuthors(): Author[] {
const segmentRegExp = /\s?([^<]+)\s+<([^>]+)>/g;
@@ -113,56 +113,54 @@ namespace Commands {
const cmd = "git shortlog -se " + specs.join(" ");
console.log(cmd);
const outputRegExp = /\d+\s+([^<]+)<([^>]+)>/;
- const tty = process.platform === 'win32' ? 'CON' : '/dev/tty';
const authors: { name: string, email: string, knownAuthor?: Author }[] = [];
- child_process.exec(`${cmd} < ${tty}`, { cwd: path.resolve("../") }, function (error, stdout, stderr) {
- if (error) {
- console.log(stderr.toString());
- }
- else {
- const output = stdout.toString();
- const lines = output.split("\n");
- lines.forEach(line => {
- if (line) {
- let match: RegExpExecArray | null;
- if (match = outputRegExp.exec(line)) {
- authors.push({ name: match[1], email: match[2] });
- }
- else {
- throw new Error("Could not parse output: " + line);
- }
+ const {output: [error, stdout, stderr]} = child_process.spawnSync(`git`, ["shortlog", "-se", ...specs], { cwd: path.resolve(__dirname, "../") });
+ if (error) {
+ console.log(stderr.toString());
+ }
+ else {
+ const output = stdout.toString();
+ const lines = output.split("\n");
+ lines.forEach(line => {
+ if (line) {
+ let match: RegExpExecArray | null;
+ if (match = outputRegExp.exec(line)) {
+ authors.push({ name: match[1], email: match[2] });
+ }
+ else {
+ throw new Error("Could not parse output: " + line);
}
- });
-
- const maps = getKnownAuthorMaps();
-
- const lookupAuthor = function ({name, email}: { name: string, email: string }) {
- return maps.authorsByEmail[email.toLocaleLowerCase()] || maps.authorsByName[name];
- };
-
- const knownAuthors = authors
- .map(lookupAuthor)
- .filter(a => !!a)
- .map(getAuthorName);
- const unknownAuthors = authors
- .filter(a => !lookupAuthor(a))
- .map(a => `${a.name} <${a.email}>`);
-
- if (knownAuthors.length) {
- console.log("\r\n");
- console.log("Found known authors: ");
- console.log("=====================");
- deduplicate(knownAuthors).sort(sortAuthors).forEach(log);
}
+ });
- if (unknownAuthors.length) {
- console.log("\r\n");
- console.log("Found unknown authors: ");
- console.log("=====================");
- deduplicate(unknownAuthors).sort(sortAuthors).forEach(log);
- }
+ const maps = getKnownAuthorMaps();
+
+ const lookupAuthor = function ({name, email}: { name: string, email: string }) {
+ return maps.authorsByEmail[email.toLocaleLowerCase()] || maps.authorsByName[name];
+ };
+
+ const knownAuthors = authors
+ .map(lookupAuthor)
+ .filter(a => !!a)
+ .map(getAuthorName);
+ const unknownAuthors = authors
+ .filter(a => !lookupAuthor(a))
+ .map(a => `${a.name} <${a.email}>`);
+
+ if (knownAuthors.length) {
+ console.log("\r\n");
+ console.log("Found known authors: ");
+ console.log("=====================");
+ deduplicate(knownAuthors).sort(sortAuthors).forEach(log);
}
- });
+
+ if (unknownAuthors.length) {
+ console.log("\r\n");
+ console.log("Found unknown authors: ");
+ console.log("=====================");
+ deduplicate(unknownAuthors).sort(sortAuthors).forEach(log);
+ }
+ }
};
listAuthors.description = "List known and unknown authors for a given spec, e.g. 'node authors.js listAuthors origin/release-2.6..origin/release-2.7'";
}
diff --git a/scripts/perf-result-post.js b/scripts/perf-result-post.js
new file mode 100644
index 00000000000..5b1c4814a93
--- /dev/null
+++ b/scripts/perf-result-post.js
@@ -0,0 +1,48 @@
+// @ts-check
+///
+// Must reference esnext.asynciterable lib, since octokit uses AsyncIterable internally
+const Octokit = require("@octokit/rest");
+const fs = require("fs");
+
+const requester = process.env.requesting_user;
+const source = process.env.source_issue;
+const postedComment = process.env.status_comment;
+console.log(`Loading fragment from ${process.argv[3]}...`);
+const outputTableText = fs.readFileSync(process.argv[3], { encoding: "utf8" });
+console.log(`Fragment contents:
+${outputTableText}`);
+
+const gh = new Octokit();
+gh.authenticate({
+ type: "token",
+ token: process.argv[2]
+});
+gh.issues.createComment({
+ number: +source,
+ owner: "Microsoft",
+ repo: "TypeScript",
+ body: `@${requester}
+The results of the perf run you requested are in! Here they are:
+
+${outputTableText}`
+}).then(async data => {
+ console.log(`Results posted!`);
+ const newCommentUrl = data.data.html_url;
+ const comment = await gh.issues.getComment({
+ owner: "Microsoft",
+ repo: "TypeScript",
+ comment_id: +postedComment
+ });
+ const newBody = `${comment.data.body}
+
+Update: [The results are in!](${newCommentUrl})`;
+ return await gh.issues.updateComment({
+ owner: "Microsoft",
+ repo: "TypeScript",
+ comment_id: +postedComment,
+ body: newBody
+ });
+}).catch(e => {
+ console.error(e);
+ process.exit(1);
+});
diff --git a/src/compiler/builderState.ts b/src/compiler/builderState.ts
index ff21d76ad8e..b7f01b838fd 100644
--- a/src/compiler/builderState.ts
+++ b/src/compiler/builderState.ts
@@ -230,7 +230,7 @@ namespace ts.BuilderState {
// Create the reference map, and set the file infos
for (const sourceFile of newProgram.getSourceFiles()) {
- const version = sourceFile.version;
+ const version = Debug.assertDefined(sourceFile.version, "Program intended to be used with Builder should have source files with versions set");
const oldInfo = useOldState ? oldState!.fileInfos.get(sourceFile.path) : undefined;
if (referencedMap) {
const newReferences = getReferencedFiles(newProgram, sourceFile, getCanonicalFileName);
diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index 5142d608515..98a459b6ccd 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -232,6 +232,7 @@ namespace ts {
getResolvedSignatureForSignatureHelp: (node, candidatesOutArray, agumentCount) =>
getResolvedSignatureWorker(node, candidatesOutArray, agumentCount, CheckMode.IsForSignatureHelp),
getExpandedParameters,
+ hasEffectiveRestParameter,
getConstantValue: nodeIn => {
const node = getParseTreeNode(nodeIn, canHaveConstantValue);
return node ? getConstantValue(node) : undefined;
@@ -304,6 +305,8 @@ namespace ts {
getNeverType: () => neverType,
isSymbolAccessible,
getObjectFlags,
+ isArrayType,
+ isTupleType,
isArrayLikeType,
isTypeInvalidDueToUnionDiscriminant,
getAllPossiblePropertiesOfTypes,
@@ -388,7 +391,7 @@ namespace ts {
const intersectionTypes = createMap();
const literalTypes = createMap();
const indexedAccessTypes = createMap();
- const conditionalTypes = createMap();
+ const conditionalTypes = createMap();
const evolvingArrayTypes: EvolvingArrayType[] = [];
const undefinedProperties = createMap() as UnderscoreEscapedMap;
@@ -1471,7 +1474,14 @@ namespace ts {
// @y method(x, y) {} // <-- decorator y should be resolved at the class declaration, not the method.
// }
//
- if (location.parent && isClassElement(location.parent)) {
+
+ // class Decorators are resolved outside of the class to avoid referencing type parameters of that class.
+ //
+ // type T = number;
+ // declare function y(x: T): any;
+ // @param(1 as T) // <-- T should resolve to the type alias outside of class C
+ // class C {}
+ if (location.parent && (isClassElement(location.parent) || location.parent.kind === SyntaxKind.ClassDeclaration)) {
location = location.parent;
}
break;
@@ -2342,19 +2352,12 @@ namespace ts {
}
if (moduleNotFoundError) {
- // For relative paths, see if this was possibly a projectReference redirect
- if (pathIsRelative(moduleReference)) {
- const sourceFile = getSourceFileOfNode(location);
- const redirects = sourceFile.redirectedReferences;
- if (redirects) {
- const normalizedTargetPath = getNormalizedAbsolutePath(moduleReference, getDirectoryPath(sourceFile.fileName));
- for (const ext of [Extension.Ts, Extension.Tsx]) {
- const probePath = normalizedTargetPath + ext;
- if (redirects.indexOf(probePath) >= 0) {
- error(errorNode, Diagnostics.Output_file_0_has_not_been_built_from_source_file_1, moduleReference, probePath);
- return undefined;
- }
- }
+ // See if this was possibly a projectReference redirect
+ if (resolvedModule) {
+ const redirect = host.getProjectReferenceRedirect(resolvedModule.resolvedFileName);
+ if (redirect) {
+ error(errorNode, Diagnostics.Output_file_0_has_not_been_built_from_source_file_1, redirect, resolvedModule.resolvedFileName);
+ return undefined;
}
}
@@ -3489,8 +3492,8 @@ namespace ts {
context.inferTypeParameters = (type).root.inferTypeParameters;
const extendsTypeNode = typeToTypeNodeHelper((type).extendsType, context);
context.inferTypeParameters = saveInferTypeParameters;
- const trueTypeNode = typeToTypeNodeHelper(getTrueTypeFromConditionalType(type), context);
- const falseTypeNode = typeToTypeNodeHelper(getFalseTypeFromConditionalType(type), context);
+ const trueTypeNode = typeToTypeNodeHelper((type).trueType, context);
+ const falseTypeNode = typeToTypeNodeHelper((type).falseType, context);
context.approximateLength += 15;
return createConditionalTypeNode(checkTypeNode, extendsTypeNode, trueTypeNode, falseTypeNode);
}
@@ -5471,9 +5474,6 @@ namespace ts {
}
return type;
}
- if (declaration.kind === SyntaxKind.ExportAssignment) {
- return widenTypeForVariableLikeDeclaration(checkExpressionCached((declaration).expression), declaration);
- }
// Handle variable, parameter or property
if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) {
@@ -5484,7 +5484,10 @@ namespace ts {
return reportCircularityError(symbol);
}
let type: Type | undefined;
- if (isInJSFile(declaration) &&
+ if (declaration.kind === SyntaxKind.ExportAssignment) {
+ type = widenTypeForVariableLikeDeclaration(checkExpressionCached((declaration).expression), declaration);
+ }
+ else if (isInJSFile(declaration) &&
(isCallExpression(declaration) || isBinaryExpression(declaration) || isPropertyAccessExpression(declaration) && isBinaryExpression(declaration.parent))) {
type = getWidenedTypeFromAssignmentDeclaration(symbol);
}
@@ -7113,6 +7116,15 @@ namespace ts {
let stringIndexInfo: IndexInfo | undefined;
if (symbol.exports) {
members = getExportsOfSymbol(symbol);
+ if (symbol === globalThisSymbol) {
+ const varsOnly = createMap() as SymbolTable;
+ members.forEach(p => {
+ if (!(p.flags & SymbolFlags.BlockScoped)) {
+ varsOnly.set(p.escapedName, p);
+ }
+ });
+ members = varsOnly;
+ }
}
setStructuredTypeMembers(type, members, emptyArray, emptyArray, undefined, undefined);
if (symbol.flags & SymbolFlags.Class) {
@@ -7465,6 +7477,10 @@ namespace ts {
}
function getConstraintOfIndexedAccess(type: IndexedAccessType) {
+ return hasNonCircularBaseConstraint(type) ? getConstraintFromIndexedAccess(type) : undefined;
+ }
+
+ function getConstraintFromIndexedAccess(type: IndexedAccessType) {
const objectType = getConstraintOfType(type.objectType) || type.objectType;
if (objectType !== type.objectType) {
const constraint = getIndexedAccessType(objectType, type.indexType, /*accessNode*/ undefined, errorType);
@@ -7476,24 +7492,14 @@ namespace ts {
return baseConstraint && baseConstraint !== type ? baseConstraint : undefined;
}
- function getDefaultConstraintOfTrueBranchOfConditionalType(root: ConditionalRoot, combinedMapper: TypeMapper | undefined, mapper: TypeMapper | undefined) {
- const rootTrueType = root.trueType;
- const rootTrueConstraint = !(rootTrueType.flags & TypeFlags.Substitution)
- ? rootTrueType
- : instantiateType(((rootTrueType).substitute), combinedMapper || mapper).flags & TypeFlags.AnyOrUnknown
- ? (rootTrueType).typeVariable
- : getIntersectionType([(rootTrueType).substitute, (rootTrueType).typeVariable]);
- return instantiateType(rootTrueConstraint, combinedMapper || mapper);
- }
-
function getDefaultConstraintOfConditionalType(type: ConditionalType) {
if (!type.resolvedDefaultConstraint) {
// An `any` branch of a conditional type would normally be viral - specifically, without special handling here,
// a conditional type with a single branch of type `any` would be assignable to anything, since it's constraint would simplify to
// just `any`. This result is _usually_ unwanted - so instead here we elide an `any` branch from the constraint type,
// in effect treating `any` like `never` rather than `unknown` in this location.
- const trueConstraint = getDefaultConstraintOfTrueBranchOfConditionalType(type.root, type.combinedMapper, type.mapper);
- const falseConstraint = getFalseTypeFromConditionalType(type);
+ const trueConstraint = getInferredTrueTypeFromConditionalType(type);
+ const falseConstraint = type.falseType;
type.resolvedDefaultConstraint = isTypeAny(trueConstraint) ? falseConstraint : isTypeAny(falseConstraint) ? trueConstraint : getUnionType([trueConstraint, falseConstraint]);
}
return type.resolvedDefaultConstraint;
@@ -7525,10 +7531,14 @@ namespace ts {
return undefined;
}
- function getConstraintOfConditionalType(type: ConditionalType) {
+ function getConstraintFromConditionalType(type: ConditionalType) {
return getConstraintOfDistributiveConditionalType(type) || getDefaultConstraintOfConditionalType(type);
}
+ function getConstraintOfConditionalType(type: ConditionalType) {
+ return hasNonCircularBaseConstraint(type) ? getConstraintFromConditionalType(type) : undefined;
+ }
+
function getUnionConstraintOfIntersection(type: IntersectionType, targetIsUnion: boolean) {
let constraints: Type[] | undefined;
let hasDisjointDomainType = false;
@@ -7605,7 +7615,7 @@ namespace ts {
if (!pushTypeResolution(t, TypeSystemPropertyName.ImmediateBaseConstraint)) {
return circularConstraintType;
}
- if (constraintDepth === 50) {
+ if (constraintDepth >= 50) {
// We have reached 50 recursive invocations of getImmediateBaseConstraint and there is a
// very high likelyhood we're dealing with an infinite generic type that perpetually generates
// new type identities as we descend into it. We stop the recursion here and mark this type
@@ -7672,8 +7682,11 @@ namespace ts {
return baseIndexedAccess && baseIndexedAccess !== errorType ? getBaseConstraint(baseIndexedAccess) : undefined;
}
if (t.flags & TypeFlags.Conditional) {
- const constraint = getConstraintOfConditionalType(t);
- return constraint && getBaseConstraint(constraint);
+ const constraint = getConstraintFromConditionalType(t);
+ constraintDepth++; // Penalize repeating conditional types (this captures the recursion within getConstraintFromConditionalType and carries it forward)
+ const result = constraint && getBaseConstraint(constraint);
+ constraintDepth--;
+ return result;
}
if (t.flags & TypeFlags.Substitution) {
return getBaseConstraint((t).substitute);
@@ -7769,7 +7782,7 @@ namespace ts {
}
function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: __String): Symbol | undefined {
- let props: Symbol[] | undefined;
+ const propSet = createMap();
let indexTypes: Type[] | undefined;
const isUnion = containingType.flags & TypeFlags.Union;
const excludeModifiers = isUnion ? ModifierFlags.NonPublicAccessibilityModifier : 0;
@@ -7784,7 +7797,10 @@ namespace ts {
const modifiers = prop ? getDeclarationModifierFlagsFromSymbol(prop) : 0;
if (prop && !(modifiers & excludeModifiers)) {
commonFlags &= prop.flags;
- props = appendIfUnique(props, prop);
+ const id = "" + getSymbolId(prop);
+ if (!propSet.has(id)) {
+ propSet.set(id, prop);
+ }
checkFlags |= (isReadonlySymbol(prop) ? CheckFlags.Readonly : 0) |
(!(modifiers & ModifierFlags.NonPublicAccessibilityModifier) ? CheckFlags.ContainsPublic : 0) |
(modifiers & ModifierFlags.Protected ? CheckFlags.ContainsProtected : 0) |
@@ -7806,9 +7822,10 @@ namespace ts {
}
}
}
- if (!props) {
+ if (!propSet.size) {
return undefined;
}
+ const props = arrayFrom(propSet.values());
if (props.length === 1 && !(checkFlags & CheckFlags.Partial) && !indexTypes) {
return props[0];
}
@@ -8298,7 +8315,7 @@ namespace ts {
}
}
signature.resolvedTypePredicate = type && isTypePredicateNode(type) ?
- createTypePredicateFromTypePredicateNode(type, signature.declaration!) :
+ createTypePredicateFromTypePredicateNode(type, signature) :
jsdocPredicate || noTypePredicate;
}
Debug.assert(!!signature.resolvedTypePredicate);
@@ -8306,13 +8323,13 @@ namespace ts {
return signature.resolvedTypePredicate === noTypePredicate ? undefined : signature.resolvedTypePredicate;
}
- function createTypePredicateFromTypePredicateNode(node: TypePredicateNode, func: SignatureDeclaration | JSDocSignature): IdentifierTypePredicate | ThisTypePredicate {
+ function createTypePredicateFromTypePredicateNode(node: TypePredicateNode, signature: Signature): IdentifierTypePredicate | ThisTypePredicate {
const { parameterName } = node;
const type = getTypeFromTypeNode(node.type);
if (parameterName.kind === SyntaxKind.Identifier) {
return createIdentifierTypePredicate(
parameterName.escapedText as string,
- getTypePredicateParameterIndex(func.parameters, parameterName),
+ findIndex(signature.parameters, p => p.escapedName === parameterName.escapedText),
type);
}
else {
@@ -8320,16 +8337,6 @@ namespace ts {
}
}
- function getTypePredicateParameterIndex(parameterList: ReadonlyArray, parameter: Identifier): number {
- for (let i = 0; i < parameterList.length; i++) {
- const param = parameterList[i];
- if (param.name.kind === SyntaxKind.Identifier && param.name.escapedText === parameter.escapedText) {
- return i;
- }
- }
- return -1;
- }
-
function getReturnTypeOfSignature(signature: Signature): Type {
if (!signature.resolvedReturnType) {
if (!pushTypeResolution(signature, TypeSystemPropertyName.ResolvedReturnType)) {
@@ -8860,6 +8867,9 @@ namespace ts {
}
function getSubstitutionType(typeVariable: TypeVariable, substitute: Type) {
+ if (substitute.flags & TypeFlags.AnyOrUnknown) {
+ return typeVariable;
+ }
const result = createType(TypeFlags.Substitution);
result.typeVariable = typeVariable;
result.substitute = substitute;
@@ -9880,6 +9890,7 @@ namespace ts {
getNodeLinks(accessNode!).resolvedSymbol = prop;
}
}
+
const propType = getTypeOfSymbol(prop);
return accessExpression && getAssignmentTargetKind(accessExpression) !== AssignmentKind.Definite ?
getFlowTypeOfReference(accessExpression, propType) :
@@ -9923,7 +9934,10 @@ namespace ts {
return anyType;
}
if (accessExpression && !isConstEnumObjectType(objectType)) {
- if (noImplicitAny && !compilerOptions.suppressImplicitAnyIndexErrors) {
+ if (objectType.symbol === globalThisSymbol && propName !== undefined && globalThisSymbol.exports!.has(propName) && (globalThisSymbol.exports!.get(propName)!.flags & SymbolFlags.BlockScoped)) {
+ error(accessExpression, Diagnostics.Property_0_does_not_exist_on_type_1, unescapeLeadingUnderscores(propName), typeToString(objectType));
+ }
+ else if (noImplicitAny && !compilerOptions.suppressImplicitAnyIndexErrors) {
if (propName !== undefined && typeHasStaticProperty(propName, objectType)) {
error(accessExpression, Diagnostics.Property_0_is_a_static_member_of_type_1, propName as string, typeToString(objectType));
}
@@ -10138,24 +10152,11 @@ namespace ts {
const trueType = instantiateType(root.trueType, mapper);
const falseType = instantiateType(root.falseType, mapper);
const instantiationId = `${root.isDistributive ? "d" : ""}${getTypeId(checkType)}>${getTypeId(extendsType)}?${getTypeId(trueType)}:${getTypeId(falseType)}`;
- if (conditionalTypes.has(instantiationId)) {
- const result = conditionalTypes.get(instantiationId);
- if (result !== undefined) {
- return result;
- }
- // Somehow the conditional type depends on itself - usually via `infer` types in the `extends` clause
- // paired with a (potentially deferred) circularly constrained type.
- // The conditional _must_ be deferred.
- const deferred = getDeferredConditionalType(root, mapper, /*combinedMapper*/ undefined, checkType, extendsType, trueType, falseType);
- conditionalTypes.set(instantiationId, deferred);
- return deferred;
+ const result = conditionalTypes.get(instantiationId);
+ if (result) {
+ return result;
}
- conditionalTypes.set(instantiationId, undefined);
const newResult = getConditionalTypeWorker(root, mapper, checkType, extendsType, trueType, falseType);
- const cachedRecursiveResult = conditionalTypes.get(instantiationId);
- if (cachedRecursiveResult) {
- return cachedRecursiveResult;
- }
conditionalTypes.set(instantiationId, newResult);
return newResult;
}
@@ -10164,7 +10165,7 @@ namespace ts {
// Simplifications for types of the form `T extends U ? T : never` and `T extends U ? never : T`.
if (falseType.flags & TypeFlags.Never && isTypeIdenticalTo(getActualTypeVariable(trueType), getActualTypeVariable(checkType))) {
if (checkType.flags & TypeFlags.Any || isTypeAssignableTo(getRestrictiveInstantiation(checkType), getRestrictiveInstantiation(extendsType))) { // Always true
- return getDefaultConstraintOfTrueBranchOfConditionalType(root, /*combinedMapper*/ undefined, mapper);
+ return trueType;
}
else if (isIntersectionEmpty(checkType, extendsType)) { // Always false
return neverType;
@@ -10175,7 +10176,7 @@ namespace ts {
return neverType;
}
else if (checkType.flags & TypeFlags.Any || isIntersectionEmpty(checkType, extendsType)) { // Always false
- return falseType; // TODO: Intersect negated `extends` type here
+ return falseType;
}
}
@@ -10230,21 +10231,15 @@ namespace ts {
result.extendsType = extendsType;
result.mapper = mapper;
result.combinedMapper = combinedMapper;
- if (!combinedMapper) {
- result.resolvedTrueType = trueType;
- result.resolvedFalseType = falseType;
- }
+ result.trueType = trueType;
+ result.falseType = falseType;
result.aliasSymbol = root.aliasSymbol;
result.aliasTypeArguments = instantiateTypes(root.aliasTypeArguments, mapper!); // TODO: GH#18217
return result;
}
- function getTrueTypeFromConditionalType(type: ConditionalType) {
- return type.resolvedTrueType || (type.resolvedTrueType = instantiateType(type.root.trueType, type.mapper));
- }
-
- function getFalseTypeFromConditionalType(type: ConditionalType) {
- return type.resolvedFalseType || (type.resolvedFalseType = instantiateType(type.root.falseType, type.mapper));
+ function getInferredTrueTypeFromConditionalType(type: ConditionalType) {
+ return type.resolvedInferredTrueType || (type.resolvedInferredTrueType = instantiateType(type.root.trueType, type.combinedMapper || type.mapper));
}
function getInferTypeParameters(node: ConditionalTypeNode): TypeParameter[] | undefined {
@@ -11185,7 +11180,11 @@ namespace ts {
return getSubstitutionType(maybeVariable as TypeVariable, instantiateType((type).substitute, mapper));
}
else {
- return maybeVariable;
+ const sub = instantiateType((type).substitute, mapper);
+ if (sub.flags & TypeFlags.AnyOrUnknown || isTypeSubtypeOf(getRestrictiveInstantiation(maybeVariable), getRestrictiveInstantiation(sub))) {
+ return maybeVariable;
+ }
+ return sub;
}
}
return type;
@@ -11730,6 +11729,15 @@ namespace ts {
type ErrorReporter = (message: DiagnosticMessage, arg0?: string, arg1?: string) => void;
+ /**
+ * Returns true if `s` is `(...args: any[]) => any` or `(this: any, ...args: any[]) => any`
+ */
+ function isAnySignature(s: Signature) {
+ return !s.typeParameters && (!s.thisParameter || isTypeAny(getTypeOfParameter(s.thisParameter))) && s.parameters.length === 1 &&
+ s.hasRestParameter && (getTypeOfParameter(s.parameters[0]) === anyArrayType || isTypeAny(getTypeOfParameter(s.parameters[0]))) &&
+ isTypeAny(getReturnTypeOfSignature(s));
+ }
+
/**
* See signatureRelatedTo, compareSignaturesIdentical
*/
@@ -11745,6 +11753,10 @@ namespace ts {
return Ternary.True;
}
+ if (isAnySignature(target)) {
+ return Ternary.True;
+ }
+
const targetCount = getParameterCount(target);
if (!hasEffectiveRestParameter(target) && getMinArgumentCount(source) > targetCount) {
return Ternary.False;
@@ -11832,7 +11844,7 @@ namespace ts {
if (targetTypePredicate) {
const sourceTypePredicate = getTypePredicateOfSignature(source);
if (sourceTypePredicate) {
- result &= compareTypePredicateRelatedTo(sourceTypePredicate, targetTypePredicate, source.declaration!, target.declaration!, reportErrors, errorReporter, compareTypes); // TODO: GH#18217
+ result &= compareTypePredicateRelatedTo(sourceTypePredicate, targetTypePredicate, reportErrors, errorReporter, compareTypes);
}
else if (isIdentifierTypePredicate(targetTypePredicate)) {
if (reportErrors) {
@@ -11857,8 +11869,6 @@ namespace ts {
function compareTypePredicateRelatedTo(
source: TypePredicate,
target: TypePredicate,
- sourceDeclaration: SignatureDeclaration | JSDocSignature,
- targetDeclaration: SignatureDeclaration | JSDocSignature,
reportErrors: boolean,
errorReporter: ErrorReporter | undefined,
compareTypes: (s: Type, t: Type, reportErrors?: boolean) => Ternary): Ternary {
@@ -11871,12 +11881,9 @@ namespace ts {
}
if (source.kind === TypePredicateKind.Identifier) {
- const targetPredicate = target as IdentifierTypePredicate;
- const sourceIndex = source.parameterIndex - (getThisParameter(sourceDeclaration) ? 1 : 0);
- const targetIndex = targetPredicate.parameterIndex - (getThisParameter(targetDeclaration) ? 1 : 0);
- if (sourceIndex !== targetIndex) {
+ if (source.parameterIndex !== (target as IdentifierTypePredicate).parameterIndex) {
if (reportErrors) {
- errorReporter!(Diagnostics.Parameter_0_is_not_in_the_same_position_as_parameter_1, source.parameterName, targetPredicate.parameterName);
+ errorReporter!(Diagnostics.Parameter_0_is_not_in_the_same_position_as_parameter_1, source.parameterName, (target as IdentifierTypePredicate).parameterName);
errorReporter!(Diagnostics.Type_predicate_0_is_not_assignable_to_1, typePredicateToString(source), typePredicateToString(target));
}
return Ternary.False;
@@ -12714,8 +12721,8 @@ namespace ts {
if ((source).root.isDistributive === (target).root.isDistributive) {
if (result = isRelatedTo((source).checkType, (target).checkType, /*reportErrors*/ false)) {
if (result &= isRelatedTo((source).extendsType, (target).extendsType, /*reportErrors*/ false)) {
- if (result &= isRelatedTo(getTrueTypeFromConditionalType(source), getTrueTypeFromConditionalType(target), /*reportErrors*/ false)) {
- if (result &= isRelatedTo(getFalseTypeFromConditionalType(source), getFalseTypeFromConditionalType(target), /*reportErrors*/ false)) {
+ if (result &= isRelatedTo((source).trueType, (target).trueType, /*reportErrors*/ false)) {
+ if (result &= isRelatedTo((source).falseType, (target).falseType, /*reportErrors*/ false)) {
return result;
}
}
@@ -12836,7 +12843,7 @@ namespace ts {
return result;
}
}
- const constraint = getConstraintOfType(source);
+ const constraint = getConstraintOfType(source);
if (!constraint || (source.flags & TypeFlags.TypeParameter && constraint.flags & TypeFlags.Any)) {
// A type variable with no constraint is not related to the non-primitive object type.
if (result = isRelatedTo(emptyObjectType, extractTypesOfKind(target, ~TypeFlags.NonPrimitive))) {
@@ -12868,8 +12875,8 @@ namespace ts {
// and Y1 is related to Y2.
if (isTypeIdenticalTo((source).extendsType, (target).extendsType) &&
(isRelatedTo((source).checkType, (target).checkType) || isRelatedTo((target).checkType, (source).checkType))) {
- if (result = isRelatedTo(getTrueTypeFromConditionalType(source), getTrueTypeFromConditionalType(target), reportErrors)) {
- result &= isRelatedTo(getFalseTypeFromConditionalType(source), getFalseTypeFromConditionalType(target), reportErrors);
+ if (result = isRelatedTo((source).trueType, (target).trueType, reportErrors)) {
+ result &= isRelatedTo((source).falseType, (target).falseType, reportErrors);
}
if (result) {
errorInfo = saveErrorInfo;
@@ -14283,7 +14290,7 @@ namespace ts {
}
}
- function forEachMatchingParameterType(source: Signature, target: Signature, callback: (s: Type, t: Type) => void) {
+ function applyToParameterTypes(source: Signature, target: Signature, callback: (s: Type, t: Type) => void) {
const sourceCount = getParameterCount(source);
const targetCount = getParameterCount(target);
const sourceRestType = getEffectiveRestType(source);
@@ -14305,6 +14312,18 @@ namespace ts {
}
}
+ function applyToReturnTypes(source: Signature, target: Signature, callback: (s: Type, t: Type) => void) {
+ const sourceTypePredicate = getTypePredicateOfSignature(source);
+ const targetTypePredicate = getTypePredicateOfSignature(target);
+ if (sourceTypePredicate && targetTypePredicate && sourceTypePredicate.kind === targetTypePredicate.kind &&
+ (sourceTypePredicate.kind === TypePredicateKind.This || sourceTypePredicate.parameterIndex === (targetTypePredicate).parameterIndex)) {
+ callback(sourceTypePredicate.type, targetTypePredicate.type);
+ }
+ else {
+ callback(getReturnTypeOfSignature(source), getReturnTypeOfSignature(target));
+ }
+ }
+
function createInferenceContext(typeParameters: ReadonlyArray, signature: Signature | undefined, flags: InferenceFlags, compareTypes?: TypeComparer): InferenceContext {
return createInferenceContextWorker(typeParameters.map(createInferenceInfo), signature, flags, compareTypes || compareTypesAssignable);
}
@@ -14523,10 +14542,9 @@ namespace ts {
emptyObjectType;
}
- function inferTypes(inferences: InferenceInfo[], originalSource: Type, originalTarget: Type, priority: InferencePriority = 0) {
+ function inferTypes(inferences: InferenceInfo[], originalSource: Type, originalTarget: Type, priority: InferencePriority = 0, contravariant = false) {
let symbolStack: Symbol[];
let visited: Map;
- let contravariant = false;
let bivariant = false;
let propagationType: Type;
let allowComplexConstraintInference = true;
@@ -14617,9 +14635,11 @@ namespace ts {
const candidate = propagationType || source;
// We make contravariant inferences only if we are in a pure contravariant position,
// i.e. only if we have not descended into a bivariant position.
- if (contravariant && !bivariant && !contains(inference.contraCandidates, candidate)) {
- inference.contraCandidates = append(inference.contraCandidates, candidate);
- inference.inferredType = undefined;
+ if (contravariant && !bivariant) {
+ if (!contains(inference.contraCandidates, candidate)) {
+ inference.contraCandidates = append(inference.contraCandidates, candidate);
+ inference.inferredType = undefined;
+ }
}
else if (!contains(inference.candidates, candidate)) {
inference.candidates = append(inference.candidates, candidate);
@@ -14691,12 +14711,12 @@ namespace ts {
else if (source.flags & TypeFlags.Conditional && target.flags & TypeFlags.Conditional) {
inferFromTypes((source).checkType, (target).checkType);
inferFromTypes((source).extendsType, (target).extendsType);
- inferFromTypes(getTrueTypeFromConditionalType(source), getTrueTypeFromConditionalType(target));
- inferFromTypes(getFalseTypeFromConditionalType(source), getFalseTypeFromConditionalType(target));
+ inferFromTypes((source).trueType, (target).trueType);
+ inferFromTypes((source).falseType, (target).falseType);
}
else if (target.flags & TypeFlags.Conditional && !contravariant) {
- inferFromTypes(source, getTrueTypeFromConditionalType(target));
- inferFromTypes(source, getFalseTypeFromConditionalType(target));
+ inferFromTypes(source, (target).trueType);
+ inferFromTypes(source, (target).falseType);
}
else if (target.flags & TypeFlags.UnionOrIntersection) {
for (const t of (target).types) {
@@ -14924,17 +14944,10 @@ namespace ts {
const kind = target.declaration ? target.declaration.kind : SyntaxKind.Unknown;
// Once we descend into a bivariant signature we remain bivariant for all nested inferences
bivariant = bivariant || kind === SyntaxKind.MethodDeclaration || kind === SyntaxKind.MethodSignature || kind === SyntaxKind.Constructor;
- forEachMatchingParameterType(source, target, inferFromContravariantTypes);
+ applyToParameterTypes(source, target, inferFromContravariantTypes);
bivariant = saveBivariant;
}
- const sourceTypePredicate = getTypePredicateOfSignature(source);
- const targetTypePredicate = getTypePredicateOfSignature(target);
- if (sourceTypePredicate && targetTypePredicate && sourceTypePredicate.kind === targetTypePredicate.kind) {
- inferFromTypes(sourceTypePredicate.type, targetTypePredicate.type);
- }
- else {
- inferFromTypes(getReturnTypeOfSignature(source), getReturnTypeOfSignature(target));
- }
+ applyToReturnTypes(source, target, inferFromTypes);
}
function inferFromIndexTypes(source: Type, target: Type) {
@@ -16600,7 +16613,7 @@ namespace ts {
}
if (isIdentifierTypePredicate(predicate)) {
- const predicateArgument = callExpression.arguments[predicate.parameterIndex - (signature.thisParameter ? 1 : 0)];
+ const predicateArgument = callExpression.arguments[predicate.parameterIndex];
if (predicateArgument) {
if (isMatchingReference(reference, predicateArgument)) {
return getNarrowedType(type, predicate.type, assumeTrue, isTypeSubtypeOf);
@@ -19530,7 +19543,10 @@ namespace ts {
return anyType;
}
if (leftType.symbol === globalThisSymbol) {
- if (noImplicitAny) {
+ if (globalThisSymbol.exports!.has(right.escapedText) && (globalThisSymbol.exports!.get(right.escapedText)!.flags & SymbolFlags.BlockScoped)) {
+ error(right, Diagnostics.Property_0_does_not_exist_on_type_1, unescapeLeadingUnderscores(right.escapedText), typeToString(leftType));
+ }
+ else if (noImplicitAny) {
error(right, Diagnostics.Element_implicitly_has_an_any_type_because_type_0_has_no_index_signature, typeToString(leftType));
}
return anyType;
@@ -20170,18 +20186,14 @@ namespace ts {
const restType = getEffectiveRestType(contextualSignature);
const mapper = inferenceContext && (restType && restType.flags & TypeFlags.TypeParameter ? inferenceContext.nonFixingMapper : inferenceContext.mapper);
const sourceSignature = mapper ? instantiateSignature(contextualSignature, mapper) : contextualSignature;
- forEachMatchingParameterType(sourceSignature, signature, (source, target) => {
+ applyToParameterTypes(sourceSignature, signature, (source, target) => {
// Type parameters from outer context referenced by source type are fixed by instantiation of the source type
inferTypes(context.inferences, source, target);
});
if (!inferenceContext) {
- inferTypes(context.inferences, getReturnTypeOfSignature(contextualSignature), getReturnTypeOfSignature(signature), InferencePriority.ReturnType);
- const signaturePredicate = getTypePredicateOfSignature(signature);
- const contextualPredicate = getTypePredicateOfSignature(sourceSignature);
- if (signaturePredicate && contextualPredicate && signaturePredicate.kind === contextualPredicate.kind &&
- (signaturePredicate.kind === TypePredicateKind.This || signaturePredicate.parameterIndex === (contextualPredicate as IdentifierTypePredicate).parameterIndex)) {
- inferTypes(context.inferences, contextualPredicate.type, signaturePredicate.type, InferencePriority.ReturnType);
- }
+ applyToReturnTypes(contextualSignature, signature, (source, target) => {
+ inferTypes(context.inferences, source, target, InferencePriority.ReturnType);
+ });
}
return getSignatureInstantiation(signature, getInferredTypes(context), isInJSFile(contextualSignature.declaration));
}
@@ -23520,23 +23532,30 @@ namespace ts {
// potentially add inferred type parameters to the outer function return type.
const returnSignature = context.signature && getSingleCallSignature(getReturnTypeOfSignature(context.signature));
if (returnSignature && !returnSignature.typeParameters && !every(context.inferences, hasInferenceCandidates)) {
- // Instantiate the expression type with its own type parameters as type arguments. This
- // ensures that the type parameters are not erased to type any during type inference such
- // that they can be inferred as actual types.
+ // Instantiate the signature with its own type parameters as type arguments, possibly
+ // renaming the type parameters to ensure they have unique names.
const uniqueTypeParameters = getUniqueTypeParameters(context, signature.typeParameters);
- const strippedType = getOrCreateTypeFromSignature(getSignatureInstantiationWithoutFillingInTypeArguments(signature, uniqueTypeParameters));
- // Infer from the stripped expression type to the contextual type starting with an empty
- // set of inference candidates.
+ const instantiatedSignature = getSignatureInstantiationWithoutFillingInTypeArguments(signature, uniqueTypeParameters);
+ // Infer from the parameters of the instantiated signature to the parameters of the
+ // contextual signature starting with an empty set of inference candidates.
const inferences = map(context.inferences, info => createInferenceInfo(info.typeParameter));
- inferTypes(inferences, strippedType, contextualType);
- // If we produced some inference candidates and if the type parameters for which we produced
- // candidates do not already have existing inferences, we adopt the new inference candidates and
- // add the type parameters of the expression type to the set of inferred type parameters for
- // the outer function return type.
- if (some(inferences, hasInferenceCandidates) && !hasOverlappingInferences(context.inferences, inferences)) {
- mergeInferences(context.inferences, inferences);
- context.inferredTypeParameters = concatenate(context.inferredTypeParameters, uniqueTypeParameters);
- return strippedType;
+ applyToParameterTypes(instantiatedSignature, contextualSignature, (source, target) => {
+ inferTypes(inferences, source, target, /*priority*/ 0, /*contravariant*/ true);
+ });
+ if (some(inferences, hasInferenceCandidates)) {
+ // We have inference candidates, indicating that one or more type parameters are referenced
+ // in the parameter types of the contextual signature. Now also infer from the return type.
+ applyToReturnTypes(instantiatedSignature, contextualSignature, (source, target) => {
+ inferTypes(inferences, source, target);
+ });
+ // If the type parameters for which we produced candidates do not have any inferences yet,
+ // we adopt the new inference candidates and add the type parameters of the expression type
+ // to the set of inferred type parameters for the outer function return type.
+ if (!hasOverlappingInferences(context.inferences, inferences)) {
+ mergeInferences(context.inferences, inferences);
+ context.inferredTypeParameters = concatenate(context.inferredTypeParameters, uniqueTypeParameters);
+ return getOrCreateTypeFromSignature(instantiatedSignature);
+ }
}
}
return getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, context));
@@ -23880,7 +23899,8 @@ namespace ts {
return;
}
- const typePredicate = getTypePredicateOfSignature(getSignatureFromDeclaration(parent));
+ const signature = getSignatureFromDeclaration(parent);
+ const typePredicate = getTypePredicateOfSignature(signature);
if (!typePredicate) {
return;
}
@@ -23893,14 +23913,13 @@ namespace ts {
}
else {
if (typePredicate.parameterIndex >= 0) {
- if (parent.parameters[typePredicate.parameterIndex].dotDotDotToken) {
- error(parameterName,
- Diagnostics.A_type_predicate_cannot_reference_a_rest_parameter);
+ if (signature.hasRestParameter && typePredicate.parameterIndex === signature.parameters.length - 1) {
+ error(parameterName, 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);
checkTypeAssignableTo(typePredicate.type,
- getTypeOfNode(parent.parameters[typePredicate.parameterIndex]),
+ getTypeOfSymbol(signature.parameters[typePredicate.parameterIndex]),
node.type,
/*headMessage*/ undefined,
leadingError);
@@ -27985,8 +28004,8 @@ namespace ts {
// The following checks only apply on a non-ambient instantiated module declaration.
if (symbol.flags & SymbolFlags.ValueModule
- && symbol.declarations.length > 1
&& !inAmbientContext
+ && symbol.declarations.length > 1
&& isInstantiatedModule(node, !!compilerOptions.preserveConstEnums || !!compilerOptions.isolatedModules)) {
const firstNonAmbientClassOrFunc = getFirstNonAmbientClassOrFunctionDeclaration(symbol);
if (firstNonAmbientClassOrFunc) {
diff --git a/src/compiler/program.ts b/src/compiler/program.ts
index 979423cdfaa..b188e708a62 100644
--- a/src/compiler/program.ts
+++ b/src/compiler/program.ts
@@ -74,12 +74,7 @@ namespace ts {
// TODO(shkamat): update this after reworking ts build API
export function createCompilerHostWorker(options: CompilerOptions, setParentNodes?: boolean, system = sys): CompilerHost {
const existingDirectories = createMap();
- function getCanonicalFileName(fileName: string): string {
- // if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form.
- // otherwise use toLowerCase as a canonical form.
- return system.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
- }
-
+ const getCanonicalFileName = createGetCanonicalFileName(system.useCaseSensitiveFileNames);
function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile | undefined {
let text: string | undefined;
try {
@@ -2268,7 +2263,6 @@ namespace ts {
if (refFile) {
const redirect = getProjectReferenceRedirect(fileName);
if (redirect) {
- ((refFile.redirectedReferences || (refFile.redirectedReferences = [])) as string[]).push(fileName);
fileName = redirect;
// Once we start redirecting to a file, we can potentially come back to it
// via a back-reference from another file in the .d.ts folder. If that happens we'll
diff --git a/src/compiler/transformers/es2017.ts b/src/compiler/transformers/es2017.ts
index 9508613321c..8d20f94afed 100644
--- a/src/compiler/transformers/es2017.ts
+++ b/src/compiler/transformers/es2017.ts
@@ -690,9 +690,15 @@ namespace ts {
/* parameters */ [],
/* type */ undefined,
/* equalsGreaterThanToken */ undefined,
- createPropertyAccess(
- createSuper(),
- name
+ setEmitFlags(
+ createPropertyAccess(
+ setEmitFlags(
+ createSuper(),
+ EmitFlags.NoSubstitution
+ ),
+ name
+ ),
+ EmitFlags.NoSubstitution
)
)
));
@@ -717,9 +723,16 @@ namespace ts {
/* type */ undefined,
/* equalsGreaterThanToken */ undefined,
createAssignment(
- createPropertyAccess(
- createSuper(),
- name),
+ setEmitFlags(
+ createPropertyAccess(
+ setEmitFlags(
+ createSuper(),
+ EmitFlags.NoSubstitution
+ ),
+ name
+ ),
+ EmitFlags.NoSubstitution
+ ),
createIdentifier("v")
)
)
diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts
index 4a127f3236d..63d621c6654 100644
--- a/src/compiler/transformers/ts.ts
+++ b/src/compiler/transformers/ts.ts
@@ -1338,11 +1338,14 @@ namespace ts {
let decorators: (ReadonlyArray | undefined)[] | undefined;
if (node) {
const parameters = node.parameters;
- for (let i = 0; i < parameters.length; i++) {
- const parameter = parameters[i];
+ const firstParameterIsThis = parameters.length > 0 && parameterIsThisKeyword(parameters[0]);
+ const firstParameterOffset = firstParameterIsThis ? 1 : 0;
+ const numParameters = firstParameterIsThis ? parameters.length - 1 : parameters.length;
+ for (let i = 0; i < numParameters; i++) {
+ const parameter = parameters[i + firstParameterOffset];
if (decorators || parameter.decorators) {
if (!decorators) {
- decorators = new Array(parameters.length);
+ decorators = new Array(numParameters);
}
decorators[i] = parameter.decorators;
diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts
index c649665cf72..cc79c02f1d6 100644
--- a/src/compiler/tsbuild.ts
+++ b/src/compiler/tsbuild.ts
@@ -792,6 +792,15 @@ namespace ts {
newerInputFileName: newestInputFileName
};
}
+ else {
+ // Check tsconfig time
+ const configStatus = checkConfigFileUpToDateStatus(project.options.configFilePath!, oldestOutputFileTime, oldestOutputFileName);
+ if (configStatus) return configStatus;
+
+ // Check extended config time
+ const extendedConfigStatus = forEach(project.options.configFile!.extendedSourceFiles || emptyArray, configFile => checkConfigFileUpToDateStatus(configFile, oldestOutputFileTime, oldestOutputFileName));
+ if (extendedConfigStatus) return extendedConfigStatus;
+ }
if (!buildInfoChecked.hasKey(project.options.configFilePath as ResolvedConfigFileName)) {
buildInfoChecked.setValue(project.options.configFilePath as ResolvedConfigFileName, true);
@@ -828,6 +837,18 @@ namespace ts {
};
}
+ function checkConfigFileUpToDateStatus(configFile: string, oldestOutputFileTime: Date, oldestOutputFileName: string): Status.OutOfDateWithSelf | undefined {
+ // Check tsconfig time
+ const tsconfigTime = host.getModifiedTime(configFile) || missingFileModifiedTime;
+ if (oldestOutputFileTime < tsconfigTime) {
+ return {
+ type: UpToDateStatusType.OutOfDateWithSelf,
+ outOfDateOutputFileName: oldestOutputFileName,
+ newerInputFileName: configFile
+ };
+ }
+ }
+
function invalidateProject(configFileName: string, reloadLevel?: ConfigFileProgramReloadLevel) {
invalidateResolvedProject(resolveProjectName(configFileName), reloadLevel);
}
@@ -1178,6 +1199,7 @@ namespace ts {
}
function getOldProgram(proj: ResolvedConfigFileName, parsed: ParsedCommandLine) {
+ if (options.force) return undefined;
const value = builderPrograms.getValue(proj);
if (value) return value;
return readBuilderProgram(parsed.options, readFileWithCache) as any as T;
diff --git a/src/compiler/types.ts b/src/compiler/types.ts
index fbf83e6a205..bcc3218a017 100644
--- a/src/compiler/types.ts
+++ b/src/compiler/types.ts
@@ -2740,12 +2740,6 @@ namespace ts {
/* @internal */ resolvedModules?: Map;
/* @internal */ resolvedTypeReferenceDirectiveNames: Map;
/* @internal */ imports: ReadonlyArray;
- /**
- * When a file's references are redirected due to project reference directives,
- * the original names of the references are stored in this array
- */
- /* @internal*/
- redirectedReferences?: ReadonlyArray;
// Identifier only if `declare global`
/* @internal */ moduleAugmentations: ReadonlyArray;
/* @internal */ patternAmbientModules?: PatternAmbientModule[];
@@ -3074,6 +3068,7 @@ namespace ts {
getSourceFiles(): ReadonlyArray;
getSourceFile(fileName: string): SourceFile | undefined;
getResolvedTypeReferenceDirectives(): ReadonlyMap;
+ getProjectReferenceRedirect(fileName: string): string | undefined;
readonly redirectTargetsMap: RedirectTargetsMap;
}
@@ -3171,6 +3166,7 @@ namespace ts {
getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[], argumentCount?: number): Signature | undefined;
/* @internal */ getResolvedSignatureForSignatureHelp(node: CallLikeExpression, candidatesOutArray?: Signature[], argumentCount?: number): Signature | undefined;
/* @internal */ getExpandedParameters(sig: Signature): ReadonlyArray;
+ /* @internal */ hasEffectiveRestParameter(sig: Signature): boolean;
getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature | undefined;
isImplementationOfOverload(node: SignatureDeclaration): boolean | undefined;
isUndefinedSymbol(symbol: Symbol): boolean;
@@ -3251,6 +3247,8 @@ namespace ts {
/* @internal */ getSymbolCount(): number;
/* @internal */ getTypeCount(): number;
+ /* @internal */ isArrayType(type: Type): boolean;
+ /* @internal */ isTupleType(type: Type): boolean;
/* @internal */ isArrayLikeType(type: Type): boolean;
/* @internal */ getObjectFlags(type: Type): ObjectFlags;
@@ -4312,8 +4310,10 @@ namespace ts {
root: ConditionalRoot;
checkType: Type;
extendsType: Type;
- resolvedTrueType?: Type;
- resolvedFalseType?: Type;
+ trueType: Type;
+ falseType: Type;
+ /* @internal */
+ resolvedInferredTrueType?: Type; // The `trueType` instantiated with the `combinedMapper`, if present
/* @internal */
resolvedDefaultConstraint?: Type;
/* @internal */
diff --git a/src/compiler/watch.ts b/src/compiler/watch.ts
index 8a94393e2ce..9b08c54222f 100644
--- a/src/compiler/watch.ts
+++ b/src/compiler/watch.ts
@@ -275,7 +275,7 @@ namespace ts {
}
}
- export function setGetSourceFileAsHashVersioned(compilerHost: CompilerHost, host: ProgramHost) {
+ export function setGetSourceFileAsHashVersioned(compilerHost: CompilerHost, host: { createHash?(data: string): string; }) {
const originalGetSourceFile = compilerHost.getSourceFile;
const computeHash = host.createHash || generateDjb2Hash;
compilerHost.getSourceFile = (...args) => {
@@ -383,6 +383,56 @@ namespace ts {
if (!buildInfo.program) return undefined;
return createBuildProgramUsingProgramBuildInfo(buildInfo.program);
}
+
+ export function createIncrementalCompilerHost(options: CompilerOptions, system = sys): CompilerHost {
+ const host = createCompilerHostWorker(options, /*setParentNodes*/ undefined, system);
+ host.createHash = maybeBind(system, system.createHash);
+ setGetSourceFileAsHashVersioned(host, system);
+ changeCompilerHostLikeToUseCache(host, fileName => toPath(fileName, host.getCurrentDirectory(), host.getCanonicalFileName));
+ return host;
+ }
+
+ interface IncrementalProgramOptions {
+ rootNames: ReadonlyArray;
+ options: CompilerOptions;
+ configFileParsingDiagnostics?: ReadonlyArray;
+ projectReferences?: ReadonlyArray;
+ host?: CompilerHost;
+ createProgram?: CreateProgram;
+ }
+ function createIncrementalProgram({
+ rootNames, options, configFileParsingDiagnostics, projectReferences, host, createProgram
+ }: IncrementalProgramOptions): T {
+ host = host || createIncrementalCompilerHost(options);
+ createProgram = createProgram || createEmitAndSemanticDiagnosticsBuilderProgram as any as CreateProgram;
+ const oldProgram = readBuilderProgram(options, path => host!.readFile(path)) as any as T;
+ return createProgram(rootNames, options, host, oldProgram, configFileParsingDiagnostics, projectReferences);
+ }
+
+ export interface IncrementalCompilationOptions {
+ rootNames: ReadonlyArray;
+ options: CompilerOptions;
+ configFileParsingDiagnostics?: ReadonlyArray;
+ projectReferences?: ReadonlyArray;
+ host?: CompilerHost;
+ reportDiagnostic?: DiagnosticReporter;
+ reportErrorSummary?: ReportEmitErrorSummary;
+ afterProgramEmitAndDiagnostics?(program: EmitAndSemanticDiagnosticsBuilderProgram): void;
+ system?: System;
+ }
+ export function performIncrementalCompilation(input: IncrementalCompilationOptions) {
+ const system = input.system || sys;
+ const host = input.host || (input.host = createIncrementalCompilerHost(input.options, system));
+ const builderProgram = createIncrementalProgram(input);
+ const exitStatus = emitFilesAndReportErrors(
+ builderProgram,
+ input.reportDiagnostic || createDiagnosticReporter(system),
+ s => host.trace && host.trace(s),
+ input.reportErrorSummary || input.options.pretty ? errorCount => system.write(getErrorSummaryText(errorCount, system.newLine)) : undefined
+ );
+ if (input.afterProgramEmitAndDiagnostics) input.afterProgramEmitAndDiagnostics(builderProgram);
+ return exitStatus;
+ }
}
namespace ts {
diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts
index 16f1a37ae83..089a2630dd8 100644
--- a/src/harness/fourslash.ts
+++ b/src/harness/fourslash.ts
@@ -4425,7 +4425,7 @@ namespace FourSlashInterface {
}
export namespace Completion {
const functionEntry = (name: string): ExpectedCompletionEntryObject => ({ name, kind: "function", kindModifiers: "declare" });
- const constEntry = (name: string): ExpectedCompletionEntryObject => ({ name, kind: "const", kindModifiers: "declare" });
+ const varEntry = (name: string): ExpectedCompletionEntryObject => ({ name, kind: "var", kindModifiers: "declare" });
const moduleEntry = (name: string): ExpectedCompletionEntryObject => ({ name, kind: "module", kindModifiers: "declare" });
const keywordEntry = (name: string): ExpectedCompletionEntryObject => ({ name, kind: "keyword" });
const methodEntry = (name: string): ExpectedCompletionEntryObject => ({ name, kind: "method", kindModifiers: "declare" });
@@ -4448,48 +4448,48 @@ namespace FourSlashInterface {
typeEntry("PropertyKey"),
interfaceEntry("PropertyDescriptor"),
interfaceEntry("PropertyDescriptorMap"),
- constEntry("Object"),
+ varEntry("Object"),
interfaceEntry("ObjectConstructor"),
- constEntry("Function"),
+ varEntry("Function"),
interfaceEntry("FunctionConstructor"),
typeEntry("ThisParameterType"),
typeEntry("OmitThisParameter"),
interfaceEntry("CallableFunction"),
interfaceEntry("NewableFunction"),
interfaceEntry("IArguments"),
- constEntry("String"),
+ varEntry("String"),
interfaceEntry("StringConstructor"),
- constEntry("Boolean"),
+ varEntry("Boolean"),
interfaceEntry("BooleanConstructor"),
- constEntry("Number"),
+ varEntry("Number"),
interfaceEntry("NumberConstructor"),
interfaceEntry("TemplateStringsArray"),
interfaceEntry("ImportMeta"),
- constEntry("Math"),
- constEntry("Date"),
+ varEntry("Math"),
+ varEntry("Date"),
interfaceEntry("DateConstructor"),
interfaceEntry("RegExpMatchArray"),
interfaceEntry("RegExpExecArray"),
- constEntry("RegExp"),
+ varEntry("RegExp"),
interfaceEntry("RegExpConstructor"),
- constEntry("Error"),
+ varEntry("Error"),
interfaceEntry("ErrorConstructor"),
- constEntry("EvalError"),
+ varEntry("EvalError"),
interfaceEntry("EvalErrorConstructor"),
- constEntry("RangeError"),
+ varEntry("RangeError"),
interfaceEntry("RangeErrorConstructor"),
- constEntry("ReferenceError"),
+ varEntry("ReferenceError"),
interfaceEntry("ReferenceErrorConstructor"),
- constEntry("SyntaxError"),
+ varEntry("SyntaxError"),
interfaceEntry("SyntaxErrorConstructor"),
- constEntry("TypeError"),
+ varEntry("TypeError"),
interfaceEntry("TypeErrorConstructor"),
- constEntry("URIError"),
+ varEntry("URIError"),
interfaceEntry("URIErrorConstructor"),
- constEntry("JSON"),
+ varEntry("JSON"),
interfaceEntry("ReadonlyArray"),
interfaceEntry("ConcatArray"),
- constEntry("Array"),
+ varEntry("Array"),
interfaceEntry("ArrayConstructor"),
interfaceEntry("TypedPropertyDescriptor"),
typeEntry("ClassDecorator"),
@@ -4513,30 +4513,30 @@ namespace FourSlashInterface {
typeEntry("ReturnType"),
typeEntry("InstanceType"),
interfaceEntry("ThisType"),
- constEntry("ArrayBuffer"),
+ varEntry("ArrayBuffer"),
interfaceEntry("ArrayBufferTypes"),
typeEntry("ArrayBufferLike"),
interfaceEntry("ArrayBufferConstructor"),
interfaceEntry("ArrayBufferView"),
- constEntry("DataView"),
+ varEntry("DataView"),
interfaceEntry("DataViewConstructor"),
- constEntry("Int8Array"),
+ varEntry("Int8Array"),
interfaceEntry("Int8ArrayConstructor"),
- constEntry("Uint8Array"),
+ varEntry("Uint8Array"),
interfaceEntry("Uint8ArrayConstructor"),
- constEntry("Uint8ClampedArray"),
+ varEntry("Uint8ClampedArray"),
interfaceEntry("Uint8ClampedArrayConstructor"),
- constEntry("Int16Array"),
+ varEntry("Int16Array"),
interfaceEntry("Int16ArrayConstructor"),
- constEntry("Uint16Array"),
+ varEntry("Uint16Array"),
interfaceEntry("Uint16ArrayConstructor"),
- constEntry("Int32Array"),
+ varEntry("Int32Array"),
interfaceEntry("Int32ArrayConstructor"),
- constEntry("Uint32Array"),
+ varEntry("Uint32Array"),
interfaceEntry("Uint32ArrayConstructor"),
- constEntry("Float32Array"),
+ varEntry("Float32Array"),
interfaceEntry("Float32ArrayConstructor"),
- constEntry("Float64Array"),
+ varEntry("Float64Array"),
interfaceEntry("Float64ArrayConstructor"),
moduleEntry("Intl"),
];
@@ -4552,9 +4552,47 @@ namespace FourSlashInterface {
];
}
+ function getInJsKeywords(keywords: ReadonlyArray): ReadonlyArray {
+ return keywords.filter(keyword => {
+ switch (keyword.name) {
+ case "enum":
+ case "interface":
+ case "implements":
+ case "private":
+ case "protected":
+ case "public":
+ case "abstract":
+ case "any":
+ case "boolean":
+ case "declare":
+ case "infer":
+ case "is":
+ case "keyof":
+ case "module":
+ case "namespace":
+ case "never":
+ case "readonly":
+ case "number":
+ case "object":
+ case "string":
+ case "symbol":
+ case "type":
+ case "unique":
+ case "unknown":
+ case "global":
+ case "bigint":
+ return false;
+ default:
+ return true;
+ }
+ });
+ }
+
export const classElementKeywords: ReadonlyArray =
["private", "protected", "public", "static", "abstract", "async", "constructor", "get", "readonly", "set"].map(keywordEntry);
+ export const classElementInJsKeywords = getInJsKeywords(classElementKeywords);
+
export const constructorParameterKeywords: ReadonlyArray =
["private", "protected", "public", "readonly"].map((name): ExpectedCompletionEntryObject => ({ name, kind: "keyword" }));
@@ -4692,6 +4730,8 @@ namespace FourSlashInterface {
}
});
+ export const statementInJsKeywords = getInJsKeywords(statementKeywords);
+
export const globalsVars: ReadonlyArray = [
functionEntry("eval"),
functionEntry("parseInt"),
@@ -4704,36 +4744,36 @@ namespace FourSlashInterface {
functionEntry("encodeURIComponent"),
functionEntry("escape"),
functionEntry("unescape"),
- constEntry("NaN"),
- constEntry("Infinity"),
- constEntry("Object"),
- constEntry("Function"),
- constEntry("String"),
- constEntry("Boolean"),
- constEntry("Number"),
- constEntry("Math"),
- constEntry("Date"),
- constEntry("RegExp"),
- constEntry("Error"),
- constEntry("EvalError"),
- constEntry("RangeError"),
- constEntry("ReferenceError"),
- constEntry("SyntaxError"),
- constEntry("TypeError"),
- constEntry("URIError"),
- constEntry("JSON"),
- constEntry("Array"),
- constEntry("ArrayBuffer"),
- constEntry("DataView"),
- constEntry("Int8Array"),
- constEntry("Uint8Array"),
- constEntry("Uint8ClampedArray"),
- constEntry("Int16Array"),
- constEntry("Uint16Array"),
- constEntry("Int32Array"),
- constEntry("Uint32Array"),
- constEntry("Float32Array"),
- constEntry("Float64Array"),
+ varEntry("NaN"),
+ varEntry("Infinity"),
+ varEntry("Object"),
+ varEntry("Function"),
+ varEntry("String"),
+ varEntry("Boolean"),
+ varEntry("Number"),
+ varEntry("Math"),
+ varEntry("Date"),
+ varEntry("RegExp"),
+ varEntry("Error"),
+ varEntry("EvalError"),
+ varEntry("RangeError"),
+ varEntry("ReferenceError"),
+ varEntry("SyntaxError"),
+ varEntry("TypeError"),
+ varEntry("URIError"),
+ varEntry("JSON"),
+ varEntry("Array"),
+ varEntry("ArrayBuffer"),
+ varEntry("DataView"),
+ varEntry("Int8Array"),
+ varEntry("Uint8Array"),
+ varEntry("Uint8ClampedArray"),
+ varEntry("Int16Array"),
+ varEntry("Uint16Array"),
+ varEntry("Int32Array"),
+ varEntry("Uint32Array"),
+ varEntry("Float32Array"),
+ varEntry("Float64Array"),
moduleEntry("Intl"),
];
@@ -4793,6 +4833,18 @@ namespace FourSlashInterface {
...globalKeywordsInsideFunction,
];
+ const globalInJsKeywordsInsideFunction = getInJsKeywords(globalKeywordsInsideFunction);
+
+ // TODO: many of these are inappropriate to always provide
+ export const globalsInJsInsideFunction = (plus: ReadonlyArray): ReadonlyArray => [
+ { name: "arguments", kind: "local var" },
+ { name: "globalThis", kind: "module" },
+ ...globalsVars,
+ ...plus,
+ { name: "undefined", kind: "var" },
+ ...globalInJsKeywordsInsideFunction,
+ ];
+
// TODO: many of these are inappropriate to always provide
export const globalKeywords: ReadonlyArray = [
"break",
@@ -4871,6 +4923,8 @@ namespace FourSlashInterface {
"of",
].map(keywordEntry);
+ export const globalInJsKeywords = getInJsKeywords(globalKeywords);
+
export const insideMethodKeywords: ReadonlyArray = [
"break",
"case",
@@ -4917,6 +4971,8 @@ namespace FourSlashInterface {
"await",
].map(keywordEntry);
+ export const insideMethodInJsKeywords = getInJsKeywords(insideMethodKeywords);
+
export const globalKeywordsPlusUndefined: ReadonlyArray = (() => {
const i = ts.findIndex(globalKeywords, x => x.name === "unique");
return [...globalKeywords.slice(0, i), keywordEntry("undefined"), ...globalKeywords.slice(i)];
@@ -4929,6 +4985,13 @@ namespace FourSlashInterface {
...globalKeywords
];
+ export const globalsInJs: ReadonlyArray = [
+ { name: "globalThis", kind: "module" },
+ ...globalsVars,
+ { name: "undefined", kind: "var" },
+ ...globalInJsKeywords
+ ];
+
export function globalsPlus(plus: ReadonlyArray): ReadonlyArray {
return [
{ name: "globalThis", kind: "module" },
@@ -4937,6 +5000,15 @@ namespace FourSlashInterface {
{ name: "undefined", kind: "var" },
...globalKeywords];
}
+
+ export function globalsInJsPlus(plus: ReadonlyArray): ReadonlyArray {
+ return [
+ { name: "globalThis", kind: "module" },
+ ...globalsVars,
+ ...plus,
+ { name: "undefined", kind: "var" },
+ ...globalInJsKeywords];
+ }
}
export interface ReferenceGroup {
diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts
index 4112f5a2ae7..458dc8b9252 100644
--- a/src/lib/es5.d.ts
+++ b/src/lib/es5.d.ts
@@ -2,8 +2,8 @@
/// ECMAScript APIs
/////////////////////////////
-declare const NaN: number;
-declare const Infinity: number;
+declare var NaN: number;
+declare var Infinity: number;
/**
* Evaluates JavaScript code and executes it.
@@ -244,7 +244,7 @@ interface ObjectConstructor {
/**
* Provides functionality common to all JavaScript objects.
*/
-declare const Object: ObjectConstructor;
+declare var Object: ObjectConstructor;
/**
* Creates a new function.
@@ -293,7 +293,7 @@ interface FunctionConstructor {
readonly prototype: Function;
}
-declare const Function: FunctionConstructor;
+declare var Function: FunctionConstructor;
/**
* Extracts the type of the 'this' parameter of a function type, or 'unknown' if the function type has no 'this' parameter.
@@ -504,7 +504,7 @@ interface StringConstructor {
/**
* Allows manipulation and formatting of text strings and determination and location of substrings within strings.
*/
-declare const String: StringConstructor;
+declare var String: StringConstructor;
interface Boolean {
/** Returns the primitive value of the specified object. */
@@ -517,7 +517,7 @@ interface BooleanConstructor {
readonly prototype: Boolean;
}
-declare const Boolean: BooleanConstructor;
+declare var Boolean: BooleanConstructor;
interface Number {
/**
@@ -579,7 +579,7 @@ interface NumberConstructor {
}
/** An object that represents a number of any kind. All JavaScript numbers are 64-bit floating-point numbers. */
-declare const Number: NumberConstructor;
+declare var Number: NumberConstructor;
interface TemplateStringsArray extends ReadonlyArray {
readonly raw: ReadonlyArray;
@@ -703,7 +703,7 @@ interface Math {
tan(x: number): number;
}
/** An intrinsic object that provides basic mathematics functionality and constants. */
-declare const Math: Math;
+declare var Math: Math;
/** Enables basic storage and retrieval of dates and times. */
interface Date {
@@ -884,7 +884,7 @@ interface DateConstructor {
now(): number;
}
-declare const Date: DateConstructor;
+declare var Date: DateConstructor;
interface RegExpMatchArray extends Array {
index?: number;
@@ -947,7 +947,7 @@ interface RegExpConstructor {
lastMatch: string;
}
-declare const RegExp: RegExpConstructor;
+declare var RegExp: RegExpConstructor;
interface Error {
name: string;
@@ -961,7 +961,7 @@ interface ErrorConstructor {
readonly prototype: Error;
}
-declare const Error: ErrorConstructor;
+declare var Error: ErrorConstructor;
interface EvalError extends Error {
}
@@ -972,7 +972,7 @@ interface EvalErrorConstructor {
readonly prototype: EvalError;
}
-declare const EvalError: EvalErrorConstructor;
+declare var EvalError: EvalErrorConstructor;
interface RangeError extends Error {
}
@@ -983,7 +983,7 @@ interface RangeErrorConstructor {
readonly prototype: RangeError;
}
-declare const RangeError: RangeErrorConstructor;
+declare var RangeError: RangeErrorConstructor;
interface ReferenceError extends Error {
}
@@ -994,7 +994,7 @@ interface ReferenceErrorConstructor {
readonly prototype: ReferenceError;
}
-declare const ReferenceError: ReferenceErrorConstructor;
+declare var ReferenceError: ReferenceErrorConstructor;
interface SyntaxError extends Error {
}
@@ -1005,7 +1005,7 @@ interface SyntaxErrorConstructor {
readonly prototype: SyntaxError;
}
-declare const SyntaxError: SyntaxErrorConstructor;
+declare var SyntaxError: SyntaxErrorConstructor;
interface TypeError extends Error {
}
@@ -1016,7 +1016,7 @@ interface TypeErrorConstructor {
readonly prototype: TypeError;
}
-declare const TypeError: TypeErrorConstructor;
+declare var TypeError: TypeErrorConstructor;
interface URIError extends Error {
}
@@ -1027,7 +1027,7 @@ interface URIErrorConstructor {
readonly prototype: URIError;
}
-declare const URIError: URIErrorConstructor;
+declare var URIError: URIErrorConstructor;
interface JSON {
/**
@@ -1056,7 +1056,7 @@ interface JSON {
/**
* An intrinsic object that provides functions to convert JavaScript values to and from the JavaScript Object Notation (JSON) format.
*/
-declare const JSON: JSON;
+declare var JSON: JSON;
/////////////////////////////
@@ -1345,7 +1345,7 @@ interface ArrayConstructor {
readonly prototype: Array;
}
-declare const Array: ArrayConstructor;
+declare var Array: ArrayConstructor;
interface TypedPropertyDescriptor {
enumerable?: boolean;
@@ -1504,7 +1504,7 @@ interface ArrayBufferConstructor {
new(byteLength: number): ArrayBuffer;
isView(arg: any): arg is ArrayBufferView;
}
-declare const ArrayBuffer: ArrayBufferConstructor;
+declare var ArrayBuffer: ArrayBufferConstructor;
interface ArrayBufferView {
/**
@@ -1654,7 +1654,7 @@ interface DataView {
interface DataViewConstructor {
new(buffer: ArrayBufferLike, byteOffset?: number, byteLength?: number): DataView;
}
-declare const DataView: DataViewConstructor;
+declare var DataView: DataViewConstructor;
/**
* A typed array of 8-bit integer values. The contents are initialized to 0. If the requested
@@ -1929,7 +1929,7 @@ interface Int8ArrayConstructor {
}
-declare const Int8Array: Int8ArrayConstructor;
+declare var Int8Array: Int8ArrayConstructor;
/**
* A typed array of 8-bit unsigned integer values. The contents are initialized to 0. If the
@@ -2204,7 +2204,7 @@ interface Uint8ArrayConstructor {
from(arrayLike: ArrayLike, mapfn: (v: T, k: number) => number, thisArg?: any): Uint8Array;
}
-declare const Uint8Array: Uint8ArrayConstructor;
+declare var Uint8Array: Uint8ArrayConstructor;
/**
* A typed array of 8-bit unsigned integer (clamped) values. The contents are initialized to 0.
@@ -2478,7 +2478,7 @@ interface Uint8ClampedArrayConstructor {
*/
from(arrayLike: ArrayLike, mapfn: (v: T, k: number) => number, thisArg?: any): Uint8ClampedArray;
}
-declare const Uint8ClampedArray: Uint8ClampedArrayConstructor;
+declare var Uint8ClampedArray: Uint8ClampedArrayConstructor;
/**
* A typed array of 16-bit signed integer values. The contents are initialized to 0. If the
@@ -2753,7 +2753,7 @@ interface Int16ArrayConstructor {
}
-declare const Int16Array: Int16ArrayConstructor;
+declare var Int16Array: Int16ArrayConstructor;
/**
* A typed array of 16-bit unsigned integer values. The contents are initialized to 0. If the
@@ -3029,7 +3029,7 @@ interface Uint16ArrayConstructor {
}
-declare const Uint16Array: Uint16ArrayConstructor;
+declare var Uint16Array: Uint16ArrayConstructor;
/**
* A typed array of 32-bit signed integer values. The contents are initialized to 0. If the
* requested number of bytes could not be allocated an exception is raised.
@@ -3303,7 +3303,7 @@ interface Int32ArrayConstructor {
from(arrayLike: ArrayLike, mapfn: (v: T, k: number) => number, thisArg?: any): Int32Array;
}
-declare const Int32Array: Int32ArrayConstructor;
+declare var Int32Array: Int32ArrayConstructor;
/**
* A typed array of 32-bit unsigned integer values. The contents are initialized to 0. If the
@@ -3577,7 +3577,7 @@ interface Uint32ArrayConstructor {
from(arrayLike: ArrayLike, mapfn: (v: T, k: number) => number, thisArg?: any): Uint32Array;
}
-declare const Uint32Array: Uint32ArrayConstructor;
+declare var Uint32Array: Uint32ArrayConstructor;
/**
* A typed array of 32-bit float values. The contents are initialized to 0. If the requested number
@@ -3853,7 +3853,7 @@ interface Float32ArrayConstructor {
}
-declare const Float32Array: Float32ArrayConstructor;
+declare var Float32Array: Float32ArrayConstructor;
/**
* A typed array of 64-bit float values. The contents are initialized to 0. If the requested
@@ -4128,7 +4128,7 @@ interface Float64ArrayConstructor {
from(arrayLike: ArrayLike, mapfn: (v: T, k: number) => number, thisArg?: any): Float64Array;
}
-declare const Float64Array: Float64ArrayConstructor;
+declare var Float64Array: Float64ArrayConstructor;
/////////////////////////////
/// ECMAScript Internationalization API
diff --git a/src/lib/esnext.bigint.d.ts b/src/lib/esnext.bigint.d.ts
index 667422bf890..5718e4a5751 100644
--- a/src/lib/esnext.bigint.d.ts
+++ b/src/lib/esnext.bigint.d.ts
@@ -34,7 +34,7 @@ interface BigIntConstructor {
asUintN(bits: number, int: bigint): bigint;
}
-declare const BigInt: BigIntConstructor;
+declare var BigInt: BigIntConstructor;
/**
* A typed array of 64-bit signed integer values. The contents are initialized to 0. If the
@@ -303,7 +303,7 @@ interface BigInt64ArrayConstructor {
from(arrayLike: ArrayLike, mapfn: (v: U, k: number) => bigint, thisArg?: any): BigInt64Array;
}
-declare const BigInt64Array: BigInt64ArrayConstructor;
+declare var BigInt64Array: BigInt64ArrayConstructor;
/**
* A typed array of 64-bit unsigned integer values. The contents are initialized to 0. If the
@@ -572,7 +572,7 @@ interface BigUint64ArrayConstructor {
from(arrayLike: ArrayLike, mapfn: (v: U, k: number) => bigint, thisArg?: any): BigUint64Array;
}
-declare const BigUint64Array: BigUint64ArrayConstructor;
+declare var BigUint64Array: BigUint64ArrayConstructor;
interface DataView {
/**
@@ -606,4 +606,4 @@ interface DataView {
* otherwise a little-endian value should be written.
*/
setBigUint64(byteOffset: number, value: bigint, littleEndian?: boolean): void;
-}
\ No newline at end of file
+}
diff --git a/src/server/session.ts b/src/server/session.ts
index 7cc3f595f82..6cf0619efd1 100644
--- a/src/server/session.ts
+++ b/src/server/session.ts
@@ -659,16 +659,32 @@ namespace ts.server {
}
}
- if (fileRequest && this.logger.hasLevel(LogLevel.verbose)) {
- try {
- const { file, project } = this.getFileAndProject(fileRequest);
- const scriptInfo = project.getScriptInfoForNormalizedPath(file);
- if (scriptInfo) {
- const text = getSnapshotText(scriptInfo.getSnapshot());
- msg += `\n\nFile text of ${fileRequest.file}:${indent(text)}\n`;
+ if (this.logger.hasLevel(LogLevel.verbose)) {
+ if (fileRequest) {
+ try {
+ const { file, project } = this.getFileAndProject(fileRequest);
+ const scriptInfo = project.getScriptInfoForNormalizedPath(file);
+ if (scriptInfo) {
+ const text = getSnapshotText(scriptInfo.getSnapshot());
+ msg += `\n\nFile text of ${fileRequest.file}:${indent(text)}\n`;
+ }
}
+ catch { } // tslint:disable-line no-empty
+ }
+
+ if (err.message && err.message.indexOf(`Could not find sourceFile:`) !== -1) {
+ msg += `\n\nProjects::\n`;
+ let counter = 0;
+ const addProjectInfo = (project: Project) => {
+ msg += `\nProject '${project.projectName}' (${ProjectKind[project.projectKind]}) ${counter}\n`;
+ msg += project.filesToString(/*writeProjectFileNames*/ true);
+ msg += "\n-----------------------------------------------\n";
+ counter++;
+ };
+ this.projectService.externalProjects.forEach(addProjectInfo);
+ this.projectService.configuredProjects.forEach(addProjectInfo);
+ this.projectService.inferredProjects.forEach(addProjectInfo);
}
- catch {} // tslint:disable-line no-empty
}
this.logger.msg(msg, Msg.Err);
diff --git a/src/services/completions.ts b/src/services/completions.ts
index 5cdaca020cd..01324c9dc84 100644
--- a/src/services/completions.ts
+++ b/src/services/completions.ts
@@ -30,6 +30,7 @@ namespace ts.Completions {
ConstructorParameterKeywords, // Keywords at constructor parameter
FunctionLikeBodyKeywords, // Keywords at function like body
TypeKeywords,
+ Last = TypeKeywords
}
const enum GlobalsSearch { Continue, Success, Fail }
@@ -77,7 +78,7 @@ namespace ts.Completions {
}
function completionInfoFromData(sourceFile: SourceFile, typeChecker: TypeChecker, compilerOptions: CompilerOptions, log: Log, completionData: CompletionData, preferences: UserPreferences): CompletionInfo | undefined {
- const { symbols, completionKind, isInSnippetScope, isNewIdentifierLocation, location, propertyAccessToConvert, keywordFilters, literals, symbolToOriginInfoMap, recommendedCompletion, isJsxInitializer } = completionData;
+ const { symbols, completionKind, isInSnippetScope, isNewIdentifierLocation, location, propertyAccessToConvert, keywordFilters, literals, symbolToOriginInfoMap, recommendedCompletion, isJsxInitializer, insideJsDocTagTypeExpression } = completionData;
if (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,
@@ -113,7 +114,7 @@ namespace ts.Completions {
if (keywordFilters !== KeywordCompletionFilters.None) {
const entryNames = arrayToSet(entries, e => e.name);
- for (const keywordEntry of getKeywordCompletions(keywordFilters)) {
+ for (const keywordEntry of getKeywordCompletions(keywordFilters, !insideJsDocTagTypeExpression && isSourceFileJS(sourceFile))) {
if (!entryNames.has(keywordEntry.name)) {
entries.push(keywordEntry);
}
@@ -510,6 +511,7 @@ namespace ts.Completions {
readonly recommendedCompletion: Symbol | undefined;
readonly previousToken: Node | undefined;
readonly isJsxInitializer: IsJsxInitializer;
+ readonly insideJsDocTagTypeExpression: boolean;
}
type Request = { readonly kind: CompletionDataKind.JsDocTagName | CompletionDataKind.JsDocTag } | { readonly kind: CompletionDataKind.JsDocParameterName, tag: JSDocParameterTag };
@@ -837,7 +839,22 @@ namespace ts.Completions {
const literals = mapDefined(contextualType && (contextualType.isUnion() ? contextualType.types : [contextualType]), t => t.isLiteral() ? t.value : undefined);
const recommendedCompletion = previousToken && contextualType && getRecommendedCompletion(previousToken, contextualType, typeChecker);
- return { kind: CompletionDataKind.Data, symbols, completionKind, isInSnippetScope, propertyAccessToConvert, isNewIdentifierLocation, location, keywordFilters, literals, symbolToOriginInfoMap, recommendedCompletion, previousToken, isJsxInitializer };
+ return {
+ kind: CompletionDataKind.Data,
+ symbols,
+ completionKind,
+ isInSnippetScope,
+ propertyAccessToConvert,
+ isNewIdentifierLocation,
+ location,
+ keywordFilters,
+ literals,
+ symbolToOriginInfoMap,
+ recommendedCompletion,
+ previousToken,
+ isJsxInitializer,
+ insideJsDocTagTypeExpression
+ };
type JSDocTagWithTypeExpression = JSDocParameterTag | JSDocPropertyTag | JSDocReturnTag | JSDocTypeTag | JSDocTypedefTag;
@@ -890,7 +907,9 @@ namespace ts.Completions {
}
// If the module is merged with a value, we must get the type of the class and add its propertes (for inherited static methods).
- if (!isTypeLocation && symbol.declarations.some(d => d.kind !== SyntaxKind.SourceFile && d.kind !== SyntaxKind.ModuleDeclaration && d.kind !== SyntaxKind.EnumDeclaration)) {
+ if (!isTypeLocation &&
+ symbol.declarations &&
+ symbol.declarations.some(d => d.kind !== SyntaxKind.SourceFile && d.kind !== SyntaxKind.ModuleDeclaration && d.kind !== SyntaxKind.EnumDeclaration)) {
addTypeProperties(typeChecker.getTypeOfSymbolAtLocation(symbol, node));
}
@@ -1927,7 +1946,18 @@ namespace ts.Completions {
}
return res;
});
- function getKeywordCompletions(keywordFilter: KeywordCompletionFilters): ReadonlyArray {
+
+ function getKeywordCompletions(keywordFilter: KeywordCompletionFilters, filterOutTsOnlyKeywords: boolean): ReadonlyArray {
+ if (!filterOutTsOnlyKeywords) return getTypescriptKeywordCompletions(keywordFilter);
+
+ const index = keywordFilter + KeywordCompletionFilters.Last + 1;
+ return _keywordCompletions[index] ||
+ (_keywordCompletions[index] = getTypescriptKeywordCompletions(keywordFilter)
+ .filter(entry => !isTypeScriptOnlyKeyword(stringToToken(entry.name)!))
+ );
+ }
+
+ function getTypescriptKeywordCompletions(keywordFilter: KeywordCompletionFilters): ReadonlyArray {
return _keywordCompletions[keywordFilter] || (_keywordCompletions[keywordFilter] = allKeywordsCompletions().filter(entry => {
const kind = stringToToken(entry.name)!;
switch (keywordFilter) {
@@ -1952,6 +1982,40 @@ namespace ts.Completions {
}));
}
+ function isTypeScriptOnlyKeyword(kind: SyntaxKind) {
+ switch (kind) {
+ case SyntaxKind.AbstractKeyword:
+ case SyntaxKind.AnyKeyword:
+ case SyntaxKind.BigIntKeyword:
+ case SyntaxKind.BooleanKeyword:
+ case SyntaxKind.DeclareKeyword:
+ case SyntaxKind.EnumKeyword:
+ case SyntaxKind.GlobalKeyword:
+ case SyntaxKind.ImplementsKeyword:
+ case SyntaxKind.InferKeyword:
+ case SyntaxKind.InterfaceKeyword:
+ case SyntaxKind.IsKeyword:
+ case SyntaxKind.KeyOfKeyword:
+ case SyntaxKind.ModuleKeyword:
+ case SyntaxKind.NamespaceKeyword:
+ case SyntaxKind.NeverKeyword:
+ case SyntaxKind.NumberKeyword:
+ case SyntaxKind.ObjectKeyword:
+ case SyntaxKind.PrivateKeyword:
+ case SyntaxKind.ProtectedKeyword:
+ case SyntaxKind.PublicKeyword:
+ case SyntaxKind.ReadonlyKeyword:
+ case SyntaxKind.StringKeyword:
+ case SyntaxKind.SymbolKeyword:
+ case SyntaxKind.TypeKeyword:
+ case SyntaxKind.UniqueKeyword:
+ case SyntaxKind.UnknownKeyword:
+ return true;
+ default:
+ return false;
+ }
+ }
+
function isInterfaceOrTypeLiteralCompletionKeyword(kind: SyntaxKind): boolean {
return kind === SyntaxKind.ReadonlyKeyword;
}
diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts
index ef6a344c992..147fee53393 100644
--- a/src/services/findAllReferences.ts
+++ b/src/services/findAllReferences.ts
@@ -586,25 +586,28 @@ namespace ts.FindAllReferences.Core {
}
else {
const search = state.createSearch(node, symbol, /*comingFrom*/ undefined, { allSearchSymbols: node ? populateSearchSymbolSet(symbol, node, checker, !!options.isForRename, !!options.providePrefixAndSuffixTextForRename, !!options.implementations) : [symbol] });
-
- // Try to get the smallest valid scope that we can limit our search to;
- // otherwise we'll need to search globally (i.e. include each file).
- const scope = getSymbolScope(symbol);
- if (scope) {
- getReferencesInContainer(scope, scope.getSourceFile(), search, state, /*addReferencesHere*/ !(isSourceFile(scope) && !contains(sourceFiles, scope)));
- }
- else {
- // Global search
- for (const sourceFile of state.sourceFiles) {
- state.cancellationToken.throwIfCancellationRequested();
- searchForName(sourceFile, search, state);
- }
- }
+ getReferencesInContainerOrFiles(symbol, state, search);
}
return result;
}
+ function getReferencesInContainerOrFiles(symbol: Symbol, state: State, search: Search): void {
+ // Try to get the smallest valid scope that we can limit our search to;
+ // otherwise we'll need to search globally (i.e. include each file).
+ const scope = getSymbolScope(symbol);
+ if (scope) {
+ getReferencesInContainer(scope, scope.getSourceFile(), search, state, /*addReferencesHere*/ !(isSourceFile(scope) && !contains(state.sourceFiles, scope)));
+ }
+ else {
+ // Global search
+ for (const sourceFile of state.sourceFiles) {
+ state.cancellationToken.throwIfCancellationRequested();
+ searchForName(sourceFile, search, state);
+ }
+ }
+ }
+
function getSpecialSearchKind(node: Node): SpecialSearchKind {
switch (node.kind) {
case SyntaxKind.ConstructorKeyword:
@@ -707,7 +710,6 @@ namespace ts.FindAllReferences.Core {
constructor(
readonly sourceFiles: ReadonlyArray,
readonly sourceFilesSet: ReadonlyMap,
- /** True if we're searching for constructor references. */
readonly specialSearchKind: SpecialSearchKind,
readonly checker: TypeChecker,
readonly cancellationToken: CancellationToken,
@@ -1293,6 +1295,7 @@ namespace ts.FindAllReferences.Core {
const classExtending = tryGetClassByExtendingIdentifier(referenceLocation);
if (classExtending) {
findSuperConstructorAccesses(classExtending, pusher());
+ findInheritedConstructorReferences(classExtending, state);
}
}
}
@@ -1325,35 +1328,44 @@ namespace ts.FindAllReferences.Core {
* Reference the constructor and all calls to `new this()`.
*/
function findOwnConstructorReferences(classSymbol: Symbol, sourceFile: SourceFile, addNode: (node: Node) => void): void {
- for (const decl of classSymbol.members!.get(InternalSymbolName.Constructor)!.declarations) {
- const ctrKeyword = findChildOfKind(decl, SyntaxKind.ConstructorKeyword, sourceFile)!;
- Debug.assert(decl.kind === SyntaxKind.Constructor && !!ctrKeyword);
- addNode(ctrKeyword);
+ const constructorSymbol = getClassConstructorSymbol(classSymbol);
+ if (constructorSymbol) {
+ for (const decl of constructorSymbol.declarations) {
+ const ctrKeyword = findChildOfKind(decl, SyntaxKind.ConstructorKeyword, sourceFile)!;
+ Debug.assert(decl.kind === SyntaxKind.Constructor && !!ctrKeyword);
+ addNode(ctrKeyword);
+ }
}
- classSymbol.exports!.forEach(member => {
- const decl = member.valueDeclaration;
- if (decl && decl.kind === SyntaxKind.MethodDeclaration) {
- const body = (decl).body;
- if (body) {
- forEachDescendantOfKind(body, SyntaxKind.ThisKeyword, thisKeyword => {
- if (isNewExpressionTarget(thisKeyword)) {
- addNode(thisKeyword);
- }
- });
+ if (classSymbol.exports) {
+ classSymbol.exports.forEach(member => {
+ const decl = member.valueDeclaration;
+ if (decl && decl.kind === SyntaxKind.MethodDeclaration) {
+ const body = (decl).body;
+ if (body) {
+ forEachDescendantOfKind(body, SyntaxKind.ThisKeyword, thisKeyword => {
+ if (isNewExpressionTarget(thisKeyword)) {
+ addNode(thisKeyword);
+ }
+ });
+ }
}
- }
- });
+ });
+ }
+ }
+
+ function getClassConstructorSymbol(classSymbol: Symbol): Symbol | undefined {
+ return classSymbol.members && classSymbol.members.get(InternalSymbolName.Constructor);
}
/** Find references to `super` in the constructor of an extending class. */
- function findSuperConstructorAccesses(cls: ClassLikeDeclaration, addNode: (node: Node) => void): void {
- const ctr = cls.symbol.members!.get(InternalSymbolName.Constructor);
- if (!ctr) {
+ function findSuperConstructorAccesses(classDeclaration: ClassLikeDeclaration, addNode: (node: Node) => void): void {
+ const constructor = getClassConstructorSymbol(classDeclaration.symbol);
+ if (!constructor) {
return;
}
- for (const decl of ctr.declarations) {
+ for (const decl of constructor.declarations) {
Debug.assert(decl.kind === SyntaxKind.Constructor);
const body = (decl).body;
if (body) {
@@ -1366,6 +1378,17 @@ namespace ts.FindAllReferences.Core {
}
}
+ function hasOwnConstructor(classDeclaration: ClassLikeDeclaration): boolean {
+ return !!getClassConstructorSymbol(classDeclaration.symbol);
+ }
+
+ function findInheritedConstructorReferences(classDeclaration: ClassLikeDeclaration, state: State): void {
+ if (hasOwnConstructor(classDeclaration)) return;
+ const classSymbol = classDeclaration.symbol;
+ const search = state.createSearch(/*location*/ undefined, classSymbol, /*comingFrom*/ undefined);
+ getReferencesInContainerOrFiles(classSymbol, state, search);
+ }
+
function addImplementationReferences(refNode: Node, addReference: (node: Node) => void, state: State): void {
// Check if we found a function/propertyAssignment/method with an implementation or initializer
if (isDeclarationName(refNode) && isImplementation(refNode.parent)) {
diff --git a/src/services/refactors/convertParamsToDestructuredObject.ts b/src/services/refactors/convertParamsToDestructuredObject.ts
index f813f8ef768..7d2eded741e 100644
--- a/src/services/refactors/convertParamsToDestructuredObject.ts
+++ b/src/services/refactors/convertParamsToDestructuredObject.ts
@@ -81,7 +81,7 @@ namespace ts.refactor.convertParamsToDestructuredObject {
const references = flatMap(names, /*mapfn*/ name => FindAllReferences.getReferenceEntriesForNode(-1, name, program, program.getSourceFiles(), cancellationToken));
const groupedReferences = groupReferences(references);
- if (!every(groupedReferences.declarations, decl => contains(names, decl))) {
+ if (!every(groupedReferences.declarations, /*callback*/ decl => contains(names, decl))) {
groupedReferences.valid = false;
}
@@ -99,7 +99,19 @@ namespace ts.refactor.convertParamsToDestructuredObject {
groupedReferences.valid = false;
continue;
}
- if (contains(functionSymbols, checker.getSymbolAtLocation(entry.node), symbolComparer)) {
+
+ /* We compare symbols because in some cases find all references wil return a reference that may or may not be to the refactored function.
+ Example from the refactorConvertParamsToDestructuredObject_methodCallUnion.ts test:
+ class A { foo(a: number, b: number) { return a + b; } }
+ class B { foo(c: number, d: number) { return c + d; } }
+ declare const ab: A | B;
+ ab.foo(1, 2);
+ Find all references will return `ab.foo(1, 2)` as a reference to A's `foo` but we could be calling B's `foo`.
+ When looking for constructor calls, however, the symbol on the constructor call reference is going to be the corresponding class symbol.
+ So we need to add a special case for this because when calling a constructor of a class through one of its subclasses,
+ the symbols are going to be different.
+ */
+ if (contains(functionSymbols, checker.getSymbolAtLocation(entry.node), symbolComparer) || isNewExpressionTarget(entry.node)) {
const decl = entryToDeclaration(entry);
if (decl) {
groupedReferences.declarations.push(decl);
@@ -233,6 +245,10 @@ namespace ts.refactor.convertParamsToDestructuredObject {
function getFunctionDeclarationAtPosition(file: SourceFile, startPosition: number, checker: TypeChecker): ValidFunctionDeclaration | undefined {
const node = getTouchingToken(file, startPosition);
const functionDeclaration = getContainingFunction(node);
+
+ // don't offer refactor on top-level JSDoc
+ if (isTopLevelJSDoc(node)) return undefined;
+
if (functionDeclaration
&& isValidFunctionDeclaration(functionDeclaration, checker)
&& rangeContainsRange(functionDeclaration, node)
@@ -241,18 +257,35 @@ namespace ts.refactor.convertParamsToDestructuredObject {
return undefined;
}
- function isValidFunctionDeclaration(functionDeclaration: SignatureDeclaration, checker: TypeChecker): functionDeclaration is ValidFunctionDeclaration {
- if (!isValidParameterNodeArray(functionDeclaration.parameters)) return false;
+ function isTopLevelJSDoc(node: Node): boolean {
+ const containingJSDoc = findAncestor(node, isJSDocNode);
+ if (containingJSDoc) {
+ const containingNonJSDoc = findAncestor(containingJSDoc, n => !isJSDocNode(n));
+ return !!containingNonJSDoc && isFunctionLikeDeclaration(containingNonJSDoc);
+ }
+ return false;
+ }
+
+ function isValidFunctionDeclaration(
+ functionDeclaration: SignatureDeclaration,
+ checker: TypeChecker): functionDeclaration is ValidFunctionDeclaration {
+ if (!isValidParameterNodeArray(functionDeclaration.parameters, checker)) return false;
switch (functionDeclaration.kind) {
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.MethodDeclaration:
- return !!functionDeclaration.name && !!functionDeclaration.body && !checker.isImplementationOfOverload(functionDeclaration);
+ return !!functionDeclaration.name
+ && !!functionDeclaration.body
+ && !checker.isImplementationOfOverload(functionDeclaration);
case SyntaxKind.Constructor:
if (isClassDeclaration(functionDeclaration.parent)) {
- return !!functionDeclaration.body && !!functionDeclaration.parent.name && !checker.isImplementationOfOverload(functionDeclaration);
+ return !!functionDeclaration.body
+ && !!functionDeclaration.parent.name
+ && !checker.isImplementationOfOverload(functionDeclaration);
}
else {
- return isValidVariableDeclaration(functionDeclaration.parent.parent) && !!functionDeclaration.body && !checker.isImplementationOfOverload(functionDeclaration);
+ return isValidVariableDeclaration(functionDeclaration.parent.parent)
+ && !!functionDeclaration.body
+ && !checker.isImplementationOfOverload(functionDeclaration);
}
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
@@ -261,12 +294,21 @@ namespace ts.refactor.convertParamsToDestructuredObject {
return false;
}
- function isValidParameterNodeArray(parameters: NodeArray): parameters is ValidParameterNodeArray {
- return getRefactorableParametersLength(parameters) >= minimumParameterLength && every(parameters, isValidParameterDeclaration);
+ function isValidParameterNodeArray(
+ parameters: NodeArray,
+ checker: TypeChecker): parameters is ValidParameterNodeArray {
+ return getRefactorableParametersLength(parameters) >= minimumParameterLength
+ && every(parameters, /*callback*/ paramDecl => isValidParameterDeclaration(paramDecl, checker));
}
- function isValidParameterDeclaration(paramDeclaration: ParameterDeclaration): paramDeclaration is ValidParameterDeclaration {
- return !paramDeclaration.modifiers && !paramDeclaration.decorators && isIdentifier(paramDeclaration.name);
+ function isValidParameterDeclaration(
+ parameterDeclaration: ParameterDeclaration,
+ checker: TypeChecker): parameterDeclaration is ValidParameterDeclaration {
+ if (isRestParameter(parameterDeclaration)) {
+ const type = checker.getTypeAtLocation(parameterDeclaration);
+ if (!checker.isArrayType(type) && !checker.isTupleType(type)) return false;
+ }
+ return !parameterDeclaration.modifiers && !parameterDeclaration.decorators && isIdentifier(parameterDeclaration.name);
}
function isValidVariableDeclaration(node: Node): node is ValidVariableDeclaration {
@@ -291,13 +333,23 @@ namespace ts.refactor.convertParamsToDestructuredObject {
return parameters;
}
+ function createPropertyOrShorthandAssignment(name: string, initializer: Expression): PropertyAssignment | ShorthandPropertyAssignment {
+ if (isIdentifier(initializer) && getTextOfIdentifierOrLiteral(initializer) === name) {
+ return createShorthandPropertyAssignment(name);
+ }
+ return createPropertyAssignment(name, initializer);
+ }
+
function createNewArgument(functionDeclaration: ValidFunctionDeclaration, functionArguments: NodeArray): ObjectLiteralExpression {
const parameters = getRefactorableParameters(functionDeclaration.parameters);
const hasRestParameter = isRestParameter(last(parameters));
const nonRestArguments = hasRestParameter ? functionArguments.slice(0, parameters.length - 1) : functionArguments;
const properties = map(nonRestArguments, (arg, i) => {
- const property = createPropertyAssignment(getParameterName(parameters[i]), arg);
- suppressLeadingAndTrailingTrivia(property.initializer);
+ const parameterName = getParameterName(parameters[i]);
+ const property = createPropertyOrShorthandAssignment(parameterName, arg);
+
+ suppressLeadingAndTrailingTrivia(property.name);
+ if (isPropertyAssignment(property)) suppressLeadingAndTrailingTrivia(property.initializer);
copyComments(arg, property);
return property;
});
@@ -313,15 +365,15 @@ namespace ts.refactor.convertParamsToDestructuredObject {
}
function createNewParameters(functionDeclaration: ValidFunctionDeclaration, program: Program, host: LanguageServiceHost): NodeArray {
+ const checker = program.getTypeChecker();
const refactorableParameters = getRefactorableParameters(functionDeclaration.parameters);
const bindingElements = map(refactorableParameters, createBindingElementFromParameterDeclaration);
const objectParameterName = createObjectBindingPattern(bindingElements);
const objectParameterType = createParameterTypeNode(refactorableParameters);
- const checker = program.getTypeChecker();
let objectInitializer: Expression | undefined;
// If every parameter in the original function was optional, add an empty object initializer to the new object parameter
- if (every(refactorableParameters, checker.isOptionalParameter)) {
+ if (every(refactorableParameters, isOptionalParameter)) {
objectInitializer = createObjectLiteral();
}
@@ -355,6 +407,20 @@ namespace ts.refactor.convertParamsToDestructuredObject {
}
return createNodeArray([objectParameter]);
+ function createBindingElementFromParameterDeclaration(parameterDeclaration: ValidParameterDeclaration): BindingElement {
+ const element = createBindingElement(
+ /*dotDotDotToken*/ undefined,
+ /*propertyName*/ undefined,
+ getParameterName(parameterDeclaration),
+ isRestParameter(parameterDeclaration) && isOptionalParameter(parameterDeclaration) ? createArrayLiteral() : parameterDeclaration.initializer);
+
+ suppressLeadingAndTrailingTrivia(element);
+ if (parameterDeclaration.initializer && element.initializer) {
+ copyComments(parameterDeclaration.initializer, element.initializer);
+ }
+ return element;
+ }
+
function createParameterTypeNode(parameters: NodeArray): TypeLiteralNode {
const members = map(parameters, createPropertySignatureFromParameterDeclaration);
const typeNode = addEmitFlags(createTypeLiteralNode(members), EmitFlags.SingleLine);
@@ -370,7 +436,7 @@ namespace ts.refactor.convertParamsToDestructuredObject {
const propertySignature = createPropertySignature(
/*modifiers*/ undefined,
getParameterName(parameterDeclaration),
- parameterDeclaration.initializer || isRestParameter(parameterDeclaration) ? createToken(SyntaxKind.QuestionToken) : parameterDeclaration.questionToken,
+ isOptionalParameter(parameterDeclaration) ? createToken(SyntaxKind.QuestionToken) : parameterDeclaration.questionToken,
parameterType,
/*initializer*/ undefined);
@@ -384,24 +450,17 @@ namespace ts.refactor.convertParamsToDestructuredObject {
}
function getTypeNode(node: Node): TypeNode | undefined {
- const checker = program.getTypeChecker();
const type = checker.getTypeAtLocation(node);
return getTypeNodeIfAccessible(type, node, program, host);
}
- }
- function createBindingElementFromParameterDeclaration(parameterDeclaration: ValidParameterDeclaration): BindingElement {
- const element = createBindingElement(
- /*dotDotDotToken*/ undefined,
- /*propertyName*/ undefined,
- getParameterName(parameterDeclaration),
- isRestParameter(parameterDeclaration) ? createArrayLiteral() : parameterDeclaration.initializer);
-
- suppressLeadingAndTrailingTrivia(element);
- if (parameterDeclaration.initializer && element.initializer) {
- copyComments(parameterDeclaration.initializer, element.initializer);
+ function isOptionalParameter(parameterDeclaration: ValidParameterDeclaration): boolean {
+ if (isRestParameter(parameterDeclaration)) {
+ const type = checker.getTypeAtLocation(parameterDeclaration);
+ return !checker.isTupleType(type);
+ }
+ return checker.isOptionalParameter(parameterDeclaration);
}
- return element;
}
function copyComments(sourceNode: Node, targetNode: Node) {
diff --git a/src/services/services.ts b/src/services/services.ts
index 7f5772d1489..5f0d3472a3e 100644
--- a/src/services/services.ts
+++ b/src/services/services.ts
@@ -1158,7 +1158,7 @@ namespace ts {
function getValidSourceFile(fileName: string): SourceFile {
const sourceFile = program.getSourceFile(fileName);
if (!sourceFile) {
- throw new Error("Could not find file: '" + fileName + "'.");
+ throw new Error(`Could not find sourceFile: '${fileName}' in ${program && JSON.stringify(program.getSourceFiles().map(f => f.fileName))}.`);
}
return sourceFile;
}
diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts
index 70f94e95fc9..0c9f76acacb 100644
--- a/src/services/signatureHelp.ts
+++ b/src/services/signatureHelp.ts
@@ -566,7 +566,7 @@ namespace ts.SignatureHelp {
}
function itemInfoForParameters(candidateSignature: Signature, checker: TypeChecker, enclosingDeclaration: Node, sourceFile: SourceFile): SignatureHelpItemInfo {
- const isVariadic = candidateSignature.hasRestParameter;
+ const isVariadic = checker.hasEffectiveRestParameter(candidateSignature);
const printer = createPrinter({ removeComments: true });
const typeParameterParts = mapToDisplayParts(writer => {
if (candidateSignature.typeParameters && candidateSignature.typeParameters.length) {
diff --git a/src/testRunner/unittests/config/projectReferences.ts b/src/testRunner/unittests/config/projectReferences.ts
index 6c8863314fa..3acffd7a8c6 100644
--- a/src/testRunner/unittests/config/projectReferences.ts
+++ b/src/testRunner/unittests/config/projectReferences.ts
@@ -284,6 +284,28 @@ namespace ts {
assertHasError("Issues a useful error", program.getSemanticDiagnostics(), Diagnostics.Output_file_0_has_not_been_built_from_source_file_1);
});
});
+
+ it("issues a nice error when the input file is missing when module reference is not relative", () => {
+ const spec: TestSpecification = {
+ "/alpha": {
+ files: { "/alpha/a.ts": "export const m: number = 3;" },
+ references: []
+ },
+ "/beta": {
+ files: { "/beta/b.ts": "import { m } from '@alpha/a'" },
+ references: ["../alpha"],
+ options: {
+ baseUrl: "./",
+ paths: {
+ "@alpha/*": ["/alpha/*"]
+ }
+ }
+ }
+ };
+ testProjectReferences(spec, "/beta/tsconfig.json", program => {
+ assertHasError("Issues a useful error", program.getSemanticDiagnostics(), Diagnostics.Output_file_0_has_not_been_built_from_source_file_1);
+ });
+ });
});
/**
diff --git a/src/testRunner/unittests/tsbuild/sample.ts b/src/testRunner/unittests/tsbuild/sample.ts
index c225840a564..6d128b348cc 100644
--- a/src/testRunner/unittests/tsbuild/sample.ts
+++ b/src/testRunner/unittests/tsbuild/sample.ts
@@ -168,14 +168,14 @@ namespace ts {
});
describe("can detect when and what to rebuild", () => {
- function initializeWithBuild() {
+ function initializeWithBuild(opts?: BuildOptions) {
const fs = projFs.shadow();
const host = new fakes.SolutionBuilderHost(fs);
const builder = createSolutionBuilder(host, ["/src/tests"], { verbose: true });
builder.buildAllProjects();
host.clearDiagnostics();
tick();
- builder.resetBuildContext();
+ builder.resetBuildContext(opts ? { ...opts, verbose: true } : undefined);
return { fs, host, builder };
}
@@ -254,6 +254,65 @@ namespace ts {
[Diagnostics.Building_project_0, "/src/tests/tsconfig.json"],
);
});
+
+ it("rebuilds from start if --f is passed", () => {
+ const { host, builder } = initializeWithBuild({ force: true });
+ builder.buildAllProjects();
+ host.assertDiagnosticMessages(
+ getExpectedDiagnosticForProjectsInBuild("src/core/tsconfig.json", "src/logic/tsconfig.json", "src/tests/tsconfig.json"),
+ [Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, "src/core/tsconfig.json", "src/core/anotherModule.ts", "src/core/anotherModule.js"],
+ [Diagnostics.Building_project_0, "/src/core/tsconfig.json"],
+ [Diagnostics.Project_0_is_up_to_date_with_d_ts_files_from_its_dependencies, "src/logic/tsconfig.json"],
+ [Diagnostics.Building_project_0, "/src/logic/tsconfig.json"],
+ [Diagnostics.Project_0_is_up_to_date_with_d_ts_files_from_its_dependencies, "src/tests/tsconfig.json"],
+ [Diagnostics.Building_project_0, "/src/tests/tsconfig.json"]
+ );
+ });
+
+ it("rebuilds when tsconfig changes", () => {
+ const { fs, host, builder } = initializeWithBuild();
+ replaceText(fs, "/src/tests/tsconfig.json", `"composite": true`, `"composite": true, "target": "es3"`);
+ builder.buildAllProjects();
+ host.assertDiagnosticMessages(
+ getExpectedDiagnosticForProjectsInBuild("src/core/tsconfig.json", "src/logic/tsconfig.json", "src/tests/tsconfig.json"),
+ [Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, "src/core/tsconfig.json", "src/core/anotherModule.ts", "src/core/anotherModule.js"],
+ [Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, "src/logic/tsconfig.json", "src/logic/index.ts", "src/logic/index.js"],
+ [Diagnostics.Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2, "src/tests/tsconfig.json", "src/tests/index.js", "src/tests/tsconfig.json"],
+ [Diagnostics.Building_project_0, "/src/tests/tsconfig.json"],
+ [Diagnostics.Updating_unchanged_output_timestamps_of_project_0, "/src/tests/tsconfig.json"]
+ );
+ });
+
+ it("rebuilds when extended config file changes", () => {
+ const fs = projFs.shadow();
+ fs.writeFileSync("/src/tests/tsconfig.base.json", JSON.stringify({ compilerOptions: { target: "es3" } }));
+ replaceText(fs, "/src/tests/tsconfig.json", `"references": [`, `"extends": "./tsconfig.base.json", "references": [`);
+ const host = new fakes.SolutionBuilderHost(fs);
+ const builder = createSolutionBuilder(host, ["/src/tests"], { verbose: true });
+ builder.buildAllProjects();
+ host.assertDiagnosticMessages(
+ getExpectedDiagnosticForProjectsInBuild("src/core/tsconfig.json", "src/logic/tsconfig.json", "src/tests/tsconfig.json"),
+ [Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/core/tsconfig.json", "src/core/anotherModule.js"],
+ [Diagnostics.Building_project_0, "/src/core/tsconfig.json"],
+ [Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/logic/tsconfig.json", "src/logic/index.js"],
+ [Diagnostics.Building_project_0, "/src/logic/tsconfig.json"],
+ [Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/tests/tsconfig.json", "src/tests/index.js"],
+ [Diagnostics.Building_project_0, "/src/tests/tsconfig.json"]
+ );
+ host.clearDiagnostics();
+ tick();
+ builder.resetBuildContext();
+ fs.writeFileSync("/src/tests/tsconfig.base.json", JSON.stringify({ compilerOptions: {} }));
+ builder.buildAllProjects();
+ host.assertDiagnosticMessages(
+ getExpectedDiagnosticForProjectsInBuild("src/core/tsconfig.json", "src/logic/tsconfig.json", "src/tests/tsconfig.json"),
+ [Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, "src/core/tsconfig.json", "src/core/anotherModule.ts", "src/core/anotherModule.js"],
+ [Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, "src/logic/tsconfig.json", "src/logic/index.ts", "src/logic/index.js"],
+ [Diagnostics.Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2, "src/tests/tsconfig.json", "src/tests/index.js", "src/tests/tsconfig.base.json"],
+ [Diagnostics.Building_project_0, "/src/tests/tsconfig.json"],
+ [Diagnostics.Updating_unchanged_output_timestamps_of_project_0, "/src/tests/tsconfig.json"]
+ );
+ });
});
describe("downstream-blocked compilations", () => {
diff --git a/src/testRunner/unittests/tscWatch/helpers.ts b/src/testRunner/unittests/tscWatch/helpers.ts
index 98a2d4ffa4b..f8647393cb1 100644
--- a/src/testRunner/unittests/tscWatch/helpers.ts
+++ b/src/testRunner/unittests/tscWatch/helpers.ts
@@ -57,20 +57,23 @@ namespace ts.tscWatch {
function checkOutputErrors(
host: WatchedSystem,
logsBeforeWatchDiagnostic: string[] | undefined,
- preErrorsWatchDiagnostic: Diagnostic,
+ preErrorsWatchDiagnostic: Diagnostic | undefined,
logsBeforeErrors: string[] | undefined,
errors: ReadonlyArray | ReadonlyArray,
disableConsoleClears?: boolean | undefined,
- ...postErrorsWatchDiagnostics: Diagnostic[]
+ ...postErrorsWatchDiagnostics: Diagnostic[] | string[]
) {
let screenClears = 0;
const outputs = host.getOutput();
- const expectedOutputCount = 1 + errors.length + postErrorsWatchDiagnostics.length +
- (logsBeforeWatchDiagnostic ? logsBeforeWatchDiagnostic.length : 0) + (logsBeforeErrors ? logsBeforeErrors.length : 0);
+ const expectedOutputCount = (preErrorsWatchDiagnostic ? 1 : 0) +
+ errors.length +
+ postErrorsWatchDiagnostics.length +
+ (logsBeforeWatchDiagnostic ? logsBeforeWatchDiagnostic.length : 0) +
+ (logsBeforeErrors ? logsBeforeErrors.length : 0);
assert.equal(outputs.length, expectedOutputCount, JSON.stringify(outputs));
let index = 0;
forEach(logsBeforeWatchDiagnostic, log => assertLog("logsBeforeWatchDiagnostic", log));
- assertWatchDiagnostic(preErrorsWatchDiagnostic);
+ if (preErrorsWatchDiagnostic) assertWatchDiagnostic(preErrorsWatchDiagnostic);
forEach(logsBeforeErrors, log => assertLog("logBeforeError", log));
// Verify errors
forEach(errors, assertDiagnostic);
@@ -98,13 +101,18 @@ namespace ts.tscWatch {
index++;
}
- function assertWatchDiagnostic(diagnostic: Diagnostic) {
- const expected = getWatchDiagnosticWithoutDate(diagnostic);
- if (!disableConsoleClears && contains(screenStartingMessageCodes, diagnostic.code)) {
- assert.equal(host.screenClears[screenClears], index, `Expected screen clear at this diagnostic: ${expected}`);
- screenClears++;
+ function assertWatchDiagnostic(diagnostic: Diagnostic | string) {
+ if (isString(diagnostic)) {
+ assert.equal(outputs[index], diagnostic, getOutputAtFailedMessage("Diagnostic", diagnostic));
+ }
+ else {
+ const expected = getWatchDiagnosticWithoutDate(diagnostic);
+ if (!disableConsoleClears && contains(screenStartingMessageCodes, diagnostic.code)) {
+ assert.equal(host.screenClears[screenClears], index, `Expected screen clear at this diagnostic: ${expected}`);
+ screenClears++;
+ }
+ assert.isTrue(endsWith(outputs[index], expected), getOutputAtFailedMessage("Watch diagnostic", expected));
}
- assert.isTrue(endsWith(outputs[index], expected), getOutputAtFailedMessage("Watch diagnostic", expected));
index++;
}
@@ -159,6 +167,18 @@ namespace ts.tscWatch {
assert.equal(host.exitCode, expectedExitCode);
}
+ export function checkNormalBuildErrors(host: WatchedSystem, errors: ReadonlyArray | ReadonlyArray, reportErrorSummary?: boolean) {
+ checkOutputErrors(
+ host,
+ /*logsBeforeWatchDiagnostic*/ undefined,
+ /*preErrorsWatchDiagnostic*/ undefined,
+ /*logsBeforeErrors*/ undefined,
+ errors,
+ /*disableConsoleClears*/ undefined,
+ ...(reportErrorSummary ? [getErrorSummaryText(errors.length, host.newLine)] : emptyArray)
+ );
+ }
+
function isDiagnosticMessageChain(message: DiagnosticMessage | DiagnosticMessageChain): message is DiagnosticMessageChain {
return !!(message as DiagnosticMessageChain).messageText;
}
diff --git a/src/testRunner/unittests/tscWatch/incremental.ts b/src/testRunner/unittests/tscWatch/incremental.ts
index f21f994914c..35ec5bff555 100644
--- a/src/testRunner/unittests/tscWatch/incremental.ts
+++ b/src/testRunner/unittests/tscWatch/incremental.ts
@@ -15,9 +15,51 @@ namespace ts.tscWatch {
expectedIncrementalEmit?: ReadonlyArray;
expectedIncrementalErrors?: ReadonlyArray;
}
- function verifyIncrementalWatchEmit({
- files, expectedInitialEmit, expectedInitialErrors, modifyFs, expectedIncrementalEmit, expectedIncrementalErrors
- }: VerifyIncrementalWatchEmitInput) {
+ function verifyIncrementalWatchEmit(input: VerifyIncrementalWatchEmitInput) {
+ it("with tsc --w", () => {
+ verifyIncrementalWatchEmitWorker({
+ input,
+ emitAndReportErrors: createWatchOfConfigFile,
+ verifyErrors: checkOutputErrorsInitial
+ });
+ });
+ it("with tsc", () => {
+ verifyIncrementalWatchEmitWorker({
+ input,
+ emitAndReportErrors: incrementalBuild,
+ verifyErrors: checkNormalBuildErrors
+ });
+ });
+ }
+
+ function incrementalBuild(configFile: string, host: WatchedSystem) {
+ const reportDiagnostic = createDiagnosticReporter(host);
+ const config = parseConfigFileWithSystem(configFile, {}, host, reportDiagnostic);
+ if (config) {
+ performIncrementalCompilation({
+ rootNames: config.fileNames,
+ options: config.options,
+ projectReferences: config.projectReferences,
+ configFileParsingDiagnostics: getConfigFileParsingDiagnostics(config),
+ reportDiagnostic,
+ system: host
+ });
+ }
+ return { close: noop };
+ }
+
+ interface VerifyIncrementalWatchEmitWorkerInput {
+ input: VerifyIncrementalWatchEmitInput;
+ emitAndReportErrors: (configFile: string, host: WatchedSystem) => { close(): void; };
+ verifyErrors: (host: WatchedSystem, errors: ReadonlyArray) => void;
+ }
+ function verifyIncrementalWatchEmitWorker({
+ input: {
+ files, expectedInitialEmit, expectedInitialErrors, modifyFs, expectedIncrementalEmit, expectedIncrementalErrors
+ },
+ emitAndReportErrors,
+ verifyErrors
+ }: VerifyIncrementalWatchEmitWorkerInput) {
const host = createWatchedSystem(files, { currentDirectory: project });
const originalWriteFile = host.writeFile;
const writtenFiles = createMap();
@@ -26,19 +68,41 @@ namespace ts.tscWatch {
writtenFiles.set(path, content);
originalWriteFile.call(host, path, content);
};
- verifyWatch(host, writtenFiles, expectedInitialEmit, expectedInitialErrors);
+ verifyBuild({
+ host,
+ writtenFiles,
+ emitAndReportErrors,
+ verifyErrors,
+ expectedEmit: expectedInitialEmit,
+ expectedErrors: expectedInitialErrors
+ });
if (modifyFs) {
modifyFs(host);
- verifyWatch(host, writtenFiles, Debug.assertDefined(expectedIncrementalEmit), Debug.assertDefined(expectedIncrementalErrors));
+ verifyBuild({
+ host,
+ writtenFiles,
+ emitAndReportErrors,
+ verifyErrors,
+ expectedEmit: Debug.assertDefined(expectedIncrementalEmit),
+ expectedErrors: Debug.assertDefined(expectedIncrementalErrors)
+ });
}
}
- function verifyWatch(host: WatchedSystem, writtenFiles: Map, expectedEmit: ReadonlyArray, expectedErrors: ReadonlyArray) {
+ interface VerifyBuildWorker {
+ host: WatchedSystem;
+ writtenFiles: Map;
+ emitAndReportErrors: VerifyIncrementalWatchEmitWorkerInput["emitAndReportErrors"];
+ verifyErrors: VerifyIncrementalWatchEmitWorkerInput["verifyErrors"];
+ expectedEmit: ReadonlyArray;
+ expectedErrors: ReadonlyArray;
+ }
+ function verifyBuild({ host, writtenFiles, emitAndReportErrors, verifyErrors, expectedEmit, expectedErrors }: VerifyBuildWorker) {
writtenFiles.clear();
- const watch = createWatchOfConfigFile("tsconfig.json", host);
+ const result = emitAndReportErrors("tsconfig.json", host);
checkFileEmit(writtenFiles, expectedEmit);
- checkOutputErrorsInitial(host, expectedErrors);
- watch.close();
+ verifyErrors(host, expectedErrors);
+ result.close();
}
function checkFileEmit(actual: Map, expected: ReadonlyArray) {
@@ -73,7 +137,7 @@ namespace ts.tscWatch {
content: "var y = 20;\n"
};
- it("own file emit without errors", () => {
+ describe("own file emit without errors", () => {
const modifiedFile2Content = file2.content.replace("y", "z").replace("20", "10");
verifyIncrementalWatchEmit({
files: [libFile, file1, file2, configFile],
@@ -125,7 +189,7 @@ namespace ts.tscWatch {
});
});
- it("own file emit with errors", () => {
+ describe("own file emit with errors", () => {
const fileModified: File = {
path: file2.path,
content: `const y: string = 20;`
@@ -208,7 +272,7 @@ namespace ts.tscWatch {
});
});
- it("with --out", () => {
+ describe("with --out", () => {
const config: File = {
path: configFile.path,
content: JSON.stringify({ compilerOptions: { incremental: true, outFile: "out.js" } })
@@ -279,7 +343,7 @@ namespace ts.tscWatch {
content: JSON.stringify({ compilerOptions: { incremental: true, module: "amd" } })
};
- it("own file emit without errors", () => {
+ describe("own file emit without errors", () => {
const modifiedFile2Content = file2.content.replace("y", "z").replace("20", "10");
verifyIncrementalWatchEmit({
files: [libFile, file1, file2, config],
@@ -330,7 +394,7 @@ namespace ts.tscWatch {
});
});
- it("own file emit with errors", () => {
+ describe("own file emit with errors", () => {
const fileModified: File = {
path: file2.path,
content: `export const y: string = 20;`
@@ -412,7 +476,7 @@ namespace ts.tscWatch {
});
});
- it("with --out", () => {
+ describe("with --out", () => {
const config: File = {
path: configFile.path,
content: JSON.stringify({ compilerOptions: { incremental: true, module: "amd", outFile: "out.js" } })
diff --git a/src/testRunner/unittests/tsserver/cachingFileSystemInformation.ts b/src/testRunner/unittests/tsserver/cachingFileSystemInformation.ts
index 26b7857347a..53a1cb4e421 100644
--- a/src/testRunner/unittests/tsserver/cachingFileSystemInformation.ts
+++ b/src/testRunner/unittests/tsserver/cachingFileSystemInformation.ts
@@ -139,7 +139,7 @@ namespace ts.projectSystem {
assert.isTrue(false, `should not find file '${imported.path}'`);
}
catch (e) {
- assert.isTrue(e.message.indexOf(`Could not find file: '${imported.path}'.`) === 0);
+ assert.isTrue(e.message.indexOf(`Could not find sourceFile: '${imported.path}' in ["${root.path}"].`) === 0, `Actual: ${e.message}`);
}
const f2Lookups = getLocationsForModuleLookup("f2");
callsTrackingHost.verifyCalledOnEachEntryNTimes(CalledMapsWithSingleArg.fileExists, f2Lookups, 1);
diff --git a/src/tsc/tsc.ts b/src/tsc/tsc.ts
index b5624b07ec1..ccc04d38088 100644
--- a/src/tsc/tsc.ts
+++ b/src/tsc/tsc.ts
@@ -13,7 +13,7 @@ namespace ts {
}
let reportDiagnostic = createDiagnosticReporter(sys);
- function updateReportDiagnostic(options?: CompilerOptions) {
+ function updateReportDiagnostic(options: CompilerOptions | BuildOptions) {
if (shouldBePretty(options)) {
reportDiagnostic = createDiagnosticReporter(sys, /*pretty*/ true);
}
@@ -23,7 +23,7 @@ namespace ts {
return !!sys.writeOutputIsTTY && sys.writeOutputIsTTY();
}
- function shouldBePretty(options?: CompilerOptions) {
+ function shouldBePretty(options: CompilerOptions | BuildOptions) {
if (!options || typeof options.pretty === "undefined") {
return defaultIsPretty();
}
@@ -192,7 +192,7 @@ namespace ts {
}
// Update to pretty if host supports it
- updateReportDiagnostic();
+ updateReportDiagnostic(buildOptions);
if (projects.length === 0) {
printVersion();
printHelp(buildOpts, "--build ");
@@ -209,8 +209,8 @@ namespace ts {
// Use default createProgram
const buildHost = buildOptions.watch ?
- createSolutionBuilderWithWatchHost(sys, /*createProgram*/ undefined, reportDiagnostic, createBuilderStatusReporter(sys, shouldBePretty()), createWatchStatusReporter()) :
- createSolutionBuilderHost(sys, /*createProgram*/ undefined, reportDiagnostic, createBuilderStatusReporter(sys, shouldBePretty()), createReportErrorSummary(buildOptions));
+ createSolutionBuilderWithWatchHost(sys, /*createProgram*/ undefined, reportDiagnostic, createBuilderStatusReporter(sys, shouldBePretty(buildOptions)), createWatchStatusReporter(buildOptions)) :
+ createSolutionBuilderHost(sys, /*createProgram*/ undefined, reportDiagnostic, createBuilderStatusReporter(sys, shouldBePretty(buildOptions)), createReportErrorSummary(buildOptions));
updateCreateProgram(buildHost);
buildHost.afterProgramEmitAndDiagnostics = (program: BuilderProgram) => reportStatistics(program.getProgram());
@@ -260,40 +260,16 @@ namespace ts {
function performIncrementalCompilation(config: ParsedCommandLine) {
const { options, fileNames, projectReferences } = config;
- const host = createCompilerHost(options);
- const currentDirectory = host.getCurrentDirectory();
- const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames());
- changeCompilerHostLikeToUseCache(host, fileName => toPath(fileName, currentDirectory, getCanonicalFileName));
enableStatistics(options);
- const oldProgram = readBuilderProgram(options, path => host.readFile(path));
- const configFileParsingDiagnostics = getConfigFileParsingDiagnostics(config);
- const programOptions: CreateProgramOptions = {
+ return sys.exit(ts.performIncrementalCompilation({
rootNames: fileNames,
options,
- projectReferences,
- host,
configFileParsingDiagnostics: getConfigFileParsingDiagnostics(config),
- };
- const program = createProgram(programOptions);
- const builderProgram = createEmitAndSemanticDiagnosticsBuilderProgram(
- program,
- {
- useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames,
- createHash: maybeBind(sys, sys.createHash),
- writeFile: (path, data, writeByteOrderMark) => sys.writeFile(path, data, writeByteOrderMark)
- },
- oldProgram,
- configFileParsingDiagnostics
- );
-
- const exitStatus = emitFilesAndReportErrors(
- builderProgram,
+ projectReferences,
reportDiagnostic,
- s => sys.write(s + sys.newLine),
- createReportErrorSummary(options)
- );
- reportStatistics(program);
- return sys.exit(exitStatus);
+ reportErrorSummary: createReportErrorSummary(options),
+ afterProgramEmitAndDiagnostics: builderProgram => reportStatistics(builderProgram.getProgram())
+ }));
}
function updateCreateProgram(host: { createProgram: CreateProgram; }) {
@@ -316,7 +292,7 @@ namespace ts {
};
}
- function createWatchStatusReporter(options?: CompilerOptions) {
+ function createWatchStatusReporter(options: CompilerOptions | BuildOptions) {
return ts.createWatchStatusReporter(sys, shouldBePretty(options));
}
diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts
index 59ae825a8dc..8208cdba2ab 100644
--- a/tests/baselines/reference/api/tsserverlibrary.d.ts
+++ b/tests/baselines/reference/api/tsserverlibrary.d.ts
@@ -2382,8 +2382,8 @@ declare namespace ts {
root: ConditionalRoot;
checkType: Type;
extendsType: Type;
- resolvedTrueType?: Type;
- resolvedFalseType?: Type;
+ trueType: Type;
+ falseType: Type;
}
interface SubstitutionType extends InstantiableType {
typeVariable: TypeVariable;
diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts
index 2b8056735a4..314ccf298cf 100644
--- a/tests/baselines/reference/api/typescript.d.ts
+++ b/tests/baselines/reference/api/typescript.d.ts
@@ -2382,8 +2382,8 @@ declare namespace ts {
root: ConditionalRoot;
checkType: Type;
extendsType: Type;
- resolvedTrueType?: Type;
- resolvedFalseType?: Type;
+ trueType: Type;
+ falseType: Type;
}
interface SubstitutionType extends InstantiableType {
typeVariable: TypeVariable;
diff --git a/tests/baselines/reference/asyncMethodWithSuper_es6.js b/tests/baselines/reference/asyncMethodWithSuper_es6.js
index b2a560a432a..a5f216d221a 100644
--- a/tests/baselines/reference/asyncMethodWithSuper_es6.js
+++ b/tests/baselines/reference/asyncMethodWithSuper_es6.js
@@ -124,6 +124,66 @@ class B extends A {
// element access (assign) in async arrow
(async () => super["x"] = f);
}
+
+ async * property_access_only_read_only_in_generator() {
+ // call with property access
+ super.x();
+
+ // property access (read)
+ const a = super.x;
+
+ // property access in arrow
+ (() => super.x());
+
+ // property access in async arrow
+ (async () => super.x());
+ }
+
+ async * property_access_only_write_only_in_generator() {
+ const f = () => {};
+
+ // property access (assign)
+ super.x = f;
+
+ // destructuring assign with property access
+ ({ f: super.x } = { f });
+
+ // property access (assign) in arrow
+ (() => super.x = f);
+
+ // property access (assign) in async arrow
+ (async () => super.x = f);
+ }
+
+ async * element_access_only_read_only_in_generator() {
+ // call with element access
+ super["x"]();
+
+ // element access (read)
+ const a = super["x"];
+
+ // element access in arrow
+ (() => super["x"]());
+
+ // element access in async arrow
+ (async () => super["x"]());
+ }
+
+ async * element_access_only_write_only_in_generator() {
+ const f = () => {};
+
+ // element access (assign)
+ super["x"] = f;
+
+ // destructuring assign with element access
+ ({ f: super["x"] } = { f });
+
+ // element access (assign) in arrow
+ (() => super["x"] = f);
+
+ // element access (assign) in async arrow
+ (async () => super["x"] = f);
+ }
}
@@ -253,4 +313,67 @@ class B extends A {
(() => __awaiter(this, void 0, void 0, function* () { return _superIndex("x").value = f; }));
});
}
+ property_access_only_read_only_in_generator() {
+ const _super = Object.create(null, {
+ x: { get: () => super.x }
+ });
+ return __asyncGenerator(this, arguments, function* property_access_only_read_only_in_generator_1() {
+ // call with property access
+ _super.x.call(this);
+ // property access (read)
+ const a = _super.x;
+ // property access in arrow
+ (() => _super.x.call(this));
+ // property access in async arrow
+ (() => __awaiter(this, void 0, void 0, function* () { return _super.x.call(this); }));
+ });
+ }
+ property_access_only_write_only_in_generator() {
+ const _super = Object.create(null, {
+ x: { get: () => super.x, set: v => super.x = v }
+ });
+ return __asyncGenerator(this, arguments, function* property_access_only_write_only_in_generator_1() {
+ const f = () => { };
+ // property access (assign)
+ _super.x = f;
+ // destructuring assign with property access
+ ({ f: _super.x } = { f });
+ // property access (assign) in arrow
+ (() => _super.x = f);
+ // property access (assign) in async arrow
+ (() => __awaiter(this, void 0, void 0, function* () { return _super.x = f; }));
+ });
+ }
+ element_access_only_read_only_in_generator() {
+ const _superIndex = name => super[name];
+ const _super = Object.create(null, {});
+ return __asyncGenerator(this, arguments, function* element_access_only_read_only_in_generator_1() {
+ // call with element access
+ _superIndex("x").call(this);
+ // element access (read)
+ const a = _superIndex("x");
+ // element access in arrow
+ (() => _superIndex("x").call(this));
+ // element access in async arrow
+ (() => __awaiter(this, void 0, void 0, function* () { return _superIndex("x").call(this); }));
+ });
+ }
+ element_access_only_write_only_in_generator() {
+ const _superIndex = (function (geti, seti) {
+ const cache = Object.create(null);
+ return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } });
+ })(name => super[name], (name, value) => super[name] = value);
+ const _super = Object.create(null, {});
+ return __asyncGenerator(this, arguments, function* element_access_only_write_only_in_generator_1() {
+ const f = () => { };
+ // element access (assign)
+ _superIndex("x").value = f;
+ // destructuring assign with element access
+ ({ f: _superIndex("x").value } = { f });
+ // element access (assign) in arrow
+ (() => _superIndex("x").value = f);
+ // element access (assign) in async arrow
+ (() => __awaiter(this, void 0, void 0, function* () { return _superIndex("x").value = f; }));
+ });
+ }
}
diff --git a/tests/baselines/reference/asyncMethodWithSuper_es6.symbols b/tests/baselines/reference/asyncMethodWithSuper_es6.symbols
index 842930ce900..59c844fa7de 100644
--- a/tests/baselines/reference/asyncMethodWithSuper_es6.symbols
+++ b/tests/baselines/reference/asyncMethodWithSuper_es6.symbols
@@ -252,5 +252,127 @@ class B extends A {
>"x" : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
>f : Symbol(f, Decl(asyncMethodWithSuper_es6.ts, 111, 13))
}
+
+ async * property_access_only_read_only_in_generator() {
+>property_access_only_read_only_in_generator : Symbol(B.property_access_only_read_only_in_generator, Decl(asyncMethodWithSuper_es6.ts, 124, 5))
+
+ // call with property access
+ super.x();
+>super.x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
+>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0))
+>x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
+
+ // property access (read)
+ const a = super.x;
+>a : Symbol(a, Decl(asyncMethodWithSuper_es6.ts, 131, 13))
+>super.x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
+>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0))
+>x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
+
+ // property access in arrow
+ (() => super.x());
+>super.x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
+>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0))
+>x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
+
+ // property access in async arrow
+ (async () => super.x());
+>super.x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
+>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0))
+>x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
+ }
+
+ async * property_access_only_write_only_in_generator() {
+>property_access_only_write_only_in_generator : Symbol(B.property_access_only_write_only_in_generator, Decl(asyncMethodWithSuper_es6.ts, 138, 5))
+
+ const f = () => {};
+>f : Symbol(f, Decl(asyncMethodWithSuper_es6.ts, 141, 13))
+
+ // property access (assign)
+ super.x = f;
+>super.x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
+>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0))
+>x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
+>f : Symbol(f, Decl(asyncMethodWithSuper_es6.ts, 141, 13))
+
+ // destructuring assign with property access
+ ({ f: super.x } = { f });
+>f : Symbol(f, Decl(asyncMethodWithSuper_es6.ts, 147, 10))
+>super.x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
+>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0))
+>x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
+>f : Symbol(f, Decl(asyncMethodWithSuper_es6.ts, 147, 27))
+
+ // property access (assign) in arrow
+ (() => super.x = f);
+>super.x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
+>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0))
+>x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
+>f : Symbol(f, Decl(asyncMethodWithSuper_es6.ts, 141, 13))
+
+ // property access (assign) in async arrow
+ (async () => super.x = f);
+>super.x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
+>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0))
+>x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
+>f : Symbol(f, Decl(asyncMethodWithSuper_es6.ts, 141, 13))
+ }
+
+ async * element_access_only_read_only_in_generator() {
+>element_access_only_read_only_in_generator : Symbol(B.element_access_only_read_only_in_generator, Decl(asyncMethodWithSuper_es6.ts, 154, 5))
+
+ // call with element access
+ super["x"]();
+>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0))
+>"x" : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
+
+ // element access (read)
+ const a = super["x"];
+>a : Symbol(a, Decl(asyncMethodWithSuper_es6.ts, 161, 13))
+>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0))
+>"x" : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
+
+ // element access in arrow
+ (() => super["x"]());
+>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0))
+>"x" : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
+
+ // element access in async arrow
+ (async () => super["x"]());
+>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0))
+>"x" : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
+ }
+
+ async * element_access_only_write_only_in_generator() {
+>element_access_only_write_only_in_generator : Symbol(B.element_access_only_write_only_in_generator, Decl(asyncMethodWithSuper_es6.ts, 168, 5))
+
+ const f = () => {};
+>f : Symbol(f, Decl(asyncMethodWithSuper_es6.ts, 171, 13))
+
+ // element access (assign)
+ super["x"] = f;
+>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0))
+>"x" : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
+>f : Symbol(f, Decl(asyncMethodWithSuper_es6.ts, 171, 13))
+
+ // destructuring assign with element access
+ ({ f: super["x"] } = { f });
+>f : Symbol(f, Decl(asyncMethodWithSuper_es6.ts, 177, 10))
+>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0))
+>"x" : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
+>f : Symbol(f, Decl(asyncMethodWithSuper_es6.ts, 177, 30))
+
+ // element access (assign) in arrow
+ (() => super["x"] = f);
+>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0))
+>"x" : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
+>f : Symbol(f, Decl(asyncMethodWithSuper_es6.ts, 171, 13))
+
+ // element access (assign) in async arrow
+ (async () => super["x"] = f);
+>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0))
+>"x" : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
+>f : Symbol(f, Decl(asyncMethodWithSuper_es6.ts, 171, 13))
+ }
}
diff --git a/tests/baselines/reference/asyncMethodWithSuper_es6.types b/tests/baselines/reference/asyncMethodWithSuper_es6.types
index 92e132e97b2..ae78d8bc3ad 100644
--- a/tests/baselines/reference/asyncMethodWithSuper_es6.types
+++ b/tests/baselines/reference/asyncMethodWithSuper_es6.types
@@ -332,6 +332,174 @@ class B extends A {
>super["x"] : () => void
>super : A
>"x" : "x"
+>f : () => void
+ }
+
+ async * property_access_only_read_only_in_generator() {
+>property_access_only_read_only_in_generator : () => AsyncIterableIterator
+
+ // call with property access
+ super.x();
+>super.x() : void
+>super.x : () => void
+>super : A
+>x : () => void
+
+ // property access (read)
+ const a = super.x;
+>a : () => void
+>super.x : () => void
+>super : A
+>x : () => void
+
+ // property access in arrow
+ (() => super.x());
+>(() => super.x()) : () => void
+>() => super.x() : () => void
+>super.x() : void
+>super.x : () => void
+>super : A
+>x : () => void
+
+ // property access in async arrow
+ (async () => super.x());
+>(async () => super.x()) : () => Promise
+>async () => super.x() : () => Promise
+>super.x() : void
+>super.x : () => void
+>super : A
+>x : () => void
+ }
+
+ async * property_access_only_write_only_in_generator() {
+>property_access_only_write_only_in_generator : () => AsyncIterableIterator
+
+ const f = () => {};
+>f : () => void
+>() => {} : () => void
+
+ // property access (assign)
+ super.x = f;
+>super.x = f : () => void
+>super.x : () => void
+>super : A
+>x : () => void
+>f : () => void
+
+ // destructuring assign with property access
+ ({ f: super.x } = { f });
+>({ f: super.x } = { f }) : { f: () => void; }
+>{ f: super.x } = { f } : { f: () => void; }
+>{ f: super.x } : { f: () => void; }
+>f : () => void
+>super.x : () => void
+>super : A
+>x : () => void
+>{ f } : { f: () => void; }
+>f : () => void
+
+ // property access (assign) in arrow
+ (() => super.x = f);
+>(() => super.x = f) : () => () => void
+>() => super.x = f : () => () => void
+>super.x = f : () => void
+>super.x : () => void
+>super : A
+>x : () => void
+>f : () => void
+
+ // property access (assign) in async arrow
+ (async () => super.x = f);
+>(async () => super.x = f) : () => Promise<() => void>
+>async () => super.x = f : () => Promise<() => void>
+>super.x = f : () => void
+>super.x : () => void
+>super : A
+>x : () => void
+>f : () => void
+ }
+
+ async * element_access_only_read_only_in_generator() {
+>element_access_only_read_only_in_generator : () => AsyncIterableIterator
+
+ // call with element access
+ super["x"]();
+>super["x"]() : void
+>super["x"] : () => void
+>super : A
+>"x" : "x"
+
+ // element access (read)
+ const a = super["x"];
+>a : () => void
+>super["x"] : () => void
+>super : A
+>"x" : "x"
+
+ // element access in arrow
+ (() => super["x"]());
+>(() => super["x"]()) : () => void
+>() => super["x"]() : () => void
+>super["x"]() : void
+>super["x"] : () => void
+>super : A
+>"x" : "x"
+
+ // element access in async arrow
+ (async () => super["x"]());
+>(async () => super["x"]()) : () => Promise
+>async () => super["x"]() : () => Promise
+>super["x"]() : void
+>super["x"] : () => void
+>super : A
+>"x" : "x"
+ }
+
+ async * element_access_only_write_only_in_generator() {
+>element_access_only_write_only_in_generator : () => AsyncIterableIterator
+
+ const f = () => {};
+>f : () => void
+>() => {} : () => void
+
+ // element access (assign)
+ super["x"] = f;
+>super["x"] = f : () => void
+>super["x"] : () => void
+>super : A
+>"x" : "x"
+>f : () => void
+
+ // destructuring assign with element access
+ ({ f: super["x"] } = { f });
+>({ f: super["x"] } = { f }) : { f: () => void; }
+>{ f: super["x"] } = { f } : { f: () => void; }
+>{ f: super["x"] } : { f: () => void; }
+>f : () => void
+>super["x"] : () => void
+>super : A
+>"x" : "x"
+>{ f } : { f: () => void; }
+>f : () => void
+
+ // element access (assign) in arrow
+ (() => super["x"] = f);
+>(() => super["x"] = f) : () => () => void
+>() => super["x"] = f : () => () => void
+>super["x"] = f : () => void
+>super["x"] : () => void
+>super : A
+>"x" : "x"
+>f : () => void
+
+ // element access (assign) in async arrow
+ (async () => super["x"] = f);
+>(async () => super["x"] = f) : () => Promise<() => void>
+>async () => super["x"] = f : () => Promise<() => void>
+>super["x"] = f : () => void
+>super["x"] : () => void
+>super : A
+>"x" : "x"
>f : () => void
}
}
diff --git a/tests/baselines/reference/circularTypeofWithVarOrFunc.errors.txt b/tests/baselines/reference/circularTypeofWithVarOrFunc.errors.txt
index 9adcce6c845..1fb989b75f5 100644
--- a/tests/baselines/reference/circularTypeofWithVarOrFunc.errors.txt
+++ b/tests/baselines/reference/circularTypeofWithVarOrFunc.errors.txt
@@ -4,11 +4,13 @@ tests/cases/conformance/types/specifyingTypes/typeQueries/circularTypeofWithVarO
tests/cases/conformance/types/specifyingTypes/typeQueries/circularTypeofWithVarOrFunc.ts(5,6): error TS2456: Type alias 'typeAlias2' circularly references itself.
tests/cases/conformance/types/specifyingTypes/typeQueries/circularTypeofWithVarOrFunc.ts(7,18): error TS2577: Return type annotation circularly references itself.
tests/cases/conformance/types/specifyingTypes/typeQueries/circularTypeofWithVarOrFunc.ts(9,6): error TS2456: Type alias 'typeAlias3' circularly references itself.
-tests/cases/conformance/types/specifyingTypes/typeQueries/circularTypeofWithVarOrFunc.ts(20,3): error TS2322: Type 'number' is not assignable to type 'ReturnType<(input: Input) => ReturnType>'.
-tests/cases/conformance/types/specifyingTypes/typeQueries/circularTypeofWithVarOrFunc.ts(26,20): error TS2322: Type '0' is not assignable to type 'ReturnType<() => ReturnType>'.
+tests/cases/conformance/types/specifyingTypes/typeQueries/circularTypeofWithVarOrFunc.ts(18,6): error TS2456: Type alias 'R' circularly references itself.
+tests/cases/conformance/types/specifyingTypes/typeQueries/circularTypeofWithVarOrFunc.ts(19,29): error TS2577: Return type annotation circularly references itself.
+tests/cases/conformance/types/specifyingTypes/typeQueries/circularTypeofWithVarOrFunc.ts(25,6): error TS2456: Type alias 'R2' circularly references itself.
+tests/cases/conformance/types/specifyingTypes/typeQueries/circularTypeofWithVarOrFunc.ts(26,15): error TS2577: Return type annotation circularly references itself.
-==== tests/cases/conformance/types/specifyingTypes/typeQueries/circularTypeofWithVarOrFunc.ts (8 errors) ====
+==== tests/cases/conformance/types/specifyingTypes/typeQueries/circularTypeofWithVarOrFunc.ts (10 errors) ====
type typeAlias1 = typeof varOfAliasedType1;
~~~~~~~~~~
!!! error TS2456: Type alias 'typeAlias1' circularly references itself.
@@ -39,16 +41,20 @@ tests/cases/conformance/types/specifyingTypes/typeQueries/circularTypeofWithVarO
}
type R = ReturnType;
+ ~
+!!! error TS2456: Type alias 'R' circularly references itself.
function mul(input: Input): R {
+ ~
+!!! error TS2577: Return type annotation circularly references itself.
return input.a * input.b;
- ~~~~~~~~~~~~~~~~~~~~~~~~~
-!!! error TS2322: Type 'number' is not assignable to type 'ReturnType<(input: Input) => ReturnType>'.
}
// Repro from #26104
type R2 = ReturnType;
+ ~~
+!!! error TS2456: Type alias 'R2' circularly references itself.
function f(): R2 { return 0; }
- ~~~~~~~~~
-!!! error TS2322: Type '0' is not assignable to type 'ReturnType<() => ReturnType>'.
+ ~~
+!!! error TS2577: Return type annotation circularly references itself.
\ No newline at end of file
diff --git a/tests/baselines/reference/circularTypeofWithVarOrFunc.types b/tests/baselines/reference/circularTypeofWithVarOrFunc.types
index 7f7fe21bba0..c2c8ba7947f 100644
--- a/tests/baselines/reference/circularTypeofWithVarOrFunc.types
+++ b/tests/baselines/reference/circularTypeofWithVarOrFunc.types
@@ -37,11 +37,11 @@ interface Input {
}
type R = ReturnType;
->R : ReturnType<(input: Input) => ReturnType>
->mul : (input: Input) => ReturnType
+>R : any
+>mul : (input: Input) => any
function mul(input: Input): R {
->mul : (input: Input) => ReturnType
+>mul : (input: Input) => any
>input : Input
return input.a * input.b;
@@ -57,10 +57,10 @@ function mul(input: Input): R {
// Repro from #26104
type R2 = ReturnType;
->R2 : ReturnType<() => ReturnType>
->f : () => ReturnType
+>R2 : any
+>f : () => any
function f(): R2 { return 0; }
->f : () => ReturnType
+>f : () => any
>0 : 0
diff --git a/tests/baselines/reference/conditionalTypes1.js b/tests/baselines/reference/conditionalTypes1.js
index b592bd33d10..5dc48518384 100644
--- a/tests/baselines/reference/conditionalTypes1.js
+++ b/tests/baselines/reference/conditionalTypes1.js
@@ -509,8 +509,6 @@ declare function f5(p: K): Extract;
declare let x0: {
k: "a";
-} & {
- k: "a";
a: number;
};
declare type OptionsOfKind = Extract void), Function>; // string | numbe
>T02 : string | number
type T03 = Extract void), Function>; // () => void
->T03 : Function & (() => void)
+>T03 : () => void
type T04 = NonNullable; // string | number
>T04 : string | number
@@ -113,7 +113,7 @@ type T10 = Exclude; // { k: "c", c: boolean }
>k : "a" | "b"
type T11 = Extract; // { k: "a", a: number } | { k: "b", b: string }
->T11 : ({ k: "a" | "b"; } & { k: "a"; a: number; }) | ({ k: "a" | "b"; } & { k: "b"; b: string; })
+>T11 : { k: "a"; a: number; } | { k: "b"; b: string; }
>k : "a" | "b"
type T12 = Exclude; // { k: "c", c: boolean }
@@ -122,7 +122,7 @@ type T12 = Exclude; // { k: "c", c: boolean }
>k : "b"
type T13 = Extract; // { k: "a", a: number } | { k: "b", b: string }
->T13 : ({ k: "a"; } & { k: "a"; a: number; }) | ({ k: "b"; } & { k: "a"; a: number; }) | ({ k: "a"; } & { k: "b"; b: string; }) | ({ k: "b"; } & { k: "b"; b: string; })
+>T13 : { k: "a"; a: number; } | { k: "b"; b: string; }
>k : "a"
>k : "b"
@@ -140,8 +140,8 @@ declare function f5(p: K): Extractk : K
let x0 = f5("a"); // { k: "a", a: number }
->x0 : { k: "a"; } & { k: "a"; a: number; }
->f5("a") : { k: "a"; } & { k: "a"; a: number; }
+>x0 : { k: "a"; a: number; }
+>f5("a") : { k: "a"; a: number; }
>f5 : (p: K) => Extract
>"a" : "a"
@@ -150,13 +150,13 @@ type OptionsOfKind = Extract;
>k : K
type T16 = OptionsOfKind<"a" | "b">; // { k: "a", a: number } | { k: "b", b: string }
->T16 : ({ k: "a" | "b"; } & { k: "a"; a: number; }) | ({ k: "a" | "b"; } & { k: "b"; b: string; })
+>T16 : { k: "a"; a: number; } | { k: "b"; b: string; }
type Select = Extract;
>Select : Extract
type T17 = Select; // // { k: "a", a: number } | { k: "b", b: string }
->T17 : ({ k: "a" | "b"; } & { k: "a"; a: number; }) | ({ k: "a" | "b"; } & { k: "b"; b: string; })
+>T17 : { k: "a"; a: number; } | { k: "b"; b: string; }
type TypeName =
>TypeName : TypeName
diff --git a/tests/baselines/reference/conditionalTypes2.errors.txt b/tests/baselines/reference/conditionalTypes2.errors.txt
index 6cf81cf5730..ee7c10ada58 100644
--- a/tests/baselines/reference/conditionalTypes2.errors.txt
+++ b/tests/baselines/reference/conditionalTypes2.errors.txt
@@ -21,13 +21,13 @@ tests/cases/conformance/types/conditional/conditionalTypes2.ts(25,5): error TS23
Type 'A' is not assignable to type 'B'.
tests/cases/conformance/types/conditional/conditionalTypes2.ts(73,12): error TS2345: Argument of type 'Extract, Bar>' is not assignable to parameter of type '{ foo: string; bat: string; }'.
Property 'bat' is missing in type 'Bar & Foo' but required in type '{ foo: string; bat: string; }'.
- Type 'Extract' is not assignable to type '{ foo: string; bat: string; }'.
+ Type 'Extract' is not assignable to type '{ foo: string; bat: string; }'.
Property 'bat' is missing in type 'Bar & Foo' but required in type '{ foo: string; bat: string; }'.
tests/cases/conformance/types/conditional/conditionalTypes2.ts(74,12): error TS2345: Argument of type 'Extract' is not assignable to parameter of type '{ foo: string; bat: string; }'.
Property 'bat' is missing in type 'Foo & Bar' but required in type '{ foo: string; bat: string; }'.
tests/cases/conformance/types/conditional/conditionalTypes2.ts(75,12): error TS2345: Argument of type 'Extract2' is not assignable to parameter of type '{ foo: string; bat: string; }'.
Type 'T extends Bar ? T : never' is not assignable to type '{ foo: string; bat: string; }'.
- Type 'Bar & Foo & T' is not assignable to type '{ foo: string; bat: string; }'.
+ Property 'bat' is missing in type 'Bar & Foo' but required in type '{ foo: string; bat: string; }'.
==== tests/cases/conformance/types/conditional/conditionalTypes2.ts (7 errors) ====
@@ -132,7 +132,7 @@ tests/cases/conformance/types/conditional/conditionalTypes2.ts(75,12): error TS2
~
!!! error TS2345: Argument of type 'Extract, Bar>' is not assignable to parameter of type '{ foo: string; bat: string; }'.
!!! error TS2345: Property 'bat' is missing in type 'Bar & Foo' but required in type '{ foo: string; bat: string; }'.
-!!! error TS2345: Type 'Extract' is not assignable to type '{ foo: string; bat: string; }'.
+!!! error TS2345: Type 'Extract' is not assignable to type '{ foo: string; bat: string; }'.
!!! error TS2345: Property 'bat' is missing in type 'Bar & Foo' but required in type '{ foo: string; bat: string; }'.
!!! related TS2728 tests/cases/conformance/types/conditional/conditionalTypes2.ts:62:43: 'bat' is declared here.
!!! related TS2728 tests/cases/conformance/types/conditional/conditionalTypes2.ts:62:43: 'bat' is declared here.
@@ -145,7 +145,8 @@ tests/cases/conformance/types/conditional/conditionalTypes2.ts(75,12): error TS2
~
!!! error TS2345: Argument of type 'Extract2' is not assignable to parameter of type '{ foo: string; bat: string; }'.
!!! error TS2345: Type 'T extends Bar ? T : never' is not assignable to type '{ foo: string; bat: string; }'.
-!!! error TS2345: Type 'Bar & Foo & T' is not assignable to type '{ foo: string; bat: string; }'.
+!!! error TS2345: Property 'bat' is missing in type 'Bar & Foo' but required in type '{ foo: string; bat: string; }'.
+!!! related TS2728 tests/cases/conformance/types/conditional/conditionalTypes2.ts:62:43: 'bat' is declared here.
}
// Repros from #22860
diff --git a/tests/baselines/reference/conditionalTypes2.types b/tests/baselines/reference/conditionalTypes2.types
index 7113ccc2be8..aac6ba47475 100644
--- a/tests/baselines/reference/conditionalTypes2.types
+++ b/tests/baselines/reference/conditionalTypes2.types
@@ -130,14 +130,14 @@ function f12(x: string | (() => string) | undefined) {
>x : string | (() => string) | undefined
const f = getFunction(x); // () => string
->f : Function & (() => string)
->getFunction(x) : Function & (() => string)
+>f : () => string
+>getFunction(x) : () => string
>getFunction : (item: T) => Extract
>x : string | (() => string) | undefined
f();
>f() : string
->f : Function & (() => string)
+>f : () => string
}
type Foo = { foo: string };
diff --git a/tests/baselines/reference/contravariantInferenceAndTypeGuard.js b/tests/baselines/reference/contravariantInferenceAndTypeGuard.js
new file mode 100644
index 00000000000..a56fdacf8c9
--- /dev/null
+++ b/tests/baselines/reference/contravariantInferenceAndTypeGuard.js
@@ -0,0 +1,40 @@
+//// [contravariantInferenceAndTypeGuard.ts]
+interface ListItem {
+ prev: ListItem | null;
+ next: ListItem | null;
+ data: TData;
+}
+type IteratorFn> = (this: TContext, item: TData, node: ListItem, list: List) => TResult;
+type FilterFn> = (this: TContext, item: TData, node: ListItem, list: List) => item is TResult;
+
+declare class List {
+ filter(fn: FilterFn, context: TContext): List;
+ filter(fn: FilterFn): List;
+ filter(fn: IteratorFn, context: TContext): List;
+ filter(fn: IteratorFn): List;
+}
+interface Test {
+ a: string;
+}
+const list2 = new List();
+const filter1 = list2.filter(function(item, node, list): item is Test {
+ this.b; // $ExpectType string
+ item; // $ExpectType Test | null
+ node; // $ExpectType ListItem
+ list; // $ExpectType List
+ return !!item;
+}, {b: 'c'});
+const x: List = filter1; // $ExpectType List
+
+
+//// [contravariantInferenceAndTypeGuard.js]
+"use strict";
+var list2 = new List();
+var filter1 = list2.filter(function (item, node, list) {
+ this.b; // $ExpectType string
+ item; // $ExpectType Test | null
+ node; // $ExpectType ListItem
+ list; // $ExpectType List
+ return !!item;
+}, { b: 'c' });
+var x = filter1; // $ExpectType List
diff --git a/tests/baselines/reference/contravariantInferenceAndTypeGuard.symbols b/tests/baselines/reference/contravariantInferenceAndTypeGuard.symbols
new file mode 100644
index 00000000000..bee31fb1bfc
--- /dev/null
+++ b/tests/baselines/reference/contravariantInferenceAndTypeGuard.symbols
@@ -0,0 +1,157 @@
+=== tests/cases/compiler/contravariantInferenceAndTypeGuard.ts ===
+interface ListItem {
+>ListItem : Symbol(ListItem, Decl(contravariantInferenceAndTypeGuard.ts, 0, 0))
+>TData : Symbol(TData, Decl(contravariantInferenceAndTypeGuard.ts, 0, 19))
+
+ prev: ListItem | null;
+>prev : Symbol(ListItem.prev, Decl(contravariantInferenceAndTypeGuard.ts, 0, 27))
+>ListItem : Symbol(ListItem, Decl(contravariantInferenceAndTypeGuard.ts, 0, 0))
+>TData : Symbol(TData, Decl(contravariantInferenceAndTypeGuard.ts, 0, 19))
+
+ next: ListItem | null;
+>next : Symbol(ListItem.next, Decl(contravariantInferenceAndTypeGuard.ts, 1, 33))
+>ListItem : Symbol(ListItem, Decl(contravariantInferenceAndTypeGuard.ts, 0, 0))
+>TData : Symbol(TData, Decl(contravariantInferenceAndTypeGuard.ts, 0, 19))
+
+ data: TData;
+>data : Symbol(ListItem.data, Decl(contravariantInferenceAndTypeGuard.ts, 2, 33))
+>TData : Symbol(TData, Decl(contravariantInferenceAndTypeGuard.ts, 0, 19))
+}
+type IteratorFn