Skip to content

Commit eea9b47

Browse files
authored
Merge pull request #14 from TypeScript-Heroes/develop
Release 2017-08-09
2 parents 5a528a0 + 694f29e commit eea9b47

File tree

17 files changed

+2832
-14
lines changed

17 files changed

+2832
-14
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
"tslint": "^5.5.0",
4343
"tslint-config-airbnb": "^5.2.1",
4444
"tsutils": "^2.7.1",
45-
"typedoc": "^0.7.1"
45+
"typedoc": "^0.8.0"
4646
},
4747
"dependencies": {
4848
"lodash": "^4.17.4",

src/DeclarationIndex.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { Namespace } from './resources/Namespace';
1212
import { Resource } from './resources/Resource';
1313
import { isExportableDeclaration } from './type-guards/TypescriptHeroGuards';
1414
import { TypescriptParser } from './TypescriptParser';
15-
import { normalizePathUri } from './utilities/PathHelpers';
15+
import { normalizeFilename, normalizePathUri } from './utilities/PathHelpers';
1616

1717
/**
1818
* Returns the name of the node folder. Is used as the library name for indexing.
@@ -25,8 +25,7 @@ function getNodeLibraryName(path: string): string {
2525
const dirs = path.split(/\/|\\/);
2626
const nodeIndex = dirs.indexOf('node_modules');
2727

28-
return dirs.slice(nodeIndex + 1).join('/')
29-
.replace(/([.]d)?([.]tsx?)?/g, '')
28+
return normalizeFilename(dirs.slice(nodeIndex + 1).join('/'))
3029
.replace(new RegExp(`/(index|${dirs[nodeIndex + 1]}|${dirs[dirs.length - 2]})$`), '');
3130
}
3231

@@ -222,7 +221,7 @@ export class DeclarationIndex {
222221

223222
for (const change of changes.deleted) {
224223
const filePath = normalizePathUri(change);
225-
const resource = '/' + relative(this.rootPath, filePath).replace(/[.]tsx?/g, '');
224+
const resource = '/' + normalizeFilename(relative(this.rootPath, filePath));
226225

227226
if (removeResources.indexOf(resource) < 0) {
228227
removeResources.push(resource);
@@ -237,7 +236,7 @@ export class DeclarationIndex {
237236

238237
for (const change of (changes.created || []).concat(changes.updated)) {
239238
const filePath = normalizePathUri(change);
240-
const resource = '/' + relative(this.rootPath, filePath).replace(/[.]tsx?/g, '');
239+
const resource = '/' + normalizeFilename(relative(this.rootPath, filePath));
241240

242241
if (rebuildResources.indexOf(resource) < 0) {
243242
rebuildResources.push(resource);
@@ -427,7 +426,7 @@ export class DeclarationIndex {
427426
if (sourceLib.indexOf('node_modules') > -1) {
428427
sourceLib = getNodeLibraryName(sourceLib);
429428
} else {
430-
sourceLib = '/' + relative(this.rootPath, sourceLib).replace(/([.]d)?[.]tsx?/g, '');
429+
sourceLib = '/' + normalizeFilename(relative(this.rootPath, sourceLib));
431430
}
432431

433432
if (!parsedResources[sourceLib]) {

src/TypescriptParser.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ export class TypescriptParser {
5252
* @memberof TsResourceParser
5353
*/
5454
public async parseSource(source: string): Promise<File> {
55-
return await this.parseTypescript(createSourceFile('inline.ts', source, ScriptTarget.ES2015, true), '/');
55+
return await this.parseTypescript(createSourceFile('inline.tsx', source, ScriptTarget.ES2015, true), '/');
5656
}
5757

5858
/**

src/code-generators/typescript-generators/namedImport.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,13 @@ export function generateNamedImport(
4949
const space = spaceBraces ? ' ' : '';
5050
const specifiers = imp.specifiers.sort(specifierSort).map(o => generateSymbolSpecifier(o)).join(', ');
5151
const lib = imp.libraryName;
52+
53+
let importSpecifiers = `${space}${specifiers}${space}`;
54+
if (importSpecifiers.trim().length === 0) {
55+
importSpecifiers = ' ';
56+
}
5257

53-
const importString = `import {${space}${specifiers}${space}} from ${stringQuoteStyle}${lib}${stringQuoteStyle}${eol}`;
58+
const importString = `import {${importSpecifiers}} from ${stringQuoteStyle}${lib}${stringQuoteStyle}${eol}`;
5459
if (importString.length > multiLineWrapThreshold) {
5560
const spacings = Array(tabSize + 1).join(' ');
5661
return multiLineImport(

src/resources/File.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Declaration } from '../declarations/Declaration';
44
import { Export } from '../exports/Export';
55
import { Import } from '../imports/Import';
66
import { Node } from '../Node';
7+
import { normalizeFilename } from '../utilities/PathHelpers';
78
import { Module } from './Module';
89
import { Namespace } from './Namespace';
910
import { Resource } from './Resource';
@@ -24,7 +25,7 @@ export class File implements Resource, Node {
2425
public usages: string[] = [];
2526

2627
public get identifier(): string {
27-
return '/' + relative(this.rootPath, this.filePath).replace(/([.]d)?[.]tsx?/g, '');
28+
return '/' + normalizeFilename(relative(this.rootPath, this.filePath));
2829
}
2930

3031
public get nonLocalUsages(): string[] {
@@ -33,8 +34,8 @@ export class File implements Resource, Node {
3334
!this.declarations.some(o => o.name === usage) &&
3435
!this.resources.some(o => (o instanceof Module || o instanceof Namespace) && o.name === usage))
3536
.concat(
36-
this.resources.reduce((all, cur) => all.concat(cur.nonLocalUsages), [] as string[]),
37-
);
37+
this.resources.reduce((all, cur) => all.concat(cur.nonLocalUsages), [] as string[]),
38+
);
3839
}
3940

4041
/**
@@ -59,5 +60,5 @@ export class File implements Resource, Node {
5960
return ['node_modules', 'typings'].every(o => this.filePath.indexOf(o) === -1);
6061
}
6162

62-
constructor(public filePath: string, private rootPath: string, public start: number, public end: number) {}
63+
constructor(public filePath: string, private rootPath: string, public start: number, public end: number) { }
6364
}

src/utilities/PathHelpers.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,15 @@ export function normalizePathUri(uri: string): string {
1515
}
1616
return decoded.replace('file://', '');
1717
}
18+
19+
/**
20+
* Returns an adjusted and normalized filepath to use within the index.
21+
* Essentially does remove `.tsx` `.ts` `.js` `.jsx` endings and other adjustments.
22+
*
23+
* @export
24+
* @param {string} filepath
25+
* @returns {string}
26+
*/
27+
export function normalizeFilename(filepath: string): string {
28+
return filepath.replace(/([.]d)?[.](t|j)sx?$/g, '');
29+
}

test/TypescriptParser.spec.ts

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { readFileSync } from 'fs';
2+
13
import { ClassDeclaration } from '../src/declarations/ClassDeclaration';
24
import { DeclarationVisibility } from '../src/declarations/DeclarationVisibility';
35
import { DefaultDeclaration } from '../src/declarations/DefaultDeclaration';
@@ -560,6 +562,164 @@ describe('TypescriptParser', () => {
560562
expect(usages).toContain('complexComp');
561563
expect(usages).toContain('SingleComp');
562564
});
565+
566+
it('should parse functions inside {}', () => {
567+
const usages = parsed.usages;
568+
569+
expect(usages).toContain('myFunc');
570+
});
571+
572+
it('should parse component functions inside {}', () => {
573+
const usages = parsed.usages;
574+
575+
expect(usages).toContain('MyFunc');
576+
});
577+
578+
it('should parse a component inside a map', () => {
579+
const usages = parsed.usages;
580+
581+
expect(usages).toContain('AnotherComp');
582+
expect(usages).toContain('foobarVariable');
583+
});
584+
585+
it('should parse a function inside a map', () => {
586+
const usages = parsed.usages;
587+
588+
expect(usages).toContain('valFunc');
589+
});
590+
591+
it('should parseSource correctly', async () => {
592+
const parsedSource = await parser.parseSource(readFileSync(file).toString());
593+
594+
expect(parsedSource.usages).toMatchSnapshot();
595+
});
596+
});
597+
598+
describe('TSX: Specific cases', () => {
599+
600+
const testFiles = [
601+
{
602+
filename: '1.tsx',
603+
requiredUsages: [
604+
'sortBy',
605+
'Divider',
606+
'Checkbox',
607+
],
608+
},
609+
{
610+
filename: '2.tsx',
611+
requiredUsages: [
612+
'ActionDelete',
613+
'Divider',
614+
'cloneDeep',
615+
],
616+
},
617+
{
618+
filename: '3.tsx',
619+
requiredUsages: [
620+
'ImageEdit',
621+
'IconButton',
622+
'TableHeaderColumn',
623+
],
624+
},
625+
];
626+
627+
for (const testFile of testFiles) {
628+
629+
it('should parse the correct usages with "parseFile"', async () => {
630+
const file = getWorkspaceFile(`typescript-parser/specific-cases/${testFile.filename}`);
631+
const parsed = await parser.parseFile(file, rootPath);
632+
633+
for (const usage of testFile.requiredUsages) {
634+
expect(parsed.usages).toContain(usage);
635+
}
636+
637+
expect(parsed.usages).toMatchSnapshot();
638+
});
639+
640+
it('should parse the correct usages with "parseFiles"', async () => {
641+
const file = getWorkspaceFile(`typescript-parser/specific-cases/${testFile.filename}`);
642+
const parsed = (await parser.parseFiles([file], rootPath))[0];
643+
644+
for (const usage of testFile.requiredUsages) {
645+
expect(parsed.usages).toContain(usage);
646+
}
647+
648+
expect(parsed.usages).toMatchSnapshot();
649+
});
650+
651+
it('should parse the correct usages with "parseSource"', async () => {
652+
const file = getWorkspaceFile(`typescript-parser/specific-cases/${testFile.filename}`);
653+
const fileSource = readFileSync(file).toString();
654+
const parsed = await parser.parseSource(fileSource);
655+
656+
for (const usage of testFile.requiredUsages) {
657+
expect(parsed.usages).toContain(usage);
658+
}
659+
660+
expect(parsed.usages).toMatchSnapshot();
661+
});
662+
663+
}
664+
665+
});
666+
667+
describe('JavaScript parsing', () => {
668+
669+
const file = getWorkspaceFile('typescript-parser/javascript.js');
670+
671+
it('should parse a simple javascript file correctly with "parseFile"', async () => {
672+
const parsed = await parser.parseFile(file, rootPath);
673+
delete parsed.filePath;
674+
delete (parsed as any).rootPath;
675+
676+
expect(parsed).toMatchSnapshot();
677+
});
678+
679+
it('should parse a simple javascript file correctly with "parseFiles"', async () => {
680+
const parsed = await parser.parseFiles([file], rootPath);
681+
delete parsed[0].filePath;
682+
delete (parsed[0] as any).rootPath;
683+
684+
expect(parsed).toMatchSnapshot();
685+
});
686+
687+
it('should parse a simple javascript file correctly with "parseSource"', async () => {
688+
const content = readFileSync(file).toString();
689+
const parsed = await parser.parseSource(content);
690+
691+
expect(parsed).toMatchSnapshot();
692+
});
693+
694+
});
695+
696+
describe('JSX parsing', () => {
697+
698+
const file = getWorkspaceFile('typescript-parser/jsx.jsx');
699+
700+
it('should parse a simple javascript react file correctly with "parseFile"', async () => {
701+
const parsed = await parser.parseFile(file, rootPath);
702+
delete parsed.filePath;
703+
delete (parsed as any).rootPath;
704+
705+
expect(parsed).toMatchSnapshot();
706+
});
707+
708+
it('should parse a simple javascript react file correctly with "parseFiles"', async () => {
709+
const parsed = await parser.parseFiles([file], rootPath);
710+
delete parsed[0].filePath;
711+
delete (parsed[0] as any).rootPath;
712+
713+
expect(parsed).toMatchSnapshot();
714+
});
715+
716+
it('should parse a simple javascript react file correctly with "parseSource"', async () => {
717+
const content = readFileSync(file).toString();
718+
const parsed = await parser.parseSource(content);
719+
720+
expect(parsed).toMatchSnapshot();
721+
});
722+
563723
});
564724

565725
});

0 commit comments

Comments
 (0)