Skip to content

Commit

Permalink
fix!: Correctly check if symbols are exported
Browse files Browse the repository at this point in the history
This corrects the change made in 9c3114d to use the type checker.

Also reworks converter.test.ts to remove dead code + simplify adding new tests.
  • Loading branch information
Gerrit0 committed Jan 10, 2020
1 parent 6bce37b commit 89c4041
Show file tree
Hide file tree
Showing 18 changed files with 533 additions and 472 deletions.
9 changes: 8 additions & 1 deletion scripts/rebuild_specs.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ const app = new TypeDoc.Application({
"lib.es2015.iterable.d.ts",
"lib.es2015.collection.d.ts"
],
name: 'typedoc'
name: 'typedoc',
excludeExternals: true
});

// Note that this uses the test files in dist, not in src, this is important since
Expand All @@ -27,6 +28,10 @@ const base = path.join(__dirname, '../dist/test/converter');
/** @type {[string, () => void, () => void][]} */
const conversions = [
['specs', () => { }, () => { }],
['specs.d',
() => app.options.setValue('includeDeclarations', true),
() => app.options.setValue('includeDeclarations', false)
],
['specs-without-exported',
() => app.options.setValue('excludeNotExported', true),
() => app.options.setValue('excludeNotExported', false)
Expand Down Expand Up @@ -73,7 +78,9 @@ async function rebuildRendererTest() {
const out = path.join(__dirname, '../src/test/renderer/specs');

await fs.remove(out)
app.options.setValue('excludeExternals', false);
app.generateDocs(app.expandInputFiles([src]), out)
app.options.setValue('excludeExternals', true);
await fs.remove(path.join(out, 'assets'))

/**
Expand Down
9 changes: 8 additions & 1 deletion src/lib/converter/factories/declaration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,14 @@ export function createDeclaration(context: Context, node: ts.Declaration, kind:
while (![ts.SyntaxKind.SourceFile, ts.SyntaxKind.ModuleDeclaration].includes(parentNode.kind)) {
parentNode = parentNode.parent;
}
isExported = !!context.getSymbolAtLocation(parentNode)?.exports?.get(symbol.escapedName);
const parentSymbol = context.getSymbolAtLocation(parentNode);
if (!parentSymbol) {
// This is a file with no imports/exports, so everything is
// global and therefore exported.
isExported = true;
} else {
isExported = !!parentSymbol.exports?.get(symbol.escapedName);
}
}
} else {
isExported = container.flags.isExported;
Expand Down
245 changes: 51 additions & 194 deletions src/test/converter.test.ts
Original file line number Diff line number Diff line change
@@ -1,213 +1,70 @@
import { Application, resetReflectionID, normalizePath, ProjectReflection } from '..';
import * as FS from 'fs';
import * as Path from 'path';
import Assert = require('assert');

function compareReflections(fixture, spec, path?: string) {
path = (path ? path + '/' : '') + spec.name;
Assert.deepEqual(fixture, spec);

for (let key in spec) {
if (!spec.hasOwnProperty(key)) {
continue;
}
Assert(fixture.hasOwnProperty(key), path + ': Missing property "' + key + '"');
}

for (let key in fixture) {
if (!fixture.hasOwnProperty(key) || typeof fixture[key] === 'undefined') {
continue;
}
Assert(spec.hasOwnProperty(key), path + ': Unknown property "' + key + '"');

const a = fixture[key];
const b = spec[key];
Assert(a instanceof Object === b instanceof Object, path + ': Property "' + key + '" type mismatch');

if (a instanceof Object) {
switch (key) {
case 'signatures':
case 'typeParameters':
case 'children':
compareChildren(a, b, path);
break;
case 'indexSignature':
case 'getSignature':
case 'setSignature':
compareReflections(a, b, path);
break;
default:
Assert.deepEqual(a, b, path + ': Property "' + key + '" value mismatch');
}
} else {
Assert(a === b, path + ': Property "' + key + '" value mismatch');
}
}
}

function compareChildren(fixture, spec, path) {
const a = fixture.map(function(child) { return child.id; });
const b = spec.map(function(child) { return child.id; });

Assert(a.length === b.length, path + ': Number of children differs');
Assert(a.every(function(u, i) { return u === b[i]; }), path + ': Children are different');

fixture.forEach(function(a, index) {
compareReflections(a, spec[index], path);
});
}
import { deepStrictEqual as equal, ok } from 'assert';

describe('Converter', function() {
const base = Path.join(__dirname, 'converter');
let app: Application;

before('constructs', function() {
app = new Application({
mode: 'Modules',
logger: 'none',
target: 'ES5',
module: 'CommonJS',
experimentalDecorators: true,
jsx: 'react',
name: 'typedoc',
ignoreCompilerErrors: true
});
const app = new Application({
mode: 'Modules',
logger: 'none',
target: 'ES5',
module: 'CommonJS',
experimentalDecorators: true,
jsx: 'react',
name: 'typedoc',
ignoreCompilerErrors: true,
excludeExternals: true
});

const checks: [string, () => void, () => void][] = [
['specs', () => { }, () => { }],
['specs.d',
() => app.options.setValue('includeDeclarations', true),
() => app.options.setValue('includeDeclarations', false)
],
['specs-without-exported',
() => app.options.setValue('excludeNotExported', true),
() => app.options.setValue('excludeNotExported', false)
],
['specs-with-lump-categories',
() => app.options.setValue('categorizeByGroup', false),
() => app.options.setValue('categorizeByGroup', true)
]
];

FS.readdirSync(base).forEach(function (directory) {
const path = Path.join(base, directory);
if (!FS.lstatSync(path).isDirectory()) {
return;
}

describe(directory, function() {
let result: ProjectReflection | undefined;

it('converts fixtures', function() {
resetReflectionID();
result = app.convert(app.expandInputFiles([path]));
Assert(result instanceof ProjectReflection, 'No reflection returned');
});

it('matches specs', function() {
const specs = JSON.parse(FS.readFileSync(Path.join(path, 'specs.json')).toString());
let data = JSON.stringify(app.serializer.toObject(result), null, ' ');
data = data.split(normalizePath(base)).join('%BASE%');

compareReflections(JSON.parse(data), specs);
});
});
});
});

describe('Converter with categorizeByGroup=false', function() {
const base = Path.join(__dirname, 'converter');
const categoryDir = Path.join(base, 'category');
const classDir = Path.join(base, 'class');
let app: Application;

before('constructs', function() {
app = new Application({
mode: 'Modules',
logger: 'none',
target: 'ES5',
module: 'CommonJS',
experimentalDecorators: true,
categorizeByGroup: false,
jsx: 'react',
name: 'typedoc',
ignoreCompilerErrors: true
});
});

let result: ProjectReflection | undefined;

describe('category', () => {
it('converts fixtures', function() {
resetReflectionID();
result = app.convert(app.expandInputFiles([categoryDir]));
Assert(result instanceof ProjectReflection, 'No reflection returned');
});

it('matches specs', function() {
const specs = JSON.parse(FS.readFileSync(Path.join(categoryDir, 'specs-with-lump-categories.json')).toString());
let data = JSON.stringify(result!.toObject(), null, ' ');
data = data.split(normalizePath(base)).join('%BASE%');

compareReflections(JSON.parse(data), specs);
});
});

// verify that no categories are used when not specified during lump categorization
describe('class', () => {
it('converts fixtures', function() {
resetReflectionID();
result = app.convert(app.expandInputFiles([classDir]));
Assert(result instanceof ProjectReflection, 'No reflection returned');
});

it('matches specs', function() {
const specs = JSON.parse(FS.readFileSync(Path.join(classDir, 'specs.json')).toString());
let data = JSON.stringify(result!.toObject(), null, ' ');
data = data.split(normalizePath(base)).join('%BASE%');

compareReflections(JSON.parse(data), specs);
for (const [file, before, after] of checks) {
const specsFile = Path.join(path, `${file}.json`);
if (!FS.existsSync(specsFile)) {
continue;
}

let result: ProjectReflection | undefined;

it(`[${file}] converts fixtures`, function() {
before();
resetReflectionID();
result = app.convert(app.expandInputFiles([path]));
after();
ok(result instanceof ProjectReflection, 'No reflection returned');
});

it(`[${file}] matches specs`, function() {
const specs = JSON.parse(FS.readFileSync(specsFile, 'utf-8'));
let data = JSON.stringify(app.serializer.toObject(result), null, ' ');
data = data.split(normalizePath(base)).join('%BASE%');

equal(JSON.parse(data), specs);
});
}
});
});
});

describe('Converter with excludeNotExported=true', function() {
const base = Path.join(__dirname, 'converter');
const exportWithLocalDir = Path.join(base, 'export-with-local');
const classDir = Path.join(base, 'class');
let app: Application;

before('constructs', function() {
app = new Application({
mode: 'Modules',
logger: 'none',
target: 'ES5',
module: 'CommonJS',
experimentalDecorators: true,
excludeNotExported: true,
jsx: 'react',
name: 'typedoc',
ignoreCompilerErrors: true
});
});

let result: ProjectReflection | undefined;

describe('export-with-local', () => {
it('converts fixtures', function() {
resetReflectionID();
result = app.convert(app.expandInputFiles([exportWithLocalDir]));
Assert(result instanceof ProjectReflection, 'No reflection returned');
});

it('matches specs', function() {
const specs = JSON.parse(FS.readFileSync(Path.join(exportWithLocalDir, 'specs-without-exported.json')).toString());
let data = JSON.stringify(result!.toObject(), null, ' ');
data = data.split(normalizePath(base)).join('%BASE%');

compareReflections(JSON.parse(data), specs);
});
});

describe('class', () => {
it('converts fixtures', function() {
resetReflectionID();
result = app.convert(app.expandInputFiles([classDir]));
Assert(result instanceof ProjectReflection, 'No reflection returned');
});

it('matches specs', function() {
const specs = JSON.parse(FS.readFileSync(Path.join(classDir, 'specs-without-exported.json')).toString());
let data = JSON.stringify(result!.toObject(), null, ' ');
data = data.split(normalizePath(base)).join('%BASE%');

compareReflections(JSON.parse(data), specs);
});
});

});
5 changes: 5 additions & 0 deletions src/test/converter/declaration/declaration.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
declare class Decl {
prop: number;
}

declare const x: number
3 changes: 3 additions & 0 deletions src/test/converter/declaration/export-declaration.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export declare class Exported {}

declare class NotExported {}

0 comments on commit 89c4041

Please sign in to comment.