Skip to content

Commit

Permalink
Add test from TypeStrong#1103
Browse files Browse the repository at this point in the history
Also:
- clean up scripts/rebuild_specs.js, making it easier to use for debugging a single test.
- move log message about TS version to the CLI
- Use rimraf instead of rm for Windows compatibility when developing
- Fix bugs with object literals causing a crash, rebuild tests.
  • Loading branch information
Gerrit0 committed Nov 3, 2019
1 parent c94942d commit db47e79
Show file tree
Hide file tree
Showing 34 changed files with 1,632 additions and 1,033 deletions.
764 changes: 179 additions & 585 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Expand Up @@ -65,15 +65,15 @@
],
"scripts": {
"pretest": "node scripts/copy_test_files.js",
"test": "nyc --reporter=html --reporter=text-summary mocha --timeout=10000 dist/test/*.test.js",
"test": "nyc --reporter=html --reporter=text-summary mocha --prof --timeout=10000 dist/test/*.test.js",
"test:ts": "mocha --require ts-node/register --watch-extensions ts --timeout=10000 src/test/*.test.ts",
"build": "tsc --project .",
"postbuild": "node scripts/replace_application_version.js",
"build_and_test": "npm run build && npm run test",
"lint": "tslint --project .",
"prepublishOnly": "npm run lint && npm run build_and_test",
"prepare": "npm run build",
"clean": "rm -rf node_modules package-lock.json lib coverage"
"clean": "rimraf node_modules package-lock.json lib coverage"
},
"keywords": [
"typescript",
Expand Down
153 changes: 85 additions & 68 deletions scripts/rebuild_specs.js
Expand Up @@ -31,80 +31,97 @@ const conversions = [
() => app.options.setValue('categorizeByGroup', false),
() => app.options.setValue('categorizeByGroup', true)
],
]
];

fs.remove(path.join(__dirname, '../src/test/renderer/specs'))
.then(() => fs.readdir(base))
.then(dirs => {
// Get converter directories
return Promise.all(dirs.map(dir => {
const dirPath = path.join(base, dir);
return Promise.all([dirPath, fs.stat(dirPath)]);
/**
* Rebuilds the converter specs for the provided dirs.
* @param {string[]} dirs
*/
function rebuildConverterTests(dirs) {
return Promise.all(dirs.map(fullPath => {
console.log(fullPath);
const src = app.expandInputFiles([fullPath]);
return Promise.all(conversions.map(([file, before, after]) => {
const out = path.join(fullPath, `${file}.json`);
if (fs.existsSync(out)) {
TypeDoc.resetReflectionID();
before();
const result = app.convert(src);
const data = JSON.stringify(result.toObject(), null, ' ')
.split(TypeDoc.normalizePath(base))
.join('%BASE%');
after();
return fs.writeFile(out, data);
}
}));
}).then(dirs => {
// Rebuild converter specs
return dirs.map(([fullPath, stat]) => {
if (!stat.isDirectory()) return;
}));
}

console.log(fullPath);
const src = app.expandInputFiles([fullPath]);
return Promise.all(conversions.map(([file, before, after]) => {
const out = path.join(fullPath, `${file}.json`);
if (fs.existsSync(out)) {
TypeDoc.resetReflectionID();
before();
const result = app.convert(src);
const data = JSON.stringify(result.toObject(), null, ' ')
.split(TypeDoc.normalizePath(base))
.join('%BASE%');
after();
return fs.writeFile(out, data);
}
}));
})
}).then(() => {
// Rebuild renderer example
const src = path.join(__dirname, '../examples/basic/src');
const out = path.join(__dirname, '../src/test/renderer/specs');
async function rebuildRendererTest() {
await fs.remove(path.join(__dirname, '../src/test/renderer/specs'));
const src = path.join(__dirname, '../examples/basic/src');
const out = path.join(__dirname, '../src/test/renderer/specs');

return fs.remove(out)
.then(() => app.generateDocs(app.expandInputFiles([src]), out))
.then(() => fs.remove(path.join(out, 'assets')))
.then(() => out);
}).then(out => {
// Rewrite GitHub urls
await fs.remove(out)
app.generateDocs(app.expandInputFiles([src]), out)
await fs.remove(path.join(out, 'assets'))

/**
* Avoiding sync methods here is... difficult.
* @param {string} base
* @param {string} dir
* @param {string[]} results
* @returns {string[]}
*/
function getFiles(base, dir = '', results = []) {
const files = fs.readdirSync(path.join(base, dir));
for (const file of files) {
const relativeToBase = path.join(dir, file);
if (fs.statSync(path.join(base, relativeToBase)).isDirectory()) {
getFiles(base, relativeToBase, results);
} else {
results.push(relativeToBase);
}
/**
* Avoiding sync methods here is... difficult.
* @param {string} base
* @param {string} dir
* @param {string[]} results
* @returns {string[]}
*/
function getFiles(base, dir = '', results = []) {
const files = fs.readdirSync(path.join(base, dir));
for (const file of files) {
const relativeToBase = path.join(dir, file);
if (fs.statSync(path.join(base, relativeToBase)).isDirectory()) {
getFiles(base, relativeToBase, results);
} else {
results.push(relativeToBase);
}
return results;
}
return results;
}

const gitHubRegExp = /https:\/\/github.com\/[A-Za-z0-9\-]+\/typedoc\/blob\/[^\/]*\/examples/g;
return getFiles(out).map(file => {
const full = path.join(out, file);
return fs.readFile(full, { encoding: 'utf-8' })
.then(text => fs.writeFile(
full,
text.replace(gitHubRegExp, 'https://github.com/sebastian-lenz/typedoc/blob/master/examples')
));
});
})
.catch(reason => {
console.error(reason);
process.exit(1);
const gitHubRegExp = /https:\/\/github.com\/[A-Za-z0-9\-]+\/typedoc\/blob\/[^\/]*\/examples/g;
return getFiles(out).map(file => {
const full = path.join(out, file);
return fs.readFile(full, { encoding: 'utf-8' })
.then(text => fs.writeFile(
full,
text.replace(gitHubRegExp, 'https://github.com/sebastian-lenz/typedoc/blob/master/examples')
));
});
}

async function main(command = 'all', filter = '') {
if (!['all', 'converter', 'renderer'].includes(command)) {
console.error('Invalid command. Usage: node scripts/rebuild_specs.js <all|converter|renderer> [filter]');
throw new Error();
}

if (['all', 'converter'].includes(command)) {
const dirs = await Promise.all((await fs.readdir(base)).map(dir => {
const dirPath = path.join(base, dir);
return Promise.all([dirPath, fs.stat(dirPath)]);
}));

await rebuildConverterTests(dirs.filter(([fullPath, stat]) => {
if (!stat.isDirectory()) return false;
return fullPath.endsWith(filter);
}).map(([path]) => path));
}

if (['all', 'renderer'].includes(command)) {
await fs.remove(path.join(__dirname, '../src/test/renderer/specs'));
await rebuildRendererTest();
}
}

main(process.argv[2], process.argv[3]).catch(reason => {
console.error(reason);
process.exit(1);
});
6 changes: 0 additions & 6 deletions src/lib/application.ts
Expand Up @@ -162,12 +162,6 @@ export class Application extends ChildableComponent<Application, AbstractCompone
* @returns An instance of ProjectReflection on success, undefined otherwise.
*/
public convert(src: string[]): ProjectReflection | undefined {
this.logger.writeln(
'Using TypeScript %s from %s',
this.getTypeScriptVersion(),
this.getTypeScriptPath()
);

const result = this.converter.convert(src);
if (result.errors && result.errors.length) {
this.logger.diagnostics(result.errors);
Expand Down
5 changes: 5 additions & 0 deletions src/lib/cli.ts
Expand Up @@ -62,6 +62,11 @@ export class CliApplication extends Application {
typescript.sys.write(getOptionsHelp(this.options));
process.exit(ExitCode.NoInputFiles);
} else {
this.logger.writeln(
'Using TypeScript %s from %s',
this.getTypeScriptVersion(),
this.getTypeScriptPath()
);
const src = this.expandInputFiles(result.inputFiles);
const project = this.convert(src);
if (project) {
Expand Down
1 change: 1 addition & 0 deletions src/lib/converter/factories/parameter.ts
Expand Up @@ -23,6 +23,7 @@ export function createParameter(context: Context, node: ts.ParameterDeclaration)
}

const parameter = new ParameterReflection(node.symbol.name, ReflectionKind.Parameter, signature);
parameter.flags.setFlag(ReflectionFlag.Exported, context.scope.flags.isExported);
context.registerReflection(parameter, node);
context.withScope(parameter, () => {
if (ts.isArrayBindingPattern(node.name) || ts.isObjectBindingPattern(node.name)) {
Expand Down
3 changes: 2 additions & 1 deletion src/lib/converter/factories/signature.ts
@@ -1,6 +1,6 @@
import * as ts from 'typescript';

import { ReflectionKind, SignatureReflection, ContainerReflection, DeclarationReflection, Type } from '../../models/index';
import { ReflectionKind, SignatureReflection, ContainerReflection, DeclarationReflection, Type, ReflectionFlag } from '../../models/index';
import { Context } from '../context';
import { Converter } from '../converter';
import { createParameter } from './parameter';
Expand All @@ -22,6 +22,7 @@ export function createSignature(context: Context, node: ts.SignatureDeclaration,
}

const signature = new SignatureReflection(name, kind, container);
signature.flags.setFlag(ReflectionFlag.Exported, context.scope.flags.isExported);
context.registerReflection(signature, node);
context.withScope(signature, node.typeParameters, true, () => {
node.parameters.forEach((parameter: ts.ParameterDeclaration) => {
Expand Down
3 changes: 2 additions & 1 deletion src/lib/converter/factories/type-parameter.ts
@@ -1,6 +1,6 @@
import * as ts from 'typescript';

import { TypeParameterContainer, TypeParameterReflection, TypeParameterType } from '../../models/index';
import { TypeParameterContainer, TypeParameterReflection, TypeParameterType, ReflectionFlag } from '../../models/index';
import { Context } from '../context';
import { Converter } from '../converter';

Expand All @@ -23,6 +23,7 @@ export function createTypeParameter(context: Context, node: ts.TypeParameterDecl

const reflection = <TypeParameterContainer> context.scope;
const typeParameterReflection = new TypeParameterReflection(typeParameter, reflection);
typeParameterReflection.flags.setFlag(ReflectionFlag.Exported, reflection.flags.isExported);

if (!reflection.typeParameters) {
reflection.typeParameters = [];
Expand Down
7 changes: 5 additions & 2 deletions src/lib/converter/nodes/literal-type.ts
@@ -1,6 +1,6 @@
import * as ts from 'typescript';

import { Reflection } from '../../models/index';
import { Reflection, ReflectionFlag } from '../../models/index';
import { Context } from '../context';
import { Component, ConverterNodeComponent } from '../components';

Expand All @@ -23,7 +23,10 @@ export class TypeLiteralConverter extends ConverterNodeComponent<ts.TypeLiteralN
convert(context: Context, node: ts.TypeLiteralNode): Reflection {
if (node.members) {
node.members.forEach((node) => {
this.owner.convertNode(context, node);
const reflection = this.owner.convertNode(context, node);
if (reflection) {
reflection.flags.setFlag(ReflectionFlag.Exported, context.scope.flags.isExported);
}
});
}

Expand Down
9 changes: 4 additions & 5 deletions src/lib/converter/types/reference.ts
@@ -1,7 +1,7 @@
import * as ts from 'typescript';

import { Type, IntrinsicType, ReflectionType } from '../../models/types/index';
import { ReflectionKind, DeclarationReflection } from '../../models/reflections/index';
import { ReflectionKind, DeclarationReflection, ReflectionFlag } from '../../models/reflections/index';
import { createReferenceType } from '../factories/index';
import { Component, ConverterTypeComponent, TypeNodeConverter } from '../components';
import { Context } from '../context';
Expand Down Expand Up @@ -115,16 +115,15 @@ export class ReferenceConverter extends ConverterTypeComponent implements TypeNo
if (context.visitStack.includes(declaration)) {
if (declaration.kind === ts.SyntaxKind.TypeLiteral ||
declaration.kind === ts.SyntaxKind.ObjectLiteralExpression) {
// TODO: Check if this type assertion is safe and document.
return createReferenceType(context, declaration.parent.symbol!);
return createReferenceType(context, declaration.parent.symbol);
} else {
// TODO: Check if this type assertion is safe and document.
return createReferenceType(context, declaration.symbol!);
return createReferenceType(context, declaration.symbol);
}
}
}

const declaration = new DeclarationReflection('__type', ReflectionKind.TypeLiteral, context.scope);
declaration.flags.setFlag(ReflectionFlag.Exported, context.scope.flags.isExported);

context.registerReflection(declaration, undefined, symbol);
context.trigger(Converter.EVENT_CREATE_DECLARATION, declaration, node);
Expand Down

0 comments on commit db47e79

Please sign in to comment.