mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'master' into saferIndexedAccessTypes
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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 &&
|
||||
|
||||
@@ -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,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`;
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
@@ -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
@@ -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();
|
||||
|
||||
|
||||
@@ -327,6 +327,8 @@ namespace ts {
|
||||
createVariableDeclarationList(lexicalEnvironmentVariableDeclarations)
|
||||
);
|
||||
|
||||
setEmitFlags(statement, EmitFlags.CustomPrologue);
|
||||
|
||||
if (!statements) {
|
||||
statements = [statement];
|
||||
}
|
||||
|
||||
+27
-11
@@ -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
@@ -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];
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -90,7 +90,7 @@ namespace ts.server {
|
||||
return <T>request;
|
||||
}
|
||||
|
||||
private processResponse<T extends protocol.Response>(request: protocol.Request): T {
|
||||
private processResponse<T extends protocol.Response>(request: protocol.Request, expectEmptyBody = false): T {
|
||||
let foundResponseMessage = false;
|
||||
let response!: T;
|
||||
while (!foundResponseMessage) {
|
||||
@@ -118,7 +118,8 @@ namespace ts.server {
|
||||
throw new Error("Error " + response.message);
|
||||
}
|
||||
|
||||
Debug.assert(!!response.body, "Malformed response: Unexpected empty response body.");
|
||||
Debug.assert(expectEmptyBody || !!response.body, "Malformed response: Unexpected empty response body.");
|
||||
Debug.assert(!expectEmptyBody || !response.body, "Malformed response: Unexpected non-empty response body.");
|
||||
|
||||
return response;
|
||||
}
|
||||
@@ -696,7 +697,8 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
configurePlugin(pluginName: string, configuration: any): void {
|
||||
this.processRequest<protocol.ConfigurePluginRequest>("configurePlugin", { pluginName, configuration });
|
||||
const request = this.processRequest<protocol.ConfigurePluginRequest>("configurePlugin", { pluginName, configuration });
|
||||
this.processResponse<protocol.ConfigurePluginResponse>(request, /*expectEmptyBody*/ true);
|
||||
}
|
||||
|
||||
getIndentationAtPosition(_fileName: string, _position: number, _options: EditorOptions): number {
|
||||
|
||||
@@ -4507,6 +4507,7 @@ namespace FourSlashInterface {
|
||||
typeEntry("Record"),
|
||||
typeEntry("Exclude"),
|
||||
typeEntry("Extract"),
|
||||
typeEntry("Omit"),
|
||||
typeEntry("NonNullable"),
|
||||
typeEntry("Parameters"),
|
||||
typeEntry("ConstructorParameters"),
|
||||
|
||||
Vendored
+5
@@ -1443,6 +1443,11 @@ type Exclude<T, U> = T extends U ? never : T;
|
||||
*/
|
||||
type Extract<T, U> = T extends U ? T : never;
|
||||
|
||||
/**
|
||||
* Construct a type with the properties of T except for those in type K.
|
||||
*/
|
||||
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
|
||||
|
||||
/**
|
||||
* Exclude null and undefined from T
|
||||
*/
|
||||
|
||||
@@ -1607,7 +1607,8 @@ namespace ts.server {
|
||||
this.documentRegistry,
|
||||
compilerOptions,
|
||||
/*lastFileExceededProgramSize*/ this.getFilenameForExceededTotalSizeLimitForNonTsFiles(projectFileName, compilerOptions, files, externalFilePropertyReader),
|
||||
options.compileOnSave === undefined ? true : options.compileOnSave);
|
||||
options.compileOnSave === undefined ? true : options.compileOnSave,
|
||||
/*projectFilePath*/ undefined, this.currentPluginConfigOverrides);
|
||||
project.excludedFiles = excludedFiles;
|
||||
|
||||
this.addFilesToNonInferredProject(project, files, externalFilePropertyReader, typeAcquisition);
|
||||
|
||||
@@ -958,6 +958,9 @@ namespace ts.server {
|
||||
);
|
||||
const elapsed = timestamp() - start;
|
||||
this.writeLog(`Finishing updateGraphWorker: Project: ${this.getProjectName()} Version: ${this.getProjectVersion()} structureChanged: ${hasNewProgram} Elapsed: ${elapsed}ms`);
|
||||
if (this.program !== oldProgram) {
|
||||
this.print();
|
||||
}
|
||||
return hasNewProgram;
|
||||
}
|
||||
|
||||
@@ -1610,7 +1613,8 @@ namespace ts.server {
|
||||
compilerOptions: CompilerOptions,
|
||||
lastFileExceededProgramSize: string | undefined,
|
||||
public compileOnSaveEnabled: boolean,
|
||||
projectFilePath?: string) {
|
||||
projectFilePath?: string,
|
||||
pluginConfigOverrides?: Map<any>) {
|
||||
super(externalProjectName,
|
||||
ProjectKind.External,
|
||||
projectService,
|
||||
@@ -1621,6 +1625,7 @@ namespace ts.server {
|
||||
compileOnSaveEnabled,
|
||||
projectService.host,
|
||||
getDirectoryPath(projectFilePath || normalizeSlashes(externalProjectName)));
|
||||
this.enableGlobalPlugins(this.getCompilerOptions(), pluginConfigOverrides);
|
||||
}
|
||||
|
||||
updateGraph() {
|
||||
|
||||
@@ -1392,6 +1392,9 @@ namespace ts.server.protocol {
|
||||
arguments: ConfigurePluginRequestArguments;
|
||||
}
|
||||
|
||||
export interface ConfigurePluginResponse extends Response {
|
||||
}
|
||||
|
||||
/**
|
||||
* Information found in an "open" request.
|
||||
*/
|
||||
|
||||
@@ -2412,6 +2412,7 @@ namespace ts.server {
|
||||
},
|
||||
[CommandNames.ConfigurePlugin]: (request: protocol.ConfigurePluginRequest) => {
|
||||
this.configurePlugin(request.arguments);
|
||||
this.doOutput(/*info*/ undefined, CommandNames.ConfigurePlugin, request.seq, /*success*/ true);
|
||||
return this.notRequired();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -10,6 +10,7 @@ interface ExecResult {
|
||||
|
||||
interface UserConfig {
|
||||
types: string[];
|
||||
path?: string;
|
||||
}
|
||||
|
||||
abstract class ExternalCompileRunnerBase extends RunnerBase {
|
||||
@@ -57,7 +58,7 @@ abstract class ExternalCompileRunnerBase extends RunnerBase {
|
||||
ts.Debug.assert(!!config.types, "Bad format from test.json: Types field must be present.");
|
||||
types = config.types;
|
||||
|
||||
cwd = submoduleDir;
|
||||
cwd = config.path ? path.join(cwd, config.path) : submoduleDir;
|
||||
}
|
||||
if (fs.existsSync(path.join(cwd, "package.json"))) {
|
||||
if (fs.existsSync(path.join(cwd, "package-lock.json"))) {
|
||||
|
||||
@@ -365,6 +365,26 @@ namespace ts {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("parse --incremental", () => {
|
||||
// --lib es6 0.ts
|
||||
assertParseResult(["--incremental", "0.ts"],
|
||||
{
|
||||
errors: [],
|
||||
fileNames: ["0.ts"],
|
||||
options: { incremental: true }
|
||||
});
|
||||
});
|
||||
|
||||
it("parse --tsBuildInfoFile", () => {
|
||||
// --lib es6 0.ts
|
||||
assertParseResult(["--tsBuildInfoFile", "build.tsbuildinfo", "0.ts"],
|
||||
{
|
||||
errors: [],
|
||||
fileNames: ["0.ts"],
|
||||
options: { tsBuildInfoFile: "build.tsbuildinfo" }
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("unittests:: config:: commandLineParsing:: parseBuildOptions", () => {
|
||||
@@ -456,6 +476,33 @@ namespace ts {
|
||||
});
|
||||
});
|
||||
|
||||
it("parse build with --incremental", () => {
|
||||
// --lib es6 0.ts
|
||||
assertParseResult(["--incremental", "tests"],
|
||||
{
|
||||
errors: [],
|
||||
projects: ["tests"],
|
||||
buildOptions: { incremental: true }
|
||||
});
|
||||
});
|
||||
|
||||
it("parse build with --tsBuildInfoFile", () => {
|
||||
// --lib es6 0.ts
|
||||
assertParseResult(["--tsBuildInfoFile", "build.tsbuildinfo", "tests"],
|
||||
{
|
||||
errors: [{
|
||||
messageText: "Unknown build option '--tsBuildInfoFile'.",
|
||||
category: Diagnostics.Unknown_build_option_0.category,
|
||||
code: Diagnostics.Unknown_build_option_0.code,
|
||||
file: undefined,
|
||||
start: undefined,
|
||||
length: undefined
|
||||
}],
|
||||
projects: ["build.tsbuildinfo", "tests"],
|
||||
buildOptions: { }
|
||||
});
|
||||
});
|
||||
|
||||
describe("Combining options that make no sense together", () => {
|
||||
function verifyInvalidCombination(flag1: keyof BuildOptions, flag2: keyof BuildOptions) {
|
||||
it(`--${flag1} and --${flag2} together is invalid`, () => {
|
||||
|
||||
@@ -445,5 +445,13 @@ var x = 0;`, {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
transpilesCorrectly("Supports readonly keyword for arrays", "let x: readonly string[];", {
|
||||
options: { compilerOptions: { module: ModuleKind.CommonJS } }
|
||||
});
|
||||
|
||||
transpilesCorrectly("Supports 'as const' arrays", `([] as const).forEach(k => console.log(k));`, {
|
||||
options: { compilerOptions: { module: ModuleKind.CommonJS } }
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -198,6 +198,58 @@ ${internal} export enum internalEnum { a, b, c }`);
|
||||
modifyAgainFs: fs => replaceText(fs, sources[project.lib][source.ts][1], `export const`, `/*@internal*/ export const`),
|
||||
});
|
||||
});
|
||||
|
||||
describe("when the module resolution finds original source file", () => {
|
||||
function modifyFs(fs: vfs.FileSystem) {
|
||||
// Make lib to output to parent dir
|
||||
replaceText(fs, sources[project.lib][source.config], `"outFile": "module.js"`, `"outFile": "../module.js", "rootDir": "../"`);
|
||||
// Change reference to file1 module to resolve to lib/file1
|
||||
replaceText(fs, sources[project.app][source.ts][0], "file1", "lib/file1");
|
||||
}
|
||||
|
||||
const libOutputFile: OutputFile = [
|
||||
"/src/lib/module.js",
|
||||
"/src/lib/module.js.map",
|
||||
"/src/lib/module.d.ts",
|
||||
"/src/lib/module.d.ts.map",
|
||||
"/src/lib/module.tsbuildinfo"
|
||||
];
|
||||
verifyTsbuildOutput({
|
||||
scenario: "when the module resolution finds original source file",
|
||||
projFs: () => outFileFs,
|
||||
time,
|
||||
tick,
|
||||
proj: "amdModulesWithOut",
|
||||
rootNames: ["/src/app"],
|
||||
expectedMapFileNames: [
|
||||
libOutputFile[ext.jsmap],
|
||||
libOutputFile[ext.dtsmap],
|
||||
outputFiles[project.app][ext.jsmap],
|
||||
outputFiles[project.app][ext.dtsmap],
|
||||
],
|
||||
expectedBuildInfoFilesForSectionBaselines: [
|
||||
[libOutputFile[ext.buildinfo], libOutputFile[ext.js], libOutputFile[ext.dts]],
|
||||
[outputFiles[project.app][ext.buildinfo], outputFiles[project.app][ext.js], outputFiles[project.app][ext.dts]]
|
||||
],
|
||||
lastProjectOutputJs: outputFiles[project.app][ext.js],
|
||||
initialBuild: {
|
||||
modifyFs,
|
||||
expectedDiagnostics: [
|
||||
getExpectedDiagnosticForProjectsInBuild("src/lib/tsconfig.json", "src/app/tsconfig.json"),
|
||||
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/lib/tsconfig.json", "src/module.js"],
|
||||
[Diagnostics.Building_project_0, sources[project.lib][source.config]],
|
||||
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/app/tsconfig.json", "src/app/module.js"],
|
||||
[Diagnostics.Building_project_0, sources[project.app][source.config]],
|
||||
]
|
||||
},
|
||||
outputFiles: [
|
||||
...libOutputFile,
|
||||
...outputFiles[project.app]
|
||||
],
|
||||
baselineOnly: true,
|
||||
verifyDiagnostics: true
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -234,10 +234,11 @@ Mismatch Actual(path, actual, expected): ${JSON.stringify(arrayFrom(mapDefinedIt
|
||||
incrementalDtsUnchangedBuild?: BuildState;
|
||||
incrementalHeaderChangedBuild?: BuildState;
|
||||
baselineOnly?: true;
|
||||
verifyDiagnostics?: true;
|
||||
}
|
||||
|
||||
export function verifyTsbuildOutput({
|
||||
scenario, projFs, time, tick, proj, rootNames, outputFiles, baselineOnly,
|
||||
scenario, projFs, time, tick, proj, rootNames, outputFiles, baselineOnly, verifyDiagnostics,
|
||||
expectedMapFileNames, expectedBuildInfoFilesForSectionBaselines, lastProjectOutputJs,
|
||||
initialBuild, incrementalDtsChangedBuild, incrementalDtsUnchangedBuild, incrementalHeaderChangedBuild
|
||||
}: VerifyTsBuildInput) {
|
||||
@@ -264,7 +265,7 @@ Mismatch Actual(path, actual, expected): ${JSON.stringify(arrayFrom(mapDefinedIt
|
||||
host = undefined!;
|
||||
});
|
||||
describe("initialBuild", () => {
|
||||
if (!baselineOnly) {
|
||||
if (!baselineOnly || verifyDiagnostics) {
|
||||
it(`verify diagnostics`, () => {
|
||||
host.assertDiagnosticMessages(...(initialBuild.expectedDiagnostics || emptyArray));
|
||||
});
|
||||
|
||||
@@ -197,8 +197,8 @@ namespace ts {
|
||||
dtsUnchangedExpectedReadFilesDependOrdered = undefined!;
|
||||
});
|
||||
|
||||
function createSolutionBuilder(host: fakes.SolutionBuilderHost) {
|
||||
return ts.createSolutionBuilder(host, ["/src/third"], { dry: false, force: false, verbose: true });
|
||||
function createSolutionBuilder(host: fakes.SolutionBuilderHost, baseOptions?: BuildOptions) {
|
||||
return ts.createSolutionBuilder(host, ["/src/third"], { dry: false, force: false, verbose: true, ...(baseOptions || {}) });
|
||||
}
|
||||
|
||||
function getInitialExpectedReadFiles(additionalSourceFiles?: ReadonlyArray<string>) {
|
||||
@@ -446,6 +446,49 @@ namespace ts {
|
||||
);
|
||||
});
|
||||
|
||||
it("rebuilds completely when command line incremental flag changes between non dts changes", () => {
|
||||
const fs = outFileFs.shadow();
|
||||
// Make non composite third project
|
||||
replaceText(fs, sources[project.third][source.config], `"composite": true,`, "");
|
||||
|
||||
// Build with command line incremental
|
||||
const host = new fakes.SolutionBuilderHost(fs);
|
||||
const builder = createSolutionBuilder(host, { incremental: true });
|
||||
builder.buildAllProjects();
|
||||
host.assertDiagnosticMessages(...initialExpectedDiagnostics);
|
||||
host.clearDiagnostics();
|
||||
tick();
|
||||
|
||||
// Make non incremental build with change in file that doesnt affect dts
|
||||
appendText(fs, relSources[project.first][source.ts][part.one], "console.log(s);");
|
||||
builder.resetBuildContext({ verbose: true });
|
||||
builder.buildAllProjects();
|
||||
host.assertDiagnosticMessages(getExpectedDiagnosticForProjectsInBuild(relSources[project.first][source.config], relSources[project.second][source.config], relSources[project.third][source.config]),
|
||||
[Diagnostics.Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2, relSources[project.first][source.config], relOutputFiles[project.first][ext.js], relSources[project.first][source.ts][part.one]],
|
||||
[Diagnostics.Building_project_0, sources[project.first][source.config]],
|
||||
[Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, relSources[project.second][source.config], relSources[project.second][source.ts][part.one], relOutputFiles[project.second][ext.js]],
|
||||
[Diagnostics.Project_0_is_out_of_date_because_output_of_its_dependency_1_has_changed, relSources[project.third][source.config], "src/first"],
|
||||
[Diagnostics.Building_project_0, sources[project.third][source.config]]
|
||||
);
|
||||
host.clearDiagnostics();
|
||||
tick();
|
||||
|
||||
// Make incremental build with change in file that doesnt affect dts
|
||||
appendText(fs, relSources[project.first][source.ts][part.one], "console.log(s);");
|
||||
builder.resetBuildContext({ verbose: true, incremental: true });
|
||||
builder.buildAllProjects();
|
||||
// Builds completely because tsbuildinfo is old.
|
||||
host.assertDiagnosticMessages(
|
||||
getExpectedDiagnosticForProjectsInBuild(relSources[project.first][source.config], relSources[project.second][source.config], relSources[project.third][source.config]),
|
||||
[Diagnostics.Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2, relSources[project.first][source.config], relOutputFiles[project.first][ext.js], relSources[project.first][source.ts][part.one]],
|
||||
[Diagnostics.Building_project_0, sources[project.first][source.config]],
|
||||
[Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, relSources[project.second][source.config], relSources[project.second][source.ts][part.one], relOutputFiles[project.second][ext.js]],
|
||||
[Diagnostics.Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2, relSources[project.third][source.config], relOutputFiles[project.third][ext.buildinfo], "src/first"],
|
||||
[Diagnostics.Building_project_0, sources[project.third][source.config]]
|
||||
);
|
||||
host.clearDiagnostics();
|
||||
});
|
||||
|
||||
describe("Prepend output with .tsbuildinfo", () => {
|
||||
// Prologues
|
||||
describe("Prologues", () => {
|
||||
|
||||
@@ -427,14 +427,14 @@ export class cNew {}`);
|
||||
builder.buildAllProjects();
|
||||
assert.deepEqual(host.traces, [
|
||||
"TSFILE: /src/core/anotherModule.js",
|
||||
"TSFILE: /src/core/anotherModule.d.ts",
|
||||
"TSFILE: /src/core/anotherModule.d.ts.map",
|
||||
"TSFILE: /src/core/anotherModule.d.ts",
|
||||
"TSFILE: /src/core/index.js",
|
||||
"TSFILE: /src/core/index.d.ts",
|
||||
"TSFILE: /src/core/index.d.ts.map",
|
||||
"TSFILE: /src/core/index.d.ts",
|
||||
"TSFILE: /src/core/tsconfig.tsbuildinfo",
|
||||
"TSFILE: /src/logic/index.js",
|
||||
"TSFILE: /src/logic/index.js.map",
|
||||
"TSFILE: /src/logic/index.js",
|
||||
"TSFILE: /src/logic/index.d.ts",
|
||||
"TSFILE: /src/logic/tsconfig.tsbuildinfo",
|
||||
"TSFILE: /src/tests/index.js",
|
||||
|
||||
@@ -65,6 +65,8 @@ export const b = new A();`);
|
||||
const expectedFileTraces = [
|
||||
...getLibs(),
|
||||
"/src/a.ts",
|
||||
...getLibs(),
|
||||
"/src/b.ts"
|
||||
];
|
||||
verifyBuild(fs => modifyFsBTsToNonRelativeImport(fs, "node"),
|
||||
allExpectedOutputs,
|
||||
|
||||
@@ -50,6 +50,68 @@ namespace ts.projectSystem {
|
||||
});
|
||||
});
|
||||
|
||||
it("load global plugins", () => {
|
||||
const f1 = {
|
||||
path: "/a/file1.ts",
|
||||
content: "let x = [1, 2];"
|
||||
};
|
||||
const p1 = { projectFileName: "/a/proj1.csproj", rootFiles: [toExternalFile(f1.path)], options: {} };
|
||||
|
||||
const host = createServerHost([f1]);
|
||||
host.require = (_initialPath, moduleName) => {
|
||||
assert.equal(moduleName, "myplugin");
|
||||
return {
|
||||
module: () => ({
|
||||
create(info: server.PluginCreateInfo) {
|
||||
const proxy = Harness.LanguageService.makeDefaultProxy(info);
|
||||
proxy.getSemanticDiagnostics = filename => {
|
||||
const prev = info.languageService.getSemanticDiagnostics(filename);
|
||||
const sourceFile: SourceFile = info.project.getSourceFile(toPath(filename, /*basePath*/ undefined, createGetCanonicalFileName(info.serverHost.useCaseSensitiveFileNames)))!;
|
||||
prev.push({
|
||||
category: DiagnosticCategory.Warning,
|
||||
file: sourceFile,
|
||||
code: 9999,
|
||||
length: 3,
|
||||
messageText: `Plugin diagnostic`,
|
||||
start: 0
|
||||
});
|
||||
return prev;
|
||||
};
|
||||
return proxy;
|
||||
}
|
||||
}),
|
||||
error: undefined
|
||||
};
|
||||
};
|
||||
const session = createSession(host, { globalPlugins: ["myplugin"] });
|
||||
|
||||
session.executeCommand(<protocol.OpenExternalProjectsRequest>{
|
||||
seq: 1,
|
||||
type: "request",
|
||||
command: "openExternalProjects",
|
||||
arguments: { projects: [p1] }
|
||||
});
|
||||
|
||||
const projectService = session.getProjectService();
|
||||
checkNumberOfProjects(projectService, { externalProjects: 1 });
|
||||
assert.equal(projectService.externalProjects[0].getProjectName(), p1.projectFileName);
|
||||
|
||||
const handlerResponse = session.executeCommand(<protocol.SemanticDiagnosticsSyncRequest>{
|
||||
seq: 2,
|
||||
type: "request",
|
||||
command: "semanticDiagnosticsSync",
|
||||
arguments: {
|
||||
file: f1.path,
|
||||
projectFileName: p1.projectFileName
|
||||
}
|
||||
});
|
||||
|
||||
assert.isDefined(handlerResponse.response);
|
||||
const response = handlerResponse.response as protocol.Diagnostic[];
|
||||
assert.equal(response.length, 1);
|
||||
assert.equal(response[0].text, "Plugin diagnostic");
|
||||
});
|
||||
|
||||
it("remove not-listed external projects", () => {
|
||||
const f1 = {
|
||||
path: "/a/app.ts",
|
||||
|
||||
@@ -479,6 +479,90 @@ namespace ts.projectSystem {
|
||||
session.clearMessages();
|
||||
}
|
||||
});
|
||||
|
||||
it("Correct errors when resolution resolves to file that has same ambient module and is also module", () => {
|
||||
const projectRootPath = "/users/username/projects/myproject";
|
||||
const aFile: File = {
|
||||
path: `${projectRootPath}/src/a.ts`,
|
||||
content: `import * as myModule from "@custom/plugin";
|
||||
function foo() {
|
||||
// hello
|
||||
}`
|
||||
};
|
||||
const config: File = {
|
||||
path: `${projectRootPath}/tsconfig.json`,
|
||||
content: JSON.stringify({ include: ["src"] })
|
||||
};
|
||||
const plugin: File = {
|
||||
path: `${projectRootPath}/node_modules/@custom/plugin/index.d.ts`,
|
||||
content: `import './proposed';
|
||||
declare module '@custom/plugin' {
|
||||
export const version: string;
|
||||
}`
|
||||
};
|
||||
const pluginProposed: File = {
|
||||
path: `${projectRootPath}/node_modules/@custom/plugin/proposed.d.ts`,
|
||||
content: `declare module '@custom/plugin' {
|
||||
export const bar = 10;
|
||||
}`
|
||||
};
|
||||
const files = [libFile, aFile, config, plugin, pluginProposed];
|
||||
const host = createServerHost(files);
|
||||
const session = createSession(host, { canUseEvents: true });
|
||||
const service = session.getProjectService();
|
||||
openFilesForSession([aFile], session);
|
||||
|
||||
checkNumberOfProjects(service, { configuredProjects: 1 });
|
||||
session.clearMessages();
|
||||
checkErrors();
|
||||
|
||||
session.executeCommandSeq<protocol.ChangeRequest>({
|
||||
command: protocol.CommandTypes.Change,
|
||||
arguments: {
|
||||
file: aFile.path,
|
||||
line: 3,
|
||||
offset: 8,
|
||||
endLine: 3,
|
||||
endOffset: 8,
|
||||
insertString: "o"
|
||||
}
|
||||
});
|
||||
checkErrors();
|
||||
|
||||
function checkErrors() {
|
||||
host.checkTimeoutQueueLength(0);
|
||||
const expectedSequenceId = session.getNextSeq();
|
||||
session.executeCommandSeq<protocol.GeterrRequest>({
|
||||
command: server.CommandNames.Geterr,
|
||||
arguments: {
|
||||
delay: 0,
|
||||
files: [aFile.path],
|
||||
}
|
||||
});
|
||||
|
||||
host.checkTimeoutQueueLengthAndRun(1);
|
||||
|
||||
checkErrorMessage(session, "syntaxDiag", { file: aFile.path, diagnostics: [] }, /*isMostRecent*/ true);
|
||||
session.clearMessages();
|
||||
|
||||
host.runQueuedImmediateCallbacks(1);
|
||||
|
||||
checkErrorMessage(session, "semanticDiag", { file: aFile.path, diagnostics: [] });
|
||||
session.clearMessages();
|
||||
|
||||
host.runQueuedImmediateCallbacks(1);
|
||||
|
||||
checkErrorMessage(session, "suggestionDiag", {
|
||||
file: aFile.path,
|
||||
diagnostics: [
|
||||
createDiagnostic({ line: 1, offset: 1 }, { line: 1, offset: 44 }, Diagnostics._0_is_declared_but_its_value_is_never_read, ["myModule"], "suggestion", /*reportsUnnecessary*/ true),
|
||||
createDiagnostic({ line: 2, offset: 10 }, { line: 2, offset: 13 }, Diagnostics._0_is_declared_but_its_value_is_never_read, ["foo"], "suggestion", /*reportsUnnecessary*/ true)
|
||||
],
|
||||
});
|
||||
checkCompleteEvent(session, 2, expectedSequenceId);
|
||||
session.clearMessages();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("unittests:: tsserver:: Project Errors for Configure file diagnostics events", () => {
|
||||
|
||||
@@ -165,6 +165,9 @@ namespace ts {
|
||||
reportWatchModeWithoutSysSupport();
|
||||
createWatchOfFilesAndCompilerOptions(commandLine.fileNames, commandLineOptions);
|
||||
}
|
||||
else if (isIncrementalCompilation(commandLineOptions)) {
|
||||
performIncrementalCompilation(commandLine);
|
||||
}
|
||||
else {
|
||||
performCompilation(commandLine.fileNames, /*references*/ undefined, commandLineOptions);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user