Merge branch 'master' into saferIndexedAccessTypes

This commit is contained in:
Anders Hejlsberg
2019-04-05 16:23:48 -10:00
272 changed files with 3313 additions and 1079 deletions
+1 -2
View File
@@ -2710,8 +2710,7 @@ namespace ts {
}
else {
const s = forEachIdentifierInEntityName(e.expression, parent, action);
if (!s || !s.exports) return Debug.fail();
return action(e.name, s.exports.get(e.name.escapedText), s);
return action(e.name, s && s.exports && s.exports.get(e.name.escapedText), s);
}
}
+3 -3
View File
@@ -792,7 +792,7 @@ namespace ts {
state,
// When whole program is affected, do emit only once (eg when --out or --outFile is specified)
// Otherwise just affected file
affected.emitBuildInfo(writeFile || host.writeFile, cancellationToken),
affected.emitBuildInfo(writeFile || maybeBind(host, host.writeFile), cancellationToken),
affected,
/*isPendingEmitFile*/ false,
/*isBuildInfoEmit*/ true
@@ -820,7 +820,7 @@ namespace ts {
state,
// When whole program is affected, do emit only once (eg when --out or --outFile is specified)
// Otherwise just affected file
Debug.assertDefined(state.program).emit(affected === state.program ? undefined : affected as SourceFile, writeFile || host.writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers),
Debug.assertDefined(state.program).emit(affected === state.program ? undefined : affected as SourceFile, writeFile || maybeBind(host, host.writeFile), cancellationToken, emitOnlyDtsFiles, customTransformers),
affected,
isPendingEmitFile
);
@@ -862,7 +862,7 @@ namespace ts {
};
}
}
return Debug.assertDefined(state.program).emit(targetSourceFile, writeFile || host.writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers);
return Debug.assertDefined(state.program).emit(targetSourceFile, writeFile || maybeBind(host, host.writeFile), cancellationToken, emitOnlyDtsFiles, customTransformers);
}
/**
+79 -25
View File
@@ -392,6 +392,7 @@ namespace ts {
const literalTypes = createMap<LiteralType>();
const indexedAccessTypes = createMap<IndexedAccessType>();
const conditionalTypes = createMap<Type>();
const substitutionTypes = createMap<SubstitutionType>();
const evolvingArrayTypes: EvolvingArrayType[] = [];
const undefinedProperties = createMap<Symbol>() as UnderscoreEscapedMap<Symbol>;
@@ -1137,6 +1138,10 @@ namespace ts {
// still might be illegal if the usage is within a computed property name in the class (eg class A { static p = "a"; [A.p]() {} })
return !findAncestor(usage, n => isComputedPropertyName(n) && n.parent.parent === declaration);
}
else if (isPropertyDeclaration(declaration)) {
// still might be illegal if a self-referencing property initializer (eg private x = this.x)
return !isPropertyImmediatelyReferencedWithinDeclaration(declaration, usage);
}
return true;
}
@@ -1211,6 +1216,40 @@ namespace ts {
return false;
});
}
function isPropertyImmediatelyReferencedWithinDeclaration(declaration: PropertyDeclaration, usage: Node) {
// always legal if usage is after declaration
if (usage.end > declaration.end) {
return false;
}
// still might be legal if usage is deferred (e.g. x: any = () => this.x)
// otherwise illegal if immediately referenced within the declaration (e.g. x: any = this.x)
const ancestorChangingReferenceScope = findAncestor(usage, (node: Node) => {
if (node === declaration) {
return "quit";
}
switch (node.kind) {
case SyntaxKind.ArrowFunction:
case SyntaxKind.PropertyDeclaration:
return true;
case SyntaxKind.Block:
switch (node.parent.kind) {
case SyntaxKind.GetAccessor:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.SetAccessor:
return true;
default:
return false;
}
default:
return false;
}
});
return ancestorChangingReferenceScope === undefined;
}
}
/**
@@ -7339,7 +7378,7 @@ namespace ts {
const declaredType = <MappedType>getTypeFromMappedTypeNode(type.declaration);
const constraint = getConstraintTypeFromMappedType(declaredType);
const extendedConstraint = constraint && constraint.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(<TypeParameter>constraint) : constraint;
type.modifiersType = extendedConstraint && extendedConstraint.flags & TypeFlags.Index ? instantiateType((<IndexType>extendedConstraint).type, type.mapper || identityMapper) : emptyObjectType;
type.modifiersType = extendedConstraint && extendedConstraint.flags & TypeFlags.Index ? instantiateType((<IndexType>extendedConstraint).type, type.mapper || identityMapper) : unknownType;
}
}
return type.modifiersType;
@@ -7785,7 +7824,7 @@ namespace ts {
* type itself. Note that the apparent type of a union type is the union type itself.
*/
function getApparentType(type: Type): Type {
const t = type.flags & TypeFlags.Instantiable ? getBaseConstraintOfType(type) || emptyObjectType : type;
const t = type.flags & TypeFlags.Instantiable ? getBaseConstraintOfType(type) || unknownType : type;
return getObjectFlags(t) & ObjectFlags.Mapped ? getApparentTypeOfMappedType(<MappedType>t) :
t.flags & TypeFlags.Intersection ? getApparentTypeOfIntersectionType(<IntersectionType>t) :
t.flags & TypeFlags.StringLike ? globalStringType :
@@ -7795,6 +7834,7 @@ namespace ts {
t.flags & TypeFlags.ESSymbolLike ? getGlobalESSymbolType(/*reportErrors*/ languageVersion >= ScriptTarget.ES2015) :
t.flags & TypeFlags.NonPrimitive ? emptyObjectType :
t.flags & TypeFlags.Index ? keyofConstraintType :
t.flags & TypeFlags.Unknown && !strictNullChecks ? emptyObjectType :
t;
}
@@ -8118,7 +8158,7 @@ namespace ts {
const baseDefaultType = getDefaultTypeArgumentType(isJavaScriptImplicitAny);
for (let i = numTypeArguments; i < numTypeParameters; i++) {
let defaultType = getDefaultFromTypeParameter(typeParameters![i]);
if (isJavaScriptImplicitAny && defaultType && isTypeIdenticalTo(defaultType, emptyObjectType)) {
if (isJavaScriptImplicitAny && defaultType && (isTypeIdenticalTo(defaultType, unknownType) || isTypeIdenticalTo(defaultType, emptyObjectType))) {
defaultType = anyType;
}
result[i] = defaultType ? instantiateType(defaultType, createTypeMapper(typeParameters!, result)) : baseDefaultType;
@@ -8497,7 +8537,7 @@ namespace ts {
const typeParameters = signature.typeParameters;
if (typeParameters) {
const typeEraser = createTypeEraser(typeParameters);
const baseConstraints = map(typeParameters, tp => instantiateType(getBaseConstraintOfType(tp), typeEraser) || emptyObjectType);
const baseConstraints = map(typeParameters, tp => instantiateType(getBaseConstraintOfType(tp), typeEraser) || unknownType);
return instantiateSignature(signature, createTypeMapper(typeParameters, baseConstraints), /*eraseTypeParameters*/ true);
}
return signature;
@@ -8887,9 +8927,15 @@ namespace ts {
if (substitute.flags & TypeFlags.AnyOrUnknown) {
return typeVariable;
}
const id = `${getTypeId(typeVariable)}>${getTypeId(substitute)}`;
const cached = substitutionTypes.get(id);
if (cached) {
return cached;
}
const result = <SubstitutionType>createType(TypeFlags.Substitution);
result.typeVariable = typeVariable;
result.substitute = substitute;
substitutionTypes.set(id, result);
return result;
}
@@ -10839,7 +10885,7 @@ namespace ts {
* This is used during inference when instantiating type parameter defaults.
*/
function createBackreferenceMapper(context: InferenceContext, index: number): TypeMapper {
return t => findIndex(context.inferences, info => info.typeParameter === t) >= index ? emptyObjectType : t;
return t => findIndex(context.inferences, info => info.typeParameter === t) >= index ? unknownType : t;
}
function combineTypeMappers(mapper1: TypeMapper | undefined, mapper2: TypeMapper): TypeMapper;
@@ -11386,7 +11432,7 @@ namespace ts {
function isTypeDerivedFrom(source: Type, target: Type): boolean {
return source.flags & TypeFlags.Union ? every((<UnionType>source).types, t => isTypeDerivedFrom(t, target)) :
target.flags & TypeFlags.Union ? some((<UnionType>target).types, t => isTypeDerivedFrom(source, t)) :
source.flags & TypeFlags.InstantiableNonPrimitive ? isTypeDerivedFrom(getBaseConstraintOfType(source) || emptyObjectType, target) :
source.flags & TypeFlags.InstantiableNonPrimitive ? isTypeDerivedFrom(getBaseConstraintOfType(source) || unknownType, target) :
target === globalObjectType ? !!(source.flags & (TypeFlags.Object | TypeFlags.NonPrimitive)) :
target === globalFunctionType ? !!(source.flags & TypeFlags.Object) && isFunctionObjectType(source as ObjectType) :
hasBaseType(source, getTargetType(target));
@@ -13404,7 +13450,7 @@ namespace ts {
return indexTypesIdenticalTo(source, target, kind);
}
const targetInfo = getIndexInfoOfType(target, kind);
if (!targetInfo || targetInfo.type.flags & TypeFlags.AnyOrUnknown && !sourceIsPrimitive) {
if (!targetInfo || targetInfo.type.flags & TypeFlags.Any && !sourceIsPrimitive) {
// Index signature of type any permits assignment from everything but primitives
return Ternary.True;
}
@@ -14555,7 +14601,7 @@ namespace ts {
const templateType = getTemplateTypeFromMappedType(target);
const inference = createInferenceInfo(typeParameter);
inferTypes([inference], sourceType, templateType);
return getTypeFromInference(inference) || emptyObjectType;
return getTypeFromInference(inference) || unknownType;
}
function* getUnmatchedProperties(source: Type, target: Type, requireOptionalProperties: boolean, matchDiscriminantProperties: boolean) {
@@ -15154,7 +15200,7 @@ namespace ts {
}
function getDefaultTypeArgumentType(isInJavaScriptFile: boolean): Type {
return isInJavaScriptFile ? anyType : emptyObjectType;
return isInJavaScriptFile ? anyType : unknownType;
}
function getInferredTypes(context: InferenceContext): Type[] {
@@ -15498,7 +15544,7 @@ namespace ts {
return strictNullChecks ? TypeFacts.ObjectStrictFacts : TypeFacts.ObjectFacts;
}
if (flags & TypeFlags.Instantiable) {
return getTypeFacts(getBaseConstraintOfType(type) || emptyObjectType);
return getTypeFacts(getBaseConstraintOfType(type) || unknownType);
}
if (flags & TypeFlags.UnionOrIntersection) {
return getTypeFactsOfTypes((<UnionOrIntersectionType>type).types);
@@ -16804,7 +16850,7 @@ namespace ts {
}
function typeHasNullableConstraint(type: Type) {
return type.flags & TypeFlags.InstantiableNonPrimitive && maybeTypeOfKind(getBaseConstraintOfType(type) || emptyObjectType, TypeFlags.Nullable);
return type.flags & TypeFlags.InstantiableNonPrimitive && maybeTypeOfKind(getBaseConstraintOfType(type) || unknownType, TypeFlags.Nullable);
}
function getConstraintForLocation(type: Type, node: Node): Type;
@@ -18254,7 +18300,7 @@ namespace ts {
}
function getJsxPropsTypeFromCallSignature(sig: Signature, context: JsxOpeningLikeElement) {
let propsType = getTypeOfFirstParameterOfSignatureWithFallback(sig, emptyObjectType);
let propsType = getTypeOfFirstParameterOfSignatureWithFallback(sig, unknownType);
propsType = getJsxManagedAttributesFromLocatedAttributes(context, getJsxNamespaceAt(context), propsType);
const intrinsicAttribs = getJsxType(JsxNames.IntrinsicAttributes, context);
if (intrinsicAttribs !== errorType) {
@@ -18328,7 +18374,7 @@ namespace ts {
const forcedLookupLocation = getJsxElementPropertiesName(ns);
let attributesType = forcedLookupLocation === undefined
// If there is no type ElementAttributesProperty, return the type of the first parameter of the signature, which should be the props type
? getTypeOfFirstParameterOfSignatureWithFallback(sig, emptyObjectType)
? getTypeOfFirstParameterOfSignatureWithFallback(sig, unknownType)
: forcedLookupLocation === ""
// If there is no e.g. 'props' member in ElementAttributesProperty, use the element class type instead
? getReturnTypeOfSignature(sig)
@@ -18340,7 +18386,7 @@ namespace ts {
if (!!forcedLookupLocation && !!length(context.attributes.properties)) {
error(context, Diagnostics.JSX_element_class_does_not_support_attributes_because_it_does_not_have_a_0_property, unescapeLeadingUnderscores(forcedLookupLocation));
}
return emptyObjectType;
return unknownType;
}
attributesType = getJsxManagedAttributesFromLocatedAttributes(context, ns, attributesType);
@@ -19551,7 +19597,7 @@ namespace ts {
undefinedDiagnostic?: DiagnosticMessage,
nullOrUndefinedDiagnostic?: DiagnosticMessage
): Type {
if (type.flags & TypeFlags.Unknown) {
if (strictNullChecks && type.flags & TypeFlags.Unknown) {
error(node, Diagnostics.Object_is_of_type_unknown);
return errorType;
}
@@ -19568,6 +19614,14 @@ namespace ts {
return type;
}
function checkNonNullNonVoidType(type: Type, node: Node): Type {
const nonNullType = checkNonNullType(type, node);
if (nonNullType !== errorType && nonNullType.flags & TypeFlags.Void) {
error(node, Diagnostics.Object_is_possibly_undefined);
}
return nonNullType;
}
function checkPropertyAccessExpression(node: PropertyAccessExpression) {
return checkPropertyAccessExpressionOrQualifiedName(node, node.expression, node.name);
}
@@ -22047,7 +22101,7 @@ namespace ts {
const decl = parameter.valueDeclaration as ParameterDeclaration;
if (decl.name.kind !== SyntaxKind.Identifier) {
// if inference didn't come up with anything but {}, fall back to the binding pattern if present.
if (links.type === emptyObjectType) {
if (links.type === unknownType) {
links.type = getTypeFromBindingPattern(decl.name);
}
assignBindingElementTypes(decl.name);
@@ -22060,11 +22114,11 @@ namespace ts {
const globalPromiseType = getGlobalPromiseType(/*reportErrors*/ true);
if (globalPromiseType !== emptyGenericType) {
// if the promised type is itself a promise, get the underlying type; otherwise, fallback to the promised type
promisedType = getAwaitedType(promisedType) || emptyObjectType;
promisedType = getAwaitedType(promisedType) || unknownType;
return createTypeReference(globalPromiseType, [promisedType]);
}
return emptyObjectType;
return unknownType;
}
function createPromiseLikeType(promisedType: Type): Type {
@@ -22072,16 +22126,16 @@ namespace ts {
const globalPromiseLikeType = getGlobalPromiseLikeType(/*reportErrors*/ true);
if (globalPromiseLikeType !== emptyGenericType) {
// if the promised type is itself a promise, get the underlying type; otherwise, fallback to the promised type
promisedType = getAwaitedType(promisedType) || emptyObjectType;
promisedType = getAwaitedType(promisedType) || unknownType;
return createTypeReference(globalPromiseLikeType, [promisedType]);
}
return emptyObjectType;
return unknownType;
}
function createPromiseReturnType(func: FunctionLikeDeclaration | ImportCall, promisedType: Type) {
const promiseType = createPromiseType(promisedType);
if (promiseType === emptyObjectType) {
if (promiseType === unknownType) {
error(func, isImportCall(func) ?
Diagnostics.A_dynamic_import_call_returns_a_Promise_Make_sure_you_have_a_declaration_for_Promise_or_include_ES2015_in_your_lib_option :
Diagnostics.An_async_function_or_method_must_return_a_Promise_Make_sure_you_have_a_declaration_for_Promise_or_include_ES2015_in_your_lib_option);
@@ -23514,7 +23568,7 @@ namespace ts {
// If the contextual type is a type variable constrained to a primitive type, consider
// this a literal context for literals of that primitive type. For example, given a
// type parameter 'T extends string', infer string literal types for T.
const constraint = getBaseConstraintOfType(contextualType) || emptyObjectType;
const constraint = getBaseConstraintOfType(contextualType) || unknownType;
return maybeTypeOfKind(constraint, TypeFlags.String) && maybeTypeOfKind(candidateType, TypeFlags.StringLiteral) ||
maybeTypeOfKind(constraint, TypeFlags.Number) && maybeTypeOfKind(candidateType, TypeFlags.NumberLiteral) ||
maybeTypeOfKind(constraint, TypeFlags.BigInt) && maybeTypeOfKind(candidateType, TypeFlags.BigIntLiteral) ||
@@ -26313,7 +26367,7 @@ namespace ts {
if (node.initializer && node.parent.parent.kind !== SyntaxKind.ForInStatement) {
const initializerType = checkExpressionCached(node.initializer);
if (strictNullChecks && node.name.elements.length === 0) {
checkNonNullType(initializerType, node);
checkNonNullNonVoidType(initializerType, node);
}
else {
checkTypeAssignableToAndOptionallyElaborate(initializerType, getWidenedTypeForVariableLikeDeclaration(node), node, node.initializer);
@@ -30354,7 +30408,7 @@ namespace ts {
autoArrayType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
}
globalReadonlyArrayType = <GenericType>getGlobalTypeOrUndefined("ReadonlyArray" as __String, /*arity*/ 1);
globalReadonlyArrayType = <GenericType>getGlobalTypeOrUndefined("ReadonlyArray" as __String, /*arity*/ 1) || globalArrayType;
anyReadonlyArrayType = globalReadonlyArrayType ? createTypeFromGenericGlobalType(globalReadonlyArrayType, [anyType]) : anyArrayType;
globalThisType = <GenericType>getGlobalTypeOrUndefined("ThisType" as __String, /*arity*/ 1);
@@ -31509,7 +31563,7 @@ namespace ts {
}
if (node.exclamationToken && (node.parent.parent.kind !== SyntaxKind.VariableStatement || !node.type || node.initializer || node.flags & NodeFlags.Ambient)) {
return grammarErrorOnNode(node.exclamationToken, Diagnostics.A_definite_assignment_assertion_is_not_permitted_in_this_context);
return grammarErrorOnNode(node.exclamationToken, Diagnostics.Definite_assignment_assertions_can_only_be_used_along_with_a_type_annotation);
}
if (compilerOptions.module !== ModuleKind.ES2015 && compilerOptions.module !== ModuleKind.ESNext && compilerOptions.module !== ModuleKind.System && !compilerOptions.noEmit &&
+7 -8
View File
@@ -136,6 +136,13 @@ namespace ts {
category: Diagnostics.Advanced_Options,
description: Diagnostics.Show_verbose_diagnostic_information
},
{
name: "incremental",
shortName: "i",
type: "boolean",
category: Diagnostics.Basic_Options,
description: Diagnostics.Enable_incremental_compilation,
},
];
/* @internal */
@@ -331,19 +338,11 @@ namespace ts {
category: Diagnostics.Basic_Options,
description: Diagnostics.Enable_project_compilation,
},
{
name: "incremental",
type: "boolean",
isTSConfigOnly: true,
category: Diagnostics.Basic_Options,
description: Diagnostics.Enable_incremental_compilation,
},
{
name: "tsBuildInfoFile",
type: "string",
isFilePath: true,
paramType: Diagnostics.FILE,
isTSConfigOnly: true,
category: Diagnostics.Basic_Options,
description: Diagnostics.Specify_file_to_store_incremental_compilation_information,
},
+1 -1
View File
@@ -1,7 +1,7 @@
namespace ts {
// WARNING: The script `configureNightly.ts` uses a regexp to parse out these values.
// If changing the text in this section, be sure to test `configureNightly` too.
export const versionMajorMinor = "3.4";
export const versionMajorMinor = "3.5";
/** The version of the TypeScript compiler release */
export const version = `${versionMajorMinor}.0-dev`;
}
+8
View File
@@ -847,6 +847,10 @@
"category": "Error",
"code": 1257
},
"Definite assignment assertions can only be used along with a type annotation.": {
"category": "Error",
"code": 1258
},
"'with' statements are not allowed in an async function block.": {
"category": "Error",
"code": 1300
@@ -3072,6 +3076,10 @@
"category": "Error",
"code": 5073
},
"Option '--incremental' can only be specified using tsconfig, emitting to single file or when option `--tsBuildInfoFile` is specified.": {
"category": "Error",
"code": 5074
},
"Generates a sourcemap for each corresponding '.d.ts' file.": {
"category": "Message",
+2 -1
View File
@@ -54,7 +54,7 @@ namespace ts {
/*@internal*/
export function getOutputPathForBuildInfo(options: CompilerOptions) {
const configFile = options.configFilePath;
if (!configFile || !isIncrementalCompilation(options)) return undefined;
if (!isIncrementalCompilation(options)) return undefined;
if (options.tsBuildInfoFile) return options.tsBuildInfoFile;
const outPath = options.outFile || options.out;
let buildInfoExtensionLess: string;
@@ -62,6 +62,7 @@ namespace ts {
buildInfoExtensionLess = removeFileExtension(outPath);
}
else {
if (!configFile) return undefined;
const configFileExtensionLess = removeFileExtension(configFile);
buildInfoExtensionLess = options.outDir ?
options.rootDir ?
+18 -17
View File
@@ -3693,9 +3693,11 @@ namespace ts {
// - "(x = 10)" is an assignment expression parsed as a signature with a default parameter value.
// - "(x,y)" is a comma expression parsed as a signature with two parameters.
// - "a ? (b): c" will have "(b):" parsed as a signature with a return type annotation.
// - "a ? (b): function() {}" will too, since function() is a valid JSDoc function type.
//
// So we need just a bit of lookahead to ensure that it can only be a signature.
if (!allowAmbiguity && token() !== SyntaxKind.EqualsGreaterThanToken && token() !== SyntaxKind.OpenBraceToken) {
const hasJSDocFunctionType = node.type && isJSDocFunctionType(node.type);
if (!allowAmbiguity && token() !== SyntaxKind.EqualsGreaterThanToken && (hasJSDocFunctionType || token() !== SyntaxKind.OpenBraceToken)) {
// Returning undefined here will cause our caller to rewind to where we started from.
return undefined;
}
@@ -7749,17 +7751,17 @@ namespace ts {
context.pragmas = createMap() as PragmaMap;
for (const pragma of pragmas) {
if (context.pragmas.has(pragma!.name)) { // TODO: GH#18217
const currentValue = context.pragmas.get(pragma!.name);
if (context.pragmas.has(pragma.name)) {
const currentValue = context.pragmas.get(pragma.name);
if (currentValue instanceof Array) {
currentValue.push(pragma!.args);
currentValue.push(pragma.args);
}
else {
context.pragmas.set(pragma!.name, [currentValue, pragma!.args]);
context.pragmas.set(pragma.name, [currentValue, pragma.args]);
}
continue;
}
context.pragmas.set(pragma!.name, pragma!.args);
context.pragmas.set(pragma.name, pragma.args);
}
}
@@ -7783,9 +7785,8 @@ namespace ts {
const typeReferenceDirectives = context.typeReferenceDirectives;
const libReferenceDirectives = context.libReferenceDirectives;
forEach(toArray(entryOrList), (arg: PragmaPseudoMap["reference"]) => {
// TODO: GH#18217
const { types, lib, path } = arg!.arguments;
if (arg!.arguments["no-default-lib"]) {
const { types, lib, path } = arg.arguments;
if (arg.arguments["no-default-lib"]) {
context.hasNoDefaultLib = true;
}
else if (types) {
@@ -7798,7 +7799,7 @@ namespace ts {
referencedFiles.push({ pos: path.pos, end: path.end, fileName: path.value });
}
else {
reportDiagnostic(arg!.range.pos, arg!.range.end - arg!.range.pos, Diagnostics.Invalid_reference_directive_syntax);
reportDiagnostic(arg.range.pos, arg.range.end - arg.range.pos, Diagnostics.Invalid_reference_directive_syntax);
}
});
break;
@@ -7806,7 +7807,7 @@ namespace ts {
case "amd-dependency": {
context.amdDependencies = map(
toArray(entryOrList),
(x: PragmaPseudoMap["amd-dependency"]) => ({ name: x!.arguments.name!, path: x!.arguments.path })); // TODO: GH#18217
(x: PragmaPseudoMap["amd-dependency"]) => ({ name: x.arguments.name, path: x.arguments.path }));
break;
}
case "amd-module": {
@@ -7814,13 +7815,13 @@ namespace ts {
for (const entry of entryOrList) {
if (context.moduleName) {
// TODO: It's probably fine to issue this diagnostic on all instances of the pragma
reportDiagnostic(entry!.range.pos, entry!.range.end - entry!.range.pos, Diagnostics.An_AMD_module_cannot_have_multiple_name_assignments);
reportDiagnostic(entry.range.pos, entry.range.end - entry.range.pos, Diagnostics.An_AMD_module_cannot_have_multiple_name_assignments);
}
context.moduleName = (entry as PragmaPseudoMap["amd-module"])!.arguments.name;
context.moduleName = (entry as PragmaPseudoMap["amd-module"]).arguments.name;
}
}
else {
context.moduleName = (entryOrList as PragmaPseudoMap["amd-module"])!.arguments.name;
context.moduleName = (entryOrList as PragmaPseudoMap["amd-module"]).arguments.name;
}
break;
}
@@ -7828,11 +7829,11 @@ namespace ts {
case "ts-check": {
// _last_ of either nocheck or check in a file is the "winner"
forEach(toArray(entryOrList), entry => {
if (!context.checkJsDirective || entry!.range.pos > context.checkJsDirective.pos) { // TODO: GH#18217
if (!context.checkJsDirective || entry.range.pos > context.checkJsDirective.pos) {
context.checkJsDirective = {
enabled: key === "ts-check",
end: entry!.range.end,
pos: entry!.range.pos
end: entry.range.end,
pos: entry.range.pos
};
}
});
+28 -9
View File
@@ -193,7 +193,8 @@ namespace ts {
getDirectories: (path: string) => system.getDirectories(path),
realpath,
readDirectory: (path, extensions, include, exclude, depth) => system.readDirectory(path, extensions, include, exclude, depth),
createDirectory: d => system.createDirectory(d)
createDirectory: d => system.createDirectory(d),
createHash: maybeBind(system, system.createHash)
};
return compilerHost;
}
@@ -315,7 +316,10 @@ namespace ts {
};
}
export function getPreEmitDiagnostics(program: Program, sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic> {
// tslint:disable unified-signatures
export function getPreEmitDiagnostics(program: Program, sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
/*@internal*/ export function getPreEmitDiagnostics(program: BuilderProgram, sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
export function getPreEmitDiagnostics(program: Program | BuilderProgram, sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic> {
const diagnostics = [
...program.getConfigFileParsingDiagnostics(),
...program.getOptionsDiagnostics(cancellationToken),
@@ -330,6 +334,7 @@ namespace ts {
return sortAndDeduplicateDiagnostics(diagnostics);
}
// tslint:enable unified-signatures
export interface FormatDiagnosticsHost {
getCurrentDirectory(): string;
@@ -1129,7 +1134,7 @@ namespace ts {
function moduleNameResolvesToAmbientModuleInNonModifiedFile(moduleName: string): boolean {
const resolutionToFile = getResolvedModule(oldSourceFile!, moduleName);
const resolvedFile = resolutionToFile && oldProgram!.getSourceFile(resolutionToFile.resolvedFileName);
if (resolutionToFile && resolvedFile && !resolvedFile.externalModuleIndicator) {
if (resolutionToFile && resolvedFile) {
// In the old program, we resolved to an ambient module that was in the same
// place as we expected to find an actual module file.
// We actually need to return 'false' here even though this seems like a 'true' case
@@ -2261,8 +2266,13 @@ namespace ts {
let redirectedPath: Path | undefined;
if (refFile) {
const redirect = getProjectReferenceRedirect(fileName);
if (redirect) {
const redirectProject = getProjectReferenceRedirectProject(fileName);
if (redirectProject) {
if (redirectProject.commandLine.options.outFile || redirectProject.commandLine.options.out) {
// Shouldnt create many to 1 mapping file in --out scenario
return undefined;
}
const redirect = getProjectReferenceOutputName(redirectProject, 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
@@ -2359,6 +2369,11 @@ namespace ts {
}
function getProjectReferenceRedirect(fileName: string): string | undefined {
const referencedProject = getProjectReferenceRedirectProject(fileName);
return referencedProject && getProjectReferenceOutputName(referencedProject, fileName);
}
function getProjectReferenceRedirectProject(fileName: string) {
// Ignore dts or any of the non ts files
if (!resolvedProjectReferences || !resolvedProjectReferences.length || fileExtensionIs(fileName, Extension.Dts) || !fileExtensionIsOneOf(fileName, supportedTSExtensions)) {
return undefined;
@@ -2366,10 +2381,11 @@ namespace ts {
// If this file is produced by a referenced project, we need to rewrite it to
// look in the output folder of the referenced project rather than the input
const referencedProject = getResolvedProjectReferenceToRedirect(fileName);
if (!referencedProject) {
return undefined;
}
return getResolvedProjectReferenceToRedirect(fileName);
}
function getProjectReferenceOutputName(referencedProject: ResolvedProjectReference, fileName: string) {
const out = referencedProject.commandLine.options.outFile || referencedProject.commandLine.options.out;
return out ?
changeExtension(out, Extension.Dts) :
@@ -2730,6 +2746,9 @@ namespace ts {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, "tsBuildInfoFile", "incremental", "composite");
}
}
else if (options.incremental && !options.outFile && !options.out && !options.configFilePath) {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_incremental_can_only_be_specified_using_tsconfig_emitting_to_single_file_or_when_option_tsBuildInfoFile_is_specified));
}
verifyProjectReferences();
+2
View File
@@ -327,6 +327,8 @@ namespace ts {
createVariableDeclarationList(lexicalEnvironmentVariableDeclarations)
);
setEmitFlags(statement, EmitFlags.CustomPrologue);
if (!statements) {
statements = [statement];
}
+27 -11
View File
@@ -30,6 +30,7 @@ namespace ts {
listEmittedFiles?: boolean;
listFiles?: boolean;
pretty?: boolean;
incremental?: boolean;
traceResolution?: boolean;
/* @internal */ diagnostics?: boolean;
@@ -363,7 +364,7 @@ namespace ts {
function getCompilerOptionsOfBuildOptions(buildOptions: BuildOptions): CompilerOptions {
const result = {} as CompilerOptions;
commonOptionsWithBuild.forEach(option => {
result[option.name] = buildOptions[option.name];
if (hasProperty(buildOptions, option.name)) result[option.name] = buildOptions[option.name];
});
return result;
}
@@ -393,7 +394,7 @@ namespace ts {
const projectStatus = createFileMap<UpToDateStatus>(toPath);
const missingRoots = createMap<true>();
let globalDependencyGraph: DependencyGraph | undefined;
const writeFileName = (s: string) => host.trace && host.trace(s);
const writeFileName = host.trace ? (s: string) => host.trace!(s) : undefined;
let readFileWithCache = (f: string) => host.readFile(f);
let projectCompilerOptions = baseCompilerOptions;
const compilerHost = createCompilerHostFromProgramHost(host, () => projectCompilerOptions);
@@ -1128,7 +1129,7 @@ namespace ts {
let declDiagnostics: Diagnostic[] | undefined;
const reportDeclarationDiagnostics = (d: Diagnostic) => (declDiagnostics || (declDiagnostics = [])).push(d);
const outputFiles: OutputFile[] = [];
emitFilesAndReportErrors(program, reportDeclarationDiagnostics, writeFileName, /*reportSummary*/ undefined, (name, text, writeByteOrderMark) => outputFiles.push({ name, text, writeByteOrderMark }));
emitFilesAndReportErrors(program, reportDeclarationDiagnostics, /*writeFileName*/ undefined, /*reportSummary*/ undefined, (name, text, writeByteOrderMark) => outputFiles.push({ name, text, writeByteOrderMark }));
// Don't emit .d.ts if there are decl file errors
if (declDiagnostics) {
program.restoreState();
@@ -1137,7 +1138,7 @@ namespace ts {
// Actual Emit
const emitterDiagnostics = createDiagnosticCollection();
const emittedOutputs = createFileMap<true>(toPath as ToPath);
const emittedOutputs = createFileMap<string>(toPath as ToPath);
outputFiles.forEach(({ name, text, writeByteOrderMark }) => {
let priorChangeTime: Date | undefined;
if (!anyDtsChanged && isDeclarationFile(name)) {
@@ -1151,7 +1152,7 @@ namespace ts {
}
}
emittedOutputs.setValue(name, true);
emittedOutputs.setValue(name, name);
writeFile(compilerHost, emitterDiagnostics, name, text, writeByteOrderMark);
if (priorChangeTime !== undefined) {
newestDeclarationFileContentChangedTime = newer(priorChangeTime, newestDeclarationFileContentChangedTime);
@@ -1164,6 +1165,11 @@ namespace ts {
return buildErrors(emitDiagnostics, BuildResultFlags.EmitErrors, "Emit");
}
if (writeFileName) {
emittedOutputs.forEach(name => listEmittedFile(configFile, name));
listFiles(program, writeFileName);
}
// Update time stamps for rest of the outputs
newestDeclarationFileContentChangedTime = updateOutputTimestampsWorker(configFile, newestDeclarationFileContentChangedTime, Diagnostics.Updating_unchanged_output_timestamps_of_project_0, emittedOutputs);
@@ -1181,6 +1187,8 @@ namespace ts {
function buildErrors(diagnostics: ReadonlyArray<Diagnostic>, errorFlags: BuildResultFlags, errorType: string) {
resultFlags |= errorFlags;
reportAndStoreErrors(proj, diagnostics);
// List files if any other build error using program (emit errors already report files)
if (writeFileName) listFiles(program, writeFileName);
projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: `${errorType} errors` });
afterProgramCreate(proj, program);
projectCompilerOptions = baseCompilerOptions;
@@ -1188,6 +1196,12 @@ namespace ts {
}
}
function listEmittedFile(proj: ParsedCommandLine, file: string) {
if (writeFileName && proj.options.listEmittedFiles) {
writeFileName(`TSFILE: ${file}`);
}
}
function afterProgramCreate(proj: ResolvedConfigFileName, program: T) {
if (host.afterProgramEmitAndDiagnostics) {
host.afterProgramEmitAndDiagnostics(program);
@@ -1228,9 +1242,9 @@ namespace ts {
// Actual Emit
Debug.assert(!!outputFiles.length);
const emitterDiagnostics = createDiagnosticCollection();
const emittedOutputs = createFileMap<true>(toPath as ToPath);
const emittedOutputs = createFileMap<string>(toPath as ToPath);
outputFiles.forEach(({ name, text, writeByteOrderMark }) => {
emittedOutputs.setValue(name, true);
emittedOutputs.setValue(name, name);
writeFile(compilerHost, emitterDiagnostics, name, text, writeByteOrderMark);
});
const emitDiagnostics = emitterDiagnostics.getDiagnostics();
@@ -1241,6 +1255,10 @@ namespace ts {
return BuildResultFlags.DeclarationOutputUnchanged | BuildResultFlags.EmitErrors;
}
if (writeFileName) {
emittedOutputs.forEach(name => listEmittedFile(config, name));
}
// Update timestamps for dts
const newestDeclarationFileContentChangedTime = updateOutputTimestampsWorker(config, minimumDate, Diagnostics.Updating_unchanged_output_timestamps_of_project_0, emittedOutputs);
@@ -1269,7 +1287,7 @@ namespace ts {
projectStatus.setValue(proj.options.configFilePath as ResolvedConfigFilePath, status);
}
function updateOutputTimestampsWorker(proj: ParsedCommandLine, priorNewestUpdateTime: Date, verboseMessage: DiagnosticMessage, skipOutputs?: FileMap<true>) {
function updateOutputTimestampsWorker(proj: ParsedCommandLine, priorNewestUpdateTime: Date, verboseMessage: DiagnosticMessage, skipOutputs?: FileMap<string>) {
const outputs = getAllProjectOutputs(proj, !host.useCaseSensitiveFileNames());
if (!skipOutputs || outputs.length !== skipOutputs.getSize()) {
if (options.verbose) {
@@ -1286,9 +1304,7 @@ namespace ts {
}
host.setModifiedTime(file, now);
if (proj.options.listEmittedFiles) {
writeFileName(`TSFILE: ${file}`);
}
listEmittedFile(proj, file);
}
}
+20 -28
View File
@@ -5951,26 +5951,18 @@ namespace ts {
/* @internal */
export interface PragmaDefinition<T1 extends string = string, T2 extends string = string, T3 extends string = string, T4 extends string = string> {
args?:
| [PragmaArgumentSpecification<T1>]
| [PragmaArgumentSpecification<T1>, PragmaArgumentSpecification<T2>]
| [PragmaArgumentSpecification<T1>, PragmaArgumentSpecification<T2>, PragmaArgumentSpecification<T3>]
| [PragmaArgumentSpecification<T1>, PragmaArgumentSpecification<T2>, PragmaArgumentSpecification<T3>, PragmaArgumentSpecification<T4>];
| readonly [PragmaArgumentSpecification<T1>]
| readonly [PragmaArgumentSpecification<T1>, PragmaArgumentSpecification<T2>]
| readonly [PragmaArgumentSpecification<T1>, PragmaArgumentSpecification<T2>, PragmaArgumentSpecification<T3>]
| readonly [PragmaArgumentSpecification<T1>, PragmaArgumentSpecification<T2>, PragmaArgumentSpecification<T3>, PragmaArgumentSpecification<T4>];
// If not present, defaults to PragmaKindFlags.Default
kind?: PragmaKindFlags;
}
/**
* This function only exists to cause exact types to be inferred for all the literals within `commentPragmas`
*/
/* @internal */
function _contextuallyTypePragmas<T extends {[name: string]: PragmaDefinition<K1, K2, K3, K4>}, K1 extends string, K2 extends string, K3 extends string, K4 extends string>(args: T): T {
return args;
}
// While not strictly a type, this is here because `PragmaMap` needs to be here to be used with `SourceFile`, and we don't
// fancy effectively defining it twice, once in value-space and once in type-space
/* @internal */
export const commentPragmas = _contextuallyTypePragmas({
export const commentPragmas = {
"reference": {
args: [
{ name: "types", optional: true, captureSpan: true },
@@ -5998,7 +5990,7 @@ namespace ts {
args: [{ name: "factory" }],
kind: PragmaKindFlags.MultiLine
},
});
} as const;
/* @internal */
type PragmaArgTypeMaybeCapture<TDesc> = TDesc extends {captureSpan: true} ? {value: string, pos: number, end: number} : string;
@@ -6009,29 +6001,29 @@ namespace ts {
? {[K in TName]?: PragmaArgTypeMaybeCapture<TDesc>}
: {[K in TName]: PragmaArgTypeMaybeCapture<TDesc>};
/* @internal */
type UnionToIntersection<U> =
(U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
/* @internal */
type ArgumentDefinitionToFieldUnion<T extends readonly PragmaArgumentSpecification<any>[]> = {
[K in keyof T]: PragmaArgTypeOptional<T[K], T[K] extends {name: infer TName} ? TName extends string ? TName : never : never>
}[Extract<keyof T, number>]; // The mapped type maps over only the tuple members, but this reindex gets _all_ members - by extracting only `number` keys, we get only the tuple members
/**
* Maps a pragma definition into the desired shape for its arguments object
* Maybe the below is a good argument for types being iterable on struture in some way.
*/
/* @internal */
type PragmaArgumentType<T extends PragmaDefinition> =
T extends { args: [PragmaArgumentSpecification<infer TName1>, PragmaArgumentSpecification<infer TName2>, PragmaArgumentSpecification<infer TName3>, PragmaArgumentSpecification<infer TName4>] }
? PragmaArgTypeOptional<T["args"][0], TName1> & PragmaArgTypeOptional<T["args"][1], TName2> & PragmaArgTypeOptional<T["args"][2], TName3> & PragmaArgTypeOptional<T["args"][2], TName4>
: T extends { args: [PragmaArgumentSpecification<infer TName1>, PragmaArgumentSpecification<infer TName2>, PragmaArgumentSpecification<infer TName3>] }
? PragmaArgTypeOptional<T["args"][0], TName1> & PragmaArgTypeOptional<T["args"][1], TName2> & PragmaArgTypeOptional<T["args"][2], TName3>
: T extends { args: [PragmaArgumentSpecification<infer TName1>, PragmaArgumentSpecification<infer TName2>] }
? PragmaArgTypeOptional<T["args"][0], TName1> & PragmaArgTypeOptional<T["args"][1], TName2>
: T extends { args: [PragmaArgumentSpecification<infer TName>] }
? PragmaArgTypeOptional<T["args"][0], TName>
: object;
// The above fallback to `object` when there's no args to allow `{}` (as intended), but not the number 2, for example
// TODO: Swap to `undefined` for a cleaner API once strictNullChecks is enabled
type PragmaArgumentType<KPrag extends keyof ConcretePragmaSpecs> =
ConcretePragmaSpecs[KPrag] extends { args: readonly PragmaArgumentSpecification<any>[] }
? UnionToIntersection<ArgumentDefinitionToFieldUnion<ConcretePragmaSpecs[KPrag]["args"]>>
: never;
/* @internal */
type ConcretePragmaSpecs = typeof commentPragmas;
/* @internal */
export type PragmaPseudoMap = {[K in keyof ConcretePragmaSpecs]?: {arguments: PragmaArgumentType<ConcretePragmaSpecs[K]>, range: CommentRange}};
export type PragmaPseudoMap = {[K in keyof ConcretePragmaSpecs]: {arguments: PragmaArgumentType<K>, range: CommentRange}};
/* @internal */
export type PragmaPseudoMapEntry = {[K in keyof PragmaPseudoMap]: {name: K, args: PragmaPseudoMap[K]}}[keyof PragmaPseudoMap];
+9 -6
View File
@@ -121,6 +121,14 @@ namespace ts {
emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback): EmitResult;
}
export function listFiles(program: ProgramToEmitFilesAndReportErrors, writeFileName: (s: string) => void) {
if (program.getCompilerOptions().listFiles) {
forEach(program.getSourceFiles(), file => {
writeFileName(file.fileName);
});
}
}
/**
* Helper that emit files, report diagnostics and lists emitted and/or source files depending on compiler options
*/
@@ -152,12 +160,7 @@ namespace ts {
const filepath = getNormalizedAbsolutePath(file, currentDir);
writeFileName(`TSFILE: ${filepath}`);
});
if (program.getCompilerOptions().listFiles) {
forEach(program.getSourceFiles(), file => {
writeFileName(file.fileName);
});
}
listFiles(program, writeFileName);
}
if (reportSummary) {