Skip to content

Release 2017-08-09 #14

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Aug 9, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"tslint": "^5.5.0",
"tslint-config-airbnb": "^5.2.1",
"tsutils": "^2.7.1",
"typedoc": "^0.7.1"
"typedoc": "^0.8.0"
},
"dependencies": {
"lodash": "^4.17.4",
Expand Down
11 changes: 5 additions & 6 deletions src/DeclarationIndex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { Namespace } from './resources/Namespace';
import { Resource } from './resources/Resource';
import { isExportableDeclaration } from './type-guards/TypescriptHeroGuards';
import { TypescriptParser } from './TypescriptParser';
import { normalizePathUri } from './utilities/PathHelpers';
import { normalizeFilename, normalizePathUri } from './utilities/PathHelpers';

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

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

Expand Down Expand Up @@ -222,7 +221,7 @@ export class DeclarationIndex {

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

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

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

if (rebuildResources.indexOf(resource) < 0) {
rebuildResources.push(resource);
Expand Down Expand Up @@ -427,7 +426,7 @@ export class DeclarationIndex {
if (sourceLib.indexOf('node_modules') > -1) {
sourceLib = getNodeLibraryName(sourceLib);
} else {
sourceLib = '/' + relative(this.rootPath, sourceLib).replace(/([.]d)?[.]tsx?/g, '');
sourceLib = '/' + normalizeFilename(relative(this.rootPath, sourceLib));
}

if (!parsedResources[sourceLib]) {
Expand Down
2 changes: 1 addition & 1 deletion src/TypescriptParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export class TypescriptParser {
* @memberof TsResourceParser
*/
public async parseSource(source: string): Promise<File> {
return await this.parseTypescript(createSourceFile('inline.ts', source, ScriptTarget.ES2015, true), '/');
return await this.parseTypescript(createSourceFile('inline.tsx', source, ScriptTarget.ES2015, true), '/');
}

/**
Expand Down
7 changes: 6 additions & 1 deletion src/code-generators/typescript-generators/namedImport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,13 @@ export function generateNamedImport(
const space = spaceBraces ? ' ' : '';
const specifiers = imp.specifiers.sort(specifierSort).map(o => generateSymbolSpecifier(o)).join(', ');
const lib = imp.libraryName;

let importSpecifiers = `${space}${specifiers}${space}`;
if (importSpecifiers.trim().length === 0) {
importSpecifiers = ' ';
}

const importString = `import {${space}${specifiers}${space}} from ${stringQuoteStyle}${lib}${stringQuoteStyle}${eol}`;
const importString = `import {${importSpecifiers}} from ${stringQuoteStyle}${lib}${stringQuoteStyle}${eol}`;
if (importString.length > multiLineWrapThreshold) {
const spacings = Array(tabSize + 1).join(' ');
return multiLineImport(
Expand Down
9 changes: 5 additions & 4 deletions src/resources/File.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Declaration } from '../declarations/Declaration';
import { Export } from '../exports/Export';
import { Import } from '../imports/Import';
import { Node } from '../Node';
import { normalizeFilename } from '../utilities/PathHelpers';
import { Module } from './Module';
import { Namespace } from './Namespace';
import { Resource } from './Resource';
Expand All @@ -24,7 +25,7 @@ export class File implements Resource, Node {
public usages: string[] = [];

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

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

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

constructor(public filePath: string, private rootPath: string, public start: number, public end: number) {}
constructor(public filePath: string, private rootPath: string, public start: number, public end: number) { }
}
12 changes: 12 additions & 0 deletions src/utilities/PathHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,15 @@ export function normalizePathUri(uri: string): string {
}
return decoded.replace('file://', '');
}

/**
* Returns an adjusted and normalized filepath to use within the index.
* Essentially does remove `.tsx` `.ts` `.js` `.jsx` endings and other adjustments.
*
* @export
* @param {string} filepath
* @returns {string}
*/
export function normalizeFilename(filepath: string): string {
return filepath.replace(/([.]d)?[.](t|j)sx?$/g, '');
}
160 changes: 160 additions & 0 deletions test/TypescriptParser.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { readFileSync } from 'fs';

import { ClassDeclaration } from '../src/declarations/ClassDeclaration';
import { DeclarationVisibility } from '../src/declarations/DeclarationVisibility';
import { DefaultDeclaration } from '../src/declarations/DefaultDeclaration';
Expand Down Expand Up @@ -560,6 +562,164 @@ describe('TypescriptParser', () => {
expect(usages).toContain('complexComp');
expect(usages).toContain('SingleComp');
});

it('should parse functions inside {}', () => {
const usages = parsed.usages;

expect(usages).toContain('myFunc');
});

it('should parse component functions inside {}', () => {
const usages = parsed.usages;

expect(usages).toContain('MyFunc');
});

it('should parse a component inside a map', () => {
const usages = parsed.usages;

expect(usages).toContain('AnotherComp');
expect(usages).toContain('foobarVariable');
});

it('should parse a function inside a map', () => {
const usages = parsed.usages;

expect(usages).toContain('valFunc');
});

it('should parseSource correctly', async () => {
const parsedSource = await parser.parseSource(readFileSync(file).toString());

expect(parsedSource.usages).toMatchSnapshot();
});
});

describe('TSX: Specific cases', () => {

const testFiles = [
{
filename: '1.tsx',
requiredUsages: [
'sortBy',
'Divider',
'Checkbox',
],
},
{
filename: '2.tsx',
requiredUsages: [
'ActionDelete',
'Divider',
'cloneDeep',
],
},
{
filename: '3.tsx',
requiredUsages: [
'ImageEdit',
'IconButton',
'TableHeaderColumn',
],
},
];

for (const testFile of testFiles) {

it('should parse the correct usages with "parseFile"', async () => {
const file = getWorkspaceFile(`typescript-parser/specific-cases/${testFile.filename}`);
const parsed = await parser.parseFile(file, rootPath);

for (const usage of testFile.requiredUsages) {
expect(parsed.usages).toContain(usage);
}

expect(parsed.usages).toMatchSnapshot();
});

it('should parse the correct usages with "parseFiles"', async () => {
const file = getWorkspaceFile(`typescript-parser/specific-cases/${testFile.filename}`);
const parsed = (await parser.parseFiles([file], rootPath))[0];

for (const usage of testFile.requiredUsages) {
expect(parsed.usages).toContain(usage);
}

expect(parsed.usages).toMatchSnapshot();
});

it('should parse the correct usages with "parseSource"', async () => {
const file = getWorkspaceFile(`typescript-parser/specific-cases/${testFile.filename}`);
const fileSource = readFileSync(file).toString();
const parsed = await parser.parseSource(fileSource);

for (const usage of testFile.requiredUsages) {
expect(parsed.usages).toContain(usage);
}

expect(parsed.usages).toMatchSnapshot();
});

}

});

describe('JavaScript parsing', () => {

const file = getWorkspaceFile('typescript-parser/javascript.js');

it('should parse a simple javascript file correctly with "parseFile"', async () => {
const parsed = await parser.parseFile(file, rootPath);
delete parsed.filePath;
delete (parsed as any).rootPath;

expect(parsed).toMatchSnapshot();
});

it('should parse a simple javascript file correctly with "parseFiles"', async () => {
const parsed = await parser.parseFiles([file], rootPath);
delete parsed[0].filePath;
delete (parsed[0] as any).rootPath;

expect(parsed).toMatchSnapshot();
});

it('should parse a simple javascript file correctly with "parseSource"', async () => {
const content = readFileSync(file).toString();
const parsed = await parser.parseSource(content);

expect(parsed).toMatchSnapshot();
});

});

describe('JSX parsing', () => {

const file = getWorkspaceFile('typescript-parser/jsx.jsx');

it('should parse a simple javascript react file correctly with "parseFile"', async () => {
const parsed = await parser.parseFile(file, rootPath);
delete parsed.filePath;
delete (parsed as any).rootPath;

expect(parsed).toMatchSnapshot();
});

it('should parse a simple javascript react file correctly with "parseFiles"', async () => {
const parsed = await parser.parseFiles([file], rootPath);
delete parsed[0].filePath;
delete (parsed[0] as any).rootPath;

expect(parsed).toMatchSnapshot();
});

it('should parse a simple javascript react file correctly with "parseSource"', async () => {
const content = readFileSync(file).toString();
const parsed = await parser.parseSource(content);

expect(parsed).toMatchSnapshot();
});

});

});
Loading