Skip to content

Commit bfa943a

Browse files
committed
Adds existing tests
1 parent 4825db1 commit bfa943a

File tree

66 files changed

+513
-173
lines changed

Some content is hidden

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

66 files changed

+513
-173
lines changed

Diff for: src/compiler/types.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -6499,7 +6499,7 @@ namespace ts {
64996499
}
65006500

65016501
export const enum SemanticClassificationFormat {
6502-
Original = "orginal",
6502+
Original = "original",
65036503
TwentyTwenty = "2020"
65046504
}
65056505

Diff for: src/harness/fourslashImpl.ts

+70-4
Original file line numberDiff line numberDiff line change
@@ -2449,9 +2449,50 @@ namespace FourSlash {
24492449
Harness.IO.log(this.spanInfoToString(this.getNameOrDottedNameSpan(pos)!, "**"));
24502450
}
24512451

2452+
private classificationToIdentifier(classification: number){
2453+
2454+
const tokenTypes: string[] = [];
2455+
tokenTypes[ts.classifier.vscode.TokenType.class] = "class";
2456+
tokenTypes[ts.classifier.vscode.TokenType.enum] = "enum";
2457+
tokenTypes[ts.classifier.vscode.TokenType.interface] = "interface";
2458+
tokenTypes[ts.classifier.vscode.TokenType.namespace] = "namespace";
2459+
tokenTypes[ts.classifier.vscode.TokenType.typeParameter] = "typeParameter";
2460+
tokenTypes[ts.classifier.vscode.TokenType.type] = "type";
2461+
tokenTypes[ts.classifier.vscode.TokenType.parameter] = "parameter";
2462+
tokenTypes[ts.classifier.vscode.TokenType.variable] = "variable";
2463+
tokenTypes[ts.classifier.vscode.TokenType.enumMember] = "enumMember";
2464+
tokenTypes[ts.classifier.vscode.TokenType.property] = "property";
2465+
tokenTypes[ts.classifier.vscode.TokenType.function] = "function";
2466+
tokenTypes[ts.classifier.vscode.TokenType.member] = "member";
2467+
2468+
const tokenModifiers: string[] = [];
2469+
tokenModifiers[ts.classifier.vscode.TokenModifier.async] = "async";
2470+
tokenModifiers[ts.classifier.vscode.TokenModifier.declaration] = "declaration";
2471+
tokenModifiers[ts.classifier.vscode.TokenModifier.readonly] = "readonly";
2472+
tokenModifiers[ts.classifier.vscode.TokenModifier.static] = "static";
2473+
tokenModifiers[ts.classifier.vscode.TokenModifier.local] = "local";
2474+
tokenModifiers[ts.classifier.vscode.TokenModifier.defaultLibrary] = "defaultLibrary";
2475+
2476+
2477+
function getTokenTypeFromClassification(tsClassification: number): number | undefined {
2478+
if (tsClassification > ts.classifier.vscode.TokenEncodingConsts.modifierMask) {
2479+
return (tsClassification >> ts.classifier.vscode.TokenEncodingConsts.typeOffset) - 1;
2480+
}
2481+
return undefined;
2482+
}
2483+
2484+
function getTokenModifierFromClassification(tsClassification: number) {
2485+
return tsClassification & ts.classifier.vscode.TokenEncodingConsts.modifierMask;
2486+
}
2487+
2488+
const typeIdx = getTokenTypeFromClassification(classification) || 0;
2489+
const modSet = getTokenModifierFromClassification(classification);
2490+
2491+
const tokenClassifiction = [tokenTypes[typeIdx], ...tokenModifiers.filter((_, i) => modSet & 1 << i)].join(".");
2492+
return tokenClassifiction;
2493+
}
2494+
24522495
private verifyClassifications(expected: { classificationType: string | number, text?: string; textSpan?: TextSpan }[], actual: ts.ClassifiedSpan[], sourceFileText: string) {
2453-
console.log("expected:", expected);
2454-
console.log("actual:", actual);
24552496
if (actual.length !== expected.length) {
24562497
this.raiseError("verifyClassifications failed - expected total classifications to be " + expected.length +
24572498
", but was " + actual.length +
@@ -2460,10 +2501,12 @@ namespace FourSlash {
24602501

24612502
ts.zipWith(expected, actual, (expectedClassification, actualClassification) => {
24622503
const expectedType = expectedClassification.classificationType;
2463-
if (expectedType !== actualClassification.classificationType) {
2504+
const actualType = typeof actualClassification.classificationType === "number" ? this.classificationToIdentifier(actualClassification.classificationType) : actualClassification.classificationType;
2505+
2506+
if (expectedType !== actualType) {
24642507
this.raiseError("verifyClassifications failed - expected classifications type to be " +
24652508
expectedType + ", but was " +
2466-
actualClassification.classificationType +
2509+
actualType +
24672510
jsonMismatchString());
24682511
}
24692512

@@ -2514,6 +2557,29 @@ namespace FourSlash {
25142557
}
25152558
}
25162559

2560+
public replaceWithSemanticClassifications(format: ts.SemanticClassificationFormat.TwentyTwenty) {
2561+
const actual = this.languageService.getSemanticClassifications(this.activeFile.fileName,
2562+
ts.createTextSpan(0, this.activeFile.content.length), format);
2563+
const replacement = [`const c2 = classification("2020");`,`verify.semanticClassificationsAre("2020",`];
2564+
actual.forEach(a => {
2565+
const identifier = this.classificationToIdentifier(a.classificationType as number);
2566+
const text = this.activeFile.content.slice(a.textSpan.start, a.textSpan.start + a.textSpan.length);
2567+
replacement.push(` c2.semanticToken("${identifier}", "${text}"), `);
2568+
});
2569+
replacement.push(");");
2570+
2571+
throw new Error("You need to change the source code of fourslash test to use replaceWithSemanticClassifications");
2572+
2573+
/**
2574+
const fs = require("fs");
2575+
const testfilePath = this.originalInputFileName.slice(1);
2576+
const testfile = fs.readFileSync(testfilePath, "utf8");
2577+
const newfile = testfile.replace("verify.replaceWithSemanticClassifications(\"2020\")", replacement.join("\n"));
2578+
fs.writeFileSync(testfilePath, newfile);
2579+
*/
2580+
}
2581+
2582+
25172583
public verifySemanticClassifications(format: ts.SemanticClassificationFormat, expected: { classificationType: string | number; text?: string }[]) {
25182584
const actual = this.languageService.getSemanticClassifications(this.activeFile.fileName,
25192585
ts.createTextSpan(0, this.activeFile.content.length), format);

Diff for: src/harness/fourslashInterfaceImpl.ts

+6-55
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,10 @@ namespace FourSlashInterface {
504504
this.state.verifySemanticClassifications(format, classifications);
505505
}
506506

507+
public replaceWithSemanticClassifications(format: ts.SemanticClassificationFormat.TwentyTwenty) {
508+
this.state.replaceWithSemanticClassifications(format);
509+
}
510+
507511
public renameInfoSucceeded(displayName?: string, fullDisplayName?: string, kind?: string, kindModifiers?: string, fileToRename?: string, expectedRange?: FourSlash.Range, options?: ts.RenameInfoOptions) {
508512
this.state.verifyRenameInfoSucceeded(displayName, fullDisplayName, kind, kindModifiers, fileToRename, expectedRange, options);
509513
}
@@ -745,7 +749,7 @@ namespace FourSlashInterface {
745749
}
746750

747751
interface Classification {
748-
classificationType: ts.ClassificationTypeNames | number;
752+
classificationType: ts.ClassificationTypeNames | string;
749753
text?: string;
750754
textSpan?: FourSlash.TextSpan;
751755
}
@@ -754,61 +758,8 @@ namespace FourSlashInterface {
754758
export function classification(format: ts.SemanticClassificationFormat) {
755759

756760
function semanticToken(identifier: string, text: string, _position: number): Classification {
757-
758-
const tokenTypes = {
759-
class: ts.classifier.vscode.TokenType.class,
760-
enum: ts.classifier.vscode.TokenType.enum,
761-
interface: ts.classifier.vscode.TokenType.interface,
762-
namespace: ts.classifier.vscode.TokenType.namespace,
763-
typeParameter: ts.classifier.vscode.TokenType.typeParameter,
764-
type: ts.classifier.vscode.TokenType.type,
765-
parameter: ts.classifier.vscode.TokenType.parameter,
766-
variable: ts.classifier.vscode.TokenType.variable,
767-
enumMember: ts.classifier.vscode.TokenType.enumMember,
768-
property: ts.classifier.vscode.TokenType.property,
769-
function: ts.classifier.vscode.TokenType.function,
770-
member: ts.classifier.vscode.TokenType.member
771-
};
772-
773-
const tokenModifiers = {
774-
async: ts.classifier.vscode.TokenModifier.async,
775-
declaration: ts.classifier.vscode.TokenModifier.declaration,
776-
readonly: ts.classifier.vscode.TokenModifier.readonly,
777-
static: ts.classifier.vscode.TokenModifier.static,
778-
local: ts.classifier.vscode.TokenModifier.local,
779-
defaultLibrary: ts.classifier.vscode.TokenModifier.defaultLibrary,
780-
};
781-
782-
function identifierToClassificationID(identifier: string): number {
783-
const [tokenType, ...modifiers] = identifier.split(".");
784-
// @ts-expect-error
785-
const tokenValue = tokenTypes[tokenType];
786-
if (tokenValue === undefined) {
787-
throw new Error(`Did not find ${tokenType} in tokenTypes for classifiers.`);
788-
}
789-
790-
let classification = (tokenValue + 1) << 8;
791-
ts.forEach(modifiers, (modifier) => {
792-
// @ts-expect-error
793-
const modifierValue = tokenModifiers[modifiers];
794-
if (tokenValue === undefined) {
795-
throw new Error(`Did not find ${modifier} in tokenModifiers for classifiers.`);
796-
}
797-
classification += modifierValue + 1;
798-
console.log("adding: ", modifierValue);
799-
});
800-
801-
// debugger;
802-
803-
return classification;
804-
}
805-
806761
return {
807-
classificationType: identifierToClassificationID(identifier),
808-
// textSpan: {
809-
// start: position,
810-
// end: -1
811-
// },
762+
classificationType: identifier,
812763
text
813764
};
814765
}

Diff for: src/services/classifierVscode.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
namespace ts.classifier.vscode {
22

3+
/** @internal */
4+
export enum TokenEncodingConsts {
5+
typeOffset = 8,
6+
modifierMask = (1 << typeOffset) - 1
7+
}
8+
39
/** @internal */
410
export enum TokenType {
511
class, enum, interface, namespace, typeParameter, type, parameter, variable, enumMember, property, function, member, _
@@ -10,12 +16,6 @@ namespace ts.classifier.vscode {
1016
declaration, static, async, readonly, defaultLibrary, local, _
1117
}
1218

13-
/** @internal */
14-
export enum TokenEncodingConsts {
15-
typeOffset = 8,
16-
modifierMask = (1 << typeOffset) - 1
17-
}
18-
1919
/** This is mainly used internally for testing */
2020
export function getSemanticClassifications(program: Program, _cancellationToken: CancellationToken, sourceFile: SourceFile, span: TextSpan): ClassifiedSpan[] {
2121
const classifications = getEncodedSemanticClassifications(program, _cancellationToken, sourceFile, span);

Diff for: src/services/services.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -1787,11 +1787,11 @@ namespace ts {
17871787
}
17881788
synchronizeHostData();
17891789

1790-
const responseFormat = format || "original";
1791-
if (responseFormat === "original") {
1790+
const responseFormat = format || SemanticClassificationFormat.Original;
1791+
if (responseFormat === SemanticClassificationFormat.Original) {
17921792
return ts.getSemanticClassifications(program.getTypeChecker(), cancellationToken, getValidSourceFile(fileName), program.getClassifiableNames(), span);
17931793
}
1794-
else {
1794+
else {
17951795
return classifier.vscode.getSemanticClassifications(program, cancellationToken, getValidSourceFile(fileName), span);
17961796
}
17971797
}
@@ -1803,11 +1803,11 @@ namespace ts {
18031803
}
18041804
synchronizeHostData();
18051805

1806-
const responseFormat = format || "original";
1807-
if (responseFormat === "original") {
1806+
const responseFormat = format || SemanticClassificationFormat.Original;
1807+
if (responseFormat === SemanticClassificationFormat.Original) {
18081808
return ts.getEncodedSemanticClassifications(program.getTypeChecker(), cancellationToken, getValidSourceFile(fileName), program.getClassifiableNames(), span);
18091809
}
1810-
else {
1810+
else {
18111811
return classifier.vscode.getEncodedSemanticClassifications(program, cancellationToken, getValidSourceFile(fileName), span);
18121812
}
18131813
}

Diff for: tests/cases/fourslash/classifyThisParameter.ts

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

33
////function f(this){}
44

5-
var c = classification;
5+
const c = classification("original");
66
verify.syntacticClassificationsAre(
77
c.keyword("function"),
88
c.identifier("f"),

Diff for: tests/cases/fourslash/fourslash.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,8 @@ declare namespace FourSlashInterface {
357357
text?: string;
358358
textSpan?: TextSpan;
359359
}[]): void;
360+
/** Edits the current testfile and replaces with the semantic classifications */
361+
replaceWithSemanticClassifications(format: "2020")
360362
renameInfoSucceeded(displayName?: string, fullDisplayName?: string, kind?: string, kindModifiers?: string, fileToRename?: string, range?: Range, allowRenameOfImportPath?: boolean): void;
361363
renameInfoFailed(message?: string, allowRenameOfImportPath?: boolean): void;
362364
renameLocations(startRanges: ArrayOrSingle<Range>, options: RenameLocationsOptions): void;
@@ -455,7 +457,7 @@ declare namespace FourSlashInterface {
455457
}
456458

457459
interface ModernClassificationFactory {
458-
semanticToken(identifier: string, name: string, position: number)
460+
semanticToken(identifier: string, name: string)
459461
}
460462

461463
interface ClassificationFactory {

Diff for: tests/cases/fourslash/incrementalJsDocAdjustsLengthsRight.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
//// * @param {Number} wid/*1*/
1010
goTo.marker('1');
1111
edit.insert("th\n@");
12-
const c = classification;
12+
const c = classification("original");
1313
verify.syntacticClassificationsAre(
1414
c.comment("/**\n * Pad `str` to `width`.\n *\n * "),
1515
c.punctuation("@"),

Diff for: tests/cases/fourslash/semanticClassification1.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
//// }
77
//// interface /*2*/X extends /*3*/M./*4*/I { }
88

9-
var c = classification("original");
9+
const c = classification("original");
1010
verify.semanticClassificationsAre("original",
1111
c.moduleName("M", test.marker("0").position),
1212
c.interfaceName("I", test.marker("1").position),
@@ -16,10 +16,10 @@ verify.semanticClassificationsAre("original",
1616

1717
var c2 = classification("2020")
1818
verify.semanticClassificationsAre("2020",
19-
c2.semanticToken("namespace.declaration", "M", test.marker("0").position),
20-
c2.semanticToken("interface.declaration", "I", test.marker("1").position),
21-
c2.semanticToken("interface.declaration", "X", test.marker("2").position),
22-
c2.semanticToken("namespace", "M", test.marker("3").position),
23-
c2.semanticToken("interface", "I", test.marker("4").position),
19+
c2.semanticToken("namespace.declaration", "M"),
20+
c2.semanticToken("interface.declaration", "I"),
21+
c2.semanticToken("interface.declaration", "X"),
22+
c2.semanticToken("namespace", "M"),
23+
c2.semanticToken("interface", "I"),
2424
)
2525

Diff for: tests/cases/fourslash/semanticClassification2.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,14 @@
77
//// var Thing = 0;
88
//// Thing.toExponential();
99

10-
var c = classification;
10+
const c = classification("original");
1111
verify.semanticClassificationsAre("original", c.interfaceName("Thing", test.marker("0").position));
12+
13+
const c2 = classification("2020");
14+
verify.semanticClassificationsAre("2020",
15+
c2.semanticToken("interface.declaration", "Thing"),
16+
c2.semanticToken("member.declaration", "toExponential"),
17+
c2.semanticToken("variable.declaration", "Thing"),
18+
c2.semanticToken("variable", "Thing"),
19+
c2.semanticToken("member.defaultLibrary", "toExponential")
20+
);

Diff for: tests/cases/fourslash/semanticClassificationAlias.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,18 @@
1111
goTo.file("/b.ts");
1212

1313
const [m0, m1, m2, m3] = test.markers();
14-
const c = classification;
14+
const c = classification("original");
1515
verify.semanticClassificationsAre("original",
1616
c.typeAliasName("x", m0.position),
1717
c.className("y", m1.position),
1818
c.typeAliasName("x", m2.position),
1919
c.className("y", m3.position),
2020
);
21+
22+
const c2 = classification("2020");
23+
verify.semanticClassificationsAre("2020",
24+
25+
c2.semanticToken("variable.declaration.readonly", "v"),
26+
c2.semanticToken("type", "x"),
27+
c2.semanticToken("class", "y"),
28+
);

Diff for: tests/cases/fourslash/semanticClassificationClassExpression.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,19 @@
33
//// var x = class /*0*/C {}
44
//// class /*1*/C {}
55
//// class /*2*/D extends class /*3*/B{} { }
6-
var c = classification;
6+
const c = classification("original");
77
verify.semanticClassificationsAre("original",
88
c.className("C", test.marker("0").position),
99
c.className("C", test.marker("1").position),
1010
c.className("D", test.marker("2").position),
1111
c.className("B", test.marker("3").position)
1212
);
13+
14+
const c2 = classification("2020");
15+
verify.semanticClassificationsAre("2020",
16+
c2.semanticToken("class.declaration", "x"),
17+
c2.semanticToken("class", "C"),
18+
c2.semanticToken("class.declaration", "C"),
19+
c2.semanticToken("class.declaration", "D"),
20+
c2.semanticToken("class", "B"),
21+
);

Diff for: tests/cases/fourslash/semanticClassificationInTemplateExpressions.ts

+16-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
////}
1111
////`abcd${ /*3*/M./*4*/C.x + /*5*/M./*6*/E.E1}efg`
1212

13-
var c = classification;
13+
const c = classification("original");
1414
verify.semanticClassificationsAre("original",
1515
c.moduleName("M", test.marker("0").position),
1616
c.className("C", test.marker("1").position),
@@ -19,3 +19,18 @@ verify.semanticClassificationsAre("original",
1919
c.className("C", test.marker("4").position),
2020
c.moduleName("M", test.marker("5").position),
2121
c.enumName("E", test.marker("6").position));
22+
23+
const c2 = classification("2020");
24+
verify.semanticClassificationsAre("2020",
25+
c2.semanticToken("namespace.declaration", "M"),
26+
c2.semanticToken("class.declaration", "C"),
27+
c2.semanticToken("property.declaration.static", "x"),
28+
c2.semanticToken("enum.declaration", "E"),
29+
c2.semanticToken("enumMember.declaration.readonly", "E1"),
30+
c2.semanticToken("namespace", "M"),
31+
c2.semanticToken("class", "C"),
32+
c2.semanticToken("property.static", "x"),
33+
c2.semanticToken("namespace", "M"),
34+
c2.semanticToken("enum", "E"),
35+
c2.semanticToken("enumMember.readonly", "E1"),
36+
);

0 commit comments

Comments
 (0)