Skip to content

Commit 26cd24a

Browse files
committed
add multiple code fixes and code action filtering and polishing
1 parent 6d024dc commit 26cd24a

39 files changed

+286
-212
lines changed

src/compiler/checker.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,13 +102,12 @@ namespace ts {
102102
isImplementationOfOverload,
103103
getAliasedSymbol: resolveAlias,
104104
getEmitResolver,
105-
getExportsOfModuleAsArray,
106-
getExportsOfModule,
105+
getExportsOfModule: getExportsOfModuleAsArray,
107106
getAmbientModules,
108-
109107
getJsxElementAttributesType,
110108
getJsxIntrinsicTagNames,
111109
isOptionalParameter,
110+
tryGetMemberInModuleExports,
112111
tryFindAmbientModuleWithoutAugmentations: moduleName => {
113112
// we deliberately exclude augmentations
114113
// since we are only interested in declarations of the module itself
@@ -1465,6 +1464,13 @@ namespace ts {
14651464
return symbolsToArray(getExportsOfModule(moduleSymbol));
14661465
}
14671466

1467+
function tryGetMemberInModuleExports(memberName: string, moduleSymbol: Symbol): Symbol | undefined {
1468+
const symbolTable = getExportsOfModule(moduleSymbol);
1469+
if (symbolTable) {
1470+
return symbolTable[memberName];
1471+
}
1472+
}
1473+
14681474
function getExportsOfSymbol(symbol: Symbol): SymbolTable {
14691475
return symbol.flags & SymbolFlags.Module ? getExportsOfModule(symbol) : symbol.exports || emptySymbols;
14701476
}

src/compiler/types.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2291,14 +2291,15 @@ namespace ts {
22912291
getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number;
22922292
isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: string): boolean;
22932293
getAliasedSymbol(symbol: Symbol): Symbol;
2294-
getExportsOfModuleAsArray(moduleSymbol: Symbol): Symbol[];
2295-
getExportsOfModule(moduleSymbol: Symbol): Map<Symbol> | undefined;
2294+
getExportsOfModule(moduleSymbol: Symbol): Symbol[];
22962295

22972296
getJsxElementAttributesType(elementNode: JsxOpeningLikeElement): Type;
22982297
getJsxIntrinsicTagNames(): Symbol[];
22992298
isOptionalParameter(node: ParameterDeclaration): boolean;
23002299
getAmbientModules(): Symbol[];
23012300

2301+
tryGetMemberInModuleExports(memberName: string, moduleSymbol: Symbol): Symbol | undefined;
2302+
23022303
/* @internal */ tryFindAmbientModuleWithoutAugmentations(moduleName: string): Symbol;
23032304

23042305
// Should not be called directly. Should only be accessed through the Program instance.

src/harness/fourslash.ts

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2018,27 +2018,31 @@ namespace FourSlash {
20182018
return this.languageService.getCodeFixesAtPosition(fileName, diagnostic.start, diagnostic.length, [diagnostic.code]);
20192019
}
20202020

2021-
public verifyCodeFixAtPosition(expectedText: string, errorCode?: number) {
2021+
public verifyCodeFixAtPosition(expectedTextArray: string[], errorCode?: number) {
20222022
const ranges = this.getRanges();
20232023
if (ranges.length == 0) {
20242024
this.raiseError("At least one range should be specified in the testfile.");
20252025
}
20262026

2027-
const actual = this.getCodeFixes(errorCode);
2027+
const codeFixes = this.getCodeFixes(errorCode);
20282028

2029-
if (!actual || actual.length == 0) {
2029+
if (!codeFixes || codeFixes.length == 0) {
20302030
this.raiseError("No codefixes returned.");
20312031
}
20322032

2033-
if (actual.length > 1) {
2034-
this.raiseError("More than 1 codefix returned.");
2033+
const actualTextArray: string[] = [];
2034+
const scriptInfo = this.languageServiceAdapterHost.getScriptInfo(codeFixes[0].changes[0].fileName);
2035+
const originalContent = scriptInfo.content;
2036+
for (const codeFix of codeFixes) {
2037+
this.applyEdits(codeFix.changes[0].fileName, codeFix.changes[0].textChanges, /*isFormattingEdit*/ false);
2038+
actualTextArray.push(this.normalizeNewlines(this.rangeText(ranges[0])));
2039+
scriptInfo.updateContent(originalContent);
20352040
}
2036-
2037-
this.applyEdits(actual[0].changes[0].fileName, actual[0].changes[0].textChanges, /*isFormattingEdit*/ false);
2038-
const actualText = this.rangeText(ranges[0]);
2039-
2040-
if (this.removeWhitespace(actualText) !== this.removeWhitespace(expectedText)) {
2041-
this.raiseError(`Actual text doesn't match expected text. Actual: '${actualText}' Expected: '${expectedText}'`);
2041+
const sortedExpectedArray = ts.map(expectedTextArray, str => this.normalizeNewlines(str)).sort();
2042+
const sortedActualArray = actualTextArray.sort();
2043+
if (!ts.arrayIsEqualTo(sortedExpectedArray, sortedActualArray)) {
2044+
this.raiseError(
2045+
`Actual text array doesn't match expected text array. \nActual: \n'${sortedActualArray.join('\n\n')}'\n---\nExpected: \n'${sortedExpectedArray.join('\n\n')}'`);
20422046
}
20432047
}
20442048

@@ -2075,6 +2079,10 @@ namespace FourSlash {
20752079
});
20762080
}
20772081

2082+
private normalizeNewlines(str: string) {
2083+
return str.replace(/\r?\n/g, "\n");
2084+
}
2085+
20782086
public verifyBraceCompletionAtPosition(negative: boolean, openingBrace: string) {
20792087

20802088
const openBraceMap = ts.createMap<ts.CharacterCodes>({
@@ -3291,8 +3299,8 @@ namespace FourSlashInterface {
32913299
this.DocCommentTemplate(/*expectedText*/ undefined, /*expectedOffset*/ undefined, /*empty*/ true);
32923300
}
32933301

3294-
public codeFixAtPosition(expectedText: string, errorCode?: number): void {
3295-
this.state.verifyCodeFixAtPosition(expectedText, errorCode);
3302+
public codeFixAtPosition(expectedTextArray: string[], errorCode?: number): void {
3303+
this.state.verifyCodeFixAtPosition(expectedTextArray, errorCode);
32963304
}
32973305

32983306
public navigationBar(json: any) {

0 commit comments

Comments
 (0)