mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'master' into codefix_add_missing_new_operator
This commit is contained in:
@@ -75,6 +75,7 @@
|
||||
"gulp-typescript": "latest",
|
||||
"istanbul": "latest",
|
||||
"jake": "latest",
|
||||
"lodash": "4.17.10",
|
||||
"merge2": "latest",
|
||||
"minimist": "latest",
|
||||
"mkdirp": "latest",
|
||||
|
||||
@@ -2465,7 +2465,7 @@ namespace ts {
|
||||
node.left.parent = node;
|
||||
node.right.parent = node;
|
||||
const lhs = node.left as PropertyAccessEntityNameExpression;
|
||||
bindPropertyAssignment(lhs, lhs, /*isPrototypeProperty*/ false);
|
||||
bindPropertyAssignment(lhs.expression, lhs, /*isPrototypeProperty*/ false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2522,7 +2522,7 @@ namespace ts {
|
||||
const isToplevel = isBinaryExpression(propertyAccess.parent)
|
||||
? getParentOfBinaryExpression(propertyAccess.parent).parent.kind === SyntaxKind.SourceFile
|
||||
: propertyAccess.parent.parent.kind === SyntaxKind.SourceFile;
|
||||
if (!isPrototypeProperty && (!namespaceSymbol || !(namespaceSymbol.flags & SymbolFlags.Namespace)) && isToplevel) {
|
||||
if (isToplevel && !isPrototypeProperty && (!namespaceSymbol || !(namespaceSymbol.flags & SymbolFlags.Namespace))) {
|
||||
// make symbols or add declarations for intermediate containers
|
||||
const flags = SymbolFlags.Module | SymbolFlags.Assignment;
|
||||
const excludeFlags = SymbolFlags.ValueModuleExcludes & ~SymbolFlags.Assignment;
|
||||
|
||||
@@ -88,7 +88,7 @@ namespace ts.BuilderState {
|
||||
function getReferencedFileFromImportedModuleSymbol(symbol: Symbol) {
|
||||
if (symbol.declarations && symbol.declarations[0]) {
|
||||
const declarationSourceFile = getSourceFileOfNode(symbol.declarations[0]);
|
||||
return declarationSourceFile && declarationSourceFile.path;
|
||||
return declarationSourceFile && (declarationSourceFile.resolvedPath || declarationSourceFile.path);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,6 +100,13 @@ namespace ts.BuilderState {
|
||||
return symbol && getReferencedFileFromImportedModuleSymbol(symbol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the path to reference file from file name, it could be resolvedPath if present otherwise path
|
||||
*/
|
||||
function getReferencedFileFromFileName(program: Program, fileName: string, sourceFileDirectory: Path, getCanonicalFileName: GetCanonicalFileName): Path {
|
||||
return toPath(program.getProjectReferenceRedirect(fileName) || fileName, sourceFileDirectory, getCanonicalFileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the referenced files for a file from the program with values for the keys as referenced file's path to be true
|
||||
*/
|
||||
@@ -123,7 +130,7 @@ namespace ts.BuilderState {
|
||||
// Handle triple slash references
|
||||
if (sourceFile.referencedFiles && sourceFile.referencedFiles.length > 0) {
|
||||
for (const referencedFile of sourceFile.referencedFiles) {
|
||||
const referencedPath = toPath(referencedFile.fileName, sourceFileDirectory, getCanonicalFileName);
|
||||
const referencedPath = getReferencedFileFromFileName(program, referencedFile.fileName, sourceFileDirectory, getCanonicalFileName);
|
||||
addReferencedFile(referencedPath);
|
||||
}
|
||||
}
|
||||
@@ -136,7 +143,7 @@ namespace ts.BuilderState {
|
||||
}
|
||||
|
||||
const fileName = resolvedTypeReferenceDirective.resolvedFileName!; // TODO: GH#18217
|
||||
const typeFilePath = toPath(fileName, sourceFileDirectory, getCanonicalFileName);
|
||||
const typeFilePath = getReferencedFileFromFileName(program, fileName, sourceFileDirectory, getCanonicalFileName);
|
||||
addReferencedFile(typeFilePath);
|
||||
});
|
||||
}
|
||||
|
||||
+149
-57
@@ -601,6 +601,8 @@ namespace ts {
|
||||
FunctionFacts = FunctionStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull | Falsy,
|
||||
UndefinedFacts = TypeofNEString | TypeofNENumber | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | EQUndefined | EQUndefinedOrNull | NENull | Falsy,
|
||||
NullFacts = TypeofEQObject | TypeofNEString | TypeofNENumber | TypeofNEBoolean | TypeofNESymbol | TypeofNEFunction | TypeofNEHostObject | EQNull | EQUndefinedOrNull | NEUndefined | Falsy,
|
||||
EmptyObjectStrictFacts = All & ~(EQUndefined | EQNull | EQUndefinedOrNull),
|
||||
EmptyObjectFacts = All,
|
||||
}
|
||||
|
||||
const typeofEQFacts = createMapFromTemplate({
|
||||
@@ -640,7 +642,7 @@ namespace ts {
|
||||
const identityRelation = createMap<RelationComparisonResult>();
|
||||
const enumRelation = createMap<RelationComparisonResult>();
|
||||
|
||||
type TypeSystemEntity = Symbol | Type | Signature;
|
||||
type TypeSystemEntity = Node | Symbol | Type | Signature;
|
||||
|
||||
const enum TypeSystemPropertyName {
|
||||
Type,
|
||||
@@ -648,6 +650,7 @@ namespace ts {
|
||||
DeclaredType,
|
||||
ResolvedReturnType,
|
||||
ImmediateBaseConstraint,
|
||||
EnumTagType,
|
||||
}
|
||||
|
||||
const enum CheckMode {
|
||||
@@ -3470,8 +3473,8 @@ namespace ts {
|
||||
const arity = getTypeReferenceArity(type);
|
||||
const tupleConstituentNodes = mapToTypeNodes(typeArguments.slice(0, arity), context);
|
||||
const hasRestElement = (<TupleType>type.target).hasRestElement;
|
||||
if (tupleConstituentNodes && tupleConstituentNodes.length > 0) {
|
||||
for (let i = (<TupleType>type.target).minLength; i < arity; i++) {
|
||||
if (tupleConstituentNodes) {
|
||||
for (let i = (<TupleType>type.target).minLength; i < Math.min(arity, tupleConstituentNodes.length); i++) {
|
||||
tupleConstituentNodes[i] = hasRestElement && i === arity - 1 ?
|
||||
createRestTypeNode(createArrayTypeNode(tupleConstituentNodes[i])) :
|
||||
createOptionalTypeNode(tupleConstituentNodes[i]);
|
||||
@@ -4475,6 +4478,8 @@ namespace ts {
|
||||
switch (propertyName) {
|
||||
case TypeSystemPropertyName.Type:
|
||||
return !!getSymbolLinks(<Symbol>target).type;
|
||||
case TypeSystemPropertyName.EnumTagType:
|
||||
return !!(getNodeLinks(target as JSDocEnumTag).resolvedEnumType);
|
||||
case TypeSystemPropertyName.DeclaredType:
|
||||
return !!getSymbolLinks(<Symbol>target).declaredType;
|
||||
case TypeSystemPropertyName.ResolvedBaseConstructorType:
|
||||
@@ -8252,9 +8257,18 @@ namespace ts {
|
||||
}
|
||||
|
||||
// JS are 'string' or 'number', not an enum type.
|
||||
const enumTag = symbol.valueDeclaration && getJSDocEnumTag(symbol.valueDeclaration);
|
||||
const enumTag = isInJSFile(node) && symbol.valueDeclaration && getJSDocEnumTag(symbol.valueDeclaration);
|
||||
if (enumTag) {
|
||||
return enumTag.typeExpression ? getTypeFromTypeNode(enumTag.typeExpression) : errorType;
|
||||
const links = getNodeLinks(enumTag);
|
||||
if (!pushTypeResolution(enumTag, TypeSystemPropertyName.EnumTagType)) {
|
||||
return errorType;
|
||||
}
|
||||
let type = enumTag.typeExpression ? getTypeFromTypeNode(enumTag.typeExpression) : errorType;
|
||||
if (!popTypeResolution()) {
|
||||
type = errorType;
|
||||
error(node, Diagnostics.Enum_type_0_circularly_references_itself, symbolToString(symbol));
|
||||
}
|
||||
return (links.resolvedEnumType = type);
|
||||
}
|
||||
|
||||
// Get type from reference to named type that cannot be generic (enum or type parameter)
|
||||
@@ -10624,6 +10638,8 @@ namespace ts {
|
||||
return elaborateArrayLiteral(node as ArrayLiteralExpression, source, target, relation);
|
||||
case SyntaxKind.JsxAttributes:
|
||||
return elaborateJsxAttributes(node as JsxAttributes, source, target, relation);
|
||||
case SyntaxKind.ArrowFunction:
|
||||
return elaborateArrowFunction(node as ArrowFunction, source, target, relation);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -10649,6 +10665,46 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
function elaborateArrowFunction(node: ArrowFunction, source: Type, target: Type, relation: Map<RelationComparisonResult>): boolean {
|
||||
// Don't elaborate blocks
|
||||
if (isBlock(node.body)) {
|
||||
return false;
|
||||
}
|
||||
// Or functions with annotated parameter types
|
||||
if (some(node.parameters, ts.hasType)) {
|
||||
return false;
|
||||
}
|
||||
const sourceSig = getSingleCallSignature(source);
|
||||
if (!sourceSig) {
|
||||
return false;
|
||||
}
|
||||
const targetSignatures = getSignaturesOfType(target, SignatureKind.Call);
|
||||
if (!length(targetSignatures)) {
|
||||
return false;
|
||||
}
|
||||
const returnExpression = node.body;
|
||||
const sourceReturn = getReturnTypeOfSignature(sourceSig);
|
||||
const targetReturn = getUnionType(map(targetSignatures, getReturnTypeOfSignature));
|
||||
if (!checkTypeRelatedTo(sourceReturn, targetReturn, relation, /*errorNode*/ undefined)) {
|
||||
const elaborated = returnExpression && elaborateError(returnExpression, sourceReturn, targetReturn, relation, /*headMessage*/ undefined);
|
||||
if (elaborated) {
|
||||
return elaborated;
|
||||
}
|
||||
const resultObj: { error?: Diagnostic } = {};
|
||||
checkTypeRelatedTo(sourceReturn, targetReturn, relation, returnExpression, /*message*/ undefined, /*chain*/ undefined, resultObj);
|
||||
if (resultObj.error) {
|
||||
if (target.symbol && length(target.symbol.declarations)) {
|
||||
addRelatedInfo(resultObj.error, createDiagnosticForNode(
|
||||
target.symbol.declarations[0],
|
||||
Diagnostics.The_expected_type_comes_from_the_return_type_of_this_signature,
|
||||
));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
type ElaborationIterator = IterableIterator<{ errorNode: Node, innerExpression: Expression | undefined, nameType: Type, errorMessage?: DiagnosticMessage | undefined }>;
|
||||
/**
|
||||
* For every element returned from the iterator, checks that element to issue an error on a property of that element's type
|
||||
@@ -10662,7 +10718,7 @@ namespace ts {
|
||||
const { errorNode: prop, innerExpression: next, nameType, errorMessage } = status.value;
|
||||
const sourcePropType = getIndexedAccessType(source, nameType, /*accessNode*/ undefined, errorType);
|
||||
const targetPropType = getIndexedAccessType(target, nameType, /*accessNode*/ undefined, errorType);
|
||||
if (sourcePropType !== errorType && targetPropType !== errorType && !isTypeAssignableTo(sourcePropType, targetPropType)) {
|
||||
if (sourcePropType !== errorType && targetPropType !== errorType && !checkTypeRelatedTo(sourcePropType, targetPropType, relation, /*errorNode*/ undefined)) {
|
||||
const elaborated = next && elaborateError(next, sourcePropType, targetPropType, relation, /*headMessage*/ undefined);
|
||||
if (elaborated) {
|
||||
reportedError = true;
|
||||
@@ -10687,19 +10743,22 @@ namespace ts {
|
||||
const indexInfo = isTypeAssignableToKind(nameType, TypeFlags.NumberLike) && getIndexInfoOfType(target, IndexKind.Number) ||
|
||||
getIndexInfoOfType(target, IndexKind.String) ||
|
||||
undefined;
|
||||
if (indexInfo && indexInfo.declaration) {
|
||||
if (indexInfo && indexInfo.declaration && !getSourceFileOfNode(indexInfo.declaration).hasNoDefaultLib) {
|
||||
issuedElaboration = true;
|
||||
addRelatedInfo(reportedDiag, createDiagnosticForNode(indexInfo.declaration, Diagnostics.The_expected_type_comes_from_this_index_signature));
|
||||
}
|
||||
}
|
||||
|
||||
if (!issuedElaboration && (targetProp && length(targetProp.declarations) || target.symbol && length(target.symbol.declarations))) {
|
||||
addRelatedInfo(reportedDiag, createDiagnosticForNode(
|
||||
targetProp && length(targetProp.declarations) ? targetProp.declarations[0] : target.symbol.declarations[0],
|
||||
Diagnostics.The_expected_type_comes_from_property_0_which_is_declared_here_on_type_1,
|
||||
propertyName && !(nameType.flags & TypeFlags.UniqueESSymbol) ? unescapeLeadingUnderscores(propertyName) : typeToString(nameType),
|
||||
typeToString(target)
|
||||
));
|
||||
const targetNode = targetProp && length(targetProp.declarations) ? targetProp.declarations[0] : target.symbol.declarations[0];
|
||||
if (!getSourceFileOfNode(targetNode).hasNoDefaultLib) {
|
||||
addRelatedInfo(reportedDiag, createDiagnosticForNode(
|
||||
targetNode,
|
||||
Diagnostics.The_expected_type_comes_from_property_0_which_is_declared_here_on_type_1,
|
||||
propertyName && !(nameType.flags & TypeFlags.UniqueESSymbol) ? unescapeLeadingUnderscores(propertyName) : typeToString(nameType),
|
||||
typeToString(target)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
reportedError = true;
|
||||
@@ -10738,6 +10797,11 @@ namespace ts {
|
||||
if (isTupleLikeType(source)) {
|
||||
return elaborateElementwise(generateLimitedTupleElements(node, target), source, target, relation);
|
||||
}
|
||||
// recreate a tuple from the elements, if possible
|
||||
const tupleizedType = checkArrayLiteral(node, CheckMode.Contextual, /*forceTuple*/ true);
|
||||
if (isTupleLikeType(tupleizedType)) {
|
||||
return elaborateElementwise(generateLimitedTupleElements(node, target), tupleizedType, target, relation);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -11774,8 +11838,12 @@ namespace ts {
|
||||
const simplified = getSimplifiedType((<IndexType>target).type);
|
||||
const constraint = simplified !== (<IndexType>target).type ? simplified : getConstraintOfType((<IndexType>target).type);
|
||||
if (constraint) {
|
||||
if (result = isRelatedTo(source, getIndexType(constraint, (target as IndexType).stringsOnly), reportErrors)) {
|
||||
return result;
|
||||
// We require Ternary.True here such that circular constraints don't cause
|
||||
// false positives. For example, given 'T extends { [K in keyof T]: string }',
|
||||
// 'keyof T' has itself as its constraint and produces a Ternary.Maybe when
|
||||
// related to other types.
|
||||
if (isRelatedTo(source, getIndexType(constraint, (target as IndexType).stringsOnly), reportErrors) === Ternary.True) {
|
||||
return Ternary.True;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13373,7 +13441,7 @@ namespace ts {
|
||||
let propagationType: Type;
|
||||
inferFromTypes(originalSource, originalTarget);
|
||||
|
||||
function inferFromTypes(source: Type, target: Type) {
|
||||
function inferFromTypes(source: Type, target: Type): void {
|
||||
if (!couldContainTypeVariables(target)) {
|
||||
return;
|
||||
}
|
||||
@@ -13508,6 +13576,9 @@ namespace ts {
|
||||
inferFromTypes(getTrueTypeFromConditionalType(<ConditionalType>source), getTrueTypeFromConditionalType(<ConditionalType>target));
|
||||
inferFromTypes(getFalseTypeFromConditionalType(<ConditionalType>source), getFalseTypeFromConditionalType(<ConditionalType>target));
|
||||
}
|
||||
else if (target.flags & TypeFlags.Conditional) {
|
||||
inferFromTypes(source, getUnionType([getTrueTypeFromConditionalType(<ConditionalType>target), getFalseTypeFromConditionalType(<ConditionalType>target)]));
|
||||
}
|
||||
else if (target.flags & TypeFlags.UnionOrIntersection) {
|
||||
const targetTypes = (<UnionOrIntersectionType>target).types;
|
||||
let typeVariableCount = 0;
|
||||
@@ -13541,7 +13612,14 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
if (!(priority & InferencePriority.NoConstraints && source.flags & (TypeFlags.Intersection | TypeFlags.Instantiable))) {
|
||||
source = getApparentType(source);
|
||||
const apparentSource = getApparentType(source);
|
||||
// getApparentType can return _any_ type, since an indexed access or conditional may simplify to any other type.
|
||||
// If that occurs and it doesn't simplify to an object or intersection, we'll need to restart `inferFromTypes`
|
||||
// with the simplified source.
|
||||
if (apparentSource !== source && !(apparentSource.flags & (TypeFlags.Object | TypeFlags.Intersection))) {
|
||||
return inferFromTypes(apparentSource, target);
|
||||
}
|
||||
source = apparentSource;
|
||||
}
|
||||
if (source.flags & (TypeFlags.Object | TypeFlags.Intersection)) {
|
||||
const key = source.id + "," + target.id;
|
||||
@@ -13747,7 +13825,7 @@ namespace ts {
|
||||
|
||||
function hasPrimitiveConstraint(type: TypeParameter): boolean {
|
||||
const constraint = getConstraintOfTypeParameter(type);
|
||||
return !!constraint && maybeTypeOfKind(constraint, TypeFlags.Primitive | TypeFlags.Index);
|
||||
return !!constraint && maybeTypeOfKind(constraint.flags & TypeFlags.Conditional ? getDefaultConstraintOfConditionalType(constraint as ConditionalType) : constraint, TypeFlags.Primitive | TypeFlags.Index);
|
||||
}
|
||||
|
||||
function isObjectLiteralType(type: Type) {
|
||||
@@ -14169,9 +14247,11 @@ namespace ts {
|
||||
(type === falseType || type === regularFalseType) ? TypeFacts.FalseFacts : TypeFacts.TrueFacts;
|
||||
}
|
||||
if (flags & TypeFlags.Object) {
|
||||
return isFunctionObjectType(<ObjectType>type) ?
|
||||
strictNullChecks ? TypeFacts.FunctionStrictFacts : TypeFacts.FunctionFacts :
|
||||
strictNullChecks ? TypeFacts.ObjectStrictFacts : TypeFacts.ObjectFacts;
|
||||
return getObjectFlags(type) & ObjectFlags.Anonymous && isEmptyObjectType(<ObjectType>type) ?
|
||||
strictNullChecks ? TypeFacts.EmptyObjectStrictFacts : TypeFacts.EmptyObjectFacts :
|
||||
isFunctionObjectType(<ObjectType>type) ?
|
||||
strictNullChecks ? TypeFacts.FunctionStrictFacts : TypeFacts.FunctionFacts :
|
||||
strictNullChecks ? TypeFacts.ObjectStrictFacts : TypeFacts.ObjectFacts;
|
||||
}
|
||||
if (flags & (TypeFlags.Void | TypeFlags.Undefined)) {
|
||||
return TypeFacts.UndefinedFacts;
|
||||
@@ -14734,6 +14814,14 @@ namespace ts {
|
||||
// reference 'x.y.z', we may be at an assignment to 'x.y' or 'x'. In that case,
|
||||
// return the declared type.
|
||||
if (containsMatchingReference(reference, node)) {
|
||||
// A matching dotted name might also be an expando property on a function *expression*,
|
||||
// in which case we continue control flow analysis back to the function's declaration
|
||||
if (isVariableDeclaration(node) && (isInJSFile(node) || isVarConst(node))) {
|
||||
const init = getDeclaredExpandoInitializer(node);
|
||||
if (init && (init.kind === SyntaxKind.FunctionExpression || init.kind === SyntaxKind.ArrowFunction)) {
|
||||
return getTypeAtFlowNode(flow.antecedent);
|
||||
}
|
||||
}
|
||||
return declaredType;
|
||||
}
|
||||
// Assignment doesn't affect reference
|
||||
@@ -15083,23 +15171,24 @@ namespace ts {
|
||||
return getTypeWithFacts(assumeTrue ? mapType(type, narrowTypeForTypeof) : type, facts);
|
||||
|
||||
function narrowTypeForTypeof(type: Type) {
|
||||
if (assumeTrue && !(type.flags & TypeFlags.Union)) {
|
||||
if (type.flags & TypeFlags.Unknown && literal.text === "object") {
|
||||
return getUnionType([nonPrimitiveType, nullType]);
|
||||
if (type.flags & TypeFlags.Unknown && literal.text === "object") {
|
||||
return getUnionType([nonPrimitiveType, nullType]);
|
||||
}
|
||||
// We narrow a non-union type to an exact primitive type if the non-union type
|
||||
// is a supertype of that primitive type. For example, type 'any' can be narrowed
|
||||
// to one of the primitive types.
|
||||
const targetType = literal.text === "function" ? globalFunctionType : typeofTypesByName.get(literal.text);
|
||||
if (targetType) {
|
||||
if (isTypeSubtypeOf(type, targetType)) {
|
||||
return type;
|
||||
}
|
||||
// We narrow a non-union type to an exact primitive type if the non-union type
|
||||
// is a supertype of that primitive type. For example, type 'any' can be narrowed
|
||||
// to one of the primitive types.
|
||||
const targetType = literal.text === "function" ? globalFunctionType : typeofTypesByName.get(literal.text);
|
||||
if (targetType) {
|
||||
if (isTypeSubtypeOf(targetType, type)) {
|
||||
return isTypeAny(type) ? targetType : getIntersectionType([type, targetType]); // Intersection to handle `string` being a subtype of `keyof T`
|
||||
}
|
||||
if (type.flags & TypeFlags.Instantiable) {
|
||||
const constraint = getBaseConstraintOfType(type) || anyType;
|
||||
if (isTypeSubtypeOf(targetType, constraint)) {
|
||||
return getIntersectionType([type, targetType]);
|
||||
}
|
||||
if (isTypeSubtypeOf(targetType, type)) {
|
||||
return targetType;
|
||||
}
|
||||
if (type.flags & TypeFlags.Instantiable) {
|
||||
const constraint = getBaseConstraintOfType(type) || anyType;
|
||||
if (isTypeSubtypeOf(targetType, constraint)) {
|
||||
return getIntersectionType([type, targetType]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16951,7 +17040,7 @@ namespace ts {
|
||||
(node.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>node).operatorToken.kind === SyntaxKind.EqualsToken);
|
||||
}
|
||||
|
||||
function checkArrayLiteral(node: ArrayLiteralExpression, checkMode: CheckMode | undefined): Type {
|
||||
function checkArrayLiteral(node: ArrayLiteralExpression, checkMode: CheckMode | undefined, forceTuple: boolean | undefined): Type {
|
||||
const elements = node.elements;
|
||||
const elementCount = elements.length;
|
||||
let hasNonEndingSpreadElement = false;
|
||||
@@ -16973,7 +17062,7 @@ namespace ts {
|
||||
// get the contextual element type from it. So we do something similar to
|
||||
// getContextualTypeForElementExpression, which will crucially not error
|
||||
// if there is no index type / iterated type.
|
||||
const restArrayType = checkExpression((<SpreadElement>e).expression, checkMode);
|
||||
const restArrayType = checkExpression((<SpreadElement>e).expression, checkMode, forceTuple);
|
||||
const restElementType = getIndexTypeOfType(restArrayType, IndexKind.Number) ||
|
||||
getIteratedTypeOrElementType(restArrayType, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterables*/ false, /*checkAssignability*/ false);
|
||||
if (restElementType) {
|
||||
@@ -16982,7 +17071,7 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
const elementContextualType = getContextualTypeForElementExpression(contextualType, index);
|
||||
const type = checkExpressionForMutableLocation(e, checkMode, elementContextualType);
|
||||
const type = checkExpressionForMutableLocation(e, checkMode, elementContextualType, forceTuple);
|
||||
elementTypes.push(type);
|
||||
}
|
||||
if (index < elementCount - 1 && e.kind === SyntaxKind.SpreadElement) {
|
||||
@@ -17020,6 +17109,9 @@ namespace ts {
|
||||
}
|
||||
return createTupleType(elementTypes, minLength, hasRestElement);
|
||||
}
|
||||
else if (forceTuple) {
|
||||
return createTupleType(elementTypes, minLength, hasRestElement);
|
||||
}
|
||||
}
|
||||
return getArrayLiteralType(elementTypes, UnionReduction.Subtype);
|
||||
}
|
||||
@@ -18208,7 +18300,7 @@ namespace ts {
|
||||
// Referencing abstract properties within their own constructors is not allowed
|
||||
if ((flags & ModifierFlags.Abstract) && isThisProperty(node) && symbolHasNonMethodDeclaration(prop)) {
|
||||
const declaringClassDeclaration = getClassLikeDeclarationOfSymbol(getParentOfSymbol(prop)!);
|
||||
if (declaringClassDeclaration && isNodeUsedDuringClassInitialization(node, declaringClassDeclaration)) {
|
||||
if (declaringClassDeclaration && isNodeUsedDuringClassInitialization(node)) {
|
||||
error(errorNode, Diagnostics.Abstract_property_0_in_class_1_cannot_be_accessed_in_the_constructor, symbolToString(prop), getTextOfIdentifierOrLiteral(declaringClassDeclaration.name!)); // TODO: GH#18217
|
||||
return false;
|
||||
}
|
||||
@@ -18395,6 +18487,9 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (strictNullChecks && prop && prop.valueDeclaration && isPropertyAccessExpression(prop.valueDeclaration) && getAssignmentDeclarationPropertyAccessKind(prop.valueDeclaration)) {
|
||||
assumeUninitialized = true;
|
||||
}
|
||||
const flowType = getFlowTypeOfReference(node, propType, assumeUninitialized ? getOptionalType(propType) : propType);
|
||||
if (assumeUninitialized && !(getFalsyFlags(propType) & TypeFlags.Undefined) && getFalsyFlags(flowType) & TypeFlags.Undefined) {
|
||||
error(right, Diagnostics.Property_0_is_used_before_being_assigned, symbolToString(prop!)); // TODO: GH#18217
|
||||
@@ -20192,18 +20287,15 @@ namespace ts {
|
||||
assigned || inferred;
|
||||
}
|
||||
|
||||
function getAssignedClassType(symbol: Symbol) {
|
||||
function getAssignedClassType(symbol: Symbol): Type | undefined {
|
||||
const decl = symbol.valueDeclaration;
|
||||
const assignmentSymbol = decl && decl.parent &&
|
||||
(isFunctionDeclaration(decl) && getSymbolOfNode(decl) ||
|
||||
isBinaryExpression(decl.parent) && getSymbolOfNode(decl.parent.left) ||
|
||||
isVariableDeclaration(decl.parent) && getSymbolOfNode(decl.parent));
|
||||
if (assignmentSymbol) {
|
||||
const prototype = forEach(assignmentSymbol.declarations, getAssignedJSPrototype);
|
||||
if (prototype) {
|
||||
return checkExpression(prototype);
|
||||
}
|
||||
}
|
||||
const prototype = assignmentSymbol && assignmentSymbol.exports && assignmentSymbol.exports.get("prototype" as __String);
|
||||
const init = prototype && getAssignedJSPrototype(prototype.valueDeclaration);
|
||||
return init ? checkExpression(init) : undefined;
|
||||
}
|
||||
|
||||
function getAssignedJSPrototype(node: Node) {
|
||||
@@ -22067,11 +22159,11 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
function checkExpressionForMutableLocation(node: Expression, checkMode: CheckMode | undefined, contextualType?: Type): Type {
|
||||
function checkExpressionForMutableLocation(node: Expression, checkMode: CheckMode | undefined, contextualType?: Type, forceTuple?: boolean): Type {
|
||||
if (arguments.length === 2) {
|
||||
contextualType = getContextualType(node);
|
||||
}
|
||||
const type = checkExpression(node, checkMode);
|
||||
const type = checkExpression(node, checkMode, forceTuple);
|
||||
return isTypeAssertion(node) ? type :
|
||||
getWidenedLiteralLikeTypeForContextualType(type, contextualType);
|
||||
}
|
||||
@@ -22171,13 +22263,13 @@ namespace ts {
|
||||
// object, it serves as an indicator that all contained function and arrow expressions should be considered to
|
||||
// have the wildcard function type; this form of type check is used during overload resolution to exclude
|
||||
// contextually typed function and arrow expressions in the initial phase.
|
||||
function checkExpression(node: Expression | QualifiedName, checkMode?: CheckMode): Type {
|
||||
function checkExpression(node: Expression | QualifiedName, checkMode?: CheckMode, forceTuple?: boolean): Type {
|
||||
let type: Type;
|
||||
if (node.kind === SyntaxKind.QualifiedName) {
|
||||
type = checkQualifiedName(<QualifiedName>node);
|
||||
}
|
||||
else {
|
||||
const uninstantiatedType = checkExpressionWorker(node, checkMode);
|
||||
const uninstantiatedType = checkExpressionWorker(node, checkMode, forceTuple);
|
||||
type = instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, checkMode);
|
||||
}
|
||||
|
||||
@@ -22207,7 +22299,7 @@ namespace ts {
|
||||
return checkExpression(node.expression, checkMode);
|
||||
}
|
||||
|
||||
function checkExpressionWorker(node: Expression, checkMode: CheckMode | undefined): Type {
|
||||
function checkExpressionWorker(node: Expression, checkMode: CheckMode | undefined, forceTuple?: boolean): Type {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.Identifier:
|
||||
return checkIdentifier(<Identifier>node);
|
||||
@@ -22232,7 +22324,7 @@ namespace ts {
|
||||
case SyntaxKind.RegularExpressionLiteral:
|
||||
return globalRegExpType;
|
||||
case SyntaxKind.ArrayLiteralExpression:
|
||||
return checkArrayLiteral(<ArrayLiteralExpression>node, checkMode);
|
||||
return checkArrayLiteral(<ArrayLiteralExpression>node, checkMode, forceTuple);
|
||||
case SyntaxKind.ObjectLiteralExpression:
|
||||
return checkObjectLiteral(<ObjectLiteralExpression>node, checkMode);
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
@@ -27419,12 +27511,12 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
function isNodeUsedDuringClassInitialization(node: Node, classDeclaration: ClassLikeDeclaration) {
|
||||
function isNodeUsedDuringClassInitialization(node: Node) {
|
||||
return !!findAncestor(node, element => {
|
||||
if ((isConstructorDeclaration(element) && nodeIsPresent(element.body) || isPropertyDeclaration(element)) && element.parent === classDeclaration) {
|
||||
if (isConstructorDeclaration(element) && nodeIsPresent(element.body) || isPropertyDeclaration(element)) {
|
||||
return true;
|
||||
}
|
||||
else if (element === classDeclaration || isFunctionLikeDeclaration(element)) {
|
||||
else if (isClassLike(element) || isFunctionLikeDeclaration(element)) {
|
||||
return "quit";
|
||||
}
|
||||
|
||||
|
||||
@@ -172,6 +172,8 @@ namespace ts {
|
||||
es2018: ScriptTarget.ES2018,
|
||||
esnext: ScriptTarget.ESNext,
|
||||
}),
|
||||
affectsSourceFile: true,
|
||||
affectsModuleResolution: true,
|
||||
paramType: Diagnostics.VERSION,
|
||||
showInSimplifiedHelpView: true,
|
||||
category: Diagnostics.Basic_Options,
|
||||
@@ -190,6 +192,7 @@ namespace ts {
|
||||
es2015: ModuleKind.ES2015,
|
||||
esnext: ModuleKind.ESNext
|
||||
}),
|
||||
affectsModuleResolution: true,
|
||||
paramType: Diagnostics.KIND,
|
||||
showInSimplifiedHelpView: true,
|
||||
category: Diagnostics.Basic_Options,
|
||||
@@ -202,6 +205,7 @@ namespace ts {
|
||||
name: "lib",
|
||||
type: libMap
|
||||
},
|
||||
affectsModuleResolution: true,
|
||||
showInSimplifiedHelpView: true,
|
||||
category: Diagnostics.Basic_Options,
|
||||
description: Diagnostics.Specify_library_files_to_be_included_in_the_compilation
|
||||
@@ -209,6 +213,7 @@ namespace ts {
|
||||
{
|
||||
name: "allowJs",
|
||||
type: "boolean",
|
||||
affectsModuleResolution: true,
|
||||
showInSimplifiedHelpView: true,
|
||||
category: Diagnostics.Basic_Options,
|
||||
description: Diagnostics.Allow_javascript_files_to_be_compiled
|
||||
@@ -226,6 +231,7 @@ namespace ts {
|
||||
"react-native": JsxEmit.ReactNative,
|
||||
"react": JsxEmit.React
|
||||
}),
|
||||
affectsSourceFile: true,
|
||||
paramType: Diagnostics.KIND,
|
||||
showInSimplifiedHelpView: true,
|
||||
category: Diagnostics.Basic_Options,
|
||||
@@ -336,6 +342,7 @@ namespace ts {
|
||||
{
|
||||
name: "noImplicitAny",
|
||||
type: "boolean",
|
||||
affectsSemanticDiagnostics: true,
|
||||
strictFlag: true,
|
||||
showInSimplifiedHelpView: true,
|
||||
category: Diagnostics.Strict_Type_Checking_Options,
|
||||
@@ -344,6 +351,7 @@ namespace ts {
|
||||
{
|
||||
name: "strictNullChecks",
|
||||
type: "boolean",
|
||||
affectsSemanticDiagnostics: true,
|
||||
strictFlag: true,
|
||||
showInSimplifiedHelpView: true,
|
||||
category: Diagnostics.Strict_Type_Checking_Options,
|
||||
@@ -352,6 +360,7 @@ namespace ts {
|
||||
{
|
||||
name: "strictFunctionTypes",
|
||||
type: "boolean",
|
||||
affectsSemanticDiagnostics: true,
|
||||
strictFlag: true,
|
||||
showInSimplifiedHelpView: true,
|
||||
category: Diagnostics.Strict_Type_Checking_Options,
|
||||
@@ -360,6 +369,7 @@ namespace ts {
|
||||
{
|
||||
name: "strictPropertyInitialization",
|
||||
type: "boolean",
|
||||
affectsSemanticDiagnostics: true,
|
||||
strictFlag: true,
|
||||
showInSimplifiedHelpView: true,
|
||||
category: Diagnostics.Strict_Type_Checking_Options,
|
||||
@@ -368,6 +378,7 @@ namespace ts {
|
||||
{
|
||||
name: "noImplicitThis",
|
||||
type: "boolean",
|
||||
affectsSemanticDiagnostics: true,
|
||||
strictFlag: true,
|
||||
showInSimplifiedHelpView: true,
|
||||
category: Diagnostics.Strict_Type_Checking_Options,
|
||||
@@ -376,6 +387,7 @@ namespace ts {
|
||||
{
|
||||
name: "alwaysStrict",
|
||||
type: "boolean",
|
||||
affectsSourceFile: true,
|
||||
strictFlag: true,
|
||||
showInSimplifiedHelpView: true,
|
||||
category: Diagnostics.Strict_Type_Checking_Options,
|
||||
@@ -410,6 +422,7 @@ namespace ts {
|
||||
{
|
||||
name: "noFallthroughCasesInSwitch",
|
||||
type: "boolean",
|
||||
affectsBindDiagnostics: true,
|
||||
affectsSemanticDiagnostics: true,
|
||||
showInSimplifiedHelpView: true,
|
||||
category: Diagnostics.Additional_Checks,
|
||||
@@ -423,6 +436,7 @@ namespace ts {
|
||||
node: ModuleResolutionKind.NodeJs,
|
||||
classic: ModuleResolutionKind.Classic,
|
||||
}),
|
||||
affectsModuleResolution: true,
|
||||
paramType: Diagnostics.STRATEGY,
|
||||
category: Diagnostics.Module_Resolution_Options,
|
||||
description: Diagnostics.Specify_module_resolution_strategy_Colon_node_Node_js_or_classic_TypeScript_pre_1_6,
|
||||
@@ -430,6 +444,7 @@ namespace ts {
|
||||
{
|
||||
name: "baseUrl",
|
||||
type: "string",
|
||||
affectsModuleResolution: true,
|
||||
isFilePath: true,
|
||||
category: Diagnostics.Module_Resolution_Options,
|
||||
description: Diagnostics.Base_directory_to_resolve_non_absolute_module_names
|
||||
@@ -439,6 +454,7 @@ namespace ts {
|
||||
// use type = object to copy the value as-is
|
||||
name: "paths",
|
||||
type: "object",
|
||||
affectsModuleResolution: true,
|
||||
isTSConfigOnly: true,
|
||||
category: Diagnostics.Module_Resolution_Options,
|
||||
description: Diagnostics.A_series_of_entries_which_re_map_imports_to_lookup_locations_relative_to_the_baseUrl
|
||||
@@ -454,6 +470,7 @@ namespace ts {
|
||||
type: "string",
|
||||
isFilePath: true
|
||||
},
|
||||
affectsModuleResolution: true,
|
||||
category: Diagnostics.Module_Resolution_Options,
|
||||
description: Diagnostics.List_of_root_folders_whose_combined_content_represents_the_structure_of_the_project_at_runtime
|
||||
},
|
||||
@@ -465,6 +482,7 @@ namespace ts {
|
||||
type: "string",
|
||||
isFilePath: true
|
||||
},
|
||||
affectsModuleResolution: true,
|
||||
category: Diagnostics.Module_Resolution_Options,
|
||||
description: Diagnostics.List_of_folders_to_include_type_definitions_from
|
||||
},
|
||||
@@ -475,6 +493,7 @@ namespace ts {
|
||||
name: "types",
|
||||
type: "string"
|
||||
},
|
||||
affectsModuleResolution: true,
|
||||
showInSimplifiedHelpView: true,
|
||||
category: Diagnostics.Module_Resolution_Options,
|
||||
description: Diagnostics.Type_declaration_files_to_be_included_in_compilation
|
||||
@@ -633,12 +652,14 @@ namespace ts {
|
||||
{
|
||||
name: "noLib",
|
||||
type: "boolean",
|
||||
affectsModuleResolution: true,
|
||||
category: Diagnostics.Advanced_Options,
|
||||
description: Diagnostics.Do_not_include_the_default_library_file_lib_d_ts
|
||||
},
|
||||
{
|
||||
name: "noResolve",
|
||||
type: "boolean",
|
||||
affectsModuleResolution: true,
|
||||
category: Diagnostics.Advanced_Options,
|
||||
description: Diagnostics.Do_not_add_triple_slash_references_or_imported_modules_to_the_list_of_compiled_files
|
||||
},
|
||||
@@ -651,6 +672,7 @@ namespace ts {
|
||||
{
|
||||
name: "disableSizeLimit",
|
||||
type: "boolean",
|
||||
affectsSourceFile: true,
|
||||
category: Diagnostics.Advanced_Options,
|
||||
description: Diagnostics.Disable_size_limitations_on_JavaScript_projects
|
||||
},
|
||||
@@ -696,6 +718,7 @@ namespace ts {
|
||||
{
|
||||
name: "allowUnusedLabels",
|
||||
type: "boolean",
|
||||
affectsBindDiagnostics: true,
|
||||
affectsSemanticDiagnostics: true,
|
||||
category: Diagnostics.Advanced_Options,
|
||||
description: Diagnostics.Do_not_report_errors_on_unused_labels
|
||||
@@ -703,6 +726,7 @@ namespace ts {
|
||||
{
|
||||
name: "allowUnreachableCode",
|
||||
type: "boolean",
|
||||
affectsBindDiagnostics: true,
|
||||
affectsSemanticDiagnostics: true,
|
||||
category: Diagnostics.Advanced_Options,
|
||||
description: Diagnostics.Do_not_report_errors_on_unreachable_code
|
||||
@@ -730,6 +754,7 @@ namespace ts {
|
||||
{
|
||||
name: "maxNodeModuleJsDepth",
|
||||
type: "number",
|
||||
// TODO: GH#27108 affectsModuleResolution: true,
|
||||
category: Diagnostics.Advanced_Options,
|
||||
description: Diagnostics.The_maximum_dependency_depth_to_search_under_node_modules_and_load_JavaScript_files
|
||||
},
|
||||
@@ -759,6 +784,18 @@ namespace ts {
|
||||
}
|
||||
];
|
||||
|
||||
/* @internal */
|
||||
export const semanticDiagnosticsOptionDeclarations: ReadonlyArray<CommandLineOption> =
|
||||
optionDeclarations.filter(option => !!option.affectsSemanticDiagnostics);
|
||||
|
||||
/* @internal */
|
||||
export const moduleResolutionOptionDeclarations: ReadonlyArray<CommandLineOption> =
|
||||
optionDeclarations.filter(option => !!option.affectsModuleResolution);
|
||||
|
||||
/* @internal */
|
||||
export const sourceFileAffectingCompilerOptions: ReadonlyArray<CommandLineOption> = optionDeclarations.filter(option =>
|
||||
!!option.affectsSourceFile || !!option.affectsModuleResolution || !!option.affectsBindDiagnostics);
|
||||
|
||||
/* @internal */
|
||||
export const buildOpts: CommandLineOption[] = [
|
||||
...commonOptionsWithBuild,
|
||||
@@ -1993,7 +2030,7 @@ namespace ts {
|
||||
if (ownConfig.extendedConfigPath) {
|
||||
// copy the resolution stack so it is never reused between branches in potential diamond-problem scenarios.
|
||||
resolutionStack = resolutionStack.concat([resolvedPath]);
|
||||
const extendedConfig = getExtendedConfig(sourceFile!, ownConfig.extendedConfigPath, host, basePath, resolutionStack, errors);
|
||||
const extendedConfig = getExtendedConfig(sourceFile, ownConfig.extendedConfigPath, host, basePath, resolutionStack, errors);
|
||||
if (extendedConfig && isSuccessfulParsedTsconfig(extendedConfig)) {
|
||||
const baseRaw = extendedConfig.raw;
|
||||
const raw = ownConfig.raw;
|
||||
@@ -2134,7 +2171,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getExtendedConfig(
|
||||
sourceFile: TsConfigSourceFile,
|
||||
sourceFile: TsConfigSourceFile | undefined,
|
||||
extendedConfigPath: string,
|
||||
host: ParseConfigHost,
|
||||
basePath: string,
|
||||
@@ -2143,7 +2180,7 @@ namespace ts {
|
||||
): ParsedTsconfig | undefined {
|
||||
const extendedResult = readJsonConfigFile(extendedConfigPath, path => host.readFile(path));
|
||||
if (sourceFile) {
|
||||
(sourceFile.extendedSourceFiles || (sourceFile.extendedSourceFiles = [])).push(extendedResult.fileName);
|
||||
sourceFile.extendedSourceFiles = [extendedResult.fileName];
|
||||
}
|
||||
if (extendedResult.parseDiagnostics.length) {
|
||||
errors.push(...extendedResult.parseDiagnostics);
|
||||
@@ -2153,8 +2190,8 @@ namespace ts {
|
||||
const extendedDirname = getDirectoryPath(extendedConfigPath);
|
||||
const extendedConfig = parseConfig(/*json*/ undefined, extendedResult, host, extendedDirname,
|
||||
getBaseFileName(extendedConfigPath), resolutionStack, errors);
|
||||
if (sourceFile) {
|
||||
sourceFile.extendedSourceFiles!.push(...extendedResult.extendedSourceFiles!);
|
||||
if (sourceFile && extendedResult.extendedSourceFiles) {
|
||||
sourceFile.extendedSourceFiles!.push(...extendedResult.extendedSourceFiles);
|
||||
}
|
||||
|
||||
if (isSuccessfulParsedTsconfig(extendedConfig)) {
|
||||
|
||||
+11
-3
@@ -842,7 +842,7 @@ namespace ts {
|
||||
return deduplicateSorted(sort(array, comparer), equalityComparer || comparer);
|
||||
}
|
||||
|
||||
export function arrayIsEqualTo<T>(array1: ReadonlyArray<T> | undefined, array2: ReadonlyArray<T> | undefined, equalityComparer: (a: T, b: T) => boolean = equateValues): boolean {
|
||||
export function arrayIsEqualTo<T>(array1: ReadonlyArray<T> | undefined, array2: ReadonlyArray<T> | undefined, equalityComparer: (a: T, b: T, index: number) => boolean = equateValues): boolean {
|
||||
if (!array1 || !array2) {
|
||||
return array1 === array2;
|
||||
}
|
||||
@@ -852,7 +852,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
for (let i = 0; i < array1.length; i++) {
|
||||
if (!equalityComparer(array1[i], array2[i])) {
|
||||
if (!equalityComparer(array1[i], array2[i], i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1409,9 +1409,12 @@ namespace ts {
|
||||
/**
|
||||
* Tests whether a value is string
|
||||
*/
|
||||
export function isString(text: any): text is string {
|
||||
export function isString(text: unknown): text is string {
|
||||
return typeof text === "string";
|
||||
}
|
||||
export function isNumber(x: unknown): x is number {
|
||||
return typeof x === "number";
|
||||
}
|
||||
|
||||
export function tryCast<TOut extends TIn, TIn = any>(value: TIn | undefined, test: (value: TIn) => value is TOut): TOut | undefined;
|
||||
export function tryCast<T>(value: T, test: (value: T) => boolean): T | undefined;
|
||||
@@ -1534,6 +1537,7 @@ namespace ts {
|
||||
* Every function should be assignable to this, but this should not be assignable to every function.
|
||||
*/
|
||||
export type AnyFunction = (...args: never[]) => void;
|
||||
export type AnyConstructor = new (...args: unknown[]) => unknown;
|
||||
|
||||
export namespace Debug {
|
||||
export let currentAssertionLevel = AssertionLevel.None;
|
||||
@@ -2125,4 +2129,8 @@ namespace ts {
|
||||
deleted(oldItems[oldIndex++]);
|
||||
}
|
||||
}
|
||||
|
||||
export function fill<T>(length: number, cb: (index: number) => T): T[] {
|
||||
return new Array(length).fill(0).map((_, i) => cb(i));
|
||||
}
|
||||
}
|
||||
|
||||
+4690
-4670
File diff suppressed because it is too large
Load Diff
@@ -1041,7 +1041,7 @@ namespace ts {
|
||||
// SyntaxKind.TemplateMiddle
|
||||
// SyntaxKind.TemplateTail
|
||||
function emitLiteral(node: LiteralLikeNode) {
|
||||
const text = getLiteralTextOfNode(node);
|
||||
const text = getLiteralTextOfNode(node, printerOptions.neverAsciiEscape);
|
||||
if ((printerOptions.sourceMap || printerOptions.inlineSourceMap)
|
||||
&& (node.kind === SyntaxKind.StringLiteral || isTemplateLiteralKind(node.kind))) {
|
||||
writeLiteral(text);
|
||||
@@ -1532,7 +1532,7 @@ namespace ts {
|
||||
expression = skipPartiallyEmittedExpressions(expression);
|
||||
if (isNumericLiteral(expression)) {
|
||||
// check if numeric literal is a decimal literal that was originally written with a dot
|
||||
const text = getLiteralTextOfNode(<LiteralExpression>expression);
|
||||
const text = getLiteralTextOfNode(<LiteralExpression>expression, /*neverAsciiEscape*/ true);
|
||||
return !expression.numericLiteralFlags
|
||||
&& !stringContains(text, tokenToString(SyntaxKind.DotToken)!);
|
||||
}
|
||||
@@ -3306,20 +3306,20 @@ namespace ts {
|
||||
return getSourceTextOfNodeFromSourceFile(currentSourceFile, node, includeTrivia);
|
||||
}
|
||||
|
||||
function getLiteralTextOfNode(node: LiteralLikeNode): string {
|
||||
function getLiteralTextOfNode(node: LiteralLikeNode, neverAsciiEscape: boolean | undefined): string {
|
||||
if (node.kind === SyntaxKind.StringLiteral && (<StringLiteral>node).textSourceNode) {
|
||||
const textSourceNode = (<StringLiteral>node).textSourceNode!;
|
||||
if (isIdentifier(textSourceNode)) {
|
||||
return getEmitFlags(node) & EmitFlags.NoAsciiEscaping ?
|
||||
return neverAsciiEscape || (getEmitFlags(node) & EmitFlags.NoAsciiEscaping) ?
|
||||
`"${escapeString(getTextOfNode(textSourceNode))}"` :
|
||||
`"${escapeNonAsciiString(getTextOfNode(textSourceNode))}"`;
|
||||
}
|
||||
else {
|
||||
return getLiteralTextOfNode(textSourceNode);
|
||||
return getLiteralTextOfNode(textSourceNode, neverAsciiEscape);
|
||||
}
|
||||
}
|
||||
|
||||
return getLiteralText(node, currentSourceFile);
|
||||
return getLiteralText(node, currentSourceFile, neverAsciiEscape);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -235,7 +235,7 @@ namespace ts {
|
||||
|
||||
// Modifiers
|
||||
|
||||
export function createModifier<T extends Modifier["kind"]>(kind: T) {
|
||||
export function createModifier<T extends Modifier["kind"]>(kind: T): Token<T> {
|
||||
return createToken(kind);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
/* @internal */
|
||||
namespace ts {
|
||||
export interface InspectValueOptions {
|
||||
readonly fileNameToRequire: string;
|
||||
}
|
||||
|
||||
export const enum ValueKind { Const, Array, FunctionOrClass, Object }
|
||||
export interface ValueInfoBase {
|
||||
readonly name: string;
|
||||
}
|
||||
export type ValueInfo = ValueInfoSimple | ValueInfoArray | ValueInfoFunctionOrClass | ValueInfoObject;
|
||||
export interface ValueInfoSimple extends ValueInfoBase {
|
||||
readonly kind: ValueKind.Const;
|
||||
readonly typeName: string;
|
||||
readonly comment?: string | undefined;
|
||||
}
|
||||
export interface ValueInfoFunctionOrClass extends ValueInfoBase {
|
||||
readonly kind: ValueKind.FunctionOrClass;
|
||||
readonly source: string | number; // For a native function, this is the length.
|
||||
readonly prototypeMembers: ReadonlyArray<ValueInfo>;
|
||||
readonly namespaceMembers: ReadonlyArray<ValueInfo>;
|
||||
}
|
||||
export interface ValueInfoArray extends ValueInfoBase {
|
||||
readonly kind: ValueKind.Array;
|
||||
readonly inner: ValueInfo;
|
||||
}
|
||||
export interface ValueInfoObject extends ValueInfoBase {
|
||||
readonly kind: ValueKind.Object;
|
||||
readonly members: ReadonlyArray<ValueInfo>;
|
||||
}
|
||||
|
||||
export function inspectModule(fileNameToRequire: string): ValueInfo {
|
||||
return inspectValue(removeFileExtension(getBaseFileName(fileNameToRequire)), tryRequire(fileNameToRequire));
|
||||
}
|
||||
|
||||
export function inspectValue(name: string, value: unknown): ValueInfo {
|
||||
return getValueInfo(name, value, getRecurser());
|
||||
}
|
||||
|
||||
type Recurser = <T>(obj: unknown, name: string, cbOk: () => T, cbFail: (isCircularReference: boolean, keyStack: ReadonlyArray<string>) => T) => T;
|
||||
function getRecurser(): Recurser {
|
||||
const seen = new Set<unknown>();
|
||||
const nameStack: string[] = [];
|
||||
return (obj, name, cbOk, cbFail) => {
|
||||
if (seen.has(obj) || nameStack.length > 4) {
|
||||
return cbFail(seen.has(obj), nameStack);
|
||||
}
|
||||
|
||||
seen.add(obj);
|
||||
nameStack.push(name);
|
||||
const res = cbOk();
|
||||
nameStack.pop();
|
||||
seen.delete(obj);
|
||||
return res;
|
||||
};
|
||||
}
|
||||
|
||||
function getValueInfo(name: string, value: unknown, recurser: Recurser): ValueInfo {
|
||||
return recurser(value, name,
|
||||
(): ValueInfo => {
|
||||
if (typeof value === "function") return getFunctionOrClassInfo(value as AnyFunction, name, recurser);
|
||||
if (typeof value === "object") {
|
||||
const builtin = getBuiltinType(name, value as object, recurser);
|
||||
if (builtin !== undefined) return builtin;
|
||||
const entries = getEntriesOfObject(value as object);
|
||||
return { kind: ValueKind.Object, name, members: flatMap(entries, ({ key, value }) => getValueInfo(key, value, recurser)) };
|
||||
}
|
||||
return { kind: ValueKind.Const, name, typeName: isNullOrUndefined(value) ? "any" : typeof value };
|
||||
},
|
||||
(isCircularReference, keyStack) => anyValue(name, ` ${isCircularReference ? "Circular reference" : "Too-deep object hierarchy"} from ${keyStack.join(".")}`));
|
||||
}
|
||||
|
||||
function getFunctionOrClassInfo(fn: AnyFunction, name: string, recurser: Recurser): ValueInfoFunctionOrClass {
|
||||
const prototypeMembers = getPrototypeMembers(fn, recurser);
|
||||
const namespaceMembers = flatMap(getEntriesOfObject(fn), ({ key, value }) => getValueInfo(key, value, recurser));
|
||||
const toString = cast(Function.prototype.toString.call(fn), isString);
|
||||
const source = stringContains(toString, "{ [native code] }") ? getFunctionLength(fn) : toString;
|
||||
return { kind: ValueKind.FunctionOrClass, name, source, namespaceMembers, prototypeMembers };
|
||||
}
|
||||
|
||||
const builtins: () => ReadonlyMap<AnyConstructor> = memoize(() => {
|
||||
const map = createMap<AnyConstructor>();
|
||||
for (const { key, value } of getEntriesOfObject(global)) {
|
||||
if (typeof value === "function" && typeof value.prototype === "object" && value !== Object) {
|
||||
map.set(key, value as AnyConstructor);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
});
|
||||
function getBuiltinType(name: string, value: object, recurser: Recurser): ValueInfo | undefined {
|
||||
return isArray(value)
|
||||
? { name, kind: ValueKind.Array, inner: value.length && getValueInfo("element", first(value), recurser) || anyValue(name) }
|
||||
: forEachEntry(builtins(), (builtin, builtinName): ValueInfo | undefined =>
|
||||
value instanceof builtin ? { kind: ValueKind.Const, name, typeName: builtinName } : undefined);
|
||||
}
|
||||
|
||||
function getPrototypeMembers(fn: AnyFunction, recurser: Recurser): ReadonlyArray<ValueInfo> {
|
||||
const prototype = fn.prototype as unknown;
|
||||
// tslint:disable-next-line no-unnecessary-type-assertion (TODO: update LKG and it will really be unnecessary)
|
||||
return typeof prototype !== "object" || prototype === null ? emptyArray : mapDefined(getEntriesOfObject(prototype as object), ({ key, value }) =>
|
||||
key === "constructor" ? undefined : getValueInfo(key, value, recurser));
|
||||
}
|
||||
|
||||
const ignoredProperties: ReadonlySet<string> = new Set(["arguments", "caller", "constructor", "eval", "super_"]);
|
||||
const reservedFunctionProperties: ReadonlySet<string> = new Set(Object.getOwnPropertyNames(noop));
|
||||
interface ObjectEntry { readonly key: string; readonly value: unknown; }
|
||||
function getEntriesOfObject(obj: object): ReadonlyArray<ObjectEntry> {
|
||||
const seen = createMap<true>();
|
||||
const entries: ObjectEntry[] = [];
|
||||
let chain = obj;
|
||||
while (!isNullOrUndefined(chain) && chain !== Object.prototype && chain !== Function.prototype) {
|
||||
for (const key of Object.getOwnPropertyNames(chain)) {
|
||||
if (!isJsPrivate(key) &&
|
||||
!ignoredProperties.has(key) &&
|
||||
(typeof obj !== "function" || !reservedFunctionProperties.has(key)) &&
|
||||
// Don't add property from a higher prototype if it already exists in a lower one
|
||||
addToSeen(seen, key)) {
|
||||
const value = safeGetPropertyOfObject(chain, key);
|
||||
// Don't repeat "toString" that matches signature from Object.prototype
|
||||
if (!(key === "toString" && typeof value === "function" && value.length === 0)) {
|
||||
entries.push({ key, value });
|
||||
}
|
||||
}
|
||||
}
|
||||
chain = Object.getPrototypeOf(chain);
|
||||
}
|
||||
return entries.sort((e1, e2) => compareStringsCaseSensitive(e1.key, e2.key));
|
||||
}
|
||||
|
||||
function getFunctionLength(fn: AnyFunction): number {
|
||||
return tryCast(safeGetPropertyOfObject(fn, "length"), isNumber) || 0;
|
||||
}
|
||||
|
||||
function safeGetPropertyOfObject(obj: object, key: string): unknown {
|
||||
const desc = Object.getOwnPropertyDescriptor(obj, key);
|
||||
return desc && desc.value;
|
||||
}
|
||||
|
||||
function isNullOrUndefined(value: unknown): value is null | undefined {
|
||||
return value == null; // tslint:disable-line
|
||||
}
|
||||
|
||||
function anyValue(name: string, comment?: string): ValueInfo {
|
||||
return { kind: ValueKind.Const, name, typeName: "any", comment };
|
||||
}
|
||||
|
||||
export function isJsPrivate(name: string): boolean {
|
||||
return name.startsWith("_");
|
||||
}
|
||||
|
||||
function tryRequire(fileNameToRequire: string): unknown {
|
||||
try {
|
||||
return require(fileNameToRequire);
|
||||
}
|
||||
catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -779,14 +779,23 @@ namespace ts {
|
||||
*/
|
||||
/* @internal */
|
||||
export function resolveJSModule(moduleName: string, initialDir: string, host: ModuleResolutionHost): string {
|
||||
const { resolvedModule, failedLookupLocations } =
|
||||
nodeModuleNameResolverWorker(moduleName, initialDir, { moduleResolution: ModuleResolutionKind.NodeJs, allowJs: true }, host, /*cache*/ undefined, /*jsOnly*/ true);
|
||||
const { resolvedModule, failedLookupLocations } = tryResolveJSModuleWorker(moduleName, initialDir, host);
|
||||
if (!resolvedModule) {
|
||||
throw new Error(`Could not resolve JS module '${moduleName}' starting at '${initialDir}'. Looked in: ${failedLookupLocations.join(", ")}`);
|
||||
}
|
||||
return resolvedModule.resolvedFileName;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function tryResolveJSModule(moduleName: string, initialDir: string, host: ModuleResolutionHost): string | undefined {
|
||||
const { resolvedModule } = tryResolveJSModuleWorker(moduleName, initialDir, host);
|
||||
return resolvedModule && resolvedModule.resolvedFileName;
|
||||
}
|
||||
|
||||
function tryResolveJSModuleWorker(moduleName: string, initialDir: string, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations {
|
||||
return nodeModuleNameResolverWorker(moduleName, initialDir, { moduleResolution: ModuleResolutionKind.NodeJs, allowJs: true }, host, /*cache*/ undefined, /*jsOnly*/ true);
|
||||
}
|
||||
|
||||
export function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache): ResolvedModuleWithFailedLookupLocations {
|
||||
return nodeModuleNameResolverWorker(moduleName, getDirectoryPath(containingFile), compilerOptions, host, cache, /*jsOnly*/ false);
|
||||
}
|
||||
|
||||
+58
-34
@@ -455,7 +455,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
// If project references dont match
|
||||
if (!arrayIsEqualTo(program.getProjectReferences(), projectReferences)) {
|
||||
if (!arrayIsEqualTo(program.getProjectReferences(), projectReferences, projectReferenceUptoDate)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -483,9 +483,27 @@ namespace ts {
|
||||
|
||||
return true;
|
||||
|
||||
function sourceFileNotUptoDate(sourceFile: SourceFile): boolean {
|
||||
return sourceFile.version !== getSourceVersion(sourceFile.path) ||
|
||||
hasInvalidatedResolution(sourceFile.path);
|
||||
function sourceFileNotUptoDate(sourceFile: SourceFile) {
|
||||
return !sourceFileVersionUptoDate(sourceFile) ||
|
||||
hasInvalidatedResolution(sourceFile.resolvedPath || sourceFile.path);
|
||||
}
|
||||
|
||||
function sourceFileVersionUptoDate(sourceFile: SourceFile) {
|
||||
return sourceFile.version === getSourceVersion(sourceFile.resolvedPath || sourceFile.path);
|
||||
}
|
||||
|
||||
function projectReferenceUptoDate(oldRef: ProjectReference, newRef: ProjectReference, index: number) {
|
||||
if (!projectReferenceIsEqualTo(oldRef, newRef)) {
|
||||
return false;
|
||||
}
|
||||
const oldResolvedRef = program!.getResolvedProjectReferences()![index];
|
||||
if (oldResolvedRef) {
|
||||
// If sourceFile for the oldResolvedRef existed, check the version for uptodate
|
||||
return sourceFileVersionUptoDate(oldResolvedRef.sourceFile);
|
||||
}
|
||||
// In old program, not able to resolve project reference path,
|
||||
// so if config file doesnt exist, it is uptodate.
|
||||
return !fileExists(resolveProjectReferencePath(oldRef));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -496,23 +514,15 @@ namespace ts {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determined if source file needs to be re-created even if its text hasn't changed
|
||||
* Determine if source file needs to be re-created even if its text hasn't changed
|
||||
*/
|
||||
function shouldProgramCreateNewSourceFiles(program: Program | undefined, newOptions: CompilerOptions) {
|
||||
// If any of these options change, we can't reuse old source file even if version match
|
||||
// The change in options like these could result in change in syntax tree change
|
||||
const oldOptions = program && program.getCompilerOptions();
|
||||
return oldOptions && (
|
||||
oldOptions.target !== newOptions.target ||
|
||||
oldOptions.module !== newOptions.module ||
|
||||
oldOptions.moduleResolution !== newOptions.moduleResolution ||
|
||||
oldOptions.noResolve !== newOptions.noResolve ||
|
||||
oldOptions.jsx !== newOptions.jsx ||
|
||||
oldOptions.allowJs !== newOptions.allowJs ||
|
||||
oldOptions.disableSizeLimit !== newOptions.disableSizeLimit ||
|
||||
oldOptions.baseUrl !== newOptions.baseUrl ||
|
||||
!equalOwnProperties(oldOptions.paths, newOptions.paths)
|
||||
);
|
||||
function shouldProgramCreateNewSourceFiles(program: Program | undefined, newOptions: CompilerOptions): boolean {
|
||||
if (!program) return false;
|
||||
// If any compiler options change, we can't reuse old source file even if version match
|
||||
// The change in options like these could result in change in syntax tree or `sourceFile.bindDiagnostics`.
|
||||
const oldOptions = program.getCompilerOptions();
|
||||
return !!sourceFileAffectingCompilerOptions.some(option =>
|
||||
!isJsonEqual(getCompilerOptionValue(oldOptions, option), getCompilerOptionValue(newOptions, option)));
|
||||
}
|
||||
|
||||
function createCreateProgramOptions(rootNames: ReadonlyArray<string>, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): CreateProgramOptions {
|
||||
@@ -666,8 +676,9 @@ namespace ts {
|
||||
const parsedRef = parseProjectReferenceConfigFile(ref);
|
||||
resolvedProjectReferences!.push(parsedRef);
|
||||
if (parsedRef) {
|
||||
if (parsedRef.commandLine.options.outFile) {
|
||||
const dtsOutfile = changeExtension(parsedRef.commandLine.options.outFile, ".d.ts");
|
||||
const out = parsedRef.commandLine.options.outFile || parsedRef.commandLine.options.out;
|
||||
if (out) {
|
||||
const dtsOutfile = changeExtension(out, ".d.ts");
|
||||
processSourceFile(dtsOutfile, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined);
|
||||
}
|
||||
addProjectReferenceRedirects(parsedRef.commandLine, projectReferenceRedirects);
|
||||
@@ -766,7 +777,8 @@ namespace ts {
|
||||
getConfigFileParsingDiagnostics,
|
||||
getResolvedModuleWithFailedLookupLocationsFromCache,
|
||||
getProjectReferences,
|
||||
getResolvedProjectReferences
|
||||
getResolvedProjectReferences,
|
||||
getProjectReferenceRedirect
|
||||
};
|
||||
|
||||
verifyCompilerOptions();
|
||||
@@ -1233,6 +1245,13 @@ namespace ts {
|
||||
}
|
||||
resolvedTypeReferenceDirectives = oldProgram.getResolvedTypeReferenceDirectives();
|
||||
resolvedProjectReferences = oldProgram.getResolvedProjectReferences();
|
||||
if (resolvedProjectReferences) {
|
||||
resolvedProjectReferences.forEach(ref => {
|
||||
if (ref) {
|
||||
addProjectReferenceRedirects(ref.commandLine, projectReferenceRedirects);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
sourceFileToPackageName = oldProgram.sourceFileToPackageName;
|
||||
redirectTargetsMap = oldProgram.redirectTargetsMap;
|
||||
@@ -1288,12 +1307,13 @@ namespace ts {
|
||||
const ref = projectReferences[i];
|
||||
const resolvedRefOpts = resolvedProjectReferences![i]!.commandLine;
|
||||
if (ref.prepend && resolvedRefOpts && resolvedRefOpts.options) {
|
||||
const out = resolvedRefOpts.options.outFile || resolvedRefOpts.options.out;
|
||||
// Upstream project didn't have outFile set -- skip (error will have been issued earlier)
|
||||
if (!resolvedRefOpts.options.outFile) continue;
|
||||
if (!out) continue;
|
||||
|
||||
const dtsFilename = changeExtension(resolvedRefOpts.options.outFile, ".d.ts");
|
||||
const js = host.readFile(resolvedRefOpts.options.outFile) || `/* Input file ${resolvedRefOpts.options.outFile} was missing */\r\n`;
|
||||
const jsMapPath = resolvedRefOpts.options.outFile + ".map"; // TODO: try to read sourceMappingUrl comment from the file
|
||||
const dtsFilename = changeExtension(out, ".d.ts");
|
||||
const js = host.readFile(out) || `/* Input file ${out} was missing */\r\n`;
|
||||
const jsMapPath = out + ".map"; // TODO: try to read sourceMappingUrl comment from the file
|
||||
const jsMap = host.readFile(jsMapPath);
|
||||
const dts = host.readFile(dtsFilename) || `/* Input file ${dtsFilename} was missing */\r\n`;
|
||||
const dtsMapPath = dtsFilename + ".map";
|
||||
@@ -2435,9 +2455,10 @@ namespace ts {
|
||||
createDiagnosticForReference(i, Diagnostics.Referenced_project_0_must_have_setting_composite_Colon_true, ref.path);
|
||||
}
|
||||
if (ref.prepend) {
|
||||
if (resolvedRefOpts.outFile) {
|
||||
if (!host.fileExists(resolvedRefOpts.outFile)) {
|
||||
createDiagnosticForReference(i, Diagnostics.Output_file_0_from_project_1_does_not_exist, resolvedRefOpts.outFile, ref.path);
|
||||
const out = resolvedRefOpts.outFile || resolvedRefOpts.out;
|
||||
if (out) {
|
||||
if (!host.fileExists(out)) {
|
||||
createDiagnosticForReference(i, Diagnostics.Output_file_0_from_project_1_does_not_exist, out, ref.path);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -2511,7 +2532,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (options.declarationDir) {
|
||||
if (!options.declaration) {
|
||||
if (!getEmitDeclarations(options)) {
|
||||
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "declarationDir", "declaration");
|
||||
}
|
||||
if (options.out || options.outFile) {
|
||||
@@ -2588,8 +2609,8 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
if (!options.noEmit && options.allowJs && options.declaration) {
|
||||
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", "declaration");
|
||||
if (!options.noEmit && options.allowJs && getEmitDeclarations(options)) {
|
||||
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", options.declaration ? "declaration" : "composite");
|
||||
}
|
||||
|
||||
if (options.checkJs && !options.allowJs) {
|
||||
@@ -2829,7 +2850,10 @@ namespace ts {
|
||||
export function parseConfigHostFromCompilerHost(host: CompilerHost): ParseConfigFileHost {
|
||||
return {
|
||||
fileExists: f => host.fileExists(f),
|
||||
readDirectory: (root, extensions, includes, depth?) => host.readDirectory ? host.readDirectory(root, extensions, includes, depth) : [],
|
||||
readDirectory(root, extensions, excludes, includes, depth) {
|
||||
Debug.assertDefined(host.readDirectory, "'CompilerHost.readDirectory' must be implemented to correctly process 'projectReferences'");
|
||||
return host.readDirectory!(root, extensions, excludes, includes, depth);
|
||||
},
|
||||
readFile: f => host.readFile(f),
|
||||
useCaseSensitiveFileNames: host.useCaseSensitiveFileNames(),
|
||||
getCurrentDirectory: () => host.getCurrentDirectory(),
|
||||
|
||||
@@ -285,16 +285,17 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getOutFileOutputs(project: ParsedCommandLine): ReadonlyArray<string> {
|
||||
if (!project.options.outFile) {
|
||||
const out = project.options.outFile || project.options.out;
|
||||
if (!out) {
|
||||
return Debug.fail("outFile must be set");
|
||||
}
|
||||
const outputs: string[] = [];
|
||||
outputs.push(project.options.outFile);
|
||||
outputs.push(out);
|
||||
if (project.options.sourceMap) {
|
||||
outputs.push(`${project.options.outFile}.map`);
|
||||
outputs.push(`${out}.map`);
|
||||
}
|
||||
if (getEmitDeclarations(project.options)) {
|
||||
const dts = changeExtension(project.options.outFile, Extension.Dts);
|
||||
const dts = changeExtension(out, Extension.Dts);
|
||||
outputs.push(dts);
|
||||
if (project.options.declarationMap) {
|
||||
outputs.push(`${dts}.map`);
|
||||
@@ -862,7 +863,7 @@ namespace ts {
|
||||
if (buildProject) {
|
||||
buildSingleInvalidatedProject(buildProject.project, buildProject.reloadLevel);
|
||||
if (hasPendingInvalidatedProjects()) {
|
||||
if (!timerToBuildInvalidatedProject) {
|
||||
if (options.watch && !timerToBuildInvalidatedProject) {
|
||||
scheduleBuildInvalidatedProject();
|
||||
}
|
||||
}
|
||||
@@ -1248,7 +1249,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function getAllProjectOutputs(project: ParsedCommandLine): ReadonlyArray<string> {
|
||||
if (project.options.outFile) {
|
||||
if (project.options.outFile || project.options.out) {
|
||||
return getOutFileOutputs(project);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
"resolutionCache.ts",
|
||||
"moduleSpecifiers.ts",
|
||||
"watch.ts",
|
||||
"tsbuild.ts"
|
||||
"tsbuild.ts",
|
||||
"inspectValue.ts",
|
||||
]
|
||||
}
|
||||
|
||||
+12
-1
@@ -2551,6 +2551,11 @@ namespace ts {
|
||||
fileName: string;
|
||||
/* @internal */ path: Path;
|
||||
text: string;
|
||||
/** Resolved path can be different from path property,
|
||||
* when file is included through project reference is mapped to its output instead of source
|
||||
* in that case resolvedPath = path to output file
|
||||
* path = input file's path
|
||||
*/
|
||||
/* @internal */ resolvedPath: Path;
|
||||
|
||||
/**
|
||||
@@ -2819,6 +2824,7 @@ namespace ts {
|
||||
|
||||
getProjectReferences(): ReadonlyArray<ProjectReference> | undefined;
|
||||
getResolvedProjectReferences(): (ResolvedProjectReference | undefined)[] | undefined;
|
||||
/*@internal*/ getProjectReferenceRedirect(fileName: string): string | undefined;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
@@ -3670,6 +3676,7 @@ namespace ts {
|
||||
export interface NodeLinks {
|
||||
flags: NodeCheckFlags; // Set of flags specific to Node
|
||||
resolvedType?: Type; // Cached type of type node
|
||||
resolvedEnumType?: Type; // Cached constraint type from enum jsdoc tag
|
||||
resolvedSignature?: Signature; // Cached signature of signature node or call expression
|
||||
resolvedSignatures?: Map<Signature[]>; // Cached signatures of jsx node
|
||||
resolvedSymbol?: Symbol; // Cached name resolution result
|
||||
@@ -4569,6 +4576,9 @@ namespace ts {
|
||||
showInSimplifiedHelpView?: boolean;
|
||||
category?: DiagnosticMessage;
|
||||
strictFlag?: true; // true if the option is one of the flag under strict
|
||||
affectsSourceFile?: true; // true if we should recreate SourceFiles after this option changes
|
||||
affectsModuleResolution?: true; // currently same effect as `affectsSourceFile`
|
||||
affectsBindDiagnostics?: true; // true if this affects binding (currently same effect as `affectsSourceFile`)
|
||||
affectsSemanticDiagnostics?: true; // true if option affects semantic diagnostics
|
||||
}
|
||||
|
||||
@@ -4964,7 +4974,7 @@ namespace ts {
|
||||
/* @internal */
|
||||
export interface EmitNode {
|
||||
annotatedNodes?: Node[]; // Tracks Parse-tree nodes with EmitNodes for eventual cleanup.
|
||||
flags: EmitFlags; // Flags that customize emit
|
||||
flags: EmitFlags; // Flags that customize emit
|
||||
leadingComments?: SynthesizedComment[]; // Synthesized leading comments
|
||||
trailingComments?: SynthesizedComment[]; // Synthesized trailing comments
|
||||
commentRange?: TextRange; // The text range to use when emitting leading or trailing comments
|
||||
@@ -5324,6 +5334,7 @@ namespace ts {
|
||||
/*@internal*/ inlineSourceMap?: boolean;
|
||||
/*@internal*/ extendedDiagnostics?: boolean;
|
||||
/*@internal*/ onlyPrintJsDocStyle?: boolean;
|
||||
/*@internal*/ neverAsciiEscape?: boolean;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
|
||||
+16
-27
@@ -101,22 +101,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function changesAffectModuleResolution(oldOptions: CompilerOptions, newOptions: CompilerOptions): boolean {
|
||||
return !oldOptions ||
|
||||
(oldOptions.module !== newOptions.module) ||
|
||||
(oldOptions.moduleResolution !== newOptions.moduleResolution) ||
|
||||
(oldOptions.noResolve !== newOptions.noResolve) ||
|
||||
(oldOptions.target !== newOptions.target) ||
|
||||
(oldOptions.noLib !== newOptions.noLib) ||
|
||||
(oldOptions.jsx !== newOptions.jsx) ||
|
||||
(oldOptions.allowJs !== newOptions.allowJs) ||
|
||||
(oldOptions.rootDir !== newOptions.rootDir) ||
|
||||
(oldOptions.configFilePath !== newOptions.configFilePath) ||
|
||||
(oldOptions.baseUrl !== newOptions.baseUrl) ||
|
||||
(oldOptions.maxNodeModuleJsDepth !== newOptions.maxNodeModuleJsDepth) ||
|
||||
!arrayIsEqualTo(oldOptions.lib, newOptions.lib) ||
|
||||
!arrayIsEqualTo(oldOptions.typeRoots, newOptions.typeRoots) ||
|
||||
!arrayIsEqualTo(oldOptions.rootDirs, newOptions.rootDirs) ||
|
||||
!equalOwnProperties(oldOptions.paths, newOptions.paths);
|
||||
return oldOptions.configFilePath !== newOptions.configFilePath || moduleResolutionOptionDeclarations.some(o =>
|
||||
!isJsonEqual(getCompilerOptionValue(oldOptions, o), getCompilerOptionValue(newOptions, o)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -538,14 +524,14 @@ namespace ts {
|
||||
return emitNode && emitNode.flags || 0;
|
||||
}
|
||||
|
||||
export function getLiteralText(node: LiteralLikeNode, sourceFile: SourceFile) {
|
||||
export function getLiteralText(node: LiteralLikeNode, sourceFile: SourceFile, neverAsciiEscape: boolean | undefined) {
|
||||
// If we don't need to downlevel and we can reach the original source text using
|
||||
// the node's parent reference, then simply get the text as it was originally written.
|
||||
if (!nodeIsSynthesized(node) && node.parent && !(isNumericLiteral(node) && node.numericLiteralFlags & TokenFlags.ContainsSeparator)) {
|
||||
return getSourceTextOfNodeFromSourceFile(sourceFile, node);
|
||||
}
|
||||
|
||||
const escapeText = getEmitFlags(node) & EmitFlags.NoAsciiEscaping ? escapeString : escapeNonAsciiString;
|
||||
const escapeText = neverAsciiEscape || (getEmitFlags(node) & EmitFlags.NoAsciiEscaping) ? escapeString : escapeNonAsciiString;
|
||||
|
||||
// If we can't reach the original source text, use the canonical form if it's a number,
|
||||
// or a (possibly escaped) quoted form of the original text if it's string-like.
|
||||
@@ -7091,9 +7077,8 @@ namespace ts {
|
||||
const moduleKind = getEmitModuleKind(compilerOptions);
|
||||
return compilerOptions.allowSyntheticDefaultImports !== undefined
|
||||
? compilerOptions.allowSyntheticDefaultImports
|
||||
: compilerOptions.esModuleInterop
|
||||
? moduleKind !== ModuleKind.None && moduleKind < ModuleKind.ES2015
|
||||
: moduleKind === ModuleKind.System;
|
||||
: compilerOptions.esModuleInterop ||
|
||||
moduleKind === ModuleKind.System;
|
||||
}
|
||||
|
||||
export function getEmitDeclarations(compilerOptions: CompilerOptions): boolean {
|
||||
@@ -7106,13 +7091,13 @@ namespace ts {
|
||||
return compilerOptions[flag] === undefined ? !!compilerOptions.strict : !!compilerOptions[flag];
|
||||
}
|
||||
|
||||
export function compilerOptionsAffectSemanticDiagnostics(newOptions: CompilerOptions, oldOptions: CompilerOptions) {
|
||||
if (oldOptions === newOptions) {
|
||||
return false;
|
||||
}
|
||||
export function compilerOptionsAffectSemanticDiagnostics(newOptions: CompilerOptions, oldOptions: CompilerOptions): boolean {
|
||||
return oldOptions !== newOptions &&
|
||||
semanticDiagnosticsOptionDeclarations.some(option => !isJsonEqual(getCompilerOptionValue(oldOptions, option), getCompilerOptionValue(newOptions, option)));
|
||||
}
|
||||
|
||||
return optionDeclarations.some(option => (!!option.strictFlag && getStrictOptionValue(newOptions, option.name as StrictOptionName) !== getStrictOptionValue(oldOptions, option.name as StrictOptionName)) ||
|
||||
(!!option.affectsSemanticDiagnostics && !newOptions[option.name] !== !oldOptions[option.name]));
|
||||
export function getCompilerOptionValue(options: CompilerOptions, option: CommandLineOption): unknown {
|
||||
return option.strictFlag ? getStrictOptionValue(options, option.name as StrictOptionName) : options[option.name];
|
||||
}
|
||||
|
||||
export function hasZeroOrOneAsteriskCharacter(str: string): boolean {
|
||||
@@ -8380,4 +8365,8 @@ namespace ts {
|
||||
// '/// <reference no-default-lib="true"/>' directive.
|
||||
return options.skipLibCheck && sourceFile.isDeclarationFile || options.skipDefaultLibCheck && sourceFile.hasNoDefaultLib;
|
||||
}
|
||||
|
||||
export function isJsonEqual(a: unknown, b: unknown): boolean {
|
||||
return a === b || typeof a === "object" && a !== null && typeof b === "object" && b !== null && equalOwnProperties(a as MapLike<unknown>, b as MapLike<unknown>, isJsonEqual);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -546,7 +546,8 @@ namespace ts {
|
||||
},
|
||||
maxNumberOfFilesToIterateForInvalidation: host.maxNumberOfFilesToIterateForInvalidation,
|
||||
getCurrentProgram,
|
||||
writeLog
|
||||
writeLog,
|
||||
readDirectory: (path, extensions, exclude, include, depth?) => directoryStructureHost.readDirectory!(path, extensions, exclude, include, depth),
|
||||
};
|
||||
// Cache for the module resolution
|
||||
const resolutionCache = createResolutionCache(compilerHost, configFileName ?
|
||||
|
||||
@@ -2502,9 +2502,7 @@ Actual: ${stringify(fullActual)}`);
|
||||
|
||||
const { changes, commands } = this.languageService.getCombinedCodeFix({ type: "file", fileName: this.activeFile.fileName }, fixId, this.formatCodeSettings, ts.emptyOptions);
|
||||
assert.deepEqual<ReadonlyArray<{}> | undefined>(commands, expectedCommands);
|
||||
assert(changes.every(c => c.fileName === this.activeFile.fileName), "TODO: support testing codefixes that touch multiple files");
|
||||
this.applyChanges(changes);
|
||||
this.verifyCurrentFileContent(newFileContent);
|
||||
this.verifyNewContent({ newFileContent }, changes);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3389,6 +3387,19 @@ Actual: ${stringify(fullActual)}`);
|
||||
private getApplicableRefactorsWorker(positionOrRange: number | ts.TextRange, fileName: string, preferences = ts.emptyOptions): ReadonlyArray<ts.ApplicableRefactorInfo> {
|
||||
return this.languageService.getApplicableRefactors(fileName, positionOrRange, preferences) || ts.emptyArray;
|
||||
}
|
||||
|
||||
public generateTypes(examples: ReadonlyArray<FourSlashInterface.GenerateTypesOptions>): void {
|
||||
for (const { name = "example", value, output, outputBaseline } of examples) {
|
||||
const actual = ts.generateTypesForModule(name, value, this.formatCodeSettings);
|
||||
if (outputBaseline) {
|
||||
if (actual === undefined) throw ts.Debug.fail();
|
||||
Harness.Baseline.runBaseline(ts.combinePaths("generateTypes", outputBaseline + ts.Extension.Dts), actual);
|
||||
}
|
||||
else {
|
||||
assert.equal(actual, output, `generateTypes output for ${name} does not match`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateTextRangeForTextChanges({ pos, end }: ts.TextRange, textChanges: ReadonlyArray<ts.TextChange>): ts.TextRange {
|
||||
@@ -3442,7 +3453,7 @@ Actual: ${stringify(fullActual)}`);
|
||||
// Parse out the files and their metadata
|
||||
const testData = parseTestData(absoluteBasePath, content, absoluteFileName);
|
||||
const state = new TestState(absoluteBasePath, testType, testData);
|
||||
const output = ts.transpileModule(content, { reportDiagnostics: true });
|
||||
const output = ts.transpileModule(content, { reportDiagnostics: true, compilerOptions: { target: ts.ScriptTarget.ES2015 } });
|
||||
if (output.diagnostics!.length > 0) {
|
||||
throw new Error(`Syntax error in ${absoluteBasePath}: ${output.diagnostics![0].messageText}`);
|
||||
}
|
||||
@@ -4512,6 +4523,18 @@ namespace FourSlashInterface {
|
||||
public noMoveToNewFile(): void {
|
||||
this.state.noMoveToNewFile();
|
||||
}
|
||||
|
||||
public generateTypes(...options: GenerateTypesOptions[]): void {
|
||||
this.state.generateTypes(options);
|
||||
}
|
||||
}
|
||||
|
||||
export interface GenerateTypesOptions {
|
||||
readonly name?: string;
|
||||
readonly value: unknown;
|
||||
// Exactly one of these should be set:
|
||||
readonly output?: string;
|
||||
readonly outputBaseline?: string;
|
||||
}
|
||||
|
||||
export class Edit {
|
||||
@@ -4901,7 +4924,7 @@ namespace FourSlashInterface {
|
||||
export interface VerifyCodeFixAllOptions {
|
||||
fixId: string;
|
||||
fixAllDescription: string;
|
||||
newFileContent: string;
|
||||
newFileContent: NewFileContent;
|
||||
commands: ReadonlyArray<{}>;
|
||||
}
|
||||
|
||||
|
||||
@@ -187,9 +187,10 @@ interface Array<T> {}`
|
||||
}
|
||||
|
||||
export function checkArray(caption: string, actual: ReadonlyArray<string>, expected: ReadonlyArray<string>) {
|
||||
checkMapKeys(caption, arrayToMap(actual, identity), expected);
|
||||
assert.equal(actual.length, expected.length, `${caption}: incorrect actual number of files, expected:\r\n${expected.join("\r\n")}\r\ngot: ${actual.join("\r\n")}`);
|
||||
for (const f of expected) {
|
||||
assert.equal(true, contains(actual, f), `${caption}: expected to find ${f} in ${actual}`);
|
||||
assert.isTrue(contains(actual, f), `${caption}: expected to find ${f} in ${actual}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -654,7 +655,7 @@ interface Array<T> {}`
|
||||
invokeWatcherCallbacks(this.watchedDirectoriesRecursive.get(this.toPath(folderFullPath))!, cb => this.directoryCallback(cb, relativePath));
|
||||
}
|
||||
|
||||
invokeFileWatcher(fileFullPath: string, eventKind: FileWatcherEventKind, useFileNameInCallback?: boolean) {
|
||||
private invokeFileWatcher(fileFullPath: string, eventKind: FileWatcherEventKind, useFileNameInCallback?: boolean) {
|
||||
invokeWatcherCallbacks(this.watchedFiles.get(this.toPath(fileFullPath))!, ({ cb, fileName }) => cb(useFileNameInCallback ? fileName : fileFullPath, eventKind));
|
||||
}
|
||||
|
||||
@@ -934,7 +935,12 @@ interface Array<T> {}`
|
||||
const folder = this.fs.get(base) as FsFolder;
|
||||
Debug.assert(isFsFolder(folder));
|
||||
|
||||
this.addFileOrFolderInFolder(folder, file);
|
||||
if (!this.fs.has(file.path)) {
|
||||
this.addFileOrFolderInFolder(folder, file);
|
||||
}
|
||||
else {
|
||||
this.modifyFile(path, content);
|
||||
}
|
||||
}
|
||||
|
||||
write(message: string) {
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace ts.server {
|
||||
export const ActionSet: ActionSet = "action::set";
|
||||
export const ActionInvalidate: ActionInvalidate = "action::invalidate";
|
||||
export const ActionPackageInstalled: ActionPackageInstalled = "action::packageInstalled";
|
||||
export const ActionValueInspected: ActionValueInspected = "action::valueInspected";
|
||||
export const EventTypesRegistry: EventTypesRegistry = "event::typesRegistry";
|
||||
export const EventBeginInstallTypes: EventBeginInstallTypes = "event::beginInstallTypes";
|
||||
export const EventEndInstallTypes: EventEndInstallTypes = "event::endInstallTypes";
|
||||
|
||||
+16
-3
@@ -2,6 +2,7 @@ declare namespace ts.server {
|
||||
export type ActionSet = "action::set";
|
||||
export type ActionInvalidate = "action::invalidate";
|
||||
export type ActionPackageInstalled = "action::packageInstalled";
|
||||
export type ActionValueInspected = "action::valueInspected";
|
||||
export type EventTypesRegistry = "event::typesRegistry";
|
||||
export type EventBeginInstallTypes = "event::beginInstallTypes";
|
||||
export type EventEndInstallTypes = "event::endInstallTypes";
|
||||
@@ -12,7 +13,7 @@ declare namespace ts.server {
|
||||
}
|
||||
|
||||
export interface TypingInstallerResponse {
|
||||
readonly kind: ActionSet | ActionInvalidate | EventTypesRegistry | ActionPackageInstalled | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed;
|
||||
readonly kind: ActionSet | ActionInvalidate | EventTypesRegistry | ActionPackageInstalled | ActionValueInspected | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed;
|
||||
}
|
||||
|
||||
export interface TypingInstallerRequestWithProjectName {
|
||||
@@ -20,7 +21,7 @@ declare namespace ts.server {
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export type TypingInstallerRequestUnion = DiscoverTypings | CloseProject | TypesRegistryRequest | InstallPackageRequest;
|
||||
export type TypingInstallerRequestUnion = DiscoverTypings | CloseProject | TypesRegistryRequest | InstallPackageRequest | InspectValueRequest;
|
||||
|
||||
export interface DiscoverTypings extends TypingInstallerRequestWithProjectName {
|
||||
readonly fileNames: string[];
|
||||
@@ -47,6 +48,12 @@ declare namespace ts.server {
|
||||
readonly projectRootPath: Path;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface InspectValueRequest {
|
||||
readonly kind: "inspectValue";
|
||||
readonly options: InspectValueOptions;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface TypesRegistryResponse extends TypingInstallerResponse {
|
||||
readonly kind: EventTypesRegistry;
|
||||
@@ -59,6 +66,12 @@ declare namespace ts.server {
|
||||
readonly message: string;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface InspectValueResponse {
|
||||
readonly kind: ActionValueInspected;
|
||||
readonly result: ValueInfo;
|
||||
}
|
||||
|
||||
export interface InitializationFailedResponse extends TypingInstallerResponse {
|
||||
readonly kind: EventInitializationFailed;
|
||||
readonly message: string;
|
||||
@@ -106,5 +119,5 @@ declare namespace ts.server {
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export type TypingInstallerResponseUnion = SetTypings | InvalidateCachedTypings | TypesRegistryResponse | PackageInstalledResponse | InstallTypes | InitializationFailedResponse;
|
||||
export type TypingInstallerResponseUnion = SetTypings | InvalidateCachedTypings | TypesRegistryResponse | PackageInstalledResponse | InspectValueResponse | InstallTypes | InitializationFailedResponse;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -254,6 +254,11 @@ namespace ts.server {
|
||||
installPackage(options: InstallPackageOptions): Promise<ApplyCodeActionCommandResult> {
|
||||
return this.typingsCache.installPackage({ ...options, projectName: this.projectName, projectRootPath: this.toPath(this.currentDirectory) });
|
||||
}
|
||||
/* @internal */
|
||||
inspectValue(options: InspectValueOptions): Promise<ValueInfo> {
|
||||
return this.typingsCache.inspectValue(options);
|
||||
}
|
||||
|
||||
private get typingsCache(): TypingsCache {
|
||||
return this.projectService.typingsCache;
|
||||
}
|
||||
@@ -352,6 +357,10 @@ namespace ts.server {
|
||||
return this.projectService.host.readFile(fileName);
|
||||
}
|
||||
|
||||
writeFile(fileName: string, content: string): void {
|
||||
return this.projectService.host.writeFile(fileName, content);
|
||||
}
|
||||
|
||||
fileExists(file: string): boolean {
|
||||
// As an optimization, don't hit the disks for files we already know don't exist
|
||||
// (because we're watching for their creation).
|
||||
|
||||
@@ -1123,6 +1123,9 @@ namespace ts.server.protocol {
|
||||
* Optional modifiers for the kind (such as 'public').
|
||||
*/
|
||||
kindModifiers: string;
|
||||
|
||||
/** Span of text to rename. */
|
||||
triggerSpan: TextSpan;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+25
-14
@@ -336,16 +336,23 @@ namespace ts.server {
|
||||
function combineProjectOutputForReferences(projects: Projects, defaultProject: Project, initialLocation: sourcemaps.SourceMappableLocation, projectService: ProjectService): ReadonlyArray<ReferencedSymbol> {
|
||||
const outputs: ReferencedSymbol[] = [];
|
||||
|
||||
combineProjectOutputWorker<sourcemaps.SourceMappableLocation>(projects, defaultProject, initialLocation, projectService, ({ project, location }, tryAddToTodo) => {
|
||||
combineProjectOutputWorker<sourcemaps.SourceMappableLocation>(projects, defaultProject, initialLocation, projectService, ({ project, location }, getMappedLocation) => {
|
||||
for (const outputReferencedSymbol of project.getLanguageService().findReferences(location.fileName, location.position) || emptyArray) {
|
||||
let symbolToAddTo = find(outputs, o => documentSpansEqual(o.definition, outputReferencedSymbol.definition));
|
||||
const mappedDefinitionFile = getMappedLocation(project, documentSpanLocation(outputReferencedSymbol.definition));
|
||||
const definition: ReferencedSymbolDefinitionInfo = mappedDefinitionFile === undefined ? outputReferencedSymbol.definition : {
|
||||
...outputReferencedSymbol.definition,
|
||||
textSpan: createTextSpan(mappedDefinitionFile.position, outputReferencedSymbol.definition.textSpan.length),
|
||||
fileName: mappedDefinitionFile.fileName,
|
||||
};
|
||||
let symbolToAddTo = find(outputs, o => documentSpansEqual(o.definition, definition));
|
||||
if (!symbolToAddTo) {
|
||||
symbolToAddTo = { definition: outputReferencedSymbol.definition, references: [] };
|
||||
symbolToAddTo = { definition, references: [] };
|
||||
outputs.push(symbolToAddTo);
|
||||
}
|
||||
|
||||
for (const ref of outputReferencedSymbol.references) {
|
||||
if (!contains(symbolToAddTo.references, ref, documentSpansEqual) && !tryAddToTodo(project, documentSpanLocation(ref))) {
|
||||
// If it's in a mapped file, that is added to the todo list by `getMappedLocation`.
|
||||
if (!contains(symbolToAddTo.references, ref, documentSpansEqual) && !getMappedLocation(project, documentSpanLocation(ref))) {
|
||||
symbolToAddTo.references.push(ref);
|
||||
}
|
||||
}
|
||||
@@ -373,12 +380,17 @@ namespace ts.server {
|
||||
}
|
||||
}
|
||||
|
||||
type CombineProjectOutputCallback<TLocation extends sourcemaps.SourceMappableLocation | undefined> = (
|
||||
where: ProjectAndLocation<TLocation>,
|
||||
getMappedLocation: (project: Project, location: sourcemaps.SourceMappableLocation) => sourcemaps.SourceMappableLocation | undefined,
|
||||
) => void;
|
||||
|
||||
function combineProjectOutputWorker<TLocation extends sourcemaps.SourceMappableLocation | undefined>(
|
||||
projects: Projects,
|
||||
defaultProject: Project,
|
||||
initialLocation: TLocation,
|
||||
projectService: ProjectService,
|
||||
cb: (where: ProjectAndLocation<TLocation>, getMappedLocation: (project: Project, location: sourcemaps.SourceMappableLocation) => boolean) => void,
|
||||
cb: CombineProjectOutputCallback<TLocation>,
|
||||
getDefinition: (() => sourcemaps.SourceMappableLocation | undefined) | undefined,
|
||||
): void {
|
||||
let toDo: ProjectAndLocation<TLocation>[] | undefined;
|
||||
@@ -417,13 +429,13 @@ namespace ts.server {
|
||||
projectService: ProjectService,
|
||||
toDo: ProjectAndLocation<TLocation>[] | undefined,
|
||||
seenProjects: Map<true>,
|
||||
cb: (where: ProjectAndLocation<TLocation>, getMappedLocation: (project: Project, location: sourcemaps.SourceMappableLocation) => boolean) => void,
|
||||
cb: CombineProjectOutputCallback<TLocation>,
|
||||
): ProjectAndLocation<TLocation>[] | undefined {
|
||||
if (projectAndLocation.project.getCancellationToken().isCancellationRequested()) return undefined; // Skip rest of toDo if cancelled
|
||||
cb(projectAndLocation, (project, location) => {
|
||||
seenProjects.set(projectAndLocation.project.projectName, true);
|
||||
const originalLocation = projectService.getOriginalLocationEnsuringConfiguredProject(project, location);
|
||||
if (!originalLocation) return false;
|
||||
if (!originalLocation) return undefined;
|
||||
|
||||
const originalScriptInfo = projectService.getScriptInfo(originalLocation.fileName)!;
|
||||
toDo = toDo || [];
|
||||
@@ -437,7 +449,7 @@ namespace ts.server {
|
||||
for (const symlinkedProject of symlinkedProjects) addToTodo({ project: symlinkedProject, location: originalLocation as TLocation }, toDo!, seenProjects);
|
||||
});
|
||||
}
|
||||
return true;
|
||||
return originalLocation;
|
||||
});
|
||||
return toDo;
|
||||
}
|
||||
@@ -1149,13 +1161,12 @@ namespace ts.server {
|
||||
if (!simplifiedResult) return locations;
|
||||
|
||||
const defaultProject = this.getDefaultProject(args);
|
||||
const renameInfo = Session.mapRenameInfo(defaultProject.getLanguageService().getRenameInfo(file, position));
|
||||
const renameInfo: protocol.RenameInfo = this.mapRenameInfo(defaultProject.getLanguageService().getRenameInfo(file, position), Debug.assertDefined(this.projectService.getScriptInfo(file)));
|
||||
return { info: renameInfo, locs: this.toSpanGroups(locations) };
|
||||
}
|
||||
|
||||
// strips 'triggerSpan'
|
||||
private static mapRenameInfo({ canRename, localizedErrorMessage, displayName, fullDisplayName, kind, kindModifiers }: RenameInfo): protocol.RenameInfo {
|
||||
return { canRename, localizedErrorMessage, displayName, fullDisplayName, kind, kindModifiers };
|
||||
private mapRenameInfo({ canRename, localizedErrorMessage, displayName, fullDisplayName, kind, kindModifiers, triggerSpan }: RenameInfo, scriptInfo: ScriptInfo): protocol.RenameInfo {
|
||||
return { canRename, localizedErrorMessage, displayName, fullDisplayName, kind, kindModifiers, triggerSpan: this.toLocationTextSpan(triggerSpan, scriptInfo) };
|
||||
}
|
||||
|
||||
private toSpanGroups(locations: ReadonlyArray<RenameLocation>): ReadonlyArray<protocol.SpanGroup> {
|
||||
@@ -1818,8 +1829,8 @@ namespace ts.server {
|
||||
private applyCodeActionCommand(args: protocol.ApplyCodeActionCommandRequestArgs): {} {
|
||||
const commands = args.command as CodeActionCommand | CodeActionCommand[]; // They should be sending back the command we sent them.
|
||||
for (const command of toArray(commands)) {
|
||||
const { project } = this.getFileAndProject(command);
|
||||
project.getLanguageService().applyCodeActionCommand(command).then(
|
||||
const { file, project } = this.getFileAndProject(command);
|
||||
project.getLanguageService().applyCodeActionCommand(command, this.getFormatOptions(file)).then(
|
||||
_result => { /* TODO: GH#20447 report success message? */ },
|
||||
_error => { /* TODO: GH#20447 report errors */ });
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ namespace ts.server {
|
||||
export interface ITypingsInstaller {
|
||||
isKnownTypesPackageName(name: string): boolean;
|
||||
installPackage(options: InstallPackageOptionsWithProject): Promise<ApplyCodeActionCommandResult>;
|
||||
/* @internal */
|
||||
inspectValue(options: InspectValueOptions): Promise<ValueInfo>;
|
||||
enqueueInstallTypingsRequest(p: Project, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray<string> | undefined): void;
|
||||
attach(projectService: ProjectService): void;
|
||||
onProjectClosed(p: Project): void;
|
||||
@@ -18,6 +20,7 @@ namespace ts.server {
|
||||
isKnownTypesPackageName: returnFalse,
|
||||
// Should never be called because we never provide a types registry.
|
||||
installPackage: notImplemented,
|
||||
inspectValue: notImplemented,
|
||||
enqueueInstallTypingsRequest: noop,
|
||||
attach: noop,
|
||||
onProjectClosed: noop,
|
||||
@@ -95,6 +98,10 @@ namespace ts.server {
|
||||
return this.installer.installPackage(options);
|
||||
}
|
||||
|
||||
inspectValue(options: InspectValueOptions): Promise<ValueInfo> {
|
||||
return this.installer.inspectValue(options);
|
||||
}
|
||||
|
||||
enqueueInstallTypingsForProject(project: Project, unresolvedImports: SortedReadonlyArray<string> | undefined, forceRefresh: boolean) {
|
||||
const typeAcquisition = project.getTypeAcquisition();
|
||||
|
||||
|
||||
@@ -14,17 +14,10 @@ namespace ts.codefix {
|
||||
getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, err) => convertToAsyncFunction(changes, err.file, err.start, context.program.getTypeChecker(), context)),
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
custom type to encapsulate information for variable declarations synthesized in the refactor
|
||||
numberOfUsesOriginal - number of times the variable should be assigned in the refactor
|
||||
numberOfUsesSynthesized - count of how many times the variable has been assigned so far
|
||||
At the end of the refactor, numberOfUsesOriginal should === numberOfUsesSynthesized
|
||||
*/
|
||||
interface SynthIdentifier {
|
||||
identifier: Identifier;
|
||||
types: Type[];
|
||||
numberOfAssignmentsOriginal: number;
|
||||
numberOfAssignmentsOriginal: number; // number of times the variable should be assigned in the refactor
|
||||
}
|
||||
|
||||
interface SymbolAndIdentifier {
|
||||
@@ -179,9 +172,9 @@ namespace ts.codefix {
|
||||
|
||||
// if the identifier refers to a function we want to add the new synthesized variable for the declaration (ex. blob in let blob = res(arg))
|
||||
// Note - the choice of the last call signature is arbitrary
|
||||
if (lastCallSignature && lastCallSignature.parameters.length && !synthNamesMap.has(symbolIdString)) {
|
||||
const firstParameter = lastCallSignature.parameters[0];
|
||||
const ident = isParameter(firstParameter.valueDeclaration) && tryCast(firstParameter.valueDeclaration.name, isIdentifier) || createOptimisticUniqueName("result");
|
||||
if (lastCallSignature && !isFunctionLikeDeclaration(node.parent) && !synthNamesMap.has(symbolIdString)) {
|
||||
const firstParameter = firstOrUndefined(lastCallSignature.parameters);
|
||||
const ident = firstParameter && isParameter(firstParameter.valueDeclaration) && tryCast(firstParameter.valueDeclaration.name, isIdentifier) || createOptimisticUniqueName("result");
|
||||
const synthName = getNewNameIfConflict(ident, collidingSymbolMap);
|
||||
synthNamesMap.set(symbolIdString, synthName);
|
||||
allVarNames.push({ identifier: synthName.identifier, symbol });
|
||||
@@ -234,9 +227,7 @@ namespace ts.codefix {
|
||||
|
||||
if (renameInfo) {
|
||||
const type = checker.getTypeAtLocation(node);
|
||||
if (type) {
|
||||
originalType.set(getNodeId(clone).toString(), type);
|
||||
}
|
||||
originalType.set(getNodeId(clone).toString(), type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -320,7 +311,7 @@ namespace ts.codefix {
|
||||
const tryBlock = createBlock(transformExpression(node.expression, transformer, node, prevArgName));
|
||||
|
||||
const transformationBody = getTransformationBody(func, prevArgName, argName, node, transformer);
|
||||
const catchArg = argName.identifier.text.length > 0 ? argName.identifier.text : "e";
|
||||
const catchArg = argName ? argName.identifier.text : "e";
|
||||
const catchClause = createCatchClause(catchArg, createBlock(transformationBody));
|
||||
|
||||
/*
|
||||
@@ -362,7 +353,7 @@ namespace ts.codefix {
|
||||
|
||||
const transformationBody2 = getTransformationBody(rej, prevArgName, argNameRej, node, transformer);
|
||||
|
||||
const catchArg = argNameRej.identifier.text.length > 0 ? argNameRej.identifier.text : "e";
|
||||
const catchArg = argNameRej ? argNameRej.identifier.text : "e";
|
||||
const catchClause = createCatchClause(catchArg, createBlock(transformationBody2));
|
||||
|
||||
return [createTry(tryBlock, catchClause, /* finallyBlock */ undefined) as Statement];
|
||||
@@ -379,21 +370,25 @@ namespace ts.codefix {
|
||||
function transformPromiseCall(node: Expression, transformer: Transformer, prevArgName?: SynthIdentifier): Statement[] {
|
||||
const shouldReturn = transformer.setOfExpressionsToReturn.get(getNodeId(node).toString());
|
||||
// the identifier is empty when the handler (.then()) ignores the argument - In this situation we do not need to save the result of the promise returning call
|
||||
const hasPrevArgName = prevArgName && prevArgName.identifier.text.length > 0;
|
||||
const originalNodeParent = node.original ? node.original.parent : node.parent;
|
||||
if (hasPrevArgName && !shouldReturn && (!originalNodeParent || isPropertyAccessExpression(originalNodeParent))) {
|
||||
return createVariableDeclarationOrAssignment(prevArgName!, createAwait(node), transformer).concat(); // hack to make the types match
|
||||
if (prevArgName && !shouldReturn && (!originalNodeParent || isPropertyAccessExpression(originalNodeParent))) {
|
||||
return createTransformedStatement(prevArgName, createAwait(node), transformer);
|
||||
}
|
||||
else if (!hasPrevArgName && !shouldReturn && (!originalNodeParent || isPropertyAccessExpression(originalNodeParent))) {
|
||||
else if (!prevArgName && !shouldReturn && (!originalNodeParent || isPropertyAccessExpression(originalNodeParent))) {
|
||||
return [createStatement(createAwait(node))];
|
||||
}
|
||||
|
||||
return [createReturn(getSynthesizedDeepClone(node))];
|
||||
}
|
||||
|
||||
function createVariableDeclarationOrAssignment(prevArgName: SynthIdentifier, rightHandSide: Expression, transformer: Transformer): NodeArray<Statement> {
|
||||
function createTransformedStatement(prevArgName: SynthIdentifier | undefined, rightHandSide: Expression, transformer: Transformer): MutableNodeArray<Statement> {
|
||||
if (!prevArgName || prevArgName.identifier.text.length === 0) {
|
||||
// if there's no argName to assign to, there still might be side effects
|
||||
return createNodeArray([createStatement(rightHandSide)]);
|
||||
}
|
||||
|
||||
if (prevArgName.types.length < prevArgName.numberOfAssignmentsOriginal) {
|
||||
// if the variable has already been declared, we don't need "let" or "const"
|
||||
return createNodeArray([createStatement(createAssignment(getSynthesizedDeepClone(prevArgName.identifier), rightHandSide))]);
|
||||
}
|
||||
|
||||
@@ -402,42 +397,47 @@ namespace ts.codefix {
|
||||
}
|
||||
|
||||
// should be kept up to date with isFixablePromiseArgument in suggestionDiagnostics.ts
|
||||
function getTransformationBody(func: Node, prevArgName: SynthIdentifier | undefined, argName: SynthIdentifier, parent: CallExpression, transformer: Transformer): NodeArray<Statement> {
|
||||
function getTransformationBody(func: Expression, prevArgName: SynthIdentifier | undefined, argName: SynthIdentifier | undefined, parent: CallExpression, transformer: Transformer): NodeArray<Statement> {
|
||||
|
||||
const hasPrevArgName = prevArgName && prevArgName.identifier.text.length > 0;
|
||||
const hasArgName = argName && argName.identifier.text.length > 0;
|
||||
const shouldReturn = transformer.setOfExpressionsToReturn.get(getNodeId(parent).toString());
|
||||
switch (func.kind) {
|
||||
case SyntaxKind.NullKeyword:
|
||||
// do not produce a transformed statement for a null argument
|
||||
break;
|
||||
case SyntaxKind.Identifier:
|
||||
// identifier includes undefined
|
||||
if (!hasArgName) break;
|
||||
case SyntaxKind.Identifier: // identifier includes undefined
|
||||
if (!argName) {
|
||||
// undefined was argument passed to promise handler
|
||||
break;
|
||||
}
|
||||
|
||||
const synthCall = createCall(getSynthesizedDeepClone(func) as Identifier, /*typeArguments*/ undefined, [argName.identifier]);
|
||||
const synthCall = createCall(getSynthesizedDeepClone(func) as Identifier, /*typeArguments*/ undefined, argName ? [argName.identifier] : []);
|
||||
if (shouldReturn) {
|
||||
return createNodeArray([createReturn(synthCall)]);
|
||||
}
|
||||
|
||||
if (!hasPrevArgName) break;
|
||||
|
||||
const type = transformer.originalTypeMap.get(getNodeId(func).toString());
|
||||
const callSignatures = type && transformer.checker.getSignaturesOfType(type, SignatureKind.Call);
|
||||
const returnType = callSignatures && callSignatures[0].getReturnType();
|
||||
const varDeclOrAssignment = createVariableDeclarationOrAssignment(prevArgName!, createAwait(synthCall), transformer);
|
||||
prevArgName!.types.push(returnType!);
|
||||
const type = transformer.originalTypeMap.get(getNodeId(func).toString()) || transformer.checker.getTypeAtLocation(func);
|
||||
const callSignatures = transformer.checker.getSignaturesOfType(type, SignatureKind.Call);
|
||||
if (!callSignatures.length) {
|
||||
// if identifier in handler has no call signatures, it's invalid
|
||||
codeActionSucceeded = false;
|
||||
break;
|
||||
}
|
||||
const returnType = callSignatures[0].getReturnType();
|
||||
const varDeclOrAssignment = createTransformedStatement(prevArgName, createAwait(synthCall), transformer);
|
||||
if (prevArgName) {
|
||||
prevArgName.types.push(returnType);
|
||||
}
|
||||
return varDeclOrAssignment;
|
||||
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.FunctionExpression:
|
||||
case SyntaxKind.ArrowFunction:
|
||||
case SyntaxKind.ArrowFunction: {
|
||||
const funcBody = (func as FunctionExpression | ArrowFunction).body;
|
||||
// Arrow functions with block bodies { } will enter this control flow
|
||||
if (isFunctionLikeDeclaration(func) && func.body && isBlock(func.body) && func.body.statements) {
|
||||
if (isBlock(funcBody)) {
|
||||
let refactoredStmts: Statement[] = [];
|
||||
let seenReturnStatement = false;
|
||||
|
||||
for (const statement of func.body.statements) {
|
||||
for (const statement of funcBody.statements) {
|
||||
if (isReturnStatement(statement)) {
|
||||
seenReturnStatement = true;
|
||||
}
|
||||
@@ -451,30 +451,34 @@ namespace ts.codefix {
|
||||
}
|
||||
|
||||
return shouldReturn ? getSynthesizedDeepClones(createNodeArray(refactoredStmts)) :
|
||||
removeReturns(createNodeArray(refactoredStmts), prevArgName!.identifier, transformer.constIdentifiers, seenReturnStatement);
|
||||
removeReturns(createNodeArray(refactoredStmts), prevArgName!.identifier, transformer, seenReturnStatement);
|
||||
}
|
||||
else {
|
||||
const funcBody = (<ArrowFunction>func).body;
|
||||
const innerRetStmts = getReturnStatementsWithPromiseHandlers(createReturn(funcBody as Expression));
|
||||
const innerRetStmts = getReturnStatementsWithPromiseHandlers(createReturn(funcBody));
|
||||
const innerCbBody = getInnerTransformationBody(transformer, innerRetStmts, prevArgName);
|
||||
|
||||
if (innerCbBody.length > 0) {
|
||||
return createNodeArray(innerCbBody);
|
||||
}
|
||||
|
||||
if (hasPrevArgName && !shouldReturn) {
|
||||
if (!shouldReturn) {
|
||||
const type = transformer.checker.getTypeAtLocation(func);
|
||||
const returnType = getLastCallSignature(type, transformer.checker)!.getReturnType();
|
||||
const varDeclOrAssignment = createVariableDeclarationOrAssignment(prevArgName!, getSynthesizedDeepClone(funcBody) as Expression, transformer);
|
||||
prevArgName!.types.push(returnType);
|
||||
return varDeclOrAssignment;
|
||||
const rightHandSide = getSynthesizedDeepClone(funcBody);
|
||||
const possiblyAwaitedRightHandSide = !!transformer.checker.getPromisedTypeOfPromise(returnType) ? createAwait(rightHandSide) : rightHandSide;
|
||||
const transformedStatement = createTransformedStatement(prevArgName, possiblyAwaitedRightHandSide, transformer);
|
||||
if (prevArgName) {
|
||||
prevArgName.types.push(returnType);
|
||||
}
|
||||
return transformedStatement;
|
||||
}
|
||||
else {
|
||||
return createNodeArray([createReturn(getSynthesizedDeepClone(funcBody) as Expression)]);
|
||||
return createNodeArray([createReturn(getSynthesizedDeepClone(funcBody))]);
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
// We've found a transformation body we don't know how to handle, so the refactoring should no-op to avoid deleting code.
|
||||
// If no cases apply, we've found a transformation body we don't know how to handle, so the refactoring should no-op to avoid deleting code.
|
||||
codeActionSucceeded = false;
|
||||
break;
|
||||
}
|
||||
@@ -487,13 +491,14 @@ namespace ts.codefix {
|
||||
}
|
||||
|
||||
|
||||
function removeReturns(stmts: NodeArray<Statement>, prevArgName: Identifier, constIdentifiers: Identifier[], seenReturnStatement: boolean): NodeArray<Statement> {
|
||||
function removeReturns(stmts: NodeArray<Statement>, prevArgName: Identifier, transformer: Transformer, seenReturnStatement: boolean): NodeArray<Statement> {
|
||||
const ret: Statement[] = [];
|
||||
for (const stmt of stmts) {
|
||||
if (isReturnStatement(stmt)) {
|
||||
if (stmt.expression) {
|
||||
const possiblyAwaitedExpression = isPromiseReturningExpression(stmt.expression, transformer.checker) ? createAwait(stmt.expression) : stmt.expression;
|
||||
ret.push(createVariableStatement(/*modifiers*/ undefined,
|
||||
(createVariableDeclarationList([createVariableDeclaration(prevArgName, /*type*/ undefined, stmt.expression)], getFlagOfIdentifier(prevArgName, constIdentifiers)))));
|
||||
(createVariableDeclarationList([createVariableDeclaration(prevArgName, /*type*/ undefined, possiblyAwaitedExpression)], getFlagOfIdentifier(prevArgName, transformer.constIdentifiers)))));
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -504,7 +509,7 @@ namespace ts.codefix {
|
||||
// if block has no return statement, need to define prevArgName as undefined to prevent undeclared variables
|
||||
if (!seenReturnStatement) {
|
||||
ret.push(createVariableStatement(/*modifiers*/ undefined,
|
||||
(createVariableDeclarationList([createVariableDeclaration(prevArgName, /*type*/ undefined, createIdentifier("undefined"))], getFlagOfIdentifier(prevArgName, constIdentifiers)))));
|
||||
(createVariableDeclarationList([createVariableDeclaration(prevArgName, /*type*/ undefined, createIdentifier("undefined"))], getFlagOfIdentifier(prevArgName, transformer.constIdentifiers)))));
|
||||
}
|
||||
|
||||
return createNodeArray(ret);
|
||||
@@ -531,7 +536,7 @@ namespace ts.codefix {
|
||||
return innerCbBody;
|
||||
}
|
||||
|
||||
function getArgName(funcNode: Node, transformer: Transformer): SynthIdentifier {
|
||||
function getArgName(funcNode: Expression, transformer: Transformer): SynthIdentifier | undefined {
|
||||
|
||||
const numberOfAssignmentsOriginal = 0;
|
||||
const types: Type[] = [];
|
||||
@@ -541,20 +546,21 @@ namespace ts.codefix {
|
||||
if (isFunctionLikeDeclaration(funcNode)) {
|
||||
if (funcNode.parameters.length > 0) {
|
||||
const param = funcNode.parameters[0].name as Identifier;
|
||||
name = getMapEntryIfExists(param);
|
||||
name = getMapEntryOrDefault(param);
|
||||
}
|
||||
}
|
||||
else if (isIdentifier(funcNode)) {
|
||||
name = getMapEntryIfExists(funcNode);
|
||||
name = getMapEntryOrDefault(funcNode);
|
||||
}
|
||||
|
||||
if (!name || name.identifier === undefined || name.identifier.text === "_" || name.identifier.text === "undefined") {
|
||||
return { identifier: createIdentifier(""), types, numberOfAssignmentsOriginal };
|
||||
// return undefined argName when arg is null or undefined
|
||||
if (!name || name.identifier.text === "undefined") {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return name;
|
||||
|
||||
function getMapEntryIfExists(identifier: Identifier): SynthIdentifier {
|
||||
function getMapEntryOrDefault(identifier: Identifier): SynthIdentifier {
|
||||
const originalNode = getOriginalNode(identifier);
|
||||
const symbol = getSymbol(originalNode);
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/* @internal */
|
||||
namespace ts.codefix {
|
||||
const fixId = "fixCannotFindModule";
|
||||
const fixName = "fixCannotFindModule";
|
||||
const fixIdInstallTypesPackage = "installTypesPackage";
|
||||
const fixIdGenerateTypes = "generateTypes";
|
||||
|
||||
const errorCodeCannotFindModule = Diagnostics.Cannot_find_module_0.code;
|
||||
const errorCodes = [
|
||||
errorCodeCannotFindModule,
|
||||
@@ -10,26 +13,141 @@ namespace ts.codefix {
|
||||
errorCodes,
|
||||
getCodeActions: context => {
|
||||
const { host, sourceFile, span: { start } } = context;
|
||||
const packageName = getTypesPackageNameToInstall(host, sourceFile, start, context.errorCode);
|
||||
return packageName === undefined ? []
|
||||
: [createCodeFixAction(fixId, /*changes*/ [], [Diagnostics.Install_0, packageName], fixId, Diagnostics.Install_all_missing_types_packages, getCommand(sourceFile.fileName, packageName))];
|
||||
const packageName = tryGetImportedPackageName(sourceFile, start);
|
||||
if (packageName === undefined) return undefined;
|
||||
const typesPackageName = getTypesPackageNameToInstall(packageName, host, context.errorCode);
|
||||
return typesPackageName === undefined
|
||||
? singleElementArray(tryGetGenerateTypesAction(context, packageName))
|
||||
: [createCodeFixAction(fixName, /*changes*/ [], [Diagnostics.Install_0, typesPackageName], fixIdInstallTypesPackage, Diagnostics.Install_all_missing_types_packages, getInstallCommand(sourceFile.fileName, typesPackageName))];
|
||||
},
|
||||
fixIds: [fixIdInstallTypesPackage, fixIdGenerateTypes],
|
||||
getAllCodeActions: context => {
|
||||
let savedTypesDir: string | null | undefined = null; // tslint:disable-line no-null-keyword
|
||||
return codeFixAll(context, errorCodes, (changes, diag, commands) => {
|
||||
const packageName = tryGetImportedPackageName(diag.file, diag.start);
|
||||
if (packageName === undefined) return undefined;
|
||||
switch (context.fixId) {
|
||||
case fixIdInstallTypesPackage: {
|
||||
const pkg = getTypesPackageNameToInstall(packageName, context.host, diag.code);
|
||||
if (pkg) {
|
||||
commands.push(getInstallCommand(diag.file.fileName, pkg));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case fixIdGenerateTypes: {
|
||||
const typesDir = savedTypesDir !== null ? savedTypesDir : savedTypesDir = getOrCreateTypesDirectory(changes, context);
|
||||
const command = typesDir === undefined ? undefined : tryGenerateTypes(typesDir, packageName, context);
|
||||
if (command) commands.push(command);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Debug.fail(`Bad fixId: ${context.fixId}`);
|
||||
}
|
||||
});
|
||||
},
|
||||
fixIds: [fixId],
|
||||
getAllCodeActions: context => codeFixAll(context, errorCodes, (_, diag, commands) => {
|
||||
const pkg = getTypesPackageNameToInstall(context.host, diag.file, diag.start, diag.code);
|
||||
if (pkg) {
|
||||
commands.push(getCommand(diag.file.fileName, pkg));
|
||||
}
|
||||
}),
|
||||
});
|
||||
|
||||
function getCommand(fileName: string, packageName: string): InstallPackageAction {
|
||||
function tryGetGenerateTypesAction(context: CodeFixContextBase, packageName: string): CodeFixAction | undefined {
|
||||
let command: GenerateTypesAction | undefined;
|
||||
const changes = textChanges.ChangeTracker.with(context, t => {
|
||||
const typesDir = getOrCreateTypesDirectory(t, context);
|
||||
command = typesDir === undefined ? undefined : tryGenerateTypes(typesDir, packageName, context);
|
||||
});
|
||||
return command && createCodeFixAction(fixName, changes, [Diagnostics.Generate_types_for_0, packageName], fixIdGenerateTypes, Diagnostics.Generate_types_for_all_packages_without_types, command);
|
||||
}
|
||||
|
||||
function tryGenerateTypes(typesDir: string, packageName: string, context: CodeFixContextBase): GenerateTypesAction | undefined {
|
||||
const file = context.sourceFile.fileName;
|
||||
const fileToGenerateTypesFor = tryResolveJSModule(packageName, getDirectoryPath(file), context.host as ModuleResolutionHost); // TODO: GH#18217
|
||||
if (fileToGenerateTypesFor === undefined) return undefined;
|
||||
|
||||
const outputFileName = resolvePath(getDirectoryPath(context.program.getCompilerOptions().configFile!.fileName), typesDir, packageName + ".d.ts");
|
||||
if (context.host.fileExists!(outputFileName)) return undefined;
|
||||
return { type: "generate types", file, fileToGenerateTypesFor, outputFileName };
|
||||
}
|
||||
|
||||
// If no types directory exists yet, adds it to tsconfig.json
|
||||
function getOrCreateTypesDirectory(changes: textChanges.ChangeTracker, context: CodeFixContextBase): string | undefined {
|
||||
const { configFile } = context.program.getCompilerOptions();
|
||||
if (!configFile) return undefined;
|
||||
|
||||
const tsconfigObjectLiteral = getTsConfigObjectLiteralExpression(configFile);
|
||||
if (!tsconfigObjectLiteral) return undefined;
|
||||
|
||||
const compilerOptionsProperty = findProperty(tsconfigObjectLiteral, "compilerOptions");
|
||||
if (!compilerOptionsProperty) {
|
||||
const newCompilerOptions = createObjectLiteral([makeDefaultBaseUrl(), makeDefaultPaths()]);
|
||||
changes.insertNodeAtObjectStart(configFile, tsconfigObjectLiteral, createJsonPropertyAssignment("compilerOptions", newCompilerOptions));
|
||||
return defaultTypesDirectoryName;
|
||||
}
|
||||
|
||||
const compilerOptions = compilerOptionsProperty.initializer;
|
||||
if (!isObjectLiteralExpression(compilerOptions)) return defaultTypesDirectoryName;
|
||||
|
||||
const baseUrl = getOrAddBaseUrl(changes, configFile, compilerOptions);
|
||||
const typesDirectoryFromPathMapping = getOrAddPathMapping(changes, configFile, compilerOptions);
|
||||
return combinePaths(baseUrl, typesDirectoryFromPathMapping);
|
||||
}
|
||||
|
||||
const defaultBaseUrl = ".";
|
||||
function makeDefaultBaseUrl(): PropertyAssignment {
|
||||
return createJsonPropertyAssignment("baseUrl", createStringLiteral(defaultBaseUrl));
|
||||
}
|
||||
function getOrAddBaseUrl(changes: textChanges.ChangeTracker, tsconfig: TsConfigSourceFile, compilerOptions: ObjectLiteralExpression): string {
|
||||
const baseUrlProp = findProperty(compilerOptions, "baseUrl");
|
||||
if (baseUrlProp) {
|
||||
return isStringLiteral(baseUrlProp.initializer) ? baseUrlProp.initializer.text : defaultBaseUrl;
|
||||
}
|
||||
else {
|
||||
changes.insertNodeAtObjectStart(tsconfig, compilerOptions, makeDefaultBaseUrl());
|
||||
return defaultBaseUrl;
|
||||
}
|
||||
}
|
||||
|
||||
const defaultTypesDirectoryName = "types";
|
||||
function makeDefaultPathMapping(): PropertyAssignment {
|
||||
return createJsonPropertyAssignment("*", createArrayLiteral([createStringLiteral(`${defaultTypesDirectoryName}/*`)]));
|
||||
}
|
||||
function makeDefaultPaths(): PropertyAssignment {
|
||||
return createJsonPropertyAssignment("paths", createObjectLiteral([makeDefaultPathMapping()]));
|
||||
}
|
||||
function getOrAddPathMapping(changes: textChanges.ChangeTracker, tsconfig: TsConfigSourceFile, compilerOptions: ObjectLiteralExpression) {
|
||||
const paths = findProperty(compilerOptions, "paths");
|
||||
if (!paths || !isObjectLiteralExpression(paths.initializer)) {
|
||||
changes.insertNodeAtObjectStart(tsconfig, compilerOptions, makeDefaultPaths());
|
||||
return defaultTypesDirectoryName;
|
||||
}
|
||||
|
||||
// Look for an existing path mapping. Should look like `"*": "foo/*"`.
|
||||
const existing = firstDefined(paths.initializer.properties, prop =>
|
||||
isPropertyAssignment(prop) && isStringLiteral(prop.name) && prop.name.text === "*" && isArrayLiteralExpression(prop.initializer)
|
||||
? firstDefined(prop.initializer.elements, value => isStringLiteral(value) ? tryRemoveSuffix(value.text, "/*") : undefined)
|
||||
: undefined);
|
||||
if (existing) return existing;
|
||||
|
||||
changes.insertNodeAtObjectStart(tsconfig, paths.initializer, makeDefaultPathMapping());
|
||||
return defaultTypesDirectoryName;
|
||||
}
|
||||
|
||||
function createJsonPropertyAssignment(name: string, initializer: Expression) {
|
||||
return createPropertyAssignment(createStringLiteral(name), initializer);
|
||||
}
|
||||
|
||||
function findProperty(obj: ObjectLiteralExpression, name: string): PropertyAssignment | undefined {
|
||||
return find(obj.properties, (p): p is PropertyAssignment => isPropertyAssignment(p) && !!p.name && isStringLiteral(p.name) && p.name.text === name);
|
||||
}
|
||||
|
||||
function getInstallCommand(fileName: string, packageName: string): InstallPackageAction {
|
||||
return { type: "install package", file: fileName, packageName };
|
||||
}
|
||||
|
||||
function getTypesPackageNameToInstall(host: LanguageServiceHost, sourceFile: SourceFile, pos: number, diagCode: number): string | undefined {
|
||||
function tryGetImportedPackageName(sourceFile: SourceFile, pos: number): string | undefined {
|
||||
const moduleName = cast(getTokenAtPosition(sourceFile, pos), isStringLiteral).text;
|
||||
const { packageName } = parsePackageName(moduleName);
|
||||
return isExternalModuleNameRelative(packageName) ? undefined : packageName;
|
||||
}
|
||||
|
||||
function getTypesPackageNameToInstall(packageName: string, host: LanguageServiceHost, diagCode: number): string | undefined {
|
||||
return diagCode === errorCodeCannotFindModule
|
||||
? (JsTyping.nodeCoreModules.has(packageName) ? "@types/node" : undefined)
|
||||
: (host.isKnownTypesPackageName!(packageName) ? getTypesPackageName(packageName) : undefined); // TODO: GH#18217
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
/* @internal */
|
||||
namespace ts {
|
||||
export function generateTypesForModule(name: string, moduleValue: unknown, formatSettings: FormatCodeSettings): string {
|
||||
return valueInfoToDeclarationFileText(inspectValue(name, moduleValue), formatSettings);
|
||||
}
|
||||
|
||||
export function valueInfoToDeclarationFileText(valueInfo: ValueInfo, formatSettings: FormatCodeSettings): string {
|
||||
return textChanges.getNewFileText(toStatements(valueInfo, OutputKind.ExportEquals), ScriptKind.TS, "\n", formatting.getFormatContext(formatSettings));
|
||||
}
|
||||
|
||||
const enum OutputKind { ExportEquals, NamedExport, NamespaceMember }
|
||||
function toNamespaceMemberStatements(info: ValueInfo): ReadonlyArray<Statement> {
|
||||
return toStatements(info, OutputKind.NamespaceMember);
|
||||
}
|
||||
function toStatements(info: ValueInfo, kind: OutputKind): ReadonlyArray<Statement> {
|
||||
const isDefault = info.name === InternalSymbolName.Default;
|
||||
const name = isDefault ? "_default" : info.name;
|
||||
if (!isValidIdentifier(name) || isDefault && kind !== OutputKind.NamedExport) return emptyArray;
|
||||
|
||||
const modifiers = isDefault && info.kind === ValueKind.FunctionOrClass ? [createModifier(SyntaxKind.ExportKeyword), createModifier(SyntaxKind.DefaultKeyword)]
|
||||
: kind === OutputKind.ExportEquals ? [createModifier(SyntaxKind.DeclareKeyword)]
|
||||
: kind === OutputKind.NamedExport ? [createModifier(SyntaxKind.ExportKeyword)]
|
||||
: undefined;
|
||||
const exportEquals = () => kind === OutputKind.ExportEquals ? [exportEqualsOrDefault(info.name, /*isExportEquals*/ true)] : emptyArray;
|
||||
const exportDefault = () => isDefault ? [exportEqualsOrDefault("_default", /*isExportEquals*/ false)] : emptyArray;
|
||||
|
||||
switch (info.kind) {
|
||||
case ValueKind.FunctionOrClass:
|
||||
return [...exportEquals(), ...functionOrClassToStatements(modifiers, name, info)];
|
||||
case ValueKind.Object:
|
||||
const { members } = info;
|
||||
if (kind === OutputKind.ExportEquals) {
|
||||
return flatMap(members, v => toStatements(v, OutputKind.NamedExport));
|
||||
}
|
||||
if (members.some(m => m.kind === ValueKind.FunctionOrClass)) {
|
||||
// If some member is a function, use a namespace so it gets a FunctionDeclaration or ClassDeclaration.
|
||||
return [...exportDefault(), createNamespace(modifiers, name, flatMap(members, toNamespaceMemberStatements))];
|
||||
}
|
||||
// falls through
|
||||
case ValueKind.Const:
|
||||
case ValueKind.Array: {
|
||||
const comment = info.kind === ValueKind.Const ? info.comment : undefined;
|
||||
const constVar = createVariableStatement(modifiers, createVariableDeclarationList([createVariableDeclaration(name, toType(info))], NodeFlags.Const));
|
||||
return [...exportEquals(), ...exportDefault(), addComment(constVar, comment)];
|
||||
}
|
||||
default:
|
||||
return Debug.assertNever(info);
|
||||
}
|
||||
}
|
||||
function exportEqualsOrDefault(name: string, isExportEquals: boolean): ExportAssignment {
|
||||
return createExportAssignment(/*decorators*/ undefined, /*modifiers*/ undefined, isExportEquals, createIdentifier(name));
|
||||
}
|
||||
|
||||
function functionOrClassToStatements(modifiers: Modifiers, name: string, { source, prototypeMembers, namespaceMembers }: ValueInfoFunctionOrClass): ReadonlyArray<Statement> {
|
||||
const fnAst = parseClassOrFunctionBody(source);
|
||||
const { parameters, returnType } = fnAst === undefined ? { parameters: emptyArray, returnType: anyType() } : getParametersAndReturnType(fnAst);
|
||||
const instanceProperties = typeof fnAst === "object" ? getConstructorFunctionInstanceProperties(fnAst) : emptyArray;
|
||||
|
||||
const classStaticMembers: ClassElement[] | undefined =
|
||||
instanceProperties.length !== 0 || prototypeMembers.length !== 0 || fnAst === undefined || typeof fnAst !== "number" && fnAst.kind === SyntaxKind.Constructor ? [] : undefined;
|
||||
|
||||
const namespaceStatements = flatMap(namespaceMembers, info => {
|
||||
if (!isValidIdentifier(info.name)) return undefined;
|
||||
if (classStaticMembers) {
|
||||
switch (info.kind) {
|
||||
case ValueKind.Object:
|
||||
if (info.members.some(m => m.kind === ValueKind.FunctionOrClass)) {
|
||||
break;
|
||||
}
|
||||
// falls through
|
||||
case ValueKind.Array:
|
||||
case ValueKind.Const:
|
||||
classStaticMembers.push(
|
||||
addComment(
|
||||
createProperty(/*decorators*/ undefined, [createModifier(SyntaxKind.StaticKeyword)], info.name, /*questionOrExclamationToken*/ undefined, toType(info), /*initializer*/ undefined),
|
||||
info.kind === ValueKind.Const ? info.comment : undefined));
|
||||
return undefined;
|
||||
case ValueKind.FunctionOrClass:
|
||||
if (!info.namespaceMembers.length) { // Else, can't merge a static method with a namespace. Must make it a function on the namespace.
|
||||
const sig = tryGetMethod(info, [createModifier(SyntaxKind.StaticKeyword)]);
|
||||
if (sig) {
|
||||
classStaticMembers.push(sig);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return toStatements(info, OutputKind.NamespaceMember);
|
||||
});
|
||||
|
||||
const decl = classStaticMembers
|
||||
? createClassDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
modifiers,
|
||||
name,
|
||||
/*typeParameters*/ undefined,
|
||||
/*heritageClauses*/ undefined,
|
||||
[
|
||||
...classStaticMembers,
|
||||
...(parameters.length ? [createConstructor(/*decorators*/ undefined, /*modifiers*/ undefined, parameters, /*body*/ undefined)] : emptyArray),
|
||||
...instanceProperties,
|
||||
// ignore non-functions on the prototype
|
||||
...mapDefined(prototypeMembers, info => info.kind === ValueKind.FunctionOrClass ? tryGetMethod(info) : undefined),
|
||||
])
|
||||
: createFunctionDeclaration(/*decorators*/ undefined, modifiers, /*asteriskToken*/ undefined, name, /*typeParameters*/ undefined, parameters, returnType, /*body*/ undefined);
|
||||
return [decl, ...(namespaceStatements.length === 0 ? emptyArray : [createNamespace(modifiers && modifiers.map(m => getSynthesizedDeepClone(m)), name, namespaceStatements)])];
|
||||
}
|
||||
|
||||
function tryGetMethod({ name, source }: ValueInfoFunctionOrClass, modifiers?: Modifiers): MethodDeclaration | undefined {
|
||||
if (!isValidIdentifier(name)) return undefined;
|
||||
const fnAst = parseClassOrFunctionBody(source);
|
||||
if (fnAst === undefined || (typeof fnAst !== "number" && fnAst.kind === SyntaxKind.Constructor)) return undefined;
|
||||
const sig = getParametersAndReturnType(fnAst);
|
||||
return sig && createMethod(
|
||||
/*decorators*/ undefined,
|
||||
modifiers,
|
||||
/*asteriskToken*/ undefined,
|
||||
name,
|
||||
/*questionToken*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
sig.parameters,
|
||||
sig.returnType,
|
||||
/*body*/ undefined);
|
||||
}
|
||||
|
||||
function toType(info: ValueInfo): TypeNode {
|
||||
switch (info.kind) {
|
||||
case ValueKind.Const:
|
||||
return createTypeReferenceNode(info.typeName, /*typeArguments*/ undefined);
|
||||
case ValueKind.Array:
|
||||
return createArrayTypeNode(toType(info.inner));
|
||||
case ValueKind.FunctionOrClass:
|
||||
return createTypeReferenceNode("Function", /*typeArguments*/ undefined); // Normally we create a FunctionDeclaration, but this can happen for a function in an array.
|
||||
case ValueKind.Object:
|
||||
return createTypeLiteralNode(info.members.map(m => createPropertySignature(/*modifiers*/ undefined, m.name, /*questionToken*/ undefined, toType(m), /*initializer*/ undefined)));
|
||||
default:
|
||||
return Debug.assertNever(info);
|
||||
}
|
||||
}
|
||||
|
||||
// Parses assignments to "this.x" in the constructor into class property declarations
|
||||
function getConstructorFunctionInstanceProperties(fnAst: FunctionOrConstructorNode): ReadonlyArray<PropertyDeclaration> {
|
||||
const members: PropertyDeclaration[] = [];
|
||||
forEachOwnNodeOfFunction(fnAst, node => {
|
||||
if (isAssignmentExpression(node, /*excludeCompoundAssignment*/ true) &&
|
||||
isPropertyAccessExpression(node.left) && node.left.expression.kind === SyntaxKind.ThisKeyword) {
|
||||
const name = node.left.name.text;
|
||||
if (!isJsPrivate(name)) members.push(createProperty(/*decorators*/ undefined, /*modifiers*/ undefined, name, /*questionOrExclamationToken*/ undefined, anyType(), /*initializer*/ undefined));
|
||||
}
|
||||
});
|
||||
return members;
|
||||
}
|
||||
|
||||
interface ParametersAndReturnType { readonly parameters: ReadonlyArray<ParameterDeclaration>; readonly returnType: TypeNode; }
|
||||
function getParametersAndReturnType(fnAst: FunctionOrConstructor): ParametersAndReturnType {
|
||||
if (typeof fnAst === "number") {
|
||||
return { parameters: fill(fnAst, i => makeParameter(`p${i}`, anyType())), returnType: anyType() };
|
||||
}
|
||||
let usedArguments = false, hasReturn = false;
|
||||
forEachOwnNodeOfFunction(fnAst, node => {
|
||||
usedArguments = usedArguments || isIdentifier(node) && node.text === "arguments";
|
||||
hasReturn = hasReturn || isReturnStatement(node) && !!node.expression && node.expression.kind !== SyntaxKind.VoidExpression;
|
||||
});
|
||||
const parameters = [
|
||||
...fnAst.parameters.map(p => makeParameter(`${p.name.getText()}`, inferParameterType(fnAst, p))),
|
||||
...(usedArguments ? [makeRestParameter()] : emptyArray),
|
||||
];
|
||||
return { parameters, returnType: hasReturn ? anyType() : createKeywordTypeNode(SyntaxKind.VoidKeyword) };
|
||||
}
|
||||
function makeParameter(name: string, type: TypeNode): ParameterDeclaration {
|
||||
return createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, name, /*questionToken*/ undefined, type);
|
||||
}
|
||||
function makeRestParameter(): ParameterDeclaration {
|
||||
return createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, createToken(SyntaxKind.DotDotDotToken), "args", /*questionToken*/ undefined, createArrayTypeNode(anyType()));
|
||||
}
|
||||
|
||||
type FunctionOrConstructorNode = FunctionExpression | ArrowFunction | ConstructorDeclaration | MethodDeclaration;
|
||||
type FunctionOrConstructor = FunctionOrConstructorNode | number; // number is for native function
|
||||
/** Returns 'undefined' for class with no declared constructor */
|
||||
function parseClassOrFunctionBody(source: string | number): FunctionOrConstructor | undefined {
|
||||
if (typeof source === "number") return source;
|
||||
const classOrFunction = tryCast(parseExpression(source), (node): node is FunctionExpression | ArrowFunction | ClassExpression => isFunctionExpression(node) || isArrowFunction(node) || isClassExpression(node));
|
||||
return classOrFunction
|
||||
? isClassExpression(classOrFunction) ? find(classOrFunction.members, isConstructorDeclaration) : classOrFunction
|
||||
// If that didn't parse, it's a method `m() {}`. Parse again inside of an object literal.
|
||||
: cast(first(cast(parseExpression(`{ ${source} }`), isObjectLiteralExpression).properties), isMethodDeclaration);
|
||||
}
|
||||
|
||||
function parseExpression(expr: string): Expression {
|
||||
const text = `const _ = ${expr}`;
|
||||
const srcFile = createSourceFile("test.ts", text, ScriptTarget.Latest, /*setParentNodes*/ true);
|
||||
return first(cast(first(srcFile.statements), isVariableStatement).declarationList.declarations).initializer!;
|
||||
}
|
||||
|
||||
function inferParameterType(_fn: FunctionOrConstructor, _param: ParameterDeclaration): TypeNode {
|
||||
// TODO: Inspect function body for clues (see inferFromUsage.ts)
|
||||
return anyType();
|
||||
}
|
||||
|
||||
// Descends through all nodes in a function, but not in nested functions.
|
||||
function forEachOwnNodeOfFunction(fnAst: FunctionOrConstructorNode, cb: (node: Node) => void) {
|
||||
fnAst.body!.forEachChild(function recur(node) {
|
||||
cb(node);
|
||||
if (!isFunctionLike(node)) node.forEachChild(recur);
|
||||
});
|
||||
}
|
||||
|
||||
function isValidIdentifier(name: string): boolean {
|
||||
const keyword = stringToToken(name);
|
||||
return !(keyword && isNonContextualKeyword(keyword)) && isIdentifierText(name, ScriptTarget.ESNext);
|
||||
}
|
||||
|
||||
type Modifiers = ReadonlyArray<Modifier> | undefined;
|
||||
|
||||
function addComment<T extends Node>(node: T, comment: string | undefined): T {
|
||||
if (comment !== undefined) addSyntheticLeadingComment(node, SyntaxKind.SingleLineCommentTrivia, comment);
|
||||
return node;
|
||||
}
|
||||
|
||||
function anyType(): KeywordTypeNode {
|
||||
return createKeywordTypeNode(SyntaxKind.AnyKeyword);
|
||||
}
|
||||
|
||||
function createNamespace(modifiers: Modifiers, name: string, statements: ReadonlyArray<Statement>): NamespaceDeclaration {
|
||||
return createModuleDeclaration(/*decorators*/ undefined, modifiers, createIdentifier(name), createModuleBlock(statements), NodeFlags.Namespace) as NamespaceDeclaration;
|
||||
}
|
||||
}
|
||||
@@ -121,10 +121,6 @@ namespace ts {
|
||||
const buckets = createMap<Map<DocumentRegistryEntry>>();
|
||||
const getCanonicalFileName = createGetCanonicalFileName(!!useCaseSensitiveFileNames);
|
||||
|
||||
function getKeyForCompilationSettings(settings: CompilerOptions): DocumentRegistryBucketKey {
|
||||
return <DocumentRegistryBucketKey>`_${settings.target}|${settings.module}|${settings.noResolve}|${settings.jsx}|${settings.allowJs}|${settings.baseUrl}|${JSON.stringify(settings.typeRoots)}|${JSON.stringify(settings.rootDirs)}|${JSON.stringify(settings.paths)}`;
|
||||
}
|
||||
|
||||
function getBucketForCompilationSettings(key: DocumentRegistryBucketKey, createIfMissing: boolean): Map<DocumentRegistryEntry> {
|
||||
let bucket = buckets.get(key);
|
||||
if (!bucket && createIfMissing) {
|
||||
@@ -273,4 +269,8 @@ namespace ts {
|
||||
getKeyForCompilationSettings
|
||||
};
|
||||
}
|
||||
|
||||
function getKeyForCompilationSettings(settings: CompilerOptions): DocumentRegistryBucketKey {
|
||||
return sourceFileAffectingCompilerOptions.map(option => getCompilerOptionValue(settings, option)).join("|") as DocumentRegistryBucketKey;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -385,7 +385,7 @@ namespace ts.FindAllReferences {
|
||||
}
|
||||
|
||||
/** Iterates over all statements at the top level or in module declarations. Returns the first truthy result. */
|
||||
function forEachPossibleImportOrExportStatement<T>(sourceFileLike: SourceFileLike, action: (statement: Statement) => T): T | undefined {
|
||||
function forEachPossibleImportOrExportStatement<T>(sourceFileLike: SourceFileLike, action: (statement: Statement) => T) {
|
||||
return forEach(sourceFileLike.kind === SyntaxKind.SourceFile ? sourceFileLike.statements : sourceFileLike.body!.statements, statement => // TODO: GH#18217
|
||||
action(statement) || (isAmbientModuleDeclaration(statement) && forEach(statement.body && statement.body.statements, action)));
|
||||
}
|
||||
|
||||
@@ -39,11 +39,18 @@ namespace ts.Rename {
|
||||
}
|
||||
|
||||
function getRenameInfoForModule(node: StringLiteralLike, sourceFile: SourceFile, moduleSymbol: Symbol): RenameInfo | undefined {
|
||||
if (!isExternalModuleNameRelative(node.text)) {
|
||||
return getRenameInfoError(Diagnostics.You_cannot_rename_a_module_via_a_global_import);
|
||||
}
|
||||
|
||||
const moduleSourceFile = find(moduleSymbol.declarations, isSourceFile);
|
||||
if (!moduleSourceFile) return undefined;
|
||||
const withoutIndex = node.text.endsWith("/index") || node.text.endsWith("/index.js") ? undefined : tryRemoveSuffix(removeFileExtension(moduleSourceFile.fileName), "/index");
|
||||
const name = withoutIndex === undefined ? moduleSourceFile.fileName : withoutIndex;
|
||||
const kind = withoutIndex === undefined ? ScriptElementKind.moduleElement : ScriptElementKind.directory;
|
||||
const indexAfterLastSlash = node.text.lastIndexOf("/") + 1;
|
||||
// Span should only be the last component of the path. + 1 to account for the quote character.
|
||||
const triggerSpan = createTextSpan(node.getStart(sourceFile) + 1 + indexAfterLastSlash, node.text.length - indexAfterLastSlash);
|
||||
return {
|
||||
canRename: true,
|
||||
fileToRename: name,
|
||||
@@ -52,7 +59,7 @@ namespace ts.Rename {
|
||||
localizedErrorMessage: undefined,
|
||||
fullDisplayName: name,
|
||||
kindModifiers: ScriptElementKindModifier.none,
|
||||
triggerSpan: createTriggerSpanForNode(node, sourceFile),
|
||||
triggerSpan,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+25
-10
@@ -1218,6 +1218,10 @@ namespace ts {
|
||||
getDirectories: path => {
|
||||
return host.getDirectories ? host.getDirectories(path) : [];
|
||||
},
|
||||
readDirectory(path, extensions, exclude, include, depth) {
|
||||
Debug.assertDefined(host.readDirectory, "'LanguageServiceHost.readDirectory' must be implemented to correctly process 'projectReferences'");
|
||||
return host.readDirectory!(path, extensions, exclude, include, depth);
|
||||
},
|
||||
onReleaseOldSourceFile,
|
||||
hasInvalidatedResolution,
|
||||
hasChangedAutomaticTypeDirectiveNames: host.hasChangedAutomaticTypeDirectiveNames
|
||||
@@ -1804,25 +1808,36 @@ namespace ts {
|
||||
return ts.getEditsForFileRename(getProgram()!, oldFilePath, newFilePath, host, formatting.getFormatContext(formatOptions), preferences, sourceMapper);
|
||||
}
|
||||
|
||||
function applyCodeActionCommand(action: CodeActionCommand): Promise<ApplyCodeActionCommandResult>;
|
||||
function applyCodeActionCommand(action: CodeActionCommand[]): Promise<ApplyCodeActionCommandResult[]>;
|
||||
function applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[]): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]>;
|
||||
function applyCodeActionCommand(action: CodeActionCommand, formatSettings?: FormatCodeSettings): Promise<ApplyCodeActionCommandResult>;
|
||||
function applyCodeActionCommand(action: CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise<ApplyCodeActionCommandResult[]>;
|
||||
function applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]>;
|
||||
function applyCodeActionCommand(fileName: Path, action: CodeActionCommand): Promise<ApplyCodeActionCommandResult>;
|
||||
function applyCodeActionCommand(fileName: Path, action: CodeActionCommand[]): Promise<ApplyCodeActionCommandResult[]>;
|
||||
function applyCodeActionCommand(fileName: Path | CodeActionCommand | CodeActionCommand[], actionOrUndefined?: CodeActionCommand | CodeActionCommand[]): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]> {
|
||||
const action = typeof fileName === "string" ? actionOrUndefined! : fileName as CodeActionCommand[];
|
||||
return isArray(action) ? Promise.all(action.map(applySingleCodeActionCommand)) : applySingleCodeActionCommand(action);
|
||||
function applyCodeActionCommand(fileName: Path | CodeActionCommand | CodeActionCommand[], actionOrFormatSettingsOrUndefined?: CodeActionCommand | CodeActionCommand[] | FormatCodeSettings): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]> {
|
||||
const action = typeof fileName === "string" ? actionOrFormatSettingsOrUndefined as CodeActionCommand | CodeActionCommand[] : fileName as CodeActionCommand[];
|
||||
const formatSettings = typeof fileName !== "string" ? actionOrFormatSettingsOrUndefined as FormatCodeSettings : undefined;
|
||||
return isArray(action) ? Promise.all(action.map(a => applySingleCodeActionCommand(a, formatSettings))) : applySingleCodeActionCommand(action, formatSettings);
|
||||
}
|
||||
|
||||
function applySingleCodeActionCommand(action: CodeActionCommand): Promise<ApplyCodeActionCommandResult> {
|
||||
function applySingleCodeActionCommand(action: CodeActionCommand, formatSettings: FormatCodeSettings | undefined): Promise<ApplyCodeActionCommandResult> {
|
||||
const getPath = (path: string): Path => toPath(path, currentDirectory, getCanonicalFileName);
|
||||
switch (action.type) {
|
||||
case "install package":
|
||||
return host.installPackage
|
||||
? host.installPackage({ fileName: toPath(action.file, currentDirectory, getCanonicalFileName), packageName: action.packageName })
|
||||
? host.installPackage({ fileName: getPath(action.file), packageName: action.packageName })
|
||||
: Promise.reject("Host does not implement `installPackage`");
|
||||
case "generate types": {
|
||||
const { fileToGenerateTypesFor, outputFileName } = action;
|
||||
if (!host.inspectValue) return Promise.reject("Host does not implement `installPackage`");
|
||||
const valueInfoPromise = host.inspectValue({ fileNameToRequire: fileToGenerateTypesFor });
|
||||
return valueInfoPromise.then(valueInfo => {
|
||||
const fullOut = getPath(outputFileName);
|
||||
host.writeFile!(fullOut, valueInfoToDeclarationFileText(valueInfo, formatSettings || testFormatSettings)); // TODO: GH#18217
|
||||
return { successMessage: `Wrote types to '${fullOut}'` };
|
||||
});
|
||||
}
|
||||
default:
|
||||
return Debug.fail();
|
||||
// TODO: Debug.assertNever(action); will only work if there is more than one type.
|
||||
return Debug.assertNever(action);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+38
-20
@@ -211,8 +211,8 @@ namespace ts.textChanges {
|
||||
|
||||
export class ChangeTracker {
|
||||
private readonly changes: Change[] = [];
|
||||
private readonly newFiles: { readonly oldFile: SourceFile, readonly fileName: string, readonly statements: ReadonlyArray<Statement> }[] = [];
|
||||
private readonly classesWithNodesInsertedAtStart = createMap<ClassDeclaration>(); // Set<ClassDeclaration> implemented as Map<node id, ClassDeclaration>
|
||||
private readonly newFiles: { readonly oldFile: SourceFile | undefined, readonly fileName: string, readonly statements: ReadonlyArray<Statement> }[] = [];
|
||||
private readonly classesWithNodesInsertedAtStart = createMap<{ readonly node: ClassDeclaration | InterfaceDeclaration | ObjectLiteralExpression, readonly sourceFile: SourceFile }>(); // Set<ClassDeclaration> implemented as Map<node id, ClassDeclaration>
|
||||
private readonly deletedNodes: { readonly sourceFile: SourceFile, readonly node: Node | NodeArray<TypeParameterDeclaration> }[] = [];
|
||||
|
||||
public static fromContext(context: TextChangesContext): ChangeTracker {
|
||||
@@ -410,25 +410,33 @@ namespace ts.textChanges {
|
||||
}
|
||||
|
||||
public insertNodeAtClassStart(sourceFile: SourceFile, cls: ClassLikeDeclaration | InterfaceDeclaration, newElement: ClassElement): void {
|
||||
this.insertNodeAtStartWorker(sourceFile, cls, newElement);
|
||||
}
|
||||
public insertNodeAtObjectStart(sourceFile: SourceFile, obj: ObjectLiteralExpression, newElement: ObjectLiteralElementLike): void {
|
||||
this.insertNodeAtStartWorker(sourceFile, obj, newElement);
|
||||
}
|
||||
|
||||
private insertNodeAtStartWorker(sourceFile: SourceFile, cls: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression, newElement: ClassElement | ObjectLiteralElementLike): void {
|
||||
const clsStart = cls.getStart(sourceFile);
|
||||
const indentation = formatting.SmartIndenter.findFirstNonWhitespaceColumn(getLineStartPositionForPosition(clsStart, sourceFile), clsStart, sourceFile, this.formatContext.options)
|
||||
+ this.formatContext.options.indentSize!;
|
||||
this.insertNodeAt(sourceFile, cls.members.pos, newElement, { indentation, ...this.getInsertNodeAtClassStartPrefixSuffix(sourceFile, cls) });
|
||||
this.insertNodeAt(sourceFile, getMembersOrProperties(cls).pos, newElement, { indentation, ...this.getInsertNodeAtStartPrefixSuffix(sourceFile, cls) });
|
||||
}
|
||||
|
||||
private getInsertNodeAtClassStartPrefixSuffix(sourceFile: SourceFile, cls: ClassLikeDeclaration | InterfaceDeclaration): { prefix: string, suffix: string } {
|
||||
if (cls.members.length === 0) {
|
||||
if (addToSeen(this.classesWithNodesInsertedAtStart, getNodeId(cls), cls)) {
|
||||
private getInsertNodeAtStartPrefixSuffix(sourceFile: SourceFile, cls: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression): { prefix: string, suffix: string } {
|
||||
const comma = isObjectLiteralExpression(cls) ? "," : "";
|
||||
if (getMembersOrProperties(cls).length === 0) {
|
||||
if (addToSeen(this.classesWithNodesInsertedAtStart, getNodeId(cls), { node: cls, sourceFile })) {
|
||||
// For `class C {\n}`, don't add the trailing "\n"
|
||||
const shouldSuffix = (positionsAreOnSameLine as any)(...getClassBraceEnds(cls, sourceFile), sourceFile); // TODO: GH#4130 remove 'as any'
|
||||
return { prefix: this.newLineCharacter, suffix: shouldSuffix ? this.newLineCharacter : "" };
|
||||
const shouldSuffix = (positionsAreOnSameLine as any)(...getClassOrObjectBraceEnds(cls, sourceFile), sourceFile); // TODO: GH#4130 remove 'as any'
|
||||
return { prefix: this.newLineCharacter, suffix: comma + (shouldSuffix ? this.newLineCharacter : "") };
|
||||
}
|
||||
else {
|
||||
return { prefix: "", suffix: this.newLineCharacter };
|
||||
return { prefix: "", suffix: comma + this.newLineCharacter };
|
||||
}
|
||||
}
|
||||
else {
|
||||
return { prefix: this.newLineCharacter, suffix: "" };
|
||||
return { prefix: this.newLineCharacter, suffix: comma };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -647,9 +655,8 @@ namespace ts.textChanges {
|
||||
}
|
||||
|
||||
private finishClassesWithNodesInsertedAtStart(): void {
|
||||
this.classesWithNodesInsertedAtStart.forEach(cls => {
|
||||
const sourceFile = cls.getSourceFile();
|
||||
const [openBraceEnd, closeBraceEnd] = getClassBraceEnds(cls, sourceFile);
|
||||
this.classesWithNodesInsertedAtStart.forEach(({ node, sourceFile }) => {
|
||||
const [openBraceEnd, closeBraceEnd] = getClassOrObjectBraceEnds(node, sourceFile);
|
||||
// For `class C { }` remove the whitespace inside the braces.
|
||||
if (positionsAreOnSameLine(openBraceEnd, closeBraceEnd, sourceFile) && openBraceEnd !== closeBraceEnd - 1) {
|
||||
this.deleteRange(sourceFile, createRange(openBraceEnd, closeBraceEnd - 1));
|
||||
@@ -698,7 +705,7 @@ namespace ts.textChanges {
|
||||
return changes;
|
||||
}
|
||||
|
||||
public createNewFile(oldFile: SourceFile, fileName: string, statements: ReadonlyArray<Statement>) {
|
||||
public createNewFile(oldFile: SourceFile | undefined, fileName: string, statements: ReadonlyArray<Statement>) {
|
||||
this.newFiles.push({ oldFile, fileName, statements });
|
||||
}
|
||||
}
|
||||
@@ -708,12 +715,19 @@ namespace ts.textChanges {
|
||||
return skipTrivia(sourceFile.text, getAdjustedStartPosition(sourceFile, node, {}, Position.FullStart), /*stopAfterLineBreak*/ false, /*stopAtComments*/ true);
|
||||
}
|
||||
|
||||
function getClassBraceEnds(cls: ClassLikeDeclaration | InterfaceDeclaration, sourceFile: SourceFile): [number, number] {
|
||||
function getClassOrObjectBraceEnds(cls: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression, sourceFile: SourceFile): [number, number] {
|
||||
return [findChildOfKind(cls, SyntaxKind.OpenBraceToken, sourceFile)!.end, findChildOfKind(cls, SyntaxKind.CloseBraceToken, sourceFile)!.end];
|
||||
}
|
||||
function getMembersOrProperties(cls: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression): NodeArray<Node> {
|
||||
return isObjectLiteralExpression(cls) ? cls.properties : cls.members;
|
||||
}
|
||||
|
||||
export type ValidateNonFormattedText = (node: Node, text: string) => void;
|
||||
|
||||
export function getNewFileText(statements: ReadonlyArray<Statement>, scriptKind: ScriptKind, newLineCharacter: string, formatContext: formatting.FormatContext): string {
|
||||
return changesToText.newFileChangesWorker(/*oldFile*/ undefined, scriptKind, statements, newLineCharacter, formatContext);
|
||||
}
|
||||
|
||||
namespace changesToText {
|
||||
export function getTextChangesFromChanges(changes: ReadonlyArray<Change>, newLineCharacter: string, formatContext: formatting.FormatContext, validate: ValidateNonFormattedText | undefined): FileTextChanges[] {
|
||||
return group(changes, c => c.sourceFile.path).map(changesInFile => {
|
||||
@@ -732,13 +746,17 @@ namespace ts.textChanges {
|
||||
});
|
||||
}
|
||||
|
||||
export function newFileChanges(oldFile: SourceFile, fileName: string, statements: ReadonlyArray<Statement>, newLineCharacter: string, formatContext: formatting.FormatContext): FileTextChanges {
|
||||
export function newFileChanges(oldFile: SourceFile | undefined, fileName: string, statements: ReadonlyArray<Statement>, newLineCharacter: string, formatContext: formatting.FormatContext): FileTextChanges {
|
||||
const text = newFileChangesWorker(oldFile, getScriptKindFromFileName(fileName), statements, newLineCharacter, formatContext);
|
||||
return { fileName, textChanges: [createTextChange(createTextSpan(0, 0), text)], isNewFile: true };
|
||||
}
|
||||
|
||||
export function newFileChangesWorker(oldFile: SourceFile | undefined, scriptKind: ScriptKind, statements: ReadonlyArray<Statement>, newLineCharacter: string, formatContext: formatting.FormatContext): string {
|
||||
// TODO: this emits the file, parses it back, then formats it that -- may be a less roundabout way to do this
|
||||
const nonFormattedText = statements.map(s => getNonformattedText(s, oldFile, newLineCharacter).text).join(newLineCharacter);
|
||||
const sourceFile = createSourceFile(fileName, nonFormattedText, ScriptTarget.ESNext, /*setParentNodes*/ true);
|
||||
const sourceFile = createSourceFile("any file name", nonFormattedText, ScriptTarget.ESNext, /*setParentNodes*/ true, scriptKind);
|
||||
const changes = formatting.formatDocument(sourceFile, formatContext);
|
||||
const text = applyChanges(nonFormattedText, changes);
|
||||
return { fileName, textChanges: [createTextChange(createTextSpan(0, 0), text)], isNewFile: true };
|
||||
return applyChanges(nonFormattedText, changes);
|
||||
}
|
||||
|
||||
function computeNewText(change: Change, sourceFile: SourceFile, newLineCharacter: string, formatContext: formatting.FormatContext, validate: ValidateNonFormattedText | undefined): string {
|
||||
@@ -781,7 +799,7 @@ namespace ts.textChanges {
|
||||
function getNonformattedText(node: Node, sourceFile: SourceFile | undefined, newLineCharacter: string): { text: string, node: Node } {
|
||||
const writer = new Writer(newLineCharacter);
|
||||
const newLine = newLineCharacter === "\n" ? NewLineKind.LineFeed : NewLineKind.CarriageReturnLineFeed;
|
||||
createPrinter({ newLine }, writer).writeNode(EmitHint.Unspecified, node, sourceFile, writer);
|
||||
createPrinter({ newLine, neverAsciiEscape: true }, writer).writeNode(EmitHint.Unspecified, node, sourceFile, writer);
|
||||
return { text: writer.getText(), node: assignPositionsToNode(node) };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
"codefixes/inferFromUsage.ts",
|
||||
"codefixes/fixInvalidImportSyntax.ts",
|
||||
"codefixes/fixStrictClassInitialization.ts",
|
||||
"codefixes/generateTypes.ts",
|
||||
"codefixes/requireInTs.ts",
|
||||
"codefixes/useDefaultImport.ts",
|
||||
"codefixes/fixAddModuleReferTypeMissingTypeof.ts",
|
||||
@@ -83,6 +84,6 @@
|
||||
"services.ts",
|
||||
"breakpoints.ts",
|
||||
"transform.ts",
|
||||
"shims.ts"
|
||||
"shims.ts",
|
||||
]
|
||||
}
|
||||
|
||||
+44
-7
@@ -231,6 +231,8 @@ namespace ts {
|
||||
|
||||
isKnownTypesPackageName?(name: string): boolean;
|
||||
installPackage?(options: InstallPackageOptions): Promise<ApplyCodeActionCommandResult>;
|
||||
/* @internal */ inspectValue?(options: InspectValueOptions): Promise<ValueInfo>;
|
||||
writeFile?(fileName: string, content: string): void;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
@@ -331,9 +333,9 @@ namespace ts {
|
||||
|
||||
getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: ReadonlyArray<number>, formatOptions: FormatCodeSettings, preferences: UserPreferences): ReadonlyArray<CodeFixAction>;
|
||||
getCombinedCodeFix(scope: CombinedCodeFixScope, fixId: {}, formatOptions: FormatCodeSettings, preferences: UserPreferences): CombinedCodeActions;
|
||||
applyCodeActionCommand(action: CodeActionCommand): Promise<ApplyCodeActionCommandResult>;
|
||||
applyCodeActionCommand(action: CodeActionCommand[]): Promise<ApplyCodeActionCommandResult[]>;
|
||||
applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[]): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]>;
|
||||
applyCodeActionCommand(action: CodeActionCommand, formatSettings?: FormatCodeSettings): Promise<ApplyCodeActionCommandResult>;
|
||||
applyCodeActionCommand(action: CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise<ApplyCodeActionCommandResult[]>;
|
||||
applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]>;
|
||||
/** @deprecated `fileName` will be ignored */
|
||||
applyCodeActionCommand(fileName: string, action: CodeActionCommand): Promise<ApplyCodeActionCommandResult>;
|
||||
/** @deprecated `fileName` will be ignored */
|
||||
@@ -526,12 +528,22 @@ namespace ts {
|
||||
|
||||
// Publicly, this type is just `{}`. Internally it is a union of all the actions we use.
|
||||
// See `commands?: {}[]` in protocol.ts
|
||||
export type CodeActionCommand = InstallPackageAction;
|
||||
export type CodeActionCommand = InstallPackageAction | GenerateTypesAction;
|
||||
|
||||
export interface InstallPackageAction {
|
||||
/* @internal */ file: string;
|
||||
/* @internal */ type: "install package";
|
||||
/* @internal */ packageName: string;
|
||||
/* @internal */ readonly type: "install package";
|
||||
/* @internal */ readonly file: string;
|
||||
/* @internal */ readonly packageName: string;
|
||||
}
|
||||
|
||||
export interface GenerateTypesAction extends GenerateTypesOptions {
|
||||
/* @internal */ readonly type: "generate types";
|
||||
}
|
||||
|
||||
export interface GenerateTypesOptions {
|
||||
readonly file: string; // File that was importing fileToGenerateTypesFor; used for formatting options.
|
||||
readonly fileToGenerateTypesFor: string;
|
||||
readonly outputFileName: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -717,6 +729,31 @@ namespace ts {
|
||||
indentMultiLineObjectLiteralBeginningOnBlankLine?: boolean;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export const testFormatSettings: FormatCodeSettings = {
|
||||
baseIndentSize: 0,
|
||||
indentSize: 4,
|
||||
tabSize: 4,
|
||||
newLineCharacter: "\n",
|
||||
convertTabsToSpaces: true,
|
||||
indentStyle: IndentStyle.Smart,
|
||||
insertSpaceAfterCommaDelimiter: true,
|
||||
insertSpaceAfterSemicolonInForStatements: true,
|
||||
insertSpaceBeforeAndAfterBinaryOperators: true,
|
||||
insertSpaceAfterConstructor: false,
|
||||
insertSpaceAfterKeywordsInControlFlowStatements: true,
|
||||
insertSpaceAfterFunctionKeywordForAnonymousFunctions: false,
|
||||
insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false,
|
||||
insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false,
|
||||
insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true,
|
||||
insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false,
|
||||
insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces: false,
|
||||
insertSpaceAfterTypeAssertion: false,
|
||||
placeOpenBraceOnNewLineForFunctions: false,
|
||||
placeOpenBraceOnNewLineForControlBlocks: false,
|
||||
insertSpaceBeforeTypeAnnotation: false
|
||||
};
|
||||
|
||||
export interface DefinitionInfo extends DocumentSpan {
|
||||
kind: ScriptElementKind;
|
||||
name: string;
|
||||
|
||||
@@ -244,6 +244,20 @@ namespace ts {
|
||||
}, [
|
||||
combinePaths(basePath, "main.ts")
|
||||
]);
|
||||
|
||||
it("adds extendedSourceFiles only once", () => {
|
||||
const sourceFile = readJsonConfigFile("configs/fourth.json", (path) => host.readFile(path));
|
||||
const dir = combinePaths(basePath, "configs");
|
||||
const expected = [
|
||||
combinePaths(dir, "third.json"),
|
||||
combinePaths(dir, "second.json"),
|
||||
combinePaths(dir, "base.json"),
|
||||
];
|
||||
parseJsonSourceFileConfigFileContent(sourceFile, host, dir, {}, "fourth.json");
|
||||
assert.deepEqual(sourceFile.extendedSourceFiles, expected);
|
||||
parseJsonSourceFileConfigFileContent(sourceFile, host, dir, {}, "fourth.json");
|
||||
assert.deepEqual(sourceFile.extendedSourceFiles, expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -292,7 +292,7 @@ interface Array<T> {}`
|
||||
cancellationToken: { throwIfCancellationRequested: noop, isCancellationRequested: returnFalse },
|
||||
preferences: emptyOptions,
|
||||
host: notImplementedHost,
|
||||
formatContext: formatting.getFormatContext(testFormatOptions)
|
||||
formatContext: formatting.getFormatContext(testFormatSettings)
|
||||
};
|
||||
|
||||
const diagnostics = languageService.getSuggestionDiagnostics(f.path);
|
||||
@@ -416,6 +416,20 @@ function [#|f|](): Promise<void> {
|
||||
return fetch('https://typescriptlang.org').then( () => console.log("done") );
|
||||
}`
|
||||
);
|
||||
_testConvertToAsyncFunction("convertToAsyncFunction_IgnoreArgs3", `
|
||||
function [#|f|](): Promise<void> {
|
||||
return fetch('https://typescriptlang.org').then( () => console.log("almost done") ).then( () => console.log("done") );
|
||||
}`
|
||||
);
|
||||
_testConvertToAsyncFunction("convertToAsyncFunction_IgnoreArgs4", `
|
||||
function [#|f|]() {
|
||||
return fetch('https://typescriptlang.org').then(res);
|
||||
}
|
||||
function res(){
|
||||
console.log("done");
|
||||
}`
|
||||
);
|
||||
|
||||
_testConvertToAsyncFunction("convertToAsyncFunction_Method", `
|
||||
class Parser {
|
||||
[#|f|]():Promise<void> {
|
||||
@@ -473,6 +487,12 @@ function [#|f|]():Promise<void | Response> {
|
||||
function [#|f|]() {
|
||||
return fetch('https://typescriptlang.org').then(undefined, rejection => console.log("rejected:", rejection));
|
||||
}
|
||||
`
|
||||
);
|
||||
_testConvertToAsyncFunction("convertToAsyncFunction_NoCatchHandler", `
|
||||
function [#|f|]() {
|
||||
return fetch('https://typescriptlang.org').then(x => x.statusText).catch(undefined);
|
||||
}
|
||||
`
|
||||
);
|
||||
_testConvertToAsyncFunctionFailed("convertToAsyncFunction_NoSuggestion", `
|
||||
@@ -817,7 +837,7 @@ function [#|f|]() {
|
||||
);
|
||||
_testConvertToAsyncFunction("convertToAsyncFunction_Scope1", `
|
||||
function [#|f|]() {
|
||||
var var1:Promise<Response>, var2;
|
||||
var var1: Response, var2;
|
||||
return fetch('https://typescriptlang.org').then( _ =>
|
||||
Promise.resolve().then( res => {
|
||||
var2 = "test";
|
||||
@@ -1183,6 +1203,45 @@ function [#|f|]() {
|
||||
}
|
||||
`);
|
||||
|
||||
_testConvertToAsyncFunction("convertToAsyncFunction_runEffectfulContinuation", `
|
||||
function [#|f|]() {
|
||||
return fetch('https://typescriptlang.org').then(res).then(_ => console.log("done"));
|
||||
}
|
||||
function res(result) {
|
||||
return Promise.resolve().then(x => console.log(result));
|
||||
}
|
||||
`);
|
||||
|
||||
_testConvertToAsyncFunction("convertToAsyncFunction_callbackReturnsPromise", `
|
||||
function [#|f|]() {
|
||||
return fetch('https://typescriptlang.org').then(s => Promise.resolve(s.statusText.length)).then(x => console.log(x + 5));
|
||||
}
|
||||
`);
|
||||
|
||||
_testConvertToAsyncFunction("convertToAsyncFunction_callbackReturnsPromiseInBlock", `
|
||||
function [#|f|]() {
|
||||
return fetch('https://typescriptlang.org').then(s => { return Promise.resolve(s.statusText.length) }).then(x => x + 5);
|
||||
}
|
||||
`);
|
||||
|
||||
_testConvertToAsyncFunction("convertToAsyncFunction_callbackReturnsFixablePromise", `
|
||||
function [#|f|]() {
|
||||
return fetch('https://typescriptlang.org').then(s => Promise.resolve(s.statusText).then(st => st.length)).then(x => console.log(x + 5));
|
||||
}
|
||||
`);
|
||||
|
||||
_testConvertToAsyncFunction("convertToAsyncFunction_callbackReturnsPromiseLastInChain", `
|
||||
function [#|f|]() {
|
||||
return fetch('https://typescriptlang.org').then(s => Promise.resolve(s.statusText.length));
|
||||
}
|
||||
`);
|
||||
|
||||
|
||||
_testConvertToAsyncFunction("convertToAsyncFunction_nestedPromises", `
|
||||
function [#|f|]() {
|
||||
return fetch('https://typescriptlang.org').then(x => Promise.resolve(3).then(y => Promise.resolve(x.statusText.length + y)));
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
function _testConvertToAsyncFunction(caption: string, text: string) {
|
||||
|
||||
@@ -64,27 +64,6 @@ namespace ts {
|
||||
}
|
||||
|
||||
export const newLineCharacter = "\n";
|
||||
export const testFormatOptions: FormatCodeSettings = {
|
||||
indentSize: 4,
|
||||
tabSize: 4,
|
||||
newLineCharacter,
|
||||
convertTabsToSpaces: true,
|
||||
indentStyle: IndentStyle.Smart,
|
||||
insertSpaceAfterConstructor: false,
|
||||
insertSpaceAfterCommaDelimiter: true,
|
||||
insertSpaceAfterSemicolonInForStatements: true,
|
||||
insertSpaceBeforeAndAfterBinaryOperators: true,
|
||||
insertSpaceAfterKeywordsInControlFlowStatements: true,
|
||||
insertSpaceAfterFunctionKeywordForAnonymousFunctions: false,
|
||||
insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false,
|
||||
insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false,
|
||||
insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true,
|
||||
insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false,
|
||||
insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces: false,
|
||||
insertSpaceBeforeFunctionParenthesis: false,
|
||||
placeOpenBraceOnNewLineForFunctions: false,
|
||||
placeOpenBraceOnNewLineForControlBlocks: false,
|
||||
};
|
||||
|
||||
export const notImplementedHost: LanguageServiceHost = {
|
||||
getCompilationSettings: notImplemented,
|
||||
@@ -123,7 +102,7 @@ namespace ts {
|
||||
startPosition: selectionRange.pos,
|
||||
endPosition: selectionRange.end,
|
||||
host: notImplementedHost,
|
||||
formatContext: formatting.getFormatContext(testFormatOptions),
|
||||
formatContext: formatting.getFormatContext(testFormatSettings),
|
||||
preferences: emptyOptions,
|
||||
};
|
||||
const rangeToExtract = refactor.extractSymbol.getRangeToExtract(sourceFile, createTextSpanFromRange(selectionRange));
|
||||
@@ -185,7 +164,7 @@ namespace ts {
|
||||
startPosition: selectionRange.pos,
|
||||
endPosition: selectionRange.end,
|
||||
host: notImplementedHost,
|
||||
formatContext: formatting.getFormatContext(testFormatOptions),
|
||||
formatContext: formatting.getFormatContext(testFormatSettings),
|
||||
preferences: emptyOptions,
|
||||
};
|
||||
const rangeToExtract = refactor.extractSymbol.getRangeToExtract(sourceFile, createTextSpanFromRange(selectionRange));
|
||||
|
||||
@@ -270,7 +270,7 @@ export const Other = 1;
|
||||
content: "function F() { }",
|
||||
};
|
||||
const languageService = makeLanguageService(testFile);
|
||||
const changes = languageService.organizeImports({ type: "file", fileName: testFile.path }, testFormatOptions, emptyOptions);
|
||||
const changes = languageService.organizeImports({ type: "file", fileName: testFile.path }, testFormatSettings, emptyOptions);
|
||||
assert.isEmpty(changes);
|
||||
});
|
||||
|
||||
@@ -741,7 +741,7 @@ export * from "lib";
|
||||
function runBaseline(baselinePath: string, testFile: TestFSWithWatch.File, ...otherFiles: TestFSWithWatch.File[]) {
|
||||
const { path: testPath, content: testContent } = testFile;
|
||||
const languageService = makeLanguageService(testFile, ...otherFiles);
|
||||
const changes = languageService.organizeImports({ type: "file", fileName: testPath }, testFormatOptions, emptyOptions);
|
||||
const changes = languageService.organizeImports({ type: "file", fileName: testPath }, testFormatSettings, emptyOptions);
|
||||
assert.equal(changes.length, 1);
|
||||
assert.equal(changes[0].fileName, testPath);
|
||||
|
||||
|
||||
@@ -305,10 +305,10 @@ namespace ts {
|
||||
assert.equal(program1.structureIsReused, StructureIsReused.Not);
|
||||
});
|
||||
|
||||
it("fails if rootdir changes", () => {
|
||||
it("succeeds if rootdir changes", () => {
|
||||
const program1 = newProgram(files, ["a.ts"], { target, module: ModuleKind.CommonJS, rootDir: "/a/b" });
|
||||
updateProgram(program1, ["a.ts"], { target, module: ModuleKind.CommonJS, rootDir: "/a/c" }, noop);
|
||||
assert.equal(program1.structureIsReused, StructureIsReused.Not);
|
||||
assert.equal(program1.structureIsReused, StructureIsReused.Completely);
|
||||
});
|
||||
|
||||
it("fails if config path changes", () => {
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace ts {
|
||||
const newLineCharacter = getNewLineCharacter(printerOptions);
|
||||
|
||||
function getRuleProvider(placeOpenBraceOnNewLineForFunctions: boolean): formatting.FormatContext {
|
||||
return formatting.getFormatContext(placeOpenBraceOnNewLineForFunctions ? { ...testFormatOptions, placeOpenBraceOnNewLineForFunctions: true } : testFormatOptions);
|
||||
return formatting.getFormatContext(placeOpenBraceOnNewLineForFunctions ? { ...testFormatSettings, placeOpenBraceOnNewLineForFunctions: true } : testFormatSettings);
|
||||
}
|
||||
|
||||
// validate that positions that were recovered from the printed text actually match positions that will be created if the same text is parsed.
|
||||
|
||||
@@ -34,6 +34,10 @@ namespace ts.tscWatch {
|
||||
return `${projectPath(subProject)}/${baseFileName.toLowerCase()}`;
|
||||
}
|
||||
|
||||
function projectFileName(subProject: SubProject, baseFileName: string) {
|
||||
return `${projectPath(subProject)}/${baseFileName}`;
|
||||
}
|
||||
|
||||
function projectFile(subProject: SubProject, baseFileName: string): File {
|
||||
return {
|
||||
path: projectFilePath(subProject, baseFileName),
|
||||
@@ -94,6 +98,7 @@ namespace ts.tscWatch {
|
||||
const ui = subProjectFiles(SubProject.ui);
|
||||
const allFiles: ReadonlyArray<File> = [libFile, ...core, ...logic, ...tests, ...ui];
|
||||
const testProjectExpectedWatchedFiles = [core[0], core[1], core[2], ...logic, ...tests].map(f => f.path);
|
||||
const testProjectExpectedWatchedDirectoriesRecursive = [projectPath(SubProject.core), projectPath(SubProject.logic)];
|
||||
|
||||
function createSolutionInWatchMode(allFiles: ReadonlyArray<File>, defaultOptions?: BuildOptions, disableConsoleClears?: boolean) {
|
||||
const host = createWatchedSystem(allFiles, { currentDirectory: projectsLocation });
|
||||
@@ -110,7 +115,7 @@ namespace ts.tscWatch {
|
||||
function verifyWatches(host: WatchedSystem) {
|
||||
checkWatchedFiles(host, testProjectExpectedWatchedFiles);
|
||||
checkWatchedDirectories(host, emptyArray, /*recursive*/ false);
|
||||
checkWatchedDirectories(host, [projectPath(SubProject.core), projectPath(SubProject.logic)], /*recursive*/ true);
|
||||
checkWatchedDirectories(host, testProjectExpectedWatchedDirectoriesRecursive, /*recursive*/ true);
|
||||
}
|
||||
|
||||
it("creates solution in watch mode", () => {
|
||||
@@ -161,7 +166,7 @@ namespace ts.tscWatch {
|
||||
function verifyWatches() {
|
||||
checkWatchedFiles(host, additionalFiles ? testProjectExpectedWatchedFiles.concat(newFile.path) : testProjectExpectedWatchedFiles);
|
||||
checkWatchedDirectories(host, emptyArray, /*recursive*/ false);
|
||||
checkWatchedDirectories(host, [projectPath(SubProject.core), projectPath(SubProject.logic)], /*recursive*/ true);
|
||||
checkWatchedDirectories(host, testProjectExpectedWatchedDirectoriesRecursive, /*recursive*/ true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -347,7 +352,7 @@ function myFunc() { return 100; }`);
|
||||
function verifyWatches() {
|
||||
checkWatchedFiles(host, projectFiles.map(f => f.path));
|
||||
checkWatchedDirectories(host, emptyArray, /*recursive*/ false);
|
||||
checkWatchedDirectories(host, [projectPath(SubProject.core), projectPath(SubProject.logic)], /*recursive*/ true);
|
||||
checkWatchedDirectories(host, testProjectExpectedWatchedDirectoriesRecursive, /*recursive*/ true);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -389,12 +394,106 @@ let x: string = 10;`);
|
||||
});
|
||||
});
|
||||
|
||||
it("tsc-watch works with project references", () => {
|
||||
// Build the composite project
|
||||
const host = createSolutionInWatchMode(allFiles);
|
||||
describe("tsc-watch works with project references", () => {
|
||||
const coreIndexDts = projectFileName(SubProject.core, "index.d.ts");
|
||||
const coreAnotherModuleDts = projectFileName(SubProject.core, "anotherModule.d.ts");
|
||||
const logicIndexDts = projectFileName(SubProject.logic, "index.d.ts");
|
||||
const expectedWatchedFiles = [core[0], logic[0], ...tests, libFile].map(f => f.path).concat([coreIndexDts, coreAnotherModuleDts, logicIndexDts].map(f => f.toLowerCase()));
|
||||
const expectedWatchedDirectoriesRecursive = projectSystem.getTypeRootsFromLocation(projectPath(SubProject.tests));
|
||||
|
||||
createWatchOfConfigFile(tests[0].path, host);
|
||||
checkOutputErrorsInitial(host, emptyArray);
|
||||
function createSolution() {
|
||||
const host = createWatchedSystem(allFiles, { currentDirectory: projectsLocation });
|
||||
const solutionBuilder = createSolutionBuilder(host, [`${project}/${SubProject.tests}`], {});
|
||||
return { host, solutionBuilder };
|
||||
}
|
||||
|
||||
function createBuiltSolution() {
|
||||
const result = createSolution();
|
||||
const { host, solutionBuilder } = result;
|
||||
solutionBuilder.buildAllProjects();
|
||||
const outputFileStamps = getOutputFileStamps(host);
|
||||
for (const stamp of outputFileStamps) {
|
||||
assert.isDefined(stamp[1], `${stamp[0]} expected to be present`);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function verifyWatches(host: WatchedSystem) {
|
||||
checkWatchedFilesDetailed(host, expectedWatchedFiles, 1);
|
||||
checkWatchedDirectories(host, emptyArray, /*recursive*/ false);
|
||||
checkWatchedDirectoriesDetailed(host, expectedWatchedDirectoriesRecursive, 1, /*recursive*/ true);
|
||||
}
|
||||
|
||||
function createSolutionAndWatchMode() {
|
||||
// Build the composite project
|
||||
const { host, solutionBuilder } = createBuiltSolution();
|
||||
|
||||
// Build in watch mode
|
||||
const watch = createWatchOfConfigFileReturningBuilder(tests[0].path, host);
|
||||
checkOutputErrorsInitial(host, emptyArray);
|
||||
|
||||
return { host, solutionBuilder, watch };
|
||||
}
|
||||
|
||||
function verifyDependencies(watch: () => BuilderProgram, filePath: string, expected: ReadonlyArray<string>) {
|
||||
checkArray(`${filePath} dependencies`, watch().getAllDependencies(watch().getSourceFile(filePath)!), expected);
|
||||
}
|
||||
|
||||
describe("invoking when references are already built", () => {
|
||||
it("verifies dependencies and watches", () => {
|
||||
const { host, watch } = createSolutionAndWatchMode();
|
||||
|
||||
verifyWatches(host);
|
||||
verifyDependencies(watch, coreIndexDts, [coreIndexDts]);
|
||||
verifyDependencies(watch, coreAnotherModuleDts, [coreAnotherModuleDts]);
|
||||
verifyDependencies(watch, logicIndexDts, [logicIndexDts, coreAnotherModuleDts]);
|
||||
verifyDependencies(watch, tests[1].path, [tests[1].path, coreAnotherModuleDts, logicIndexDts, coreAnotherModuleDts]);
|
||||
});
|
||||
|
||||
it("local edit in ts file, result in watch compilation because logic.d.ts is written", () => {
|
||||
const { host, solutionBuilder, watch } = createSolutionAndWatchMode();
|
||||
host.writeFile(logic[1].path, `${logic[1].content}
|
||||
function foo() {
|
||||
}`);
|
||||
solutionBuilder.invalidateProject(`${project}/${SubProject.logic}`);
|
||||
solutionBuilder.buildInvalidatedProject();
|
||||
|
||||
host.checkTimeoutQueueLengthAndRun(1); // not ideal, but currently because of d.ts but no new file is written
|
||||
checkOutputErrorsIncremental(host, emptyArray);
|
||||
checkProgramActualFiles(watch().getProgram(), [tests[1].path, libFile.path, coreIndexDts, coreAnotherModuleDts, logicIndexDts]);
|
||||
});
|
||||
|
||||
it("non local edit in ts file, rebuilds in watch compilation", () => {
|
||||
const { host, solutionBuilder, watch } = createSolutionAndWatchMode();
|
||||
host.writeFile(logic[1].path, `${logic[1].content}
|
||||
export function gfoo() {
|
||||
}`);
|
||||
solutionBuilder.invalidateProject(logic[0].path);
|
||||
solutionBuilder.buildInvalidatedProject();
|
||||
|
||||
host.checkTimeoutQueueLengthAndRun(1);
|
||||
checkOutputErrorsIncremental(host, emptyArray);
|
||||
checkProgramActualFiles(watch().getProgram(), [tests[1].path, libFile.path, coreIndexDts, coreAnotherModuleDts, logicIndexDts]);
|
||||
});
|
||||
|
||||
it("change in project reference config file builds correctly", () => {
|
||||
const { host, solutionBuilder, watch } = createSolutionAndWatchMode();
|
||||
host.writeFile(logic[0].path, JSON.stringify({
|
||||
compilerOptions: { composite: true, declaration: true, declarationDir: "decls" },
|
||||
references: [{ path: "../core" }]
|
||||
}));
|
||||
solutionBuilder.invalidateProject(logic[0].path, ConfigFileProgramReloadLevel.Full);
|
||||
solutionBuilder.buildInvalidatedProject();
|
||||
|
||||
host.checkTimeoutQueueLengthAndRun(1);
|
||||
checkOutputErrorsIncremental(host, [
|
||||
// TODO: #26036
|
||||
// The error is reported in d.ts file because it isnt resolved from ts file path, but is resolved from .d.ts file
|
||||
"sample1/logic/decls/index.d.ts(2,22): error TS2307: Cannot find module '../core/anotherModule'.\n"
|
||||
]);
|
||||
checkProgramActualFiles(watch().getProgram(), [tests[1].path, libFile.path, coreIndexDts, coreAnotherModuleDts, projectFilePath(SubProject.logic, "decls/index.d.ts")]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -20,6 +20,13 @@ namespace ts.tscWatch {
|
||||
checkArray(`Program rootFileNames`, program.getRootFileNames(), expectedFiles);
|
||||
}
|
||||
|
||||
export function createWatchOfConfigFileReturningBuilder(configFileName: string, host: WatchedSystem, maxNumberOfFilesToIterateForInvalidation?: number) {
|
||||
const compilerHost = createWatchCompilerHostOfConfigFile(configFileName, {}, host);
|
||||
compilerHost.maxNumberOfFilesToIterateForInvalidation = maxNumberOfFilesToIterateForInvalidation;
|
||||
const watch = createWatchProgram(compilerHost);
|
||||
return () => watch.getCurrentProgram();
|
||||
}
|
||||
|
||||
export function createWatchOfConfigFile(configFileName: string, host: WatchedSystem, maxNumberOfFilesToIterateForInvalidation?: number) {
|
||||
const compilerHost = createWatchCompilerHostOfConfigFile(configFileName, {}, host);
|
||||
compilerHost.maxNumberOfFilesToIterateForInvalidation = maxNumberOfFilesToIterateForInvalidation;
|
||||
@@ -443,6 +450,33 @@ namespace ts.tscWatch {
|
||||
checkOutputErrorsIncremental(host, emptyArray);
|
||||
});
|
||||
|
||||
it("Updates diagnostics when '--noUnusedLabels' changes", () => {
|
||||
const aTs: File = { path: "/a.ts", content: "label: while (1) {}" };
|
||||
const files = [libFile, aTs];
|
||||
const paths = files.map(f => f.path);
|
||||
const options = (allowUnusedLabels: boolean) => `{ "compilerOptions": { "allowUnusedLabels": ${allowUnusedLabels} } }`;
|
||||
const tsconfig: File = { path: "/tsconfig.json", content: options(/*allowUnusedLabels*/ true) };
|
||||
|
||||
const host = createWatchedSystem([...files, tsconfig]);
|
||||
const watch = createWatchOfConfigFile(tsconfig.path, host);
|
||||
|
||||
checkProgramActualFiles(watch(), paths);
|
||||
checkOutputErrorsInitial(host, emptyArray);
|
||||
|
||||
host.modifyFile(tsconfig.path, options(/*allowUnusedLabels*/ false));
|
||||
host.checkTimeoutQueueLengthAndRun(1); // reload the configured project
|
||||
|
||||
checkProgramActualFiles(watch(), paths);
|
||||
checkOutputErrorsIncremental(host, [
|
||||
getDiagnosticOfFileFromProgram(watch(), aTs.path, 0, "label".length, Diagnostics.Unused_label),
|
||||
]);
|
||||
|
||||
host.modifyFile(tsconfig.path, options(/*allowUnusedLabels*/ true));
|
||||
host.checkTimeoutQueueLengthAndRun(1); // reload the configured project
|
||||
checkProgramActualFiles(watch(), paths);
|
||||
checkOutputErrorsIncremental(host, emptyArray);
|
||||
});
|
||||
|
||||
it("files explicitly excluded in config file", () => {
|
||||
const configFile: File = {
|
||||
path: "/a/b/tsconfig.json",
|
||||
@@ -1190,7 +1224,7 @@ namespace ts.tscWatch {
|
||||
host.reloadFS(files);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
checkProgramActualFiles(watch(), files.map(file => file.path));
|
||||
checkOutputErrorsIncremental(host, []);
|
||||
checkOutputErrorsIncremental(host, emptyArray);
|
||||
});
|
||||
|
||||
it("watched files when file is deleted and new file is added as part of change", () => {
|
||||
@@ -1322,12 +1356,10 @@ export class B
|
||||
path: `${currentDirectory}/a.ts`,
|
||||
content: `declare function foo(): null | { hello: any };
|
||||
foo().hello`
|
||||
};
|
||||
const compilerOptions: CompilerOptions = {
|
||||
};
|
||||
const config: File = {
|
||||
path: `${currentDirectory}/tsconfig.json`,
|
||||
content: JSON.stringify({ compilerOptions })
|
||||
content: JSON.stringify({ compilerOptions: {} })
|
||||
};
|
||||
const files = [aFile, config, libFile];
|
||||
const host = createWatchedSystem(files, { currentDirectory });
|
||||
@@ -1335,8 +1367,7 @@ foo().hello`
|
||||
checkProgramActualFiles(watch(), [aFile.path, libFile.path]);
|
||||
checkOutputErrorsInitial(host, emptyArray);
|
||||
const modifiedTimeOfAJs = host.getModifiedTime(`${currentDirectory}/a.js`);
|
||||
compilerOptions.strictNullChecks = true;
|
||||
host.writeFile(config.path, JSON.stringify({ compilerOptions }));
|
||||
host.writeFile(config.path, JSON.stringify({ compilerOptions: { strictNullChecks: true } }));
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
const expectedStrictNullErrors = [
|
||||
getDiagnosticOfFileFromProgram(watch(), aFile.path, aFile.content.lastIndexOf("foo()"), 5, Diagnostics.Object_is_possibly_null)
|
||||
@@ -1344,15 +1375,12 @@ foo().hello`
|
||||
checkOutputErrorsIncremental(host, expectedStrictNullErrors);
|
||||
// File a need not be rewritten
|
||||
assert.equal(host.getModifiedTime(`${currentDirectory}/a.js`), modifiedTimeOfAJs);
|
||||
compilerOptions.strict = true;
|
||||
delete (compilerOptions.strictNullChecks);
|
||||
host.writeFile(config.path, JSON.stringify({ compilerOptions }));
|
||||
host.writeFile(config.path, JSON.stringify({ compilerOptions: { strict: true, alwaysStrict: false } })); // Avoid changing 'alwaysStrict' or must re-bind
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
checkOutputErrorsIncremental(host, expectedStrictNullErrors);
|
||||
// File a need not be rewritten
|
||||
assert.equal(host.getModifiedTime(`${currentDirectory}/a.js`), modifiedTimeOfAJs);
|
||||
delete (compilerOptions.strict);
|
||||
host.writeFile(config.path, JSON.stringify({ compilerOptions }));
|
||||
host.writeFile(config.path, JSON.stringify({ compilerOptions: {} }));
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
checkOutputErrorsIncremental(host, emptyArray);
|
||||
// File a need not be rewritten
|
||||
|
||||
@@ -85,6 +85,7 @@ namespace ts.projectSystem {
|
||||
|
||||
isKnownTypesPackageName = notImplemented;
|
||||
installPackage = notImplemented;
|
||||
inspectValue = notImplemented;
|
||||
|
||||
executePendingCommands() {
|
||||
const actionsToRun = this.postExecActions;
|
||||
@@ -456,7 +457,7 @@ namespace ts.projectSystem {
|
||||
function protocolFileLocationFromSubstring(file: File, substring: string): protocol.FileLocationRequestArgs {
|
||||
return { file: file.path, ...protocolLocationFromSubstring(file.content, substring) };
|
||||
}
|
||||
function protocolFileSpanFromSubstring(file: File, substring: string, options?: SpanFromSubstringOptions) {
|
||||
function protocolFileSpanFromSubstring(file: File, substring: string, options?: SpanFromSubstringOptions): protocol.FileSpan {
|
||||
return { file: file.path, ...protocolTextSpanFromSubstring(file.content, substring, options) };
|
||||
}
|
||||
function documentSpanFromSubstring(file: File, substring: string, options?: SpanFromSubstringOptions): DocumentSpan {
|
||||
@@ -3491,7 +3492,7 @@ namespace ts.projectSystem {
|
||||
host.checkTimeoutQueueLength(2); // Update configured project and projects for open file
|
||||
checkProjectActualFiles(services.configuredProjects.get(config.path)!, filesWithFileA.map(f => f.path));
|
||||
|
||||
// host.fileExists = originalFileExists;
|
||||
// host.fileExists = originalFileExists;
|
||||
openFile(fileSubA);
|
||||
// This should create inferred project since fileSubA not on the disk
|
||||
checkProjectActualFiles(services.configuredProjects.get(config.path)!, mapDefined(filesWithFileA, f => f === fileA ? undefined : f.path));
|
||||
@@ -3672,7 +3673,7 @@ namespace ts.projectSystem {
|
||||
path: `${projectRoot}/app1/tsconfig.json`,
|
||||
content: JSON.stringify({
|
||||
files: ["app.ts", "../core/core.ts"],
|
||||
compilerOptions: { outFile : "build/output.js" },
|
||||
compilerOptions: { outFile: "build/output.js" },
|
||||
compileOnSave: true
|
||||
})
|
||||
};
|
||||
@@ -6778,9 +6779,9 @@ namespace ts.projectSystem {
|
||||
fileName: "/a.1.ts",
|
||||
textChanges: [
|
||||
{
|
||||
start: { line: 0, offset: 0 },
|
||||
end: { line: 0, offset: 0 },
|
||||
newText: "export const a = 0;",
|
||||
start: { line: 0, offset: 0 },
|
||||
end: { line: 0, offset: 0 },
|
||||
newText: "export const a = 0;",
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -8287,7 +8288,8 @@ namespace ts.projectSystem {
|
||||
protocolTextSpanFromSubstring(aFile.content, "C"),
|
||||
protocolTextSpanFromSubstring(aFile.content, "C", { index: 1 }),
|
||||
];
|
||||
const cLocs: protocol.TextSpan[] = [protocolTextSpanFromSubstring(cFile.content, "C")];
|
||||
const span = protocolTextSpanFromSubstring(cFile.content, "C");
|
||||
const cLocs: protocol.TextSpan[] = [span];
|
||||
assert.deepEqual<protocol.RenameResponseBody | undefined>(response, {
|
||||
info: {
|
||||
canRename: true,
|
||||
@@ -8296,6 +8298,7 @@ namespace ts.projectSystem {
|
||||
kind: ScriptElementKind.constElement,
|
||||
kindModifiers: ScriptElementKindModifier.exportedModifier,
|
||||
localizedErrorMessage: undefined,
|
||||
triggerSpan: span,
|
||||
},
|
||||
locs: [
|
||||
{ file: aFc, locs: cLocs },
|
||||
@@ -8672,7 +8675,7 @@ new C();`
|
||||
}));
|
||||
checkWatchedDirectories(host, [], /*recursive*/ false);
|
||||
checkWatchedDirectories(host, arrayFrom(expectedRecursiveDirectories.keys()), /*recursive*/ true);
|
||||
}
|
||||
}
|
||||
|
||||
describe("from files in same folder", () => {
|
||||
function getFiles(fileContent: string) {
|
||||
@@ -9090,7 +9093,7 @@ export const x = 10;`
|
||||
|
||||
Debug.assert(!!project.resolveModuleNames);
|
||||
|
||||
const edits = project.getLanguageService().getEditsForFileRename("/old.ts", "/new.ts", testFormatOptions, emptyOptions);
|
||||
const edits = project.getLanguageService().getEditsForFileRename("/old.ts", "/new.ts", testFormatSettings, emptyOptions);
|
||||
assert.deepEqual<ReadonlyArray<FileTextChanges>>(edits, [{
|
||||
fileName: "/user.ts",
|
||||
textChanges: [{
|
||||
@@ -9750,7 +9753,7 @@ declare class TestLib {
|
||||
function verifyATsConfigOriginalProject(session: TestSession) {
|
||||
checkNumberOfProjects(session.getProjectService(), { inferredProjects: 1, configuredProjects: 1 });
|
||||
verifyInferredProjectUnchanged(session);
|
||||
verifyATsConfigProject(session);
|
||||
verifyATsConfigProject(session);
|
||||
// Close user file should close all the projects
|
||||
closeFilesForSession([userTs], session);
|
||||
verifyOnlyOrphanInferredProject(session);
|
||||
@@ -9900,11 +9903,12 @@ declare class TestLib {
|
||||
verifyATsConfigWhenOpened(session);
|
||||
});
|
||||
|
||||
interface ReferencesFullRequest extends protocol.FileLocationRequest { readonly command: protocol.CommandTypes.ReferencesFull; }
|
||||
interface ReferencesFullResponse extends protocol.Response { readonly body: ReadonlyArray<ReferencedSymbol>; }
|
||||
|
||||
it("findAllReferencesFull", () => {
|
||||
const session = makeSampleProjects();
|
||||
|
||||
interface ReferencesFullRequest extends protocol.FileLocationRequest { command: protocol.CommandTypes.ReferencesFull; }
|
||||
interface ReferencesFullResponse extends protocol.Response { body: ReadonlyArray<ReferencedSymbol>; }
|
||||
const responseFull = executeSessionRequest<ReferencesFullRequest, ReferencesFullResponse>(session, protocol.CommandTypes.ReferencesFull, protocolFileLocationFromSubstring(userTs, "fnA()"));
|
||||
|
||||
function fnAVoid(kind: SymbolDisplayPartKind): SymbolDisplayPart[] {
|
||||
@@ -9961,6 +9965,67 @@ declare class TestLib {
|
||||
verifyATsConfigOriginalProject(session);
|
||||
});
|
||||
|
||||
it("findAllReferencesFull definition is in mapped file", () => {
|
||||
const aTs: File = { path: "/a/a.ts", content: `function f() {}` };
|
||||
const aTsconfig: File = {
|
||||
path: "/a/tsconfig.json",
|
||||
content: JSON.stringify({ compilerOptions: { declaration: true, declarationMap: true, outFile: "../bin/a.js" } }),
|
||||
};
|
||||
const bTs: File = { path: "/b/b.ts", content: `f();` };
|
||||
const bTsconfig: File = { path: "/b/tsconfig.json", content: JSON.stringify({ references: [{ path: "../a" }] }) };
|
||||
const aDts: File = { path: "/bin/a.d.ts", content: `declare function f(): void;\n//# sourceMappingURL=a.d.ts.map` };
|
||||
const aDtsMap: File = {
|
||||
path: "/bin/a.d.ts.map",
|
||||
content: JSON.stringify({ version: 3, file: "a.d.ts", sourceRoot: "", sources: ["../a/a.ts"], names: [], mappings: "AAAA,iBAAS,CAAC,SAAK" }),
|
||||
};
|
||||
|
||||
const session = createSession(createServerHost([aTs, aTsconfig, bTs, bTsconfig, aDts, aDtsMap]));
|
||||
checkDeclarationFiles(aTs, session, [aDtsMap, aDts]);
|
||||
openFilesForSession([bTs], session);
|
||||
checkNumberOfProjects(session.getProjectService(), { configuredProjects: 1 });
|
||||
|
||||
const responseFull = executeSessionRequest<ReferencesFullRequest, ReferencesFullResponse>(session, protocol.CommandTypes.ReferencesFull, protocolFileLocationFromSubstring(bTs, "f()"));
|
||||
|
||||
assert.deepEqual<ReadonlyArray<ReferencedSymbol>>(responseFull, [
|
||||
{
|
||||
definition: {
|
||||
containerKind: ScriptElementKind.unknown,
|
||||
containerName: "",
|
||||
displayParts: [
|
||||
keywordPart(SyntaxKind.FunctionKeyword),
|
||||
spacePart(),
|
||||
displayPart("f", SymbolDisplayPartKind.functionName),
|
||||
punctuationPart(SyntaxKind.OpenParenToken),
|
||||
punctuationPart(SyntaxKind.CloseParenToken),
|
||||
punctuationPart(SyntaxKind.ColonToken),
|
||||
spacePart(),
|
||||
keywordPart(SyntaxKind.VoidKeyword),
|
||||
],
|
||||
fileName: aTs.path,
|
||||
kind: ScriptElementKind.functionElement,
|
||||
name: "function f(): void",
|
||||
textSpan: { start: 9, length: 1 },
|
||||
},
|
||||
references: [
|
||||
{
|
||||
fileName: bTs.path,
|
||||
isDefinition: false,
|
||||
isInString: undefined,
|
||||
isWriteAccess: false,
|
||||
textSpan: { start: 0, length: 1 },
|
||||
},
|
||||
{
|
||||
fileName: aTs.path,
|
||||
isDefinition: true,
|
||||
isInString: undefined,
|
||||
isWriteAccess: true,
|
||||
textSpan: { start: 9, length: 1 },
|
||||
},
|
||||
],
|
||||
}
|
||||
]);
|
||||
});
|
||||
|
||||
it("findAllReferences -- target does not exist", () => {
|
||||
const session = makeSampleProjects();
|
||||
|
||||
@@ -10001,6 +10066,7 @@ declare class TestLib {
|
||||
kind: ScriptElementKind.alias,
|
||||
kindModifiers: ScriptElementKindModifier.none,
|
||||
localizedErrorMessage: undefined,
|
||||
triggerSpan: protocolTextSpanFromSubstring(userTs.content, "fnA", { index: 1 }),
|
||||
},
|
||||
locs: [renameUserTs(userTs), renameATs(aTs)],
|
||||
});
|
||||
@@ -10019,6 +10085,7 @@ declare class TestLib {
|
||||
kind: ScriptElementKind.functionElement,
|
||||
kindModifiers: ScriptElementKindModifier.exportedModifier,
|
||||
localizedErrorMessage: undefined,
|
||||
triggerSpan: protocolTextSpanFromSubstring(aTs.content, "fnA"),
|
||||
},
|
||||
locs: [renameATs(aTs), renameUserTs(userTs)],
|
||||
});
|
||||
@@ -10047,6 +10114,7 @@ declare class TestLib {
|
||||
kind: ScriptElementKind.alias,
|
||||
kindModifiers: ScriptElementKindModifier.none,
|
||||
localizedErrorMessage: undefined,
|
||||
triggerSpan: protocolTextSpanFromSubstring(userTs.content, "fnB", { index: 1 }),
|
||||
},
|
||||
locs: [
|
||||
{
|
||||
@@ -10180,6 +10248,35 @@ declare class TestLib {
|
||||
});
|
||||
});
|
||||
|
||||
describe("tsserverProjectSystem config file change", () => {
|
||||
it("Updates diagnostics when '--noUnusedLabels' changes", () => {
|
||||
const aTs: File = { path: "/a.ts", content: "label: while (1) {}" };
|
||||
const options = (allowUnusedLabels: boolean) => `{ "compilerOptions": { "allowUnusedLabels": ${allowUnusedLabels} } }`;
|
||||
const tsconfig: File = { path: "/tsconfig.json", content: options(/*allowUnusedLabels*/ true) };
|
||||
|
||||
const host = createServerHost([aTs, tsconfig]);
|
||||
const session = createSession(host);
|
||||
openFilesForSession([aTs], session);
|
||||
|
||||
host.modifyFile(tsconfig.path, options(/*allowUnusedLabels*/ false));
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
|
||||
const response = executeSessionRequest<protocol.SemanticDiagnosticsSyncRequest, protocol.SemanticDiagnosticsSyncResponse>(session, protocol.CommandTypes.SemanticDiagnosticsSync, { file: aTs.path }) as protocol.Diagnostic[] | undefined;
|
||||
assert.deepEqual<protocol.Diagnostic[] | undefined>(response, [
|
||||
{
|
||||
start: { line: 1, offset: 1 },
|
||||
end: { line: 1, offset: 1 + "label".length },
|
||||
text: "Unused label.",
|
||||
category: "error",
|
||||
code: Diagnostics.Unused_label.code,
|
||||
relatedInformation: undefined,
|
||||
reportsUnnecessary: true,
|
||||
source: undefined,
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
function makeReferenceItem(file: File, isDefinition: boolean, text: string, lineText: string, options?: SpanFromSubstringOptions): protocol.ReferencesResponseItem {
|
||||
return {
|
||||
...protocolFileSpanFromSubstring(file, text, options),
|
||||
|
||||
+16
-6
@@ -231,7 +231,8 @@ namespace ts.server {
|
||||
// buffer, but we have yet to find a way to retrieve that value.
|
||||
private static readonly maxActiveRequestCount = 10;
|
||||
private static readonly requestDelayMillis = 100;
|
||||
private packageInstalledPromise: { resolve(value: ApplyCodeActionCommandResult): void, reject(reason: any): void } | undefined;
|
||||
private packageInstalledPromise: { resolve(value: ApplyCodeActionCommandResult): void, reject(reason: unknown): void } | undefined;
|
||||
private inspectValuePromise: { resolve(value: ValueInfo): void } | undefined;
|
||||
|
||||
constructor(
|
||||
private readonly telemetryEnabled: boolean,
|
||||
@@ -261,14 +262,19 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
installPackage(options: InstallPackageOptionsWithProject): Promise<ApplyCodeActionCommandResult> {
|
||||
const rq: InstallPackageRequest = { kind: "installPackage", ...options };
|
||||
this.send(rq);
|
||||
this.send<InstallPackageRequest>({ kind: "installPackage", ...options });
|
||||
Debug.assert(this.packageInstalledPromise === undefined);
|
||||
return new Promise((resolve, reject) => {
|
||||
return new Promise<ApplyCodeActionCommandResult>((resolve, reject) => {
|
||||
this.packageInstalledPromise = { resolve, reject };
|
||||
});
|
||||
}
|
||||
|
||||
inspectValue(options: InspectValueOptions): Promise<ValueInfo> {
|
||||
this.send<InspectValueRequest>({ kind: "inspectValue", options });
|
||||
Debug.assert(this.inspectValuePromise === undefined);
|
||||
return new Promise<ValueInfo>(resolve => { this.inspectValuePromise = { resolve }; });
|
||||
}
|
||||
|
||||
attach(projectService: ProjectService) {
|
||||
this.projectService = projectService;
|
||||
if (this.logger.hasLevel(LogLevel.requestTime)) {
|
||||
@@ -320,7 +326,7 @@ namespace ts.server {
|
||||
this.send({ projectName: p.getProjectName(), kind: "closeProject" });
|
||||
}
|
||||
|
||||
private send(rq: TypingInstallerRequestUnion): void {
|
||||
private send<T extends TypingInstallerRequestUnion>(rq: T): void {
|
||||
this.installer.send(rq);
|
||||
}
|
||||
|
||||
@@ -353,7 +359,7 @@ namespace ts.server {
|
||||
}
|
||||
}
|
||||
|
||||
private handleMessage(response: TypesRegistryResponse | PackageInstalledResponse | SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes | InitializationFailedResponse) {
|
||||
private handleMessage(response: TypesRegistryResponse | PackageInstalledResponse | InspectValueResponse | SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes | InitializationFailedResponse) {
|
||||
if (this.logger.hasLevel(LogLevel.verbose)) {
|
||||
this.logger.info(`Received response:${stringifyIndented(response)}`);
|
||||
}
|
||||
@@ -378,6 +384,10 @@ namespace ts.server {
|
||||
this.event(response, "setTypings");
|
||||
break;
|
||||
}
|
||||
case ActionValueInspected:
|
||||
this.inspectValuePromise!.resolve(response.result);
|
||||
this.inspectValuePromise = undefined;
|
||||
break;
|
||||
case EventInitializationFailed:
|
||||
{
|
||||
const body: protocol.TypesInstallerInitializationFailedEventBody = {
|
||||
|
||||
@@ -164,6 +164,11 @@ namespace ts.server.typingsInstaller {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "inspectValue": {
|
||||
const response: InspectValueResponse = { kind: ActionValueInspected, result: inspectModule(req.options.fileNameToRequire) };
|
||||
this.sendResponse(response);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Debug.assertNever(req);
|
||||
}
|
||||
|
||||
@@ -2,9 +2,10 @@ tests/cases/compiler/abstractPropertyInConstructor.ts(4,24): error TS2715: Abstr
|
||||
tests/cases/compiler/abstractPropertyInConstructor.ts(7,18): error TS2715: Abstract property 'prop' in class 'AbstractClass' cannot be accessed in the constructor.
|
||||
tests/cases/compiler/abstractPropertyInConstructor.ts(9,14): error TS2715: Abstract property 'cb' in class 'AbstractClass' cannot be accessed in the constructor.
|
||||
tests/cases/compiler/abstractPropertyInConstructor.ts(25,18): error TS2715: Abstract property 'prop' in class 'AbstractClass' cannot be accessed in the constructor.
|
||||
tests/cases/compiler/abstractPropertyInConstructor.ts(39,22): error TS2715: Abstract property 'prop' in class 'AbstractClass' cannot be accessed in the constructor.
|
||||
|
||||
|
||||
==== tests/cases/compiler/abstractPropertyInConstructor.ts (4 errors) ====
|
||||
==== tests/cases/compiler/abstractPropertyInConstructor.ts (5 errors) ====
|
||||
abstract class AbstractClass {
|
||||
constructor(str: string, other: AbstractClass) {
|
||||
this.method(parseInt(str));
|
||||
@@ -45,6 +46,38 @@ tests/cases/compiler/abstractPropertyInConstructor.ts(25,18): error TS2715: Abst
|
||||
}
|
||||
}
|
||||
|
||||
abstract class DerivedAbstractClass extends AbstractClass {
|
||||
cb = (s: string) => {};
|
||||
|
||||
constructor(str: string, other: AbstractClass, yetAnother: DerivedAbstractClass) {
|
||||
super(str, other);
|
||||
// there is no implementation of 'prop' in any base class
|
||||
this.cb(this.prop.toLowerCase());
|
||||
~~~~
|
||||
!!! error TS2715: Abstract property 'prop' in class 'AbstractClass' cannot be accessed in the constructor.
|
||||
|
||||
this.method(1);
|
||||
|
||||
// OK, references are to another instance
|
||||
other.cb(other.prop);
|
||||
yetAnother.cb(yetAnother.prop);
|
||||
}
|
||||
}
|
||||
|
||||
class Implementation extends DerivedAbstractClass {
|
||||
prop = "";
|
||||
cb = (s: string) => {};
|
||||
|
||||
constructor(str: string, other: AbstractClass, yetAnother: DerivedAbstractClass) {
|
||||
super(str, other, yetAnother);
|
||||
this.cb(this.prop);
|
||||
}
|
||||
|
||||
method(n: number) {
|
||||
this.cb(this.prop + n);
|
||||
}
|
||||
}
|
||||
|
||||
class User {
|
||||
constructor(a: AbstractClass) {
|
||||
a.prop;
|
||||
|
||||
@@ -31,6 +31,36 @@ abstract class AbstractClass {
|
||||
}
|
||||
}
|
||||
|
||||
abstract class DerivedAbstractClass extends AbstractClass {
|
||||
cb = (s: string) => {};
|
||||
|
||||
constructor(str: string, other: AbstractClass, yetAnother: DerivedAbstractClass) {
|
||||
super(str, other);
|
||||
// there is no implementation of 'prop' in any base class
|
||||
this.cb(this.prop.toLowerCase());
|
||||
|
||||
this.method(1);
|
||||
|
||||
// OK, references are to another instance
|
||||
other.cb(other.prop);
|
||||
yetAnother.cb(yetAnother.prop);
|
||||
}
|
||||
}
|
||||
|
||||
class Implementation extends DerivedAbstractClass {
|
||||
prop = "";
|
||||
cb = (s: string) => {};
|
||||
|
||||
constructor(str: string, other: AbstractClass, yetAnother: DerivedAbstractClass) {
|
||||
super(str, other, yetAnother);
|
||||
this.cb(this.prop);
|
||||
}
|
||||
|
||||
method(n: number) {
|
||||
this.cb(this.prop + n);
|
||||
}
|
||||
}
|
||||
|
||||
class User {
|
||||
constructor(a: AbstractClass) {
|
||||
a.prop;
|
||||
@@ -42,6 +72,19 @@ class User {
|
||||
|
||||
|
||||
//// [abstractPropertyInConstructor.js]
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = function (d, b) {
|
||||
extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return extendStatics(d, b);
|
||||
}
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
var AbstractClass = /** @class */ (function () {
|
||||
function AbstractClass(str, other) {
|
||||
var _this = this;
|
||||
@@ -65,6 +108,35 @@ var AbstractClass = /** @class */ (function () {
|
||||
};
|
||||
return AbstractClass;
|
||||
}());
|
||||
var DerivedAbstractClass = /** @class */ (function (_super) {
|
||||
__extends(DerivedAbstractClass, _super);
|
||||
function DerivedAbstractClass(str, other, yetAnother) {
|
||||
var _this = _super.call(this, str, other) || this;
|
||||
_this.cb = function (s) { };
|
||||
// there is no implementation of 'prop' in any base class
|
||||
_this.cb(_this.prop.toLowerCase());
|
||||
_this.method(1);
|
||||
// OK, references are to another instance
|
||||
other.cb(other.prop);
|
||||
yetAnother.cb(yetAnother.prop);
|
||||
return _this;
|
||||
}
|
||||
return DerivedAbstractClass;
|
||||
}(AbstractClass));
|
||||
var Implementation = /** @class */ (function (_super) {
|
||||
__extends(Implementation, _super);
|
||||
function Implementation(str, other, yetAnother) {
|
||||
var _this = _super.call(this, str, other, yetAnother) || this;
|
||||
_this.prop = "";
|
||||
_this.cb = function (s) { };
|
||||
_this.cb(_this.prop);
|
||||
return _this;
|
||||
}
|
||||
Implementation.prototype.method = function (n) {
|
||||
this.cb(this.prop + n);
|
||||
};
|
||||
return Implementation;
|
||||
}(DerivedAbstractClass));
|
||||
var User = /** @class */ (function () {
|
||||
function User(a) {
|
||||
a.prop;
|
||||
|
||||
@@ -92,31 +92,134 @@ abstract class AbstractClass {
|
||||
}
|
||||
}
|
||||
|
||||
abstract class DerivedAbstractClass extends AbstractClass {
|
||||
>DerivedAbstractClass : Symbol(DerivedAbstractClass, Decl(abstractPropertyInConstructor.ts, 30, 1))
|
||||
>AbstractClass : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0))
|
||||
|
||||
cb = (s: string) => {};
|
||||
>cb : Symbol(DerivedAbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 32, 59))
|
||||
>s : Symbol(s, Decl(abstractPropertyInConstructor.ts, 33, 10))
|
||||
|
||||
constructor(str: string, other: AbstractClass, yetAnother: DerivedAbstractClass) {
|
||||
>str : Symbol(str, Decl(abstractPropertyInConstructor.ts, 35, 16))
|
||||
>other : Symbol(other, Decl(abstractPropertyInConstructor.ts, 35, 28))
|
||||
>AbstractClass : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0))
|
||||
>yetAnother : Symbol(yetAnother, Decl(abstractPropertyInConstructor.ts, 35, 50))
|
||||
>DerivedAbstractClass : Symbol(DerivedAbstractClass, Decl(abstractPropertyInConstructor.ts, 30, 1))
|
||||
|
||||
super(str, other);
|
||||
>super : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0))
|
||||
>str : Symbol(str, Decl(abstractPropertyInConstructor.ts, 35, 16))
|
||||
>other : Symbol(other, Decl(abstractPropertyInConstructor.ts, 35, 28))
|
||||
|
||||
// there is no implementation of 'prop' in any base class
|
||||
this.cb(this.prop.toLowerCase());
|
||||
>this.cb : Symbol(DerivedAbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 32, 59))
|
||||
>this : Symbol(DerivedAbstractClass, Decl(abstractPropertyInConstructor.ts, 30, 1))
|
||||
>cb : Symbol(DerivedAbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 32, 59))
|
||||
>this.prop.toLowerCase : Symbol(String.toLowerCase, Decl(lib.es5.d.ts, --, --))
|
||||
>this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5))
|
||||
>this : Symbol(DerivedAbstractClass, Decl(abstractPropertyInConstructor.ts, 30, 1))
|
||||
>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5))
|
||||
>toLowerCase : Symbol(String.toLowerCase, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
this.method(1);
|
||||
>this.method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 20, 37))
|
||||
>this : Symbol(DerivedAbstractClass, Decl(abstractPropertyInConstructor.ts, 30, 1))
|
||||
>method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 20, 37))
|
||||
|
||||
// OK, references are to another instance
|
||||
other.cb(other.prop);
|
||||
>other.cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 19, 26))
|
||||
>other : Symbol(other, Decl(abstractPropertyInConstructor.ts, 35, 28))
|
||||
>cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 19, 26))
|
||||
>other.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5))
|
||||
>other : Symbol(other, Decl(abstractPropertyInConstructor.ts, 35, 28))
|
||||
>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5))
|
||||
|
||||
yetAnother.cb(yetAnother.prop);
|
||||
>yetAnother.cb : Symbol(DerivedAbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 32, 59))
|
||||
>yetAnother : Symbol(yetAnother, Decl(abstractPropertyInConstructor.ts, 35, 50))
|
||||
>cb : Symbol(DerivedAbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 32, 59))
|
||||
>yetAnother.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5))
|
||||
>yetAnother : Symbol(yetAnother, Decl(abstractPropertyInConstructor.ts, 35, 50))
|
||||
>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5))
|
||||
}
|
||||
}
|
||||
|
||||
class Implementation extends DerivedAbstractClass {
|
||||
>Implementation : Symbol(Implementation, Decl(abstractPropertyInConstructor.ts, 46, 1))
|
||||
>DerivedAbstractClass : Symbol(DerivedAbstractClass, Decl(abstractPropertyInConstructor.ts, 30, 1))
|
||||
|
||||
prop = "";
|
||||
>prop : Symbol(Implementation.prop, Decl(abstractPropertyInConstructor.ts, 48, 51))
|
||||
|
||||
cb = (s: string) => {};
|
||||
>cb : Symbol(Implementation.cb, Decl(abstractPropertyInConstructor.ts, 49, 14))
|
||||
>s : Symbol(s, Decl(abstractPropertyInConstructor.ts, 50, 10))
|
||||
|
||||
constructor(str: string, other: AbstractClass, yetAnother: DerivedAbstractClass) {
|
||||
>str : Symbol(str, Decl(abstractPropertyInConstructor.ts, 52, 16))
|
||||
>other : Symbol(other, Decl(abstractPropertyInConstructor.ts, 52, 28))
|
||||
>AbstractClass : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0))
|
||||
>yetAnother : Symbol(yetAnother, Decl(abstractPropertyInConstructor.ts, 52, 50))
|
||||
>DerivedAbstractClass : Symbol(DerivedAbstractClass, Decl(abstractPropertyInConstructor.ts, 30, 1))
|
||||
|
||||
super(str, other, yetAnother);
|
||||
>super : Symbol(DerivedAbstractClass, Decl(abstractPropertyInConstructor.ts, 30, 1))
|
||||
>str : Symbol(str, Decl(abstractPropertyInConstructor.ts, 52, 16))
|
||||
>other : Symbol(other, Decl(abstractPropertyInConstructor.ts, 52, 28))
|
||||
>yetAnother : Symbol(yetAnother, Decl(abstractPropertyInConstructor.ts, 52, 50))
|
||||
|
||||
this.cb(this.prop);
|
||||
>this.cb : Symbol(Implementation.cb, Decl(abstractPropertyInConstructor.ts, 49, 14))
|
||||
>this : Symbol(Implementation, Decl(abstractPropertyInConstructor.ts, 46, 1))
|
||||
>cb : Symbol(Implementation.cb, Decl(abstractPropertyInConstructor.ts, 49, 14))
|
||||
>this.prop : Symbol(Implementation.prop, Decl(abstractPropertyInConstructor.ts, 48, 51))
|
||||
>this : Symbol(Implementation, Decl(abstractPropertyInConstructor.ts, 46, 1))
|
||||
>prop : Symbol(Implementation.prop, Decl(abstractPropertyInConstructor.ts, 48, 51))
|
||||
}
|
||||
|
||||
method(n: number) {
|
||||
>method : Symbol(Implementation.method, Decl(abstractPropertyInConstructor.ts, 55, 5))
|
||||
>n : Symbol(n, Decl(abstractPropertyInConstructor.ts, 57, 11))
|
||||
|
||||
this.cb(this.prop + n);
|
||||
>this.cb : Symbol(Implementation.cb, Decl(abstractPropertyInConstructor.ts, 49, 14))
|
||||
>this : Symbol(Implementation, Decl(abstractPropertyInConstructor.ts, 46, 1))
|
||||
>cb : Symbol(Implementation.cb, Decl(abstractPropertyInConstructor.ts, 49, 14))
|
||||
>this.prop : Symbol(Implementation.prop, Decl(abstractPropertyInConstructor.ts, 48, 51))
|
||||
>this : Symbol(Implementation, Decl(abstractPropertyInConstructor.ts, 46, 1))
|
||||
>prop : Symbol(Implementation.prop, Decl(abstractPropertyInConstructor.ts, 48, 51))
|
||||
>n : Symbol(n, Decl(abstractPropertyInConstructor.ts, 57, 11))
|
||||
}
|
||||
}
|
||||
|
||||
class User {
|
||||
>User : Symbol(User, Decl(abstractPropertyInConstructor.ts, 30, 1))
|
||||
>User : Symbol(User, Decl(abstractPropertyInConstructor.ts, 60, 1))
|
||||
|
||||
constructor(a: AbstractClass) {
|
||||
>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 33, 16))
|
||||
>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 63, 16))
|
||||
>AbstractClass : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0))
|
||||
|
||||
a.prop;
|
||||
>a.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5))
|
||||
>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 33, 16))
|
||||
>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 63, 16))
|
||||
>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5))
|
||||
|
||||
a.cb("hi");
|
||||
>a.cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 19, 26))
|
||||
>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 33, 16))
|
||||
>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 63, 16))
|
||||
>cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 19, 26))
|
||||
|
||||
a.method(12);
|
||||
>a.method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 20, 37))
|
||||
>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 33, 16))
|
||||
>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 63, 16))
|
||||
>method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 20, 37))
|
||||
|
||||
a.method2();
|
||||
>a.method2 : Symbol(AbstractClass.method2, Decl(abstractPropertyInConstructor.ts, 25, 25))
|
||||
>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 33, 16))
|
||||
>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 63, 16))
|
||||
>method2 : Symbol(AbstractClass.method2, Decl(abstractPropertyInConstructor.ts, 25, 25))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,6 +104,119 @@ abstract class AbstractClass {
|
||||
}
|
||||
}
|
||||
|
||||
abstract class DerivedAbstractClass extends AbstractClass {
|
||||
>DerivedAbstractClass : DerivedAbstractClass
|
||||
>AbstractClass : AbstractClass
|
||||
|
||||
cb = (s: string) => {};
|
||||
>cb : (s: string) => void
|
||||
>(s: string) => {} : (s: string) => void
|
||||
>s : string
|
||||
|
||||
constructor(str: string, other: AbstractClass, yetAnother: DerivedAbstractClass) {
|
||||
>str : string
|
||||
>other : AbstractClass
|
||||
>yetAnother : DerivedAbstractClass
|
||||
|
||||
super(str, other);
|
||||
>super(str, other) : void
|
||||
>super : typeof AbstractClass
|
||||
>str : string
|
||||
>other : AbstractClass
|
||||
|
||||
// there is no implementation of 'prop' in any base class
|
||||
this.cb(this.prop.toLowerCase());
|
||||
>this.cb(this.prop.toLowerCase()) : void
|
||||
>this.cb : (s: string) => void
|
||||
>this : this
|
||||
>cb : (s: string) => void
|
||||
>this.prop.toLowerCase() : string
|
||||
>this.prop.toLowerCase : () => string
|
||||
>this.prop : string
|
||||
>this : this
|
||||
>prop : string
|
||||
>toLowerCase : () => string
|
||||
|
||||
this.method(1);
|
||||
>this.method(1) : void
|
||||
>this.method : (num: number) => void
|
||||
>this : this
|
||||
>method : (num: number) => void
|
||||
>1 : 1
|
||||
|
||||
// OK, references are to another instance
|
||||
other.cb(other.prop);
|
||||
>other.cb(other.prop) : void
|
||||
>other.cb : (s: string) => void
|
||||
>other : AbstractClass
|
||||
>cb : (s: string) => void
|
||||
>other.prop : string
|
||||
>other : AbstractClass
|
||||
>prop : string
|
||||
|
||||
yetAnother.cb(yetAnother.prop);
|
||||
>yetAnother.cb(yetAnother.prop) : void
|
||||
>yetAnother.cb : (s: string) => void
|
||||
>yetAnother : DerivedAbstractClass
|
||||
>cb : (s: string) => void
|
||||
>yetAnother.prop : string
|
||||
>yetAnother : DerivedAbstractClass
|
||||
>prop : string
|
||||
}
|
||||
}
|
||||
|
||||
class Implementation extends DerivedAbstractClass {
|
||||
>Implementation : Implementation
|
||||
>DerivedAbstractClass : DerivedAbstractClass
|
||||
|
||||
prop = "";
|
||||
>prop : string
|
||||
>"" : ""
|
||||
|
||||
cb = (s: string) => {};
|
||||
>cb : (s: string) => void
|
||||
>(s: string) => {} : (s: string) => void
|
||||
>s : string
|
||||
|
||||
constructor(str: string, other: AbstractClass, yetAnother: DerivedAbstractClass) {
|
||||
>str : string
|
||||
>other : AbstractClass
|
||||
>yetAnother : DerivedAbstractClass
|
||||
|
||||
super(str, other, yetAnother);
|
||||
>super(str, other, yetAnother) : void
|
||||
>super : typeof DerivedAbstractClass
|
||||
>str : string
|
||||
>other : AbstractClass
|
||||
>yetAnother : DerivedAbstractClass
|
||||
|
||||
this.cb(this.prop);
|
||||
>this.cb(this.prop) : void
|
||||
>this.cb : (s: string) => void
|
||||
>this : this
|
||||
>cb : (s: string) => void
|
||||
>this.prop : string
|
||||
>this : this
|
||||
>prop : string
|
||||
}
|
||||
|
||||
method(n: number) {
|
||||
>method : (n: number) => void
|
||||
>n : number
|
||||
|
||||
this.cb(this.prop + n);
|
||||
>this.cb(this.prop + n) : void
|
||||
>this.cb : (s: string) => void
|
||||
>this : this
|
||||
>cb : (s: string) => void
|
||||
>this.prop + n : string
|
||||
>this.prop : string
|
||||
>this : this
|
||||
>prop : string
|
||||
>n : number
|
||||
}
|
||||
}
|
||||
|
||||
class User {
|
||||
>User : User
|
||||
|
||||
|
||||
+18
-6
@@ -4445,6 +4445,7 @@ declare namespace ts.server {
|
||||
type ActionSet = "action::set";
|
||||
type ActionInvalidate = "action::invalidate";
|
||||
type ActionPackageInstalled = "action::packageInstalled";
|
||||
type ActionValueInspected = "action::valueInspected";
|
||||
type EventTypesRegistry = "event::typesRegistry";
|
||||
type EventBeginInstallTypes = "event::beginInstallTypes";
|
||||
type EventEndInstallTypes = "event::endInstallTypes";
|
||||
@@ -4453,7 +4454,7 @@ declare namespace ts.server {
|
||||
" __sortedArrayBrand": any;
|
||||
}
|
||||
interface TypingInstallerResponse {
|
||||
readonly kind: ActionSet | ActionInvalidate | EventTypesRegistry | ActionPackageInstalled | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed;
|
||||
readonly kind: ActionSet | ActionInvalidate | EventTypesRegistry | ActionPackageInstalled | ActionValueInspected | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed;
|
||||
}
|
||||
interface TypingInstallerRequestWithProjectName {
|
||||
readonly projectName: string;
|
||||
@@ -4661,6 +4662,7 @@ declare namespace ts {
|
||||
getCustomTransformers?(): CustomTransformers | undefined;
|
||||
isKnownTypesPackageName?(name: string): boolean;
|
||||
installPackage?(options: InstallPackageOptions): Promise<ApplyCodeActionCommandResult>;
|
||||
writeFile?(fileName: string, content: string): void;
|
||||
}
|
||||
interface LanguageService {
|
||||
cleanupSemanticCache(): void;
|
||||
@@ -4718,9 +4720,9 @@ declare namespace ts {
|
||||
toLineColumnOffset?(fileName: string, position: number): LineAndCharacter;
|
||||
getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: ReadonlyArray<number>, formatOptions: FormatCodeSettings, preferences: UserPreferences): ReadonlyArray<CodeFixAction>;
|
||||
getCombinedCodeFix(scope: CombinedCodeFixScope, fixId: {}, formatOptions: FormatCodeSettings, preferences: UserPreferences): CombinedCodeActions;
|
||||
applyCodeActionCommand(action: CodeActionCommand): Promise<ApplyCodeActionCommandResult>;
|
||||
applyCodeActionCommand(action: CodeActionCommand[]): Promise<ApplyCodeActionCommandResult[]>;
|
||||
applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[]): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]>;
|
||||
applyCodeActionCommand(action: CodeActionCommand, formatSettings?: FormatCodeSettings): Promise<ApplyCodeActionCommandResult>;
|
||||
applyCodeActionCommand(action: CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise<ApplyCodeActionCommandResult[]>;
|
||||
applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]>;
|
||||
/** @deprecated `fileName` will be ignored */
|
||||
applyCodeActionCommand(fileName: string, action: CodeActionCommand): Promise<ApplyCodeActionCommandResult>;
|
||||
/** @deprecated `fileName` will be ignored */
|
||||
@@ -4882,9 +4884,16 @@ declare namespace ts {
|
||||
changes: ReadonlyArray<FileTextChanges>;
|
||||
commands?: ReadonlyArray<CodeActionCommand>;
|
||||
}
|
||||
type CodeActionCommand = InstallPackageAction;
|
||||
type CodeActionCommand = InstallPackageAction | GenerateTypesAction;
|
||||
interface InstallPackageAction {
|
||||
}
|
||||
interface GenerateTypesAction extends GenerateTypesOptions {
|
||||
}
|
||||
interface GenerateTypesOptions {
|
||||
readonly file: string;
|
||||
readonly fileToGenerateTypesFor: string;
|
||||
readonly outputFileName: string;
|
||||
}
|
||||
/**
|
||||
* A set of one or more available refactoring actions, grouped under a parent refactoring.
|
||||
*/
|
||||
@@ -6455,6 +6464,8 @@ declare namespace ts.server.protocol {
|
||||
* Optional modifiers for the kind (such as 'public').
|
||||
*/
|
||||
kindModifiers: string;
|
||||
/** Span of text to rename. */
|
||||
triggerSpan: TextSpan;
|
||||
}
|
||||
/**
|
||||
* A group of text spans, all in 'file'.
|
||||
@@ -8100,6 +8111,7 @@ declare namespace ts.server {
|
||||
useCaseSensitiveFileNames(): boolean;
|
||||
readDirectory(path: string, extensions?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): string[];
|
||||
readFile(fileName: string): string | undefined;
|
||||
writeFile(fileName: string, content: string): void;
|
||||
fileExists(file: string): boolean;
|
||||
resolveModuleNames(moduleNames: string[], containingFile: string, reusedNames?: string[]): ResolvedModuleFull[];
|
||||
getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string): ResolvedModuleWithFailedLookupLocations | undefined;
|
||||
@@ -8733,7 +8745,7 @@ declare namespace ts.server {
|
||||
private getProjects;
|
||||
private getDefaultProject;
|
||||
private getRenameLocations;
|
||||
private static mapRenameInfo;
|
||||
private mapRenameInfo;
|
||||
private toSpanGroups;
|
||||
private getReferences;
|
||||
/**
|
||||
|
||||
+14
-5
@@ -4445,6 +4445,7 @@ declare namespace ts.server {
|
||||
type ActionSet = "action::set";
|
||||
type ActionInvalidate = "action::invalidate";
|
||||
type ActionPackageInstalled = "action::packageInstalled";
|
||||
type ActionValueInspected = "action::valueInspected";
|
||||
type EventTypesRegistry = "event::typesRegistry";
|
||||
type EventBeginInstallTypes = "event::beginInstallTypes";
|
||||
type EventEndInstallTypes = "event::endInstallTypes";
|
||||
@@ -4453,7 +4454,7 @@ declare namespace ts.server {
|
||||
" __sortedArrayBrand": any;
|
||||
}
|
||||
interface TypingInstallerResponse {
|
||||
readonly kind: ActionSet | ActionInvalidate | EventTypesRegistry | ActionPackageInstalled | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed;
|
||||
readonly kind: ActionSet | ActionInvalidate | EventTypesRegistry | ActionPackageInstalled | ActionValueInspected | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed;
|
||||
}
|
||||
interface TypingInstallerRequestWithProjectName {
|
||||
readonly projectName: string;
|
||||
@@ -4661,6 +4662,7 @@ declare namespace ts {
|
||||
getCustomTransformers?(): CustomTransformers | undefined;
|
||||
isKnownTypesPackageName?(name: string): boolean;
|
||||
installPackage?(options: InstallPackageOptions): Promise<ApplyCodeActionCommandResult>;
|
||||
writeFile?(fileName: string, content: string): void;
|
||||
}
|
||||
interface LanguageService {
|
||||
cleanupSemanticCache(): void;
|
||||
@@ -4718,9 +4720,9 @@ declare namespace ts {
|
||||
toLineColumnOffset?(fileName: string, position: number): LineAndCharacter;
|
||||
getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: ReadonlyArray<number>, formatOptions: FormatCodeSettings, preferences: UserPreferences): ReadonlyArray<CodeFixAction>;
|
||||
getCombinedCodeFix(scope: CombinedCodeFixScope, fixId: {}, formatOptions: FormatCodeSettings, preferences: UserPreferences): CombinedCodeActions;
|
||||
applyCodeActionCommand(action: CodeActionCommand): Promise<ApplyCodeActionCommandResult>;
|
||||
applyCodeActionCommand(action: CodeActionCommand[]): Promise<ApplyCodeActionCommandResult[]>;
|
||||
applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[]): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]>;
|
||||
applyCodeActionCommand(action: CodeActionCommand, formatSettings?: FormatCodeSettings): Promise<ApplyCodeActionCommandResult>;
|
||||
applyCodeActionCommand(action: CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise<ApplyCodeActionCommandResult[]>;
|
||||
applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]>;
|
||||
/** @deprecated `fileName` will be ignored */
|
||||
applyCodeActionCommand(fileName: string, action: CodeActionCommand): Promise<ApplyCodeActionCommandResult>;
|
||||
/** @deprecated `fileName` will be ignored */
|
||||
@@ -4882,9 +4884,16 @@ declare namespace ts {
|
||||
changes: ReadonlyArray<FileTextChanges>;
|
||||
commands?: ReadonlyArray<CodeActionCommand>;
|
||||
}
|
||||
type CodeActionCommand = InstallPackageAction;
|
||||
type CodeActionCommand = InstallPackageAction | GenerateTypesAction;
|
||||
interface InstallPackageAction {
|
||||
}
|
||||
interface GenerateTypesAction extends GenerateTypesOptions {
|
||||
}
|
||||
interface GenerateTypesOptions {
|
||||
readonly file: string;
|
||||
readonly fileToGenerateTypesFor: string;
|
||||
readonly outputFileName: string;
|
||||
}
|
||||
/**
|
||||
* A set of one or more available refactoring actions, grouped under a parent refactoring.
|
||||
*/
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
tests/cases/compiler/arrayLiteralTypeInference.ts(14,14): error TS2322: Type '({ id: number; trueness: boolean; } | { id: number; name: string; })[]' is not assignable to type 'Action[]'.
|
||||
Type '{ id: number; trueness: boolean; } | { id: number; name: string; }' is not assignable to type 'Action'.
|
||||
Type '{ id: number; trueness: boolean; }' is not assignable to type 'Action'.
|
||||
Object literal may only specify known properties, and 'trueness' does not exist in type 'Action'.
|
||||
tests/cases/compiler/arrayLiteralTypeInference.ts(31,18): error TS2322: Type '({ id: number; trueness: boolean; } | { id: number; name: string; })[]' is not assignable to type '{ id: number; }[]'.
|
||||
Type '{ id: number; trueness: boolean; } | { id: number; name: string; }' is not assignable to type '{ id: number; }'.
|
||||
Type '{ id: number; trueness: boolean; }' is not assignable to type '{ id: number; }'.
|
||||
Object literal may only specify known properties, and 'trueness' does not exist in type '{ id: number; }'.
|
||||
tests/cases/compiler/arrayLiteralTypeInference.ts(14,14): error TS2322: Type '{ id: number; trueness: boolean; }' is not assignable to type 'Action'.
|
||||
Object literal may only specify known properties, and 'trueness' does not exist in type 'Action'.
|
||||
tests/cases/compiler/arrayLiteralTypeInference.ts(15,14): error TS2322: Type '{ id: number; name: string; }' is not assignable to type 'Action'.
|
||||
Object literal may only specify known properties, and 'name' does not exist in type 'Action'.
|
||||
tests/cases/compiler/arrayLiteralTypeInference.ts(31,18): error TS2322: Type '{ id: number; trueness: boolean; }' is not assignable to type '{ id: number; }'.
|
||||
Object literal may only specify known properties, and 'trueness' does not exist in type '{ id: number; }'.
|
||||
tests/cases/compiler/arrayLiteralTypeInference.ts(32,18): error TS2322: Type '{ id: number; name: string; }' is not assignable to type '{ id: number; }'.
|
||||
Object literal may only specify known properties, and 'name' does not exist in type '{ id: number; }'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/arrayLiteralTypeInference.ts (2 errors) ====
|
||||
==== tests/cases/compiler/arrayLiteralTypeInference.ts (4 errors) ====
|
||||
class Action {
|
||||
id: number;
|
||||
}
|
||||
@@ -24,11 +24,12 @@ tests/cases/compiler/arrayLiteralTypeInference.ts(31,18): error TS2322: Type '({
|
||||
var x1: Action[] = [
|
||||
{ id: 2, trueness: false },
|
||||
~~~~~~~~~~~~~~~
|
||||
!!! error TS2322: Type '({ id: number; trueness: boolean; } | { id: number; name: string; })[]' is not assignable to type 'Action[]'.
|
||||
!!! error TS2322: Type '{ id: number; trueness: boolean; } | { id: number; name: string; }' is not assignable to type 'Action'.
|
||||
!!! error TS2322: Type '{ id: number; trueness: boolean; }' is not assignable to type 'Action'.
|
||||
!!! error TS2322: Object literal may only specify known properties, and 'trueness' does not exist in type 'Action'.
|
||||
!!! error TS2322: Type '{ id: number; trueness: boolean; }' is not assignable to type 'Action'.
|
||||
!!! error TS2322: Object literal may only specify known properties, and 'trueness' does not exist in type 'Action'.
|
||||
{ id: 3, name: "three" }
|
||||
~~~~~~~~~~~~~
|
||||
!!! error TS2322: Type '{ id: number; name: string; }' is not assignable to type 'Action'.
|
||||
!!! error TS2322: Object literal may only specify known properties, and 'name' does not exist in type 'Action'.
|
||||
]
|
||||
|
||||
var x2: Action[] = [
|
||||
@@ -46,11 +47,12 @@ tests/cases/compiler/arrayLiteralTypeInference.ts(31,18): error TS2322: Type '({
|
||||
[
|
||||
{ id: 2, trueness: false },
|
||||
~~~~~~~~~~~~~~~
|
||||
!!! error TS2322: Type '({ id: number; trueness: boolean; } | { id: number; name: string; })[]' is not assignable to type '{ id: number; }[]'.
|
||||
!!! error TS2322: Type '{ id: number; trueness: boolean; } | { id: number; name: string; }' is not assignable to type '{ id: number; }'.
|
||||
!!! error TS2322: Type '{ id: number; trueness: boolean; }' is not assignable to type '{ id: number; }'.
|
||||
!!! error TS2322: Object literal may only specify known properties, and 'trueness' does not exist in type '{ id: number; }'.
|
||||
!!! error TS2322: Type '{ id: number; trueness: boolean; }' is not assignable to type '{ id: number; }'.
|
||||
!!! error TS2322: Object literal may only specify known properties, and 'trueness' does not exist in type '{ id: number; }'.
|
||||
{ id: 3, name: "three" }
|
||||
~~~~~~~~~~~~~
|
||||
!!! error TS2322: Type '{ id: number; name: string; }' is not assignable to type '{ id: number; }'.
|
||||
!!! error TS2322: Object literal may only specify known properties, and 'name' does not exist in type '{ id: number; }'.
|
||||
]
|
||||
|
||||
var z2: { id: number }[] =
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
tests/cases/conformance/expressions/arrayLiterals/arrayLiterals.ts(24,77): error TS2322: Type '({ a: string; b: number; c: string; } | { a: string; b: number; c: number; })[]' is not assignable to type '{ [n: number]: { a: string; b: number; }; }'.
|
||||
Index signatures are incompatible.
|
||||
Type '{ a: string; b: number; c: string; } | { a: string; b: number; c: number; }' is not assignable to type '{ a: string; b: number; }'.
|
||||
Type '{ a: string; b: number; c: string; }' is not assignable to type '{ a: string; b: number; }'.
|
||||
Object literal may only specify known properties, and 'c' does not exist in type '{ a: string; b: number; }'.
|
||||
tests/cases/conformance/expressions/arrayLiterals/arrayLiterals.ts(24,77): error TS2322: Type '{ a: string; b: number; c: string; }' is not assignable to type '{ a: string; b: number; }'.
|
||||
Object literal may only specify known properties, and 'c' does not exist in type '{ a: string; b: number; }'.
|
||||
tests/cases/conformance/expressions/arrayLiterals/arrayLiterals.ts(24,101): error TS2322: Type '{ a: string; b: number; c: number; }' is not assignable to type '{ a: string; b: number; }'.
|
||||
Object literal may only specify known properties, and 'c' does not exist in type '{ a: string; b: number; }'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/expressions/arrayLiterals/arrayLiterals.ts (1 errors) ====
|
||||
==== tests/cases/conformance/expressions/arrayLiterals/arrayLiterals.ts (2 errors) ====
|
||||
// Empty array literal with no contextual type has type Undefined[]
|
||||
|
||||
var arr1= [[], [1], ['']];
|
||||
@@ -31,11 +30,13 @@ tests/cases/conformance/expressions/arrayLiterals/arrayLiterals.ts(24,77): error
|
||||
// Contextual type C with numeric index signature makes array literal of EveryType E of type BCT(E,C)[]
|
||||
var context1: { [n: number]: { a: string; b: number; }; } = [{ a: '', b: 0, c: '' }, { a: "", b: 3, c: 0 }];
|
||||
~~~~~
|
||||
!!! error TS2322: Type '({ a: string; b: number; c: string; } | { a: string; b: number; c: number; })[]' is not assignable to type '{ [n: number]: { a: string; b: number; }; }'.
|
||||
!!! error TS2322: Index signatures are incompatible.
|
||||
!!! error TS2322: Type '{ a: string; b: number; c: string; } | { a: string; b: number; c: number; }' is not assignable to type '{ a: string; b: number; }'.
|
||||
!!! error TS2322: Type '{ a: string; b: number; c: string; }' is not assignable to type '{ a: string; b: number; }'.
|
||||
!!! error TS2322: Object literal may only specify known properties, and 'c' does not exist in type '{ a: string; b: number; }'.
|
||||
!!! error TS2322: Type '{ a: string; b: number; c: string; }' is not assignable to type '{ a: string; b: number; }'.
|
||||
!!! error TS2322: Object literal may only specify known properties, and 'c' does not exist in type '{ a: string; b: number; }'.
|
||||
!!! related TS6501 tests/cases/conformance/expressions/arrayLiterals/arrayLiterals.ts:24:17: The expected type comes from this index signature.
|
||||
~~~~
|
||||
!!! error TS2322: Type '{ a: string; b: number; c: number; }' is not assignable to type '{ a: string; b: number; }'.
|
||||
!!! error TS2322: Object literal may only specify known properties, and 'c' does not exist in type '{ a: string; b: number; }'.
|
||||
!!! related TS6501 tests/cases/conformance/expressions/arrayLiterals/arrayLiterals.ts:24:17: The expected type comes from this index signature.
|
||||
var context2 = [{ a: '', b: 0, c: '' }, { a: "", b: 3, c: 0 }];
|
||||
|
||||
// Contextual type C with numeric index signature of type Base makes array literal of Derived have type Base[]
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
tests/cases/compiler/arraySigChecking.ts(11,17): error TS1023: An index signature parameter type must be 'string' or 'number'.
|
||||
tests/cases/compiler/arraySigChecking.ts(18,5): error TS2322: Type 'void[]' is not assignable to type 'string[]'.
|
||||
Type 'void' is not assignable to type 'string'.
|
||||
tests/cases/compiler/arraySigChecking.ts(22,1): error TS2322: Type 'number[][]' is not assignable to type 'number[][][]'.
|
||||
Type 'number[]' is not assignable to type 'number[][]'.
|
||||
Type 'number' is not assignable to type 'number[]'.
|
||||
tests/cases/compiler/arraySigChecking.ts(18,27): error TS2322: Type 'void' is not assignable to type 'string'.
|
||||
tests/cases/compiler/arraySigChecking.ts(22,13): error TS2322: Type 'number' is not assignable to type 'number[]'.
|
||||
tests/cases/compiler/arraySigChecking.ts(22,16): error TS2322: Type 'number' is not assignable to type 'number[]'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/arraySigChecking.ts (3 errors) ====
|
||||
==== tests/cases/compiler/arraySigChecking.ts (4 errors) ====
|
||||
declare module M {
|
||||
interface iBar { t: any; }
|
||||
interface iFoo extends iBar {
|
||||
@@ -27,17 +25,16 @@ tests/cases/compiler/arraySigChecking.ts(22,1): error TS2322: Type 'number[][]'
|
||||
}
|
||||
var myVar: myInt;
|
||||
var strArray: string[] = [myVar.voidFn()];
|
||||
~~~~~~~~
|
||||
!!! error TS2322: Type 'void[]' is not assignable to type 'string[]'.
|
||||
!!! error TS2322: Type 'void' is not assignable to type 'string'.
|
||||
~~~~~~~~~~~~~~
|
||||
!!! error TS2322: Type 'void' is not assignable to type 'string'.
|
||||
|
||||
|
||||
var myArray: number[][][];
|
||||
myArray = [[1, 2]];
|
||||
~~~~~~~
|
||||
!!! error TS2322: Type 'number[][]' is not assignable to type 'number[][][]'.
|
||||
!!! error TS2322: Type 'number[]' is not assignable to type 'number[][]'.
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'number[]'.
|
||||
~
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'number[]'.
|
||||
~
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'number[]'.
|
||||
|
||||
function isEmpty(l: { length: number }) {
|
||||
return l.length === 0;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
tests/cases/compiler/assignmentCompatBug5.ts(2,8): error TS2345: Argument of type '{ b: number; }' is not assignable to parameter of type '{ a: number; }'.
|
||||
Object literal may only specify known properties, and 'b' does not exist in type '{ a: number; }'.
|
||||
tests/cases/compiler/assignmentCompatBug5.ts(5,6): error TS2345: Argument of type 'string[]' is not assignable to parameter of type 'number[]'.
|
||||
Type 'string' is not assignable to type 'number'.
|
||||
tests/cases/compiler/assignmentCompatBug5.ts(5,7): error TS2322: Type 'string' is not assignable to type 'number'.
|
||||
tests/cases/compiler/assignmentCompatBug5.ts(5,12): error TS2322: Type 'string' is not assignable to type 'number'.
|
||||
tests/cases/compiler/assignmentCompatBug5.ts(8,6): error TS2345: Argument of type '(s: string) => void' is not assignable to parameter of type '(n: number) => number'.
|
||||
Types of parameters 's' and 'n' are incompatible.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
@@ -9,7 +9,7 @@ tests/cases/compiler/assignmentCompatBug5.ts(9,6): error TS2345: Argument of typ
|
||||
Type 'void' is not assignable to type 'number'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/assignmentCompatBug5.ts (4 errors) ====
|
||||
==== tests/cases/compiler/assignmentCompatBug5.ts (5 errors) ====
|
||||
function foo1(x: { a: number; }) { }
|
||||
foo1({ b: 5 });
|
||||
~~~~
|
||||
@@ -18,9 +18,10 @@ tests/cases/compiler/assignmentCompatBug5.ts(9,6): error TS2345: Argument of typ
|
||||
|
||||
function foo2(x: number[]) { }
|
||||
foo2(["s", "t"]);
|
||||
~~~~~~~~~~
|
||||
!!! error TS2345: Argument of type 'string[]' is not assignable to parameter of type 'number[]'.
|
||||
!!! error TS2345: Type 'string' is not assignable to type 'number'.
|
||||
~~~
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'number'.
|
||||
~~~
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'number'.
|
||||
|
||||
function foo3(x: (n: number) =>number) { };
|
||||
foo3((s:string) => { });
|
||||
|
||||
@@ -10,7 +10,6 @@ tests/cases/compiler/assignmentToObjectAndFunction.ts(29,5): error TS2322: Type
|
||||
var errObj: Object = { toString: 0 }; // Error, incompatible toString
|
||||
~~~~~~~~
|
||||
!!! error TS2322: Type 'number' is not assignable to type '() => string'.
|
||||
!!! related TS6500 /.ts/lib.es5.d.ts:125:5: The expected type comes from property 'toString' which is declared here on type 'Object'
|
||||
var goodObj: Object = {
|
||||
toString(x?) {
|
||||
return "";
|
||||
|
||||
+6
-7
@@ -1,6 +1,5 @@
|
||||
tests/cases/compiler/chainedCallsWithTypeParameterConstrainedToOtherTypeParameter.ts(19,59): error TS2345: Argument of type '(c: C) => B' is not assignable to parameter of type '(x: C) => C'.
|
||||
Type 'B' is not assignable to type 'C'.
|
||||
Property 'z' is missing in type 'B'.
|
||||
tests/cases/compiler/chainedCallsWithTypeParameterConstrainedToOtherTypeParameter.ts(19,64): error TS2322: Type 'B' is not assignable to type 'C'.
|
||||
Property 'z' is missing in type 'B'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/chainedCallsWithTypeParameterConstrainedToOtherTypeParameter.ts (1 errors) ====
|
||||
@@ -23,7 +22,7 @@ tests/cases/compiler/chainedCallsWithTypeParameterConstrainedToOtherTypeParamete
|
||||
|
||||
// Ok to go down the chain, but error to try to climb back up
|
||||
(new Chain(new A)).then(a => new B).then(b => new C).then(c => new B).then(b => new A);
|
||||
~~~~~~~~~~
|
||||
!!! error TS2345: Argument of type '(c: C) => B' is not assignable to parameter of type '(x: C) => C'.
|
||||
!!! error TS2345: Type 'B' is not assignable to type 'C'.
|
||||
!!! error TS2345: Property 'z' is missing in type 'B'.
|
||||
~~~~~
|
||||
!!! error TS2322: Type 'B' is not assignable to type 'C'.
|
||||
!!! error TS2322: Property 'z' is missing in type 'B'.
|
||||
!!! related TS6502 tests/cases/compiler/chainedCallsWithTypeParameterConstrainedToOtherTypeParameter.ts:3:27: The expected type comes from the return type of this signature.
|
||||
+8
-10
@@ -1,7 +1,5 @@
|
||||
tests/cases/compiler/chainedCallsWithTypeParameterConstrainedToOtherTypeParameter2.ts(7,43): error TS2345: Argument of type '(ss: S) => T' is not assignable to parameter of type '(x: S) => S'.
|
||||
Type 'T' is not assignable to type 'S'.
|
||||
tests/cases/compiler/chainedCallsWithTypeParameterConstrainedToOtherTypeParameter2.ts(10,29): error TS2345: Argument of type '(ss: S) => T' is not assignable to parameter of type '(x: S) => S'.
|
||||
Type 'T' is not assignable to type 'S'.
|
||||
tests/cases/compiler/chainedCallsWithTypeParameterConstrainedToOtherTypeParameter2.ts(7,49): error TS2322: Type 'T' is not assignable to type 'S'.
|
||||
tests/cases/compiler/chainedCallsWithTypeParameterConstrainedToOtherTypeParameter2.ts(10,35): error TS2322: Type 'T' is not assignable to type 'S'.
|
||||
tests/cases/compiler/chainedCallsWithTypeParameterConstrainedToOtherTypeParameter2.ts(32,9): error TS2322: Type '""' is not assignable to type 'number'.
|
||||
tests/cases/compiler/chainedCallsWithTypeParameterConstrainedToOtherTypeParameter2.ts(36,9): error TS2322: Type '""' is not assignable to type 'number'.
|
||||
tests/cases/compiler/chainedCallsWithTypeParameterConstrainedToOtherTypeParameter2.ts(37,9): error TS2322: Type '""' is not assignable to type 'number'.
|
||||
@@ -15,15 +13,15 @@ tests/cases/compiler/chainedCallsWithTypeParameterConstrainedToOtherTypeParamete
|
||||
var s: S;
|
||||
// Ok to go down the chain, but error to climb up the chain
|
||||
(new Chain(t)).then(tt => s).then(ss => t);
|
||||
~~~~~~~
|
||||
!!! error TS2345: Argument of type '(ss: S) => T' is not assignable to parameter of type '(x: S) => S'.
|
||||
!!! error TS2345: Type 'T' is not assignable to type 'S'.
|
||||
~
|
||||
!!! error TS2322: Type 'T' is not assignable to type 'S'.
|
||||
!!! related TS6502 tests/cases/compiler/chainedCallsWithTypeParameterConstrainedToOtherTypeParameter2.ts:3:27: The expected type comes from the return type of this signature.
|
||||
|
||||
// But error to try to climb up the chain
|
||||
(new Chain(s)).then(ss => t);
|
||||
~~~~~~~
|
||||
!!! error TS2345: Argument of type '(ss: S) => T' is not assignable to parameter of type '(x: S) => S'.
|
||||
!!! error TS2345: Type 'T' is not assignable to type 'S'.
|
||||
~
|
||||
!!! error TS2322: Type 'T' is not assignable to type 'S'.
|
||||
!!! related TS6502 tests/cases/compiler/chainedCallsWithTypeParameterConstrainedToOtherTypeParameter2.ts:3:27: The expected type comes from the return type of this signature.
|
||||
|
||||
// Staying at T or S should be fine
|
||||
(new Chain(t)).then(tt => t).then(tt => t).then(tt => t);
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
tests/cases/compiler/contextualTyping11.ts(1,20): error TS2322: Type 'foo[]' is not assignable to type '{ id: number; }[]'.
|
||||
Type 'foo' is not assignable to type '{ id: number; }'.
|
||||
Property 'id' is missing in type 'foo'.
|
||||
tests/cases/compiler/contextualTyping11.ts(1,42): error TS2322: Type 'foo' is not assignable to type '{ id: number; }'.
|
||||
Property 'id' is missing in type 'foo'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/contextualTyping11.ts (1 errors) ====
|
||||
class foo { public bar:{id:number;}[] = [<foo>({})]; }
|
||||
~~~
|
||||
!!! error TS2322: Type 'foo[]' is not assignable to type '{ id: number; }[]'.
|
||||
!!! error TS2322: Type 'foo' is not assignable to type '{ id: number; }'.
|
||||
!!! error TS2322: Property 'id' is missing in type 'foo'.
|
||||
~~~~~~~~~
|
||||
!!! error TS2322: Type 'foo' is not assignable to type '{ id: number; }'.
|
||||
!!! error TS2322: Property 'id' is missing in type 'foo'.
|
||||
@@ -1,13 +1,9 @@
|
||||
tests/cases/compiler/contextualTyping12.ts(1,57): error TS2322: Type '({ id: number; } | { id: number; name: string; })[]' is not assignable to type '{ id: number; }[]'.
|
||||
Type '{ id: number; } | { id: number; name: string; }' is not assignable to type '{ id: number; }'.
|
||||
Type '{ id: number; name: string; }' is not assignable to type '{ id: number; }'.
|
||||
Object literal may only specify known properties, and 'name' does not exist in type '{ id: number; }'.
|
||||
tests/cases/compiler/contextualTyping12.ts(1,57): error TS2322: Type '{ id: number; name: string; }' is not assignable to type '{ id: number; }'.
|
||||
Object literal may only specify known properties, and 'name' does not exist in type '{ id: number; }'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/contextualTyping12.ts (1 errors) ====
|
||||
class foo { public bar:{id:number;}[] = [{id:1}, {id:2, name:"foo"}]; }
|
||||
~~~~~~~~~~
|
||||
!!! error TS2322: Type '({ id: number; } | { id: number; name: string; })[]' is not assignable to type '{ id: number; }[]'.
|
||||
!!! error TS2322: Type '{ id: number; } | { id: number; name: string; }' is not assignable to type '{ id: number; }'.
|
||||
!!! error TS2322: Type '{ id: number; name: string; }' is not assignable to type '{ id: number; }'.
|
||||
!!! error TS2322: Object literal may only specify known properties, and 'name' does not exist in type '{ id: number; }'.
|
||||
!!! error TS2322: Type '{ id: number; name: string; }' is not assignable to type '{ id: number; }'.
|
||||
!!! error TS2322: Object literal may only specify known properties, and 'name' does not exist in type '{ id: number; }'.
|
||||
@@ -1,13 +1,9 @@
|
||||
tests/cases/compiler/contextualTyping20.ts(1,58): error TS2322: Type '({ id: number; } | { id: number; name: string; })[]' is not assignable to type '{ id: number; }[]'.
|
||||
Type '{ id: number; } | { id: number; name: string; }' is not assignable to type '{ id: number; }'.
|
||||
Type '{ id: number; name: string; }' is not assignable to type '{ id: number; }'.
|
||||
Object literal may only specify known properties, and 'name' does not exist in type '{ id: number; }'.
|
||||
tests/cases/compiler/contextualTyping20.ts(1,58): error TS2322: Type '{ id: number; name: string; }' is not assignable to type '{ id: number; }'.
|
||||
Object literal may only specify known properties, and 'name' does not exist in type '{ id: number; }'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/contextualTyping20.ts (1 errors) ====
|
||||
var foo:{id:number;}[] = [{id:1}]; foo = [{id:1}, {id:2, name:"foo"}];
|
||||
~~~~~~~~~~
|
||||
!!! error TS2322: Type '({ id: number; } | { id: number; name: string; })[]' is not assignable to type '{ id: number; }[]'.
|
||||
!!! error TS2322: Type '{ id: number; } | { id: number; name: string; }' is not assignable to type '{ id: number; }'.
|
||||
!!! error TS2322: Type '{ id: number; name: string; }' is not assignable to type '{ id: number; }'.
|
||||
!!! error TS2322: Object literal may only specify known properties, and 'name' does not exist in type '{ id: number; }'.
|
||||
!!! error TS2322: Type '{ id: number; name: string; }' is not assignable to type '{ id: number; }'.
|
||||
!!! error TS2322: Object literal may only specify known properties, and 'name' does not exist in type '{ id: number; }'.
|
||||
@@ -1,11 +1,7 @@
|
||||
tests/cases/compiler/contextualTyping21.ts(1,36): error TS2322: Type '(number | { id: number; })[]' is not assignable to type '{ id: number; }[]'.
|
||||
Type 'number | { id: number; }' is not assignable to type '{ id: number; }'.
|
||||
Type 'number' is not assignable to type '{ id: number; }'.
|
||||
tests/cases/compiler/contextualTyping21.ts(1,51): error TS2322: Type 'number' is not assignable to type '{ id: number; }'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/contextualTyping21.ts (1 errors) ====
|
||||
var foo:{id:number;}[] = [{id:1}]; foo = [{id:1}, 1];
|
||||
~~~
|
||||
!!! error TS2322: Type '(number | { id: number; })[]' is not assignable to type '{ id: number; }[]'.
|
||||
!!! error TS2322: Type 'number | { id: number; }' is not assignable to type '{ id: number; }'.
|
||||
!!! error TS2322: Type 'number' is not assignable to type '{ id: number; }'.
|
||||
~
|
||||
!!! error TS2322: Type 'number' is not assignable to type '{ id: number; }'.
|
||||
@@ -1,11 +1,7 @@
|
||||
tests/cases/compiler/contextualTyping30.ts(1,37): error TS2345: Argument of type '(string | number)[]' is not assignable to parameter of type 'number[]'.
|
||||
Type 'string | number' is not assignable to type 'number'.
|
||||
Type 'string' is not assignable to type 'number'.
|
||||
tests/cases/compiler/contextualTyping30.ts(1,41): error TS2322: Type 'string' is not assignable to type 'number'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/contextualTyping30.ts (1 errors) ====
|
||||
function foo(param:number[]){}; foo([1, "a"]);
|
||||
~~~~~~~~
|
||||
!!! error TS2345: Argument of type '(string | number)[]' is not assignable to parameter of type 'number[]'.
|
||||
!!! error TS2345: Type 'string | number' is not assignable to type 'number'.
|
||||
!!! error TS2345: Type 'string' is not assignable to type 'number'.
|
||||
~~~
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'number'.
|
||||
@@ -1,13 +1,9 @@
|
||||
tests/cases/compiler/contextualTyping33.ts(1,66): error TS2345: Argument of type '((() => number) | (() => string))[]' is not assignable to parameter of type '{ (): number; (i: number): number; }[]'.
|
||||
Type '(() => number) | (() => string)' is not assignable to type '{ (): number; (i: number): number; }'.
|
||||
Type '() => string' is not assignable to type '{ (): number; (i: number): number; }'.
|
||||
Type 'string' is not assignable to type 'number'.
|
||||
tests/cases/compiler/contextualTyping33.ts(1,90): error TS2322: Type '() => string' is not assignable to type '{ (): number; (i: number): number; }'.
|
||||
Type 'string' is not assignable to type 'number'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/contextualTyping33.ts (1 errors) ====
|
||||
function foo(param: {():number; (i:number):number; }[]) { }; foo([function(){return 1;}, function(){return "foo"}]);
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2345: Argument of type '((() => number) | (() => string))[]' is not assignable to parameter of type '{ (): number; (i: number): number; }[]'.
|
||||
!!! error TS2345: Type '(() => number) | (() => string)' is not assignable to type '{ (): number; (i: number): number; }'.
|
||||
!!! error TS2345: Type '() => string' is not assignable to type '{ (): number; (i: number): number; }'.
|
||||
!!! error TS2345: Type 'string' is not assignable to type 'number'.
|
||||
~~~~~~~~
|
||||
!!! error TS2322: Type '() => string' is not assignable to type '{ (): number; (i: number): number; }'.
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'number'.
|
||||
@@ -1,13 +1,9 @@
|
||||
tests/cases/compiler/contextualTyping9.ts(1,42): error TS2322: Type '({ id: number; } | { id: number; name: string; })[]' is not assignable to type '{ id: number; }[]'.
|
||||
Type '{ id: number; } | { id: number; name: string; }' is not assignable to type '{ id: number; }'.
|
||||
Type '{ id: number; name: string; }' is not assignable to type '{ id: number; }'.
|
||||
Object literal may only specify known properties, and 'name' does not exist in type '{ id: number; }'.
|
||||
tests/cases/compiler/contextualTyping9.ts(1,42): error TS2322: Type '{ id: number; name: string; }' is not assignable to type '{ id: number; }'.
|
||||
Object literal may only specify known properties, and 'name' does not exist in type '{ id: number; }'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/contextualTyping9.ts (1 errors) ====
|
||||
var foo:{id:number;}[] = [{id:1}, {id:2, name:"foo"}];
|
||||
~~~~~~~~~~
|
||||
!!! error TS2322: Type '({ id: number; } | { id: number; name: string; })[]' is not assignable to type '{ id: number; }[]'.
|
||||
!!! error TS2322: Type '{ id: number; } | { id: number; name: string; }' is not assignable to type '{ id: number; }'.
|
||||
!!! error TS2322: Type '{ id: number; name: string; }' is not assignable to type '{ id: number; }'.
|
||||
!!! error TS2322: Object literal may only specify known properties, and 'name' does not exist in type '{ id: number; }'.
|
||||
!!! error TS2322: Type '{ id: number; name: string; }' is not assignable to type '{ id: number; }'.
|
||||
!!! error TS2322: Object literal may only specify known properties, and 'name' does not exist in type '{ id: number; }'.
|
||||
@@ -1,7 +1,4 @@
|
||||
tests/cases/compiler/contextualTypingOfArrayLiterals1.ts(5,5): error TS2322: Type '(number | Date)[]' is not assignable to type 'I'.
|
||||
Index signatures are incompatible.
|
||||
Type 'number | Date' is not assignable to type 'Date'.
|
||||
Type 'number' is not assignable to type 'Date'.
|
||||
tests/cases/compiler/contextualTypingOfArrayLiterals1.ts(5,26): error TS2322: Type 'number' is not assignable to type 'Date'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/contextualTypingOfArrayLiterals1.ts (1 errors) ====
|
||||
@@ -10,11 +7,9 @@ tests/cases/compiler/contextualTypingOfArrayLiterals1.ts(5,5): error TS2322: Typ
|
||||
}
|
||||
|
||||
var x3: I = [new Date(), 1];
|
||||
~~
|
||||
!!! error TS2322: Type '(number | Date)[]' is not assignable to type 'I'.
|
||||
!!! error TS2322: Index signatures are incompatible.
|
||||
!!! error TS2322: Type 'number | Date' is not assignable to type 'Date'.
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'Date'.
|
||||
~
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'Date'.
|
||||
!!! related TS6501 tests/cases/compiler/contextualTypingOfArrayLiterals1.ts:2:4: The expected type comes from this index signature.
|
||||
var r2 = x3[1];
|
||||
r2.getDate();
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(4,20): error TS2322: Type '(v: number) => number' is not assignable to type '(x: number) => string'.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(5,23): error TS2322: Type '(v: number) => number' is not assignable to type '(x: number) => string'.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(6,25): error TS2322: Type '(v: number) => number' is not assignable to type '(x: number) => string'.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(11,40): error TS2322: Type '(v: number) => number' is not assignable to type '(x: number) => string'.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(16,23): error TS2322: Type '(arg: string) => number' is not assignable to type '(s: string) => string'.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(4,38): error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(5,41): error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(6,43): error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(11,51): error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(16,35): error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(21,22): error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(26,14): error TS2322: Type '"baz"' is not assignable to type '"foo" | "bar"'.
|
||||
|
||||
@@ -17,34 +12,33 @@ tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTyp
|
||||
show: (x: number) => string;
|
||||
}
|
||||
function f({ show: showRename = v => v }: Show) {}
|
||||
~~~~~~~~~~
|
||||
!!! error TS2322: Type '(v: number) => number' is not assignable to type '(x: number) => string'.
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
~
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
!!! related TS6502 tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts:2:11: The expected type comes from the return type of this signature.
|
||||
function f2({ "show": showRename = v => v }: Show) {}
|
||||
~~~~~~~~~~
|
||||
!!! error TS2322: Type '(v: number) => number' is not assignable to type '(x: number) => string'.
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
~
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
!!! related TS6502 tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts:2:11: The expected type comes from the return type of this signature.
|
||||
function f3({ ["show"]: showRename = v => v }: Show) {}
|
||||
~~~~~~~~~~
|
||||
!!! error TS2322: Type '(v: number) => number' is not assignable to type '(x: number) => string'.
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
~
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
!!! related TS6502 tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts:2:11: The expected type comes from the return type of this signature.
|
||||
|
||||
interface Nested {
|
||||
nested: Show
|
||||
}
|
||||
function ff({ nested: nestedRename = { show: v => v } }: Nested) {}
|
||||
~~~~
|
||||
!!! error TS2322: Type '(v: number) => number' is not assignable to type '(x: number) => string'.
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
!!! related TS6500 tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts:2:5: The expected type comes from property 'show' which is declared here on type 'Show'
|
||||
~
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
!!! related TS6502 tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts:2:11: The expected type comes from the return type of this signature.
|
||||
|
||||
interface StringIdentity {
|
||||
stringIdentity(s: string): string;
|
||||
}
|
||||
let { stringIdentity: id = arg => arg.length }: StringIdentity = { stringIdentity: x => x};
|
||||
~~
|
||||
!!! error TS2322: Type '(arg: string) => number' is not assignable to type '(s: string) => string'.
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
~~~~~~~~~~
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
!!! related TS6502 tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts:14:5: The expected type comes from the return type of this signature.
|
||||
|
||||
interface Tuples {
|
||||
prop: [string, number];
|
||||
|
||||
@@ -67,7 +67,33 @@ function f6() {
|
||||
y; // string | undefined
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function f7(x: {}) {
|
||||
if (x) {
|
||||
x; // {}
|
||||
}
|
||||
else {
|
||||
x; // {}
|
||||
}
|
||||
}
|
||||
|
||||
function f8<T>(x: T) {
|
||||
if (x) {
|
||||
x; // {}
|
||||
}
|
||||
else {
|
||||
x; // {}
|
||||
}
|
||||
}
|
||||
|
||||
function f9<T extends object>(x: T) {
|
||||
if (x) {
|
||||
x; // {}
|
||||
}
|
||||
else {
|
||||
x; // never
|
||||
}
|
||||
}
|
||||
|
||||
//// [controlFlowTruthiness.js]
|
||||
function f1() {
|
||||
@@ -131,3 +157,27 @@ function f6() {
|
||||
y; // string | undefined
|
||||
}
|
||||
}
|
||||
function f7(x) {
|
||||
if (x) {
|
||||
x; // {}
|
||||
}
|
||||
else {
|
||||
x; // {}
|
||||
}
|
||||
}
|
||||
function f8(x) {
|
||||
if (x) {
|
||||
x; // {}
|
||||
}
|
||||
else {
|
||||
x; // {}
|
||||
}
|
||||
}
|
||||
function f9(x) {
|
||||
if (x) {
|
||||
x; // {}
|
||||
}
|
||||
else {
|
||||
x; // never
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,3 +140,54 @@ function f6() {
|
||||
}
|
||||
}
|
||||
|
||||
function f7(x: {}) {
|
||||
>f7 : Symbol(f7, Decl(controlFlowTruthiness.ts, 67, 1))
|
||||
>x : Symbol(x, Decl(controlFlowTruthiness.ts, 69, 12))
|
||||
|
||||
if (x) {
|
||||
>x : Symbol(x, Decl(controlFlowTruthiness.ts, 69, 12))
|
||||
|
||||
x; // {}
|
||||
>x : Symbol(x, Decl(controlFlowTruthiness.ts, 69, 12))
|
||||
}
|
||||
else {
|
||||
x; // {}
|
||||
>x : Symbol(x, Decl(controlFlowTruthiness.ts, 69, 12))
|
||||
}
|
||||
}
|
||||
|
||||
function f8<T>(x: T) {
|
||||
>f8 : Symbol(f8, Decl(controlFlowTruthiness.ts, 76, 1))
|
||||
>T : Symbol(T, Decl(controlFlowTruthiness.ts, 78, 12))
|
||||
>x : Symbol(x, Decl(controlFlowTruthiness.ts, 78, 15))
|
||||
>T : Symbol(T, Decl(controlFlowTruthiness.ts, 78, 12))
|
||||
|
||||
if (x) {
|
||||
>x : Symbol(x, Decl(controlFlowTruthiness.ts, 78, 15))
|
||||
|
||||
x; // {}
|
||||
>x : Symbol(x, Decl(controlFlowTruthiness.ts, 78, 15))
|
||||
}
|
||||
else {
|
||||
x; // {}
|
||||
>x : Symbol(x, Decl(controlFlowTruthiness.ts, 78, 15))
|
||||
}
|
||||
}
|
||||
|
||||
function f9<T extends object>(x: T) {
|
||||
>f9 : Symbol(f9, Decl(controlFlowTruthiness.ts, 85, 1))
|
||||
>T : Symbol(T, Decl(controlFlowTruthiness.ts, 87, 12))
|
||||
>x : Symbol(x, Decl(controlFlowTruthiness.ts, 87, 30))
|
||||
>T : Symbol(T, Decl(controlFlowTruthiness.ts, 87, 12))
|
||||
|
||||
if (x) {
|
||||
>x : Symbol(x, Decl(controlFlowTruthiness.ts, 87, 30))
|
||||
|
||||
x; // {}
|
||||
>x : Symbol(x, Decl(controlFlowTruthiness.ts, 87, 30))
|
||||
}
|
||||
else {
|
||||
x; // never
|
||||
>x : Symbol(x, Decl(controlFlowTruthiness.ts, 87, 30))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,3 +157,50 @@ function f6() {
|
||||
}
|
||||
}
|
||||
|
||||
function f7(x: {}) {
|
||||
>f7 : (x: {}) => void
|
||||
>x : {}
|
||||
|
||||
if (x) {
|
||||
>x : {}
|
||||
|
||||
x; // {}
|
||||
>x : {}
|
||||
}
|
||||
else {
|
||||
x; // {}
|
||||
>x : {}
|
||||
}
|
||||
}
|
||||
|
||||
function f8<T>(x: T) {
|
||||
>f8 : <T>(x: T) => void
|
||||
>x : T
|
||||
|
||||
if (x) {
|
||||
>x : T
|
||||
|
||||
x; // {}
|
||||
>x : T
|
||||
}
|
||||
else {
|
||||
x; // {}
|
||||
>x : T
|
||||
}
|
||||
}
|
||||
|
||||
function f9<T extends object>(x: T) {
|
||||
>f9 : <T extends object>(x: T) => void
|
||||
>x : T
|
||||
|
||||
if (x) {
|
||||
>x : T
|
||||
|
||||
x; // {}
|
||||
>x : T
|
||||
}
|
||||
else {
|
||||
x; // never
|
||||
>x : never
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,6 +6,6 @@ function /*[#|*/f/*|]*/(): Promise<void> {
|
||||
// ==ASYNC FUNCTION::Convert to async function==
|
||||
|
||||
async function f(): Promise<void> {
|
||||
await fetch('https://typescriptlang.org');
|
||||
const _ = await fetch('https://typescriptlang.org');
|
||||
console.log("done");
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
// ==ORIGINAL==
|
||||
|
||||
function /*[#|*/f/*|]*/(): Promise<void> {
|
||||
return fetch('https://typescriptlang.org').then( () => console.log("almost done") ).then( () => console.log("done") );
|
||||
}
|
||||
// ==ASYNC FUNCTION::Convert to async function==
|
||||
|
||||
async function f(): Promise<void> {
|
||||
await fetch('https://typescriptlang.org');
|
||||
console.log("almost done");
|
||||
return console.log("done");
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// ==ORIGINAL==
|
||||
|
||||
function /*[#|*/f/*|]*/() {
|
||||
return fetch('https://typescriptlang.org').then(res);
|
||||
}
|
||||
function res(){
|
||||
console.log("done");
|
||||
}
|
||||
// ==ASYNC FUNCTION::Convert to async function==
|
||||
|
||||
async function f() {
|
||||
const result = await fetch('https://typescriptlang.org');
|
||||
return res(result);
|
||||
}
|
||||
function res(){
|
||||
console.log("done");
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// ==ORIGINAL==
|
||||
|
||||
function /*[#|*/f/*|]*/() {
|
||||
return fetch('https://typescriptlang.org').then(res);
|
||||
}
|
||||
function res(){
|
||||
console.log("done");
|
||||
}
|
||||
// ==ASYNC FUNCTION::Convert to async function==
|
||||
|
||||
async function f() {
|
||||
const result = await fetch('https://typescriptlang.org');
|
||||
return res(result);
|
||||
}
|
||||
function res(){
|
||||
console.log("done");
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// ==ORIGINAL==
|
||||
|
||||
function /*[#|*/f/*|]*/() {
|
||||
return fetch('https://typescriptlang.org').then(x => x.statusText).catch(undefined);
|
||||
}
|
||||
|
||||
// ==ASYNC FUNCTION::Convert to async function==
|
||||
|
||||
async function f() {
|
||||
try {
|
||||
const x = await fetch('https://typescriptlang.org');
|
||||
return x.statusText;
|
||||
}
|
||||
catch (e) { }
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// ==ORIGINAL==
|
||||
|
||||
function /*[#|*/f/*|]*/() {
|
||||
return fetch('https://typescriptlang.org').then(x => x.statusText).catch(undefined);
|
||||
}
|
||||
|
||||
// ==ASYNC FUNCTION::Convert to async function==
|
||||
|
||||
async function f() {
|
||||
try {
|
||||
const x = await fetch('https://typescriptlang.org');
|
||||
return x.statusText;
|
||||
}
|
||||
catch (e) { }
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// ==ORIGINAL==
|
||||
|
||||
function /*[#|*/f/*|]*/() {
|
||||
var var1:Promise<Response>, var2;
|
||||
var var1: Response, var2;
|
||||
return fetch('https://typescriptlang.org').then( _ =>
|
||||
Promise.resolve().then( res => {
|
||||
var2 = "test";
|
||||
@@ -18,11 +18,11 @@ function /*[#|*/f/*|]*/() {
|
||||
// ==ASYNC FUNCTION::Convert to async function==
|
||||
|
||||
async function f() {
|
||||
var var1:Promise<Response>, var2;
|
||||
await fetch('https://typescriptlang.org');
|
||||
var var1: Response, var2;
|
||||
const _ = await fetch('https://typescriptlang.org');
|
||||
const res = await Promise.resolve();
|
||||
var2 = "test";
|
||||
const res_1 = fetch("https://microsoft.com");
|
||||
const res_1 = await fetch("https://microsoft.com");
|
||||
const response = var1 === res_1;
|
||||
return res(response);
|
||||
}
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
// ==ORIGINAL==
|
||||
|
||||
function /*[#|*/f/*|]*/() {
|
||||
return fetch('https://typescriptlang.org').then(s => Promise.resolve(s.statusText).then(st => st.length)).then(x => console.log(x + 5));
|
||||
}
|
||||
|
||||
// ==ASYNC FUNCTION::Convert to async function==
|
||||
|
||||
async function f() {
|
||||
const s = await fetch('https://typescriptlang.org');
|
||||
const st = await Promise.resolve(s.statusText);
|
||||
const x = st.length;
|
||||
return console.log(x + 5);
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
// ==ORIGINAL==
|
||||
|
||||
function /*[#|*/f/*|]*/() {
|
||||
return fetch('https://typescriptlang.org').then(s => Promise.resolve(s.statusText).then(st => st.length)).then(x => console.log(x + 5));
|
||||
}
|
||||
|
||||
// ==ASYNC FUNCTION::Convert to async function==
|
||||
|
||||
async function f() {
|
||||
const s = await fetch('https://typescriptlang.org');
|
||||
const st = await Promise.resolve(s.statusText);
|
||||
const x = st.length;
|
||||
return console.log(x + 5);
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// ==ORIGINAL==
|
||||
|
||||
function /*[#|*/f/*|]*/() {
|
||||
return fetch('https://typescriptlang.org').then(s => Promise.resolve(s.statusText.length)).then(x => console.log(x + 5));
|
||||
}
|
||||
|
||||
// ==ASYNC FUNCTION::Convert to async function==
|
||||
|
||||
async function f() {
|
||||
const s = await fetch('https://typescriptlang.org');
|
||||
const x = await Promise.resolve(s.statusText.length);
|
||||
return console.log(x + 5);
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// ==ORIGINAL==
|
||||
|
||||
function /*[#|*/f/*|]*/() {
|
||||
return fetch('https://typescriptlang.org').then(s => Promise.resolve(s.statusText.length)).then(x => console.log(x + 5));
|
||||
}
|
||||
|
||||
// ==ASYNC FUNCTION::Convert to async function==
|
||||
|
||||
async function f() {
|
||||
const s = await fetch('https://typescriptlang.org');
|
||||
const x = await Promise.resolve(s.statusText.length);
|
||||
return console.log(x + 5);
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// ==ORIGINAL==
|
||||
|
||||
function /*[#|*/f/*|]*/() {
|
||||
return fetch('https://typescriptlang.org').then(s => { return Promise.resolve(s.statusText.length) }).then(x => x + 5);
|
||||
}
|
||||
|
||||
// ==ASYNC FUNCTION::Convert to async function==
|
||||
|
||||
async function f() {
|
||||
const s = await fetch('https://typescriptlang.org');
|
||||
const x = await Promise.resolve(s.statusText.length);
|
||||
return x + 5;
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// ==ORIGINAL==
|
||||
|
||||
function /*[#|*/f/*|]*/() {
|
||||
return fetch('https://typescriptlang.org').then(s => { return Promise.resolve(s.statusText.length) }).then(x => x + 5);
|
||||
}
|
||||
|
||||
// ==ASYNC FUNCTION::Convert to async function==
|
||||
|
||||
async function f() {
|
||||
const s = await fetch('https://typescriptlang.org');
|
||||
const x = await Promise.resolve(s.statusText.length);
|
||||
return x + 5;
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
// ==ORIGINAL==
|
||||
|
||||
function /*[#|*/f/*|]*/() {
|
||||
return fetch('https://typescriptlang.org').then(s => Promise.resolve(s.statusText.length));
|
||||
}
|
||||
|
||||
// ==ASYNC FUNCTION::Convert to async function==
|
||||
|
||||
async function f() {
|
||||
const s = await fetch('https://typescriptlang.org');
|
||||
return Promise.resolve(s.statusText.length);
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
// ==ORIGINAL==
|
||||
|
||||
function /*[#|*/f/*|]*/() {
|
||||
return fetch('https://typescriptlang.org').then(s => Promise.resolve(s.statusText.length));
|
||||
}
|
||||
|
||||
// ==ASYNC FUNCTION::Convert to async function==
|
||||
|
||||
async function f() {
|
||||
const s = await fetch('https://typescriptlang.org');
|
||||
return Promise.resolve(s.statusText.length);
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// ==ORIGINAL==
|
||||
|
||||
function /*[#|*/f/*|]*/() {
|
||||
return fetch('https://typescriptlang.org').then(x => Promise.resolve(3).then(y => Promise.resolve(x.statusText.length + y)));
|
||||
}
|
||||
|
||||
// ==ASYNC FUNCTION::Convert to async function==
|
||||
|
||||
async function f() {
|
||||
const x = await fetch('https://typescriptlang.org');
|
||||
const y = await Promise.resolve(3);
|
||||
return Promise.resolve(x.statusText.length + y);
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// ==ORIGINAL==
|
||||
|
||||
function /*[#|*/f/*|]*/() {
|
||||
return fetch('https://typescriptlang.org').then(x => Promise.resolve(3).then(y => Promise.resolve(x.statusText.length + y)));
|
||||
}
|
||||
|
||||
// ==ASYNC FUNCTION::Convert to async function==
|
||||
|
||||
async function f() {
|
||||
const x = await fetch('https://typescriptlang.org');
|
||||
const y = await Promise.resolve(3);
|
||||
return Promise.resolve(x.statusText.length + y);
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// ==ORIGINAL==
|
||||
|
||||
function /*[#|*/f/*|]*/() {
|
||||
return fetch('https://typescriptlang.org').then(res).then(_ => console.log("done"));
|
||||
}
|
||||
function res(result) {
|
||||
return Promise.resolve().then(x => console.log(result));
|
||||
}
|
||||
|
||||
// ==ASYNC FUNCTION::Convert to async function==
|
||||
|
||||
async function f() {
|
||||
const result = await fetch('https://typescriptlang.org');
|
||||
const _ = await res(result);
|
||||
return console.log("done");
|
||||
}
|
||||
function res(result) {
|
||||
return Promise.resolve().then(x => console.log(result));
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// ==ORIGINAL==
|
||||
|
||||
function /*[#|*/f/*|]*/() {
|
||||
return fetch('https://typescriptlang.org').then(res).then(_ => console.log("done"));
|
||||
}
|
||||
function res(result) {
|
||||
return Promise.resolve().then(x => console.log(result));
|
||||
}
|
||||
|
||||
// ==ASYNC FUNCTION::Convert to async function==
|
||||
|
||||
async function f() {
|
||||
const result = await fetch('https://typescriptlang.org');
|
||||
const _ = await res(result);
|
||||
return console.log("done");
|
||||
}
|
||||
function res(result) {
|
||||
return Promise.resolve().then(x => console.log(result));
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
//// [test.ts]
|
||||
interface Foo {
|
||||
x: number;
|
||||
}
|
||||
export default Foo;
|
||||
|
||||
|
||||
//// [test.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
|
||||
|
||||
//// [test.d.ts]
|
||||
interface Foo {
|
||||
x: number;
|
||||
}
|
||||
export default Foo;
|
||||
@@ -0,0 +1,10 @@
|
||||
=== /foo/test.ts ===
|
||||
interface Foo {
|
||||
>Foo : Symbol(Foo, Decl(test.ts, 0, 0))
|
||||
|
||||
x: number;
|
||||
>x : Symbol(Foo.x, Decl(test.ts, 0, 15))
|
||||
}
|
||||
export default Foo;
|
||||
>Foo : Symbol(Foo, Decl(test.ts, 0, 0))
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
=== /foo/test.ts ===
|
||||
interface Foo {
|
||||
x: number;
|
||||
>x : number
|
||||
}
|
||||
export default Foo;
|
||||
>Foo : Foo
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
//// [test.ts]
|
||||
interface Foo {
|
||||
x: number;
|
||||
}
|
||||
export default Foo;
|
||||
|
||||
|
||||
//// [test.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
|
||||
|
||||
//// [test.d.ts]
|
||||
interface Foo {
|
||||
x: number;
|
||||
}
|
||||
export default Foo;
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
=== /foo/test.ts ===
|
||||
interface Foo {
|
||||
>Foo : Symbol(Foo, Decl(test.ts, 0, 0))
|
||||
|
||||
x: number;
|
||||
>x : Symbol(Foo.x, Decl(test.ts, 0, 15))
|
||||
}
|
||||
export default Foo;
|
||||
>Foo : Symbol(Foo, Decl(test.ts, 0, 0))
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
=== /foo/test.ts ===
|
||||
interface Foo {
|
||||
x: number;
|
||||
>x : number
|
||||
}
|
||||
export default Foo;
|
||||
>Foo : Foo
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
/foo/tsconfig.json(2,26): error TS5052: Option 'declarationDir' cannot be specified without specifying option 'declaration'.
|
||||
|
||||
|
||||
==== /foo/tsconfig.json (1 errors) ====
|
||||
{
|
||||
"compilerOptions": { "declarationDir": "out" }
|
||||
~~~~~~~~~~~~~~~~
|
||||
!!! error TS5052: Option 'declarationDir' cannot be specified without specifying option 'declaration'.
|
||||
}
|
||||
|
||||
==== /foo/test.ts (0 errors) ====
|
||||
interface Foo {
|
||||
x: number;
|
||||
}
|
||||
export default Foo;
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
//// [test.ts]
|
||||
interface Foo {
|
||||
x: number;
|
||||
}
|
||||
export default Foo;
|
||||
|
||||
|
||||
//// [test.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
=== /foo/test.ts ===
|
||||
interface Foo {
|
||||
>Foo : Symbol(Foo, Decl(test.ts, 0, 0))
|
||||
|
||||
x: number;
|
||||
>x : Symbol(Foo.x, Decl(test.ts, 0, 15))
|
||||
}
|
||||
export default Foo;
|
||||
>Foo : Symbol(Foo, Decl(test.ts, 0, 0))
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user