Skip to content

Commit 1558c7f

Browse files
committed
Merge branch 'main' into rewrite-extensions
2 parents fce0a2d + 89e004f commit 1558c7f

17 files changed

+542
-428
lines changed

.dprint.jsonc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
// Note: if adding new languages, make sure settings.template.json is updated too.
5454
// Also, if updating typescript, update the one in package.json.
5555
"plugins": [
56-
"https://plugins.dprint.dev/typescript-0.91.7.wasm",
56+
"https://plugins.dprint.dev/typescript-0.91.8.wasm",
5757
"https://plugins.dprint.dev/json-0.19.3.wasm",
5858
"https://plugins.dprint.dev/g-plane/pretty_yaml-v0.5.0.wasm"
5959
]

package-lock.json

Lines changed: 236 additions & 368 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@
4040
],
4141
"devDependencies": {
4242
"@dprint/formatter": "^0.4.1",
43-
"@dprint/typescript": "0.91.7",
43+
"@dprint/typescript": "0.91.8",
4444
"@esfx/canceltoken": "^1.0.0",
45-
"@eslint/js": "^9.9.1",
45+
"@eslint/js": "^9.10.0",
4646
"@octokit/rest": "^21.0.2",
4747
"@types/chai": "^4.3.19",
4848
"@types/diff": "^5.2.2",
@@ -52,9 +52,9 @@
5252
"@types/node": "latest",
5353
"@types/source-map-support": "^0.5.10",
5454
"@types/which": "^3.0.4",
55-
"@typescript-eslint/rule-tester": "^8.3.0",
56-
"@typescript-eslint/type-utils": "^8.3.0",
57-
"@typescript-eslint/utils": "^8.3.0",
55+
"@typescript-eslint/rule-tester": "^8.5.0",
56+
"@typescript-eslint/type-utils": "^8.5.0",
57+
"@typescript-eslint/utils": "^8.5.0",
5858
"azure-devops-node-api": "^14.0.2",
5959
"c8": "^10.1.2",
6060
"chai": "^4.5.0",
@@ -63,26 +63,25 @@
6363
"diff": "^5.2.0",
6464
"dprint": "^0.47.2",
6565
"esbuild": "^0.23.1",
66-
"eslint": "^9.9.1",
66+
"eslint": "^9.10.0",
6767
"eslint-formatter-autolinkable-stylish": "^1.4.0",
6868
"eslint-plugin-regexp": "^2.6.0",
69-
"fast-xml-parser": "^4.4.1",
69+
"fast-xml-parser": "^4.5.0",
7070
"glob": "^10.4.5",
7171
"globals": "^15.9.0",
7272
"hereby": "^1.9.0",
7373
"jsonc-parser": "^3.3.1",
74-
"knip": "^5.27.5",
74+
"knip": "^5.30.1",
7575
"minimist": "^1.2.8",
7676
"mocha": "^10.7.3",
7777
"mocha-fivemat-progress-reporter": "^0.1.0",
7878
"monocart-coverage-reports": "^2.10.3",
7979
"ms": "^2.1.3",
80-
"node-fetch": "^3.3.2",
81-
"playwright": "^1.46.1",
80+
"playwright": "^1.47.0",
8281
"source-map-support": "^0.5.21",
8382
"tslib": "^2.7.0",
84-
"typescript": "^5.5.4",
85-
"typescript-eslint": "^8.3.0",
83+
"typescript": "^5.6.2",
84+
"typescript-eslint": "^8.5.0",
8685
"which": "^3.0.1"
8786
},
8887
"overrides": {

scripts/post-vsts-artifact-comment.mjs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { Octokit } from "@octokit/rest";
22
import assert from "assert";
33
import ado from "azure-devops-node-api";
4-
import fetch from "node-fetch";
54

65
/**
76
* @param {string} name

src/services/codefixes/importFixes.ts

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ export function createImportAdder(sourceFile: SourceFile | FutureSourceFile, pro
241241
interface AddToExistingState {
242242
readonly importClauseOrBindingPattern: ImportClause | ObjectBindingPattern;
243243
defaultImport: Import | undefined;
244-
readonly namedImports: Map<string, AddAsTypeOnly>;
244+
readonly namedImports: Map<string, { addAsTypeOnly: AddAsTypeOnly; propertyName?: string | undefined; }>;
245245
}
246246

247247
function createImportAdderWorker(sourceFile: SourceFile | FutureSourceFile, program: Program, useAutoImportProvider: boolean, preferences: UserPreferences, host: LanguageServiceHost, cancellationToken: CancellationToken | undefined): ImportAdder {
@@ -290,15 +290,28 @@ function createImportAdderWorker(sourceFile: SourceFile | FutureSourceFile, prog
290290
let fix = getImportFixForSymbol(sourceFile, exportInfo, program, /*position*/ undefined, !!isValidTypeOnlyUseSite, useRequire, host, preferences);
291291
if (fix) {
292292
const localName = tryCast(referenceImport?.name, isIdentifier)?.text ?? symbolName;
293+
let addAsTypeOnly: AddAsTypeOnly | undefined;
294+
let propertyName: string | undefined;
293295
if (
294296
referenceImport
295297
&& isTypeOnlyImportDeclaration(referenceImport)
296298
&& (fix.kind === ImportFixKind.AddNew || fix.kind === ImportFixKind.AddToExisting)
297299
&& fix.addAsTypeOnly === AddAsTypeOnly.Allowed
298300
) {
299301
// Copy the type-only status from the reference import
300-
fix = { ...fix, addAsTypeOnly: AddAsTypeOnly.Required };
302+
addAsTypeOnly = AddAsTypeOnly.Required;
301303
}
304+
305+
if (exportedSymbol.name !== localName) {
306+
// checks if the symbol was aliased at the referenced import
307+
propertyName = exportedSymbol.name;
308+
}
309+
310+
fix = {
311+
...fix,
312+
...(addAsTypeOnly === undefined ? {} : { addAsTypeOnly }),
313+
...(propertyName === undefined ? {} : { propertyName }),
314+
};
302315
addImport({ fix, symbolName: localName ?? symbolName, errorIdentifierText: undefined });
303316
}
304317
}
@@ -375,14 +388,14 @@ function createImportAdderWorker(sourceFile: SourceFile | FutureSourceFile, prog
375388
importType.push(fix);
376389
break;
377390
case ImportFixKind.AddToExisting: {
378-
const { importClauseOrBindingPattern, importKind, addAsTypeOnly } = fix;
391+
const { importClauseOrBindingPattern, importKind, addAsTypeOnly, propertyName } = fix;
379392
let entry = addToExisting.get(importClauseOrBindingPattern);
380393
if (!entry) {
381394
addToExisting.set(importClauseOrBindingPattern, entry = { importClauseOrBindingPattern, defaultImport: undefined, namedImports: new Map() });
382395
}
383396
if (importKind === ImportKind.Named) {
384-
const prevValue = entry?.namedImports.get(symbolName);
385-
entry.namedImports.set(symbolName, reduceAddAsTypeOnlyValues(prevValue, addAsTypeOnly));
397+
const prevTypeOnly = entry?.namedImports.get(symbolName)?.addAsTypeOnly;
398+
entry.namedImports.set(symbolName, { addAsTypeOnly: reduceAddAsTypeOnlyValues(prevTypeOnly, addAsTypeOnly), propertyName });
386399
}
387400
else {
388401
Debug.assert(entry.defaultImport === undefined || entry.defaultImport.name === symbolName, "(Add to Existing) Default import should be missing or match symbolName");
@@ -394,7 +407,7 @@ function createImportAdderWorker(sourceFile: SourceFile | FutureSourceFile, prog
394407
break;
395408
}
396409
case ImportFixKind.AddNew: {
397-
const { moduleSpecifier, importKind, useRequire, addAsTypeOnly } = fix;
410+
const { moduleSpecifier, importKind, useRequire, addAsTypeOnly, propertyName } = fix;
398411
const entry = getNewImportEntry(moduleSpecifier, importKind, useRequire, addAsTypeOnly);
399412
Debug.assert(entry.useRequire === useRequire, "(Add new) Tried to add an `import` and a `require` for the same module");
400413

@@ -405,12 +418,12 @@ function createImportAdderWorker(sourceFile: SourceFile | FutureSourceFile, prog
405418
break;
406419
case ImportKind.Named:
407420
const prevValue = (entry.namedImports ||= new Map()).get(symbolName);
408-
entry.namedImports.set(symbolName, reduceAddAsTypeOnlyValues(prevValue, addAsTypeOnly));
421+
entry.namedImports.set(symbolName, [reduceAddAsTypeOnlyValues(prevValue, addAsTypeOnly), propertyName]);
409422
break;
410423
case ImportKind.CommonJS:
411424
if (compilerOptions.verbatimModuleSyntax) {
412425
const prevValue = (entry.namedImports ||= new Map()).get(symbolName);
413-
entry.namedImports.set(symbolName, reduceAddAsTypeOnlyValues(prevValue, addAsTypeOnly));
426+
entry.namedImports.set(symbolName, [reduceAddAsTypeOnlyValues(prevValue, addAsTypeOnly), propertyName]);
414427
}
415428
else {
416429
Debug.assert(entry.namespaceLikeImport === undefined || entry.namespaceLikeImport.name === symbolName, "Namespacelike import shoudl be missing or match symbolName");
@@ -582,7 +595,7 @@ function createImportAdderWorker(sourceFile: SourceFile | FutureSourceFile, prog
582595
sourceFile as SourceFile,
583596
importClauseOrBindingPattern,
584597
defaultImport,
585-
arrayFrom(namedImports.entries(), ([name, addAsTypeOnly]) => ({ addAsTypeOnly, name })),
598+
arrayFrom(namedImports.entries(), ([name, { addAsTypeOnly, propertyName }]) => ({ addAsTypeOnly, propertyName, name })),
586599
importSpecifiersToRemoveWhileAdding,
587600
preferences,
588601
);
@@ -596,7 +609,7 @@ function createImportAdderWorker(sourceFile: SourceFile | FutureSourceFile, prog
596609
moduleSpecifier,
597610
quotePreference,
598611
defaultImport,
599-
namedImports && arrayFrom(namedImports.entries(), ([name, addAsTypeOnly]) => ({ addAsTypeOnly, name })),
612+
namedImports && arrayFrom(namedImports.entries(), ([name, [addAsTypeOnly, propertyName]]) => ({ addAsTypeOnly, propertyName, name })),
600613
namespaceLikeImport,
601614
compilerOptions,
602615
preferences,
@@ -772,11 +785,13 @@ interface FixAddToExistingImport extends ImportFixBase {
772785
readonly importClauseOrBindingPattern: ImportClause | ObjectBindingPattern;
773786
readonly importKind: ImportKind.Default | ImportKind.Named;
774787
readonly addAsTypeOnly: AddAsTypeOnly;
788+
readonly propertyName?: string;
775789
}
776790
interface FixAddNewImport extends ImportFixBase {
777791
readonly kind: ImportFixKind.AddNew;
778792
readonly importKind: ImportKind;
779793
readonly addAsTypeOnly: AddAsTypeOnly;
794+
readonly propertyName?: string;
780795
readonly useRequire: boolean;
781796
readonly qualification?: Qualification;
782797
}
@@ -1794,7 +1809,7 @@ function doAddExistingFix(
17941809
factory.createObjectBindingPattern([
17951810
...clause.elements.filter(e => !removeExistingImportSpecifiers.has(e)),
17961811
...defaultImport ? [factory.createBindingElement(/*dotDotDotToken*/ undefined, /*propertyName*/ "default", defaultImport.name)] : emptyArray,
1797-
...namedImports.map(i => factory.createBindingElement(/*dotDotDotToken*/ undefined, /*propertyName*/ undefined, i.name)),
1812+
...namedImports.map(i => factory.createBindingElement(/*dotDotDotToken*/ undefined, i.propertyName, i.name)),
17981813
]),
17991814
);
18001815
return;
@@ -1803,7 +1818,7 @@ function doAddExistingFix(
18031818
addElementToBindingPattern(clause, defaultImport.name, "default");
18041819
}
18051820
for (const specifier of namedImports) {
1806-
addElementToBindingPattern(clause, specifier.name, /*propertyName*/ undefined);
1821+
addElementToBindingPattern(clause, specifier.name, specifier.propertyName);
18071822
}
18081823
return;
18091824
}
@@ -1823,7 +1838,7 @@ function doAddExistingFix(
18231838
namedImports.map(namedImport =>
18241839
factory.createImportSpecifier(
18251840
(!clause.isTypeOnly || promoteFromTypeOnly) && shouldUseTypeOnly(namedImport, preferences),
1826-
/*propertyName*/ undefined,
1841+
namedImport.propertyName === undefined ? undefined : factory.createIdentifier(namedImport.propertyName),
18271842
factory.createIdentifier(namedImport.name),
18281843
)
18291844
),
@@ -1919,11 +1934,12 @@ function getImportTypePrefix(moduleSpecifier: string, quotePreference: QuotePref
19191934
interface Import {
19201935
readonly name: string;
19211936
readonly addAsTypeOnly: AddAsTypeOnly;
1937+
readonly propertyName?: string; // Use when needing to generate an `ImportSpecifier with a `propertyName`; the name preceding "as" keyword (undefined when "as" is absent)
19221938
}
19231939

19241940
interface ImportsCollection {
19251941
readonly defaultImport?: Import;
1926-
readonly namedImports?: Map<string, AddAsTypeOnly>;
1942+
readonly namedImports?: Map<string, [AddAsTypeOnly, /*propertyName*/ string?]>;
19271943
readonly namespaceLikeImport?: {
19281944
readonly importKind: ImportKind.CommonJS | ImportKind.Namespace;
19291945
readonly name: string;
@@ -1964,7 +1980,7 @@ function getNewImports(
19641980
namedImports?.map(namedImport =>
19651981
factory.createImportSpecifier(
19661982
!topLevelTypeOnly && shouldUseTypeOnly(namedImport, preferences),
1967-
/*propertyName*/ undefined,
1983+
namedImport.propertyName === undefined ? undefined : factory.createIdentifier(namedImport.propertyName),
19681984
factory.createIdentifier(namedImport.name),
19691985
)
19701986
),
@@ -2003,7 +2019,7 @@ function getNewRequires(moduleSpecifier: string, quotePreference: QuotePreferenc
20032019
let statements: RequireVariableStatement | readonly RequireVariableStatement[] | undefined;
20042020
// const { default: foo, bar, etc } = require('./mod');
20052021
if (defaultImport || namedImports?.length) {
2006-
const bindingElements = namedImports?.map(({ name }) => factory.createBindingElement(/*dotDotDotToken*/ undefined, /*propertyName*/ undefined, name)) || [];
2022+
const bindingElements = namedImports?.map(({ name, propertyName }) => factory.createBindingElement(/*dotDotDotToken*/ undefined, propertyName, name)) || [];
20072023
if (defaultImport) {
20082024
bindingElements.unshift(factory.createBindingElement(/*dotDotDotToken*/ undefined, "default", defaultImport.name));
20092025
}

src/services/completions.ts

Lines changed: 49 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2666,7 +2666,7 @@ export function getCompletionEntriesFromSymbols(
26662666
includeSymbol = false,
26672667
): UniqueNameSet {
26682668
const start = timestamp();
2669-
const variableOrParameterDeclaration = getVariableOrParameterDeclaration(contextToken, location);
2669+
const closestSymbolDeclaration = getClosestSymbolDeclaration(contextToken, location);
26702670
const useSemicolons = probablyUsesSemicolons(sourceFile);
26712671
const typeChecker = program.getTypeChecker();
26722672
// Tracks unique names.
@@ -2745,26 +2745,33 @@ export function getCompletionEntriesFromSymbols(
27452745
}
27462746
// Filter out variables from their own initializers
27472747
// `const a = /* no 'a' here */`
2748-
if (tryCast(variableOrParameterDeclaration, isVariableDeclaration) && symbol.valueDeclaration === variableOrParameterDeclaration) {
2748+
if (tryCast(closestSymbolDeclaration, isVariableDeclaration) && symbol.valueDeclaration === closestSymbolDeclaration) {
27492749
return false;
27502750
}
27512751

2752-
// Filter out parameters from their own initializers
2752+
// Filter out current and latter parameters from defaults
27532753
// `function f(a = /* no 'a' and 'b' here */, b) { }` or
2754-
// `function f<T = /* no 'T' here */>(a: T) { }`
2754+
// `function f<T = /* no 'T' and 'T2' here */>(a: T, b: T2) { }`
27552755
const symbolDeclaration = symbol.valueDeclaration ?? symbol.declarations?.[0];
2756-
if (
2757-
variableOrParameterDeclaration && symbolDeclaration && (
2758-
(isTypeParameterDeclaration(variableOrParameterDeclaration) && isTypeParameterDeclaration(symbolDeclaration)) ||
2759-
(isParameter(variableOrParameterDeclaration) && isParameter(symbolDeclaration))
2760-
)
2761-
) {
2762-
const symbolDeclarationPos = symbolDeclaration.pos;
2763-
const parameters = isParameter(variableOrParameterDeclaration) ? variableOrParameterDeclaration.parent.parameters :
2764-
isInferTypeNode(variableOrParameterDeclaration.parent) ? undefined :
2765-
variableOrParameterDeclaration.parent.typeParameters;
2766-
if (symbolDeclarationPos >= variableOrParameterDeclaration.pos && parameters && symbolDeclarationPos < parameters.end) {
2767-
return false;
2756+
if (closestSymbolDeclaration && symbolDeclaration) {
2757+
if (isParameter(closestSymbolDeclaration) && isParameter(symbolDeclaration)) {
2758+
const parameters = closestSymbolDeclaration.parent.parameters;
2759+
if (symbolDeclaration.pos >= closestSymbolDeclaration.pos && symbolDeclaration.pos < parameters.end) {
2760+
return false;
2761+
}
2762+
}
2763+
else if (isTypeParameterDeclaration(closestSymbolDeclaration) && isTypeParameterDeclaration(symbolDeclaration)) {
2764+
if (closestSymbolDeclaration === symbolDeclaration && contextToken?.kind === SyntaxKind.ExtendsKeyword) {
2765+
// filter out the directly self-recursive type parameters
2766+
// `type A<K extends /* no 'K' here*/> = K`
2767+
return false;
2768+
}
2769+
if (isInTypeParameterDefault(contextToken) && !isInferTypeNode(closestSymbolDeclaration.parent)) {
2770+
const typeParameters = closestSymbolDeclaration.parent.typeParameters;
2771+
if (typeParameters && symbolDeclaration.pos >= closestSymbolDeclaration.pos && symbolDeclaration.pos < typeParameters.end) {
2772+
return false;
2773+
}
2774+
}
27682775
}
27692776
}
27702777

@@ -6001,20 +6008,39 @@ function isModuleSpecifierMissingOrEmpty(specifier: ModuleReference | Expression
60016008
return !tryCast(isExternalModuleReference(specifier) ? specifier.expression : specifier, isStringLiteralLike)?.text;
60026009
}
60036010

6004-
function getVariableOrParameterDeclaration(contextToken: Node | undefined, location: Node) {
6011+
function getClosestSymbolDeclaration(contextToken: Node | undefined, location: Node) {
60056012
if (!contextToken) return;
60066013

6007-
const possiblyParameterDeclaration = findAncestor(contextToken, node =>
6014+
let closestDeclaration = findAncestor(contextToken, node =>
60086015
isFunctionBlock(node) || isArrowFunctionBody(node) || isBindingPattern(node)
60096016
? "quit"
60106017
: ((isParameter(node) || isTypeParameterDeclaration(node)) && !isIndexSignatureDeclaration(node.parent)));
60116018

6012-
const possiblyVariableDeclaration = findAncestor(location, node =>
6013-
isFunctionBlock(node) || isArrowFunctionBody(node) || isBindingPattern(node)
6014-
? "quit"
6015-
: isVariableDeclaration(node));
6019+
if (!closestDeclaration) {
6020+
closestDeclaration = findAncestor(location, node =>
6021+
isFunctionBlock(node) || isArrowFunctionBody(node) || isBindingPattern(node)
6022+
? "quit"
6023+
: isVariableDeclaration(node));
6024+
}
6025+
return closestDeclaration as ParameterDeclaration | TypeParameterDeclaration | VariableDeclaration | undefined;
6026+
}
6027+
6028+
function isInTypeParameterDefault(contextToken: Node | undefined) {
6029+
if (!contextToken) {
6030+
return false;
6031+
}
60166032

6017-
return (possiblyParameterDeclaration || possiblyVariableDeclaration) as ParameterDeclaration | TypeParameterDeclaration | VariableDeclaration | undefined;
6033+
let node = contextToken;
6034+
let parent = contextToken.parent;
6035+
while (parent) {
6036+
if (isTypeParameterDeclaration(parent)) {
6037+
return parent.default === node || node.kind === SyntaxKind.EqualsToken;
6038+
}
6039+
node = parent;
6040+
parent = parent.parent;
6041+
}
6042+
6043+
return false;
60186044
}
60196045

60206046
function isArrowFunctionBody(node: Node) {

0 commit comments

Comments
 (0)