Skip to content

Commit f5dc527

Browse files
committed
Merge branch 'master' into flattened-path-based-diagnostics
2 parents 4b95ba7 + 5e06bea commit f5dc527

File tree

56 files changed

+1365
-118
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+1365
-118
lines changed

src/compiler/binder.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2859,7 +2859,7 @@ namespace ts {
28592859

28602860
// If this is a property-parameter, then also declare the property symbol into the
28612861
// containing class.
2862-
if (isParameterPropertyDeclaration(node)) {
2862+
if (isParameterPropertyDeclaration(node, node.parent)) {
28632863
const classDeclaration = <ClassLikeDeclaration>node.parent.parent;
28642864
declareSymbol(classDeclaration.symbol.members!, classDeclaration.symbol, node, SymbolFlags.Property | (node.questionToken ? SymbolFlags.Optional : SymbolFlags.None), SymbolFlags.PropertyExcludes);
28652865
}

src/compiler/checker.ts

+24-17
Original file line numberDiff line numberDiff line change
@@ -8971,9 +8971,8 @@ namespace ts {
89718971
return undefined;
89728972
}
89738973

8974-
function getConstraintDeclaration(type: TypeParameter) {
8975-
const decl = type.symbol && getDeclarationOfKind<TypeParameterDeclaration>(type.symbol, SyntaxKind.TypeParameter);
8976-
return decl && getEffectiveConstraintOfTypeParameter(decl);
8974+
function getConstraintDeclaration(type: TypeParameter): TypeNode | undefined {
8975+
return mapDefined(filter(type.symbol && type.symbol.declarations, isTypeParameterDeclaration), getEffectiveConstraintOfTypeParameter)[0];
89778976
}
89788977

89798978
function getInferredTypeParameterConstraint(typeParameter: TypeParameter) {
@@ -15154,9 +15153,9 @@ namespace ts {
1515415153
* Return true if type was inferred from an object literal, written as an object type literal, or is the shape of a module
1515515154
* with no call or construct signatures.
1515615155
*/
15157-
function isObjectTypeWithInferableIndex(type: Type) {
15158-
return type.symbol && (type.symbol.flags & (SymbolFlags.ObjectLiteral | SymbolFlags.TypeLiteral | SymbolFlags.Enum | SymbolFlags.ValueModule)) !== 0 &&
15159-
!typeHasCallOrConstructSignatures(type);
15156+
function isObjectTypeWithInferableIndex(type: Type): boolean {
15157+
return !!(type.symbol && (type.symbol.flags & (SymbolFlags.ObjectLiteral | SymbolFlags.TypeLiteral | SymbolFlags.Enum | SymbolFlags.ValueModule)) !== 0 &&
15158+
!typeHasCallOrConstructSignatures(type)) || !!(getObjectFlags(type) & ObjectFlags.ReverseMapped && isObjectTypeWithInferableIndex((type as ReverseMappedType).source));
1516015159
}
1516115160

1516215161
function createSymbolWithType(source: Symbol, type: Type | undefined) {
@@ -15558,6 +15557,13 @@ namespace ts {
1555815557
};
1555915558
}
1556015559

15560+
function cloneInferredPartOfContext(context: InferenceContext): InferenceContext | undefined {
15561+
const inferences = filter(context.inferences, hasInferenceCandidates);
15562+
return inferences.length ?
15563+
createInferenceContextWorker(map(inferences, cloneInferenceInfo), context.signature, context.flags, context.compareTypes) :
15564+
undefined;
15565+
}
15566+
1556115567
function getMapperFromContext<T extends InferenceContext | undefined>(context: T): TypeMapper | T & undefined {
1556215568
return context && context.mapper;
1556315569
}
@@ -17603,7 +17609,7 @@ namespace ts {
1760317609
assumeTrue = !assumeTrue;
1760417610
}
1760517611
const valueType = getTypeOfExpression(value);
17606-
if ((type.flags & TypeFlags.Unknown) && (operator === SyntaxKind.EqualsEqualsEqualsToken) && assumeTrue) {
17612+
if ((type.flags & TypeFlags.Unknown) && assumeTrue && (operator === SyntaxKind.EqualsEqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken)) {
1760717613
if (valueType.flags & (TypeFlags.Primitive | TypeFlags.NonPrimitive)) {
1760817614
return valueType;
1760917615
}
@@ -21615,7 +21621,7 @@ namespace ts {
2161521621
const returnContext = createInferenceContext(signature.typeParameters!, signature, context.flags);
2161621622
const returnSourceType = instantiateType(contextualType, outerContext && outerContext.returnMapper);
2161721623
inferTypes(returnContext.inferences, returnSourceType, inferenceTargetType);
21618-
context.returnMapper = some(returnContext.inferences, hasInferenceCandidates) ? getMapperFromContext(returnContext) : undefined;
21624+
context.returnMapper = some(returnContext.inferences, hasInferenceCandidates) ? getMapperFromContext(cloneInferredPartOfContext(returnContext)) : undefined;
2161921625
}
2162021626
}
2162121627

@@ -25855,7 +25861,7 @@ namespace ts {
2585525861
for (const member of node.members) {
2585625862
if (member.kind === SyntaxKind.Constructor) {
2585725863
for (const param of (member as ConstructorDeclaration).parameters) {
25858-
if (isParameterPropertyDeclaration(param) && !isBindingPattern(param.name)) {
25864+
if (isParameterPropertyDeclaration(param, member) && !isBindingPattern(param.name)) {
2585925865
addName(instanceNames, param.name, param.name.escapedText, DeclarationMeaning.GetOrSetAccessor);
2586025866
}
2586125867
}
@@ -27619,7 +27625,7 @@ namespace ts {
2761927625
const parameter = local.valueDeclaration && tryGetRootParameterDeclaration(local.valueDeclaration);
2762027626
const name = local.valueDeclaration && getNameOfDeclaration(local.valueDeclaration);
2762127627
if (parameter && name) {
27622-
if (!isParameterPropertyDeclaration(parameter) && !parameterIsThisKeyword(parameter) && !isIdentifierThatStartsWithUnderscore(name)) {
27628+
if (!isParameterPropertyDeclaration(parameter, parameter.parent) && !parameterIsThisKeyword(parameter) && !isIdentifierThatStartsWithUnderscore(name)) {
2762327629
addDiagnostic(parameter, UnusedKind.Parameter, createDiagnosticForNode(name, Diagnostics._0_is_declared_but_its_value_is_never_read, symbolName(local)));
2762427630
}
2762527631
}
@@ -28890,11 +28896,13 @@ namespace ts {
2889028896
let nextType: Type | undefined;
2889128897
if (methodName !== "throw") {
2889228898
const methodParameterType = methodParameterTypes ? getUnionType(methodParameterTypes) : unknownType;
28893-
const resolvedMethodParameterType = resolver.resolveIterationType(methodParameterType, errorNode) || anyType;
2889428899
if (methodName === "next") {
28895-
nextType = resolvedMethodParameterType;
28900+
// The value of `next(value)` is *not* awaited by async generators
28901+
nextType = methodParameterType;
2889628902
}
2889728903
else if (methodName === "return") {
28904+
// The value of `return(value)` *is* awaited by async generators
28905+
const resolvedMethodParameterType = resolver.resolveIterationType(methodParameterType, errorNode) || anyType;
2889828906
returnTypes = append(returnTypes, resolvedMethodParameterType);
2889928907
}
2890028908
}
@@ -29383,11 +29391,10 @@ namespace ts {
2938329391
const constraint = getEffectiveConstraintOfTypeParameter(source);
2938429392
const sourceConstraint = constraint && getTypeFromTypeNode(constraint);
2938529393
const targetConstraint = getConstraintOfTypeParameter(target);
29386-
if (sourceConstraint) {
29387-
// relax check if later interface augmentation has no constraint
29388-
if (!targetConstraint || !isTypeIdenticalTo(sourceConstraint, targetConstraint)) {
29389-
return false;
29390-
}
29394+
// relax check if later interface augmentation has no constraint, it's more broad and is OK to merge with
29395+
// a more constrained interface (this could be generalized to a full heirarchy check, but that's maybe overkill)
29396+
if (sourceConstraint && targetConstraint && !isTypeIdenticalTo(sourceConstraint, targetConstraint)) {
29397+
return false;
2939129398
}
2939229399

2939329400
// If the type parameter node has a default and it is not identical to the default

src/compiler/diagnosticMessages.json

+4
Original file line numberDiff line numberDiff line change
@@ -5165,6 +5165,10 @@
51655165
"category": "Message",
51665166
"code": 95092
51675167
},
5168+
"Convert 'const' to 'let'": {
5169+
"category": "Message",
5170+
"code": 95093
5171+
},
51685172

51695173
"No value exists in scope for the shorthand property '{0}'. Either declare one or provide an initializer.": {
51705174
"category": "Error",

src/compiler/transformers/classFields.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ namespace ts {
337337
if (constructor && constructor.body) {
338338
let parameterPropertyDeclarationCount = 0;
339339
for (let i = indexOfFirstStatement; i < constructor.body.statements.length; i++) {
340-
if (isParameterPropertyDeclaration(getOriginalNode(constructor.body.statements[i]))) {
340+
if (isParameterPropertyDeclaration(getOriginalNode(constructor.body.statements[i]), constructor)) {
341341
parameterPropertyDeclarationCount++;
342342
}
343343
else {

src/compiler/transformers/declarations/diagnostics.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ namespace ts {
135135
return getReturnTypeVisibilityError;
136136
}
137137
else if (isParameter(node)) {
138-
if (isParameterPropertyDeclaration(node) && hasModifier(node.parent, ModifierFlags.Private)) {
138+
if (isParameterPropertyDeclaration(node, node.parent) && hasModifier(node.parent, ModifierFlags.Private)) {
139139
return getVariableDeclarationTypeVisibilityError;
140140
}
141141
return getParameterDeclarationTypeVisibilityError;

src/compiler/transformers/ts.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -895,7 +895,7 @@ namespace ts {
895895
const members: ClassElement[] = [];
896896
const constructor = getFirstConstructorWithBody(node);
897897
const parametersWithPropertyAssignments = constructor &&
898-
filter(constructor.parameters, isParameterPropertyDeclaration);
898+
filter(constructor.parameters, p => isParameterPropertyDeclaration(p, constructor));
899899

900900
if (parametersWithPropertyAssignments) {
901901
for (const parameter of parametersWithPropertyAssignments) {
@@ -1907,7 +1907,7 @@ namespace ts {
19071907

19081908
function transformConstructorBody(body: Block, constructor: ConstructorDeclaration) {
19091909
const parametersWithPropertyAssignments = constructor &&
1910-
filter(constructor.parameters, isParameterPropertyDeclaration);
1910+
filter(constructor.parameters, p => isParameterPropertyDeclaration(p, constructor));
19111911
if (!some(parametersWithPropertyAssignments)) {
19121912
return visitFunctionBody(body, visitor, context);
19131913
}

src/compiler/utilities.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -975,6 +975,8 @@ namespace ts {
975975
return getSpanOfTokenAtPosition(sourceFile, node.pos);
976976
}
977977

978+
Debug.assert(!isJSDoc(errorNode));
979+
978980
const isMissing = nodeIsMissing(errorNode);
979981
const pos = isMissing || isJsxText(node)
980982
? errorNode.pos
@@ -1007,7 +1009,7 @@ namespace ts {
10071009
}
10081010

10091011
export function isDeclarationReadonly(declaration: Declaration): boolean {
1010-
return !!(getCombinedModifierFlags(declaration) & ModifierFlags.Readonly && !isParameterPropertyDeclaration(declaration));
1012+
return !!(getCombinedModifierFlags(declaration) & ModifierFlags.Readonly && !isParameterPropertyDeclaration(declaration, declaration.parent));
10111013
}
10121014

10131015
export function isVarConst(node: VariableDeclaration | VariableDeclarationList): boolean {
@@ -4981,8 +4983,8 @@ namespace ts {
49814983
}
49824984

49834985
export type ParameterPropertyDeclaration = ParameterDeclaration & { parent: ConstructorDeclaration, name: Identifier };
4984-
export function isParameterPropertyDeclaration(node: Node): node is ParameterPropertyDeclaration {
4985-
return hasModifier(node, ModifierFlags.ParameterPropertyModifier) && node.parent.kind === SyntaxKind.Constructor;
4986+
export function isParameterPropertyDeclaration(node: Node, parent: Node): node is ParameterPropertyDeclaration {
4987+
return hasModifier(node, ModifierFlags.ParameterPropertyModifier) && parent.kind === SyntaxKind.Constructor;
49864988
}
49874989

49884990
export function isEmptyBindingPattern(node: BindingName): node is BindingPattern {

src/lib/es2018.asyncgenerator.d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
interface AsyncGenerator<T = unknown, TReturn = any, TNext = unknown> extends AsyncIterator<T, TReturn, TNext> {
44
// NOTE: 'next' is defined using a tuple to ensure we report the correct assignability errors in all places.
5-
next(...args: [] | [TNext | PromiseLike<TNext>]): Promise<IteratorResult<T, TReturn>>;
5+
next(...args: [] | [TNext]): Promise<IteratorResult<T, TReturn>>;
66
return(value: TReturn | PromiseLike<TReturn>): Promise<IteratorResult<T, TReturn>>;
77
throw(e: any): Promise<IteratorResult<T, TReturn>>;
88
[Symbol.asyncIterator](): AsyncGenerator<T, TReturn, TNext>;

src/lib/es2018.asynciterable.d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ interface SymbolConstructor {
1111

1212
interface AsyncIterator<T, TReturn = any, TNext = undefined> {
1313
// NOTE: 'next' is defined using a tuple to ensure we report the correct assignability errors in all places.
14-
next(...args: [] | [TNext | PromiseLike<TNext>]): Promise<IteratorResult<T, TReturn>>;
14+
next(...args: [] | [TNext]): Promise<IteratorResult<T, TReturn>>;
1515
return?(value?: TReturn | PromiseLike<TReturn>): Promise<IteratorResult<T, TReturn>>;
1616
throw?(e?: any): Promise<IteratorResult<T, TReturn>>;
1717
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/* @internal */
2+
namespace ts.codefix {
3+
const fixId = "fixConvertConstToLet";
4+
const errorCodes = [Diagnostics.Cannot_assign_to_0_because_it_is_a_constant.code];
5+
6+
registerCodeFix({
7+
errorCodes,
8+
getCodeActions: context => {
9+
const { sourceFile, span, program } = context;
10+
const variableStatement = getVariableStatement(sourceFile, span.start, program);
11+
const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, variableStatement));
12+
return [createCodeFixAction(fixId, changes, Diagnostics.Convert_const_to_let, fixId, Diagnostics.Convert_const_to_let)];
13+
},
14+
fixIds: [fixId]
15+
});
16+
17+
function getVariableStatement(sourceFile: SourceFile, pos: number, program: Program) {
18+
const token = getTokenAtPosition(sourceFile, pos);
19+
const checker = program.getTypeChecker();
20+
const symbol = checker.getSymbolAtLocation(token);
21+
if (symbol) {
22+
return symbol.valueDeclaration.parent.parent as VariableStatement;
23+
}
24+
}
25+
function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, variableStatement?: VariableStatement) {
26+
if (!variableStatement) {
27+
return;
28+
}
29+
const start = variableStatement.getStart();
30+
changes.replaceRangeWithText(sourceFile, { pos: start, end: start + 5 }, "let");
31+
}
32+
}

src/services/findAllReferences.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1145,7 +1145,7 @@ namespace ts.FindAllReferences.Core {
11451145
}
11461146

11471147
export function eachSymbolReferenceInFile<T>(definition: Identifier, checker: TypeChecker, sourceFile: SourceFile, cb: (token: Identifier) => T): T | undefined {
1148-
const symbol = isParameterPropertyDeclaration(definition.parent)
1148+
const symbol = isParameterPropertyDeclaration(definition.parent, definition.parent.parent)
11491149
? first(checker.getSymbolsOfParameterPropertyDeclaration(definition.parent, definition.text))
11501150
: checker.getSymbolAtLocation(definition);
11511151
if (!symbol) return undefined;
@@ -1886,7 +1886,7 @@ namespace ts.FindAllReferences.Core {
18861886
const res = fromRoot(symbol);
18871887
if (res) return res;
18881888

1889-
if (symbol.valueDeclaration && isParameterPropertyDeclaration(symbol.valueDeclaration)) {
1889+
if (symbol.valueDeclaration && isParameterPropertyDeclaration(symbol.valueDeclaration, symbol.valueDeclaration.parent)) {
18901890
// For a parameter property, now try on the other symbol (property if this was a parameter, parameter if this was a property).
18911891
const paramProps = checker.getSymbolsOfParameterPropertyDeclaration(cast(symbol.valueDeclaration, isParameter), symbol.name);
18921892
Debug.assert(paramProps.length === 2 && !!(paramProps[0].flags & SymbolFlags.FunctionScopedVariable) && !!(paramProps[1].flags & SymbolFlags.Property)); // is [parameter, property]

src/services/navigationBar.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ namespace ts.NavigationBar {
197197

198198
// Parameter properties are children of the class, not the constructor.
199199
for (const param of ctr.parameters) {
200-
if (isParameterPropertyDeclaration(param)) {
200+
if (isParameterPropertyDeclaration(param, ctr)) {
201201
addLeafNode(param);
202202
}
203203
}

src/services/refactors/extractSymbol.ts

+5
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ namespace ts.refactor.extractSymbol {
116116
export const cannotExtractRange: DiagnosticMessage = createMessage("Cannot extract range.");
117117
export const cannotExtractImport: DiagnosticMessage = createMessage("Cannot extract import statement.");
118118
export const cannotExtractSuper: DiagnosticMessage = createMessage("Cannot extract super call.");
119+
export const cannotExtractJSDoc: DiagnosticMessage = createMessage("Cannot extract JSDoc.");
119120
export const cannotExtractEmpty: DiagnosticMessage = createMessage("Cannot extract empty range.");
120121
export const expressionExpected: DiagnosticMessage = createMessage("expression expected.");
121122
export const uselessConstantType: DiagnosticMessage = createMessage("No reason to extract constant of type.");
@@ -246,6 +247,10 @@ namespace ts.refactor.extractSymbol {
246247
return { targetRange: { range: statements, facts: rangeFacts, declarations } };
247248
}
248249

250+
if (isJSDoc(start)) {
251+
return { errors: [createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractJSDoc)] };
252+
}
253+
249254
if (isReturnStatement(start) && !start.expression) {
250255
// Makes no sense to extract an expression-less return statement.
251256
return { errors: [createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] };

src/services/refactors/generateGetAccessorAndSetAccessor.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor {
9292
}
9393

9494
function isAcceptedDeclaration(node: Node): node is AcceptedDeclaration {
95-
return isParameterPropertyDeclaration(node) || isPropertyDeclaration(node) || isPropertyAssignment(node);
95+
return isParameterPropertyDeclaration(node, node.parent) || isPropertyDeclaration(node) || isPropertyAssignment(node);
9696
}
9797

9898
function createPropertyName (name: string, originalName: AcceptedNameType) {
@@ -214,7 +214,7 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor {
214214
}
215215

216216
function insertAccessor(changeTracker: textChanges.ChangeTracker, file: SourceFile, accessor: AccessorDeclaration, declaration: AcceptedDeclaration, container: ContainerDeclaration) {
217-
isParameterPropertyDeclaration(declaration) ? changeTracker.insertNodeAtClassStart(file, <ClassLikeDeclaration>container, accessor) :
217+
isParameterPropertyDeclaration(declaration, declaration.parent) ? changeTracker.insertNodeAtClassStart(file, <ClassLikeDeclaration>container, accessor) :
218218
isPropertyAssignment(declaration) ? changeTracker.insertNodeAfterComma(file, declaration, accessor) :
219219
changeTracker.insertNodeAfter(file, declaration, accessor);
220220
}

src/services/tsconfig.json

+1
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
"codefixes/fixAddModuleReferTypeMissingTypeof.ts",
8484
"codefixes/convertToMappedObjectType.ts",
8585
"codefixes/removeUnnecessaryAwait.ts",
86+
"codefixes/convertConstToLet.ts",
8687
"refactors/convertExport.ts",
8788
"refactors/convertImport.ts",
8889
"refactors/extractSymbol.ts",

src/testRunner/unittests/services/extract/ranges.ts

+4
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,10 @@ switch (x) {
380380
`[#|{ 1;|] }`,
381381
[refactor.extractSymbol.Messages.cannotExtractRange.message]);
382382

383+
testExtractRangeFailed("extractRangeFailed19",
384+
`[#|/** @type {number} */|] const foo = 1;`,
385+
[refactor.extractSymbol.Messages.cannotExtractJSDoc.message]);
386+
383387
testExtractRangeFailed("extract-method-not-for-token-expression-statement", `[#|a|]`, [refactor.extractSymbol.Messages.cannotExtractIdentifier.message]);
384388
});
385389
}

0 commit comments

Comments
 (0)