Skip to content

Commit 520fd5e

Browse files
shobhitgbuehler
authored andcommitted
feat: Specify scriptkind for files to correctly parse usages
1 parent c09791a commit 520fd5e

File tree

3 files changed

+66
-25
lines changed

3 files changed

+66
-25
lines changed

src/TypescriptParser.ts

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@ import {
1212
InterfaceDeclaration,
1313
ModuleDeclaration,
1414
Node,
15+
ScriptKind,
1516
ScriptTarget,
1617
SourceFile,
1718
SyntaxKind,
1819
TypeAliasDeclaration,
1920
VariableStatement,
2021
} from 'typescript';
2122

23+
import { parse } from 'path';
2224
import { parseClass } from './node-parser/class-parser';
2325
import { parseEnum } from './node-parser/enum-parser';
2426
import { parseExport } from './node-parser/export-parser';
@@ -37,31 +39,39 @@ import { Resource } from './resources/Resource';
3739
* This class is the parser of the whole extension. It uses the typescript compiler to parse a file or given
3840
* source code into the token stream and therefore into the AST of the source. Afterwards an array of
3941
* resources is generated and returned.
40-
*
42+
*
4143
* @export
4244
* @class TypescriptParser
4345
*/
4446
export class TypescriptParser {
4547
/**
4648
* Parses the given source into an anonymous File resource.
4749
* Mainly used to parse source code of a document.
48-
*
50+
*
4951
* @param {string} source
52+
* @param {ScriptKind} [scriptKind=ScriptKind.TS]
5053
* @returns {Promise<File>}
51-
*
54+
*
5255
* @memberof TsResourceParser
5356
*/
54-
public async parseSource(source: string): Promise<File> {
55-
return await this.parseTypescript(createSourceFile('inline.tsx', source, ScriptTarget.ES2015, true), '/');
57+
public async parseSource(source: string, scriptKind: ScriptKind = ScriptKind.TS): Promise<File> {
58+
return await this.parseTypescript(
59+
createSourceFile(
60+
'inline.tsx',
61+
source,
62+
ScriptTarget.ES2015,
63+
true,
64+
scriptKind),
65+
'/');
5666
}
5767

5868
/**
5969
* Parses a single file into a parsed file.
60-
*
70+
*
6171
* @param {string} filePath
6272
* @param {string} rootPath
6373
* @returns {Promise<File>}
64-
*
74+
*
6575
* @memberof TsResourceParser
6676
*/
6777
public async parseFile(filePath: string, rootPath: string): Promise<File> {
@@ -71,28 +81,52 @@ export class TypescriptParser {
7181

7282
/**
7383
* Parses multiple files into parsed files.
74-
*
84+
*
7585
* @param {string[]} filePathes
7686
* @param {string} rootPath
7787
* @returns {Promise<File[]>}
78-
*
88+
*
7989
* @memberof TsResourceParser
8090
*/
81-
public async parseFiles(filePathes: string[], rootPath: string): Promise<File[]> {
91+
public async parseFiles(
92+
filePathes: string[],
93+
rootPath: string): Promise<File[]> {
8294
return filePathes
83-
.map(o => createSourceFile(o, readFileSync(o).toString(), ScriptTarget.ES2015, true))
95+
.map((o) => {
96+
let scriptKind: ScriptKind = ScriptKind.Unknown;
97+
const parsed = parse(o);
98+
switch (parsed.ext.toLowerCase()) {
99+
case 'js':
100+
scriptKind = ScriptKind.JS;
101+
break;
102+
case 'jsx':
103+
scriptKind = ScriptKind.JSX;
104+
break;
105+
case 'ts':
106+
scriptKind = ScriptKind.TS;
107+
break;
108+
case 'tsx':
109+
scriptKind = ScriptKind.TSX;
110+
break;
111+
}
112+
return createSourceFile(o,
113+
readFileSync(o).toString(),
114+
ScriptTarget.ES2015,
115+
true,
116+
scriptKind);
117+
})
84118
.map(o => this.parseTypescript(o, rootPath));
85119
}
86120

87121
/**
88122
* Parses the typescript source into the file instance. Calls .parse afterwards to
89123
* get the declarations and other information about the source.
90-
*
124+
*
91125
* @private
92126
* @param {SourceFile} source
93127
* @param {string} rootPath
94128
* @returns {TsFile}
95-
*
129+
*
96130
* @memberof TsResourceParser
97131
*/
98132
private parseTypescript(source: SourceFile, rootPath: string): File {
@@ -108,11 +142,11 @@ export class TypescriptParser {
108142
* Recursive function that runs through the AST of a source and parses the nodes.
109143
* Creates the class / function / etc declarations and instanciates a new module / namespace
110144
* resource if needed.
111-
*
145+
*
112146
* @private
113147
* @param {Resource} resource
114148
* @param {Node} node
115-
*
149+
*
116150
* @memberof TsResourceParser
117151
*/
118152
private parse(resource: Resource, node: Node): void {

test/TypescriptParser.spec.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { readFileSync } from 'fs';
2+
import { ScriptKind } from 'typescript';
23

34
import { ClassDeclaration } from '../src/declarations/ClassDeclaration';
45
import { DeclarationVisibility } from '../src/declarations/DeclarationVisibility';
@@ -617,7 +618,7 @@ describe('TypescriptParser', () => {
617618
});
618619

619620
it('should parseSource correctly', async () => {
620-
const parsedSource = await parser.parseSource(readFileSync(file).toString());
621+
const parsedSource = await parser.parseSource(readFileSync(file).toString(), ScriptKind.TSX);
621622

622623
expect(parsedSource.usages).toMatchSnapshot();
623624
});
@@ -679,7 +680,7 @@ describe('TypescriptParser', () => {
679680
it('should parse the correct usages with "parseSource"', async () => {
680681
const file = getWorkspaceFile(`typescript-parser/specific-cases/${testFile.filename}`);
681682
const fileSource = readFileSync(file).toString();
682-
const parsed = await parser.parseSource(fileSource);
683+
const parsed = await parser.parseSource(fileSource, ScriptKind.TSX);
683684

684685
for (const usage of testFile.requiredUsages) {
685686
expect(parsed.usages).toContain(usage);
@@ -714,7 +715,7 @@ describe('TypescriptParser', () => {
714715

715716
it('should parse a simple javascript file correctly with "parseSource"', async () => {
716717
const content = readFileSync(file).toString();
717-
const parsed = await parser.parseSource(content);
718+
const parsed = await parser.parseSource(content, ScriptKind.JS);
718719

719720
expect(parsed).toMatchSnapshot();
720721
});
@@ -743,7 +744,7 @@ describe('TypescriptParser', () => {
743744

744745
it('should parse a simple javascript react file correctly with "parseSource"', async () => {
745746
const content = readFileSync(file).toString();
746-
const parsed = await parser.parseSource(content);
747+
const parsed = await parser.parseSource(content, ScriptKind.JSX);
747748

748749
expect(parsed).toMatchSnapshot();
749750
});
@@ -757,7 +758,7 @@ describe('TypescriptParser', () => {
757758
public test() {
758759
let a = <T>() => { let b = null; };
759760
}
760-
}`);
761+
}`, ScriptKind.TS);
761762
expect(parsed).toMatchSnapshot();
762763
});
763764

test/__snapshots__/TypescriptParser.spec.ts.snap

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1492,21 +1492,29 @@ File {
14921492
"isExported": true,
14931493
"methods": Array [
14941494
MethodDeclaration {
1495-
"end": 144,
1495+
"end": 130,
14961496
"isAbstract": false,
14971497
"name": "test",
14981498
"parameters": Array [],
14991499
"start": 41,
15001500
"type": undefined,
15011501
"variables": Array [
15021502
VariableDeclaration {
1503-
"end": 144,
1503+
"end": 112,
15041504
"isConst": false,
15051505
"isExported": false,
15061506
"name": "a",
15071507
"start": 77,
15081508
"type": undefined,
15091509
},
1510+
VariableDeclaration {
1511+
"end": 109,
1512+
"isConst": false,
1513+
"isExported": false,
1514+
"name": "b",
1515+
"start": 96,
1516+
"type": undefined,
1517+
},
15101518
],
15111519
"visibility": 2,
15121520
},
@@ -1526,9 +1534,7 @@ File {
15261534
"usages": Array [
15271535
"a",
15281536
"T",
1529-
"let",
1530-
undefined,
1531-
"",
1537+
"b",
15321538
],
15331539
}
15341540
`;

0 commit comments

Comments
 (0)