Skip to content
This repository was archived by the owner on Nov 25, 2025. It is now read-only.

Commit 4b9003c

Browse files
author
Martynas Žilinskas
authored
Merge pull request #39 from SimplrJS/dev
2 parents 3f33d5e + 9bcff96 commit 4b9003c

File tree

84 files changed

+2132
-720
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+2132
-720
lines changed

README.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,23 @@
1-
# ts-extractor
1+
<p>
2+
<a href="https://npmjs.org/package/ts-extractor">
3+
<img src="https://img.shields.io/npm/v/ts-extractor.svg?style=flat-square" alt="version" />
4+
</a>
5+
<a href="https://travis-ci.org/SimplrJS/ts-extractor">
6+
<img src="https://img.shields.io/travis/SimplrJS/ts-extractor.svg?style=flat-square" alt="build" />
7+
</a>
8+
<a href="https://david-dm.org/simplrjs/ts-extractor">
9+
<img src="https://img.shields.io/david/SimplrJS/ts-extractor.svg?style=flat-square" alt="dependencies" />
10+
</a>
11+
<a href="https://david-dm.org/simplrjs/ts-extractor?type=dev">
12+
<img src="https://img.shields.io/david/dev/SimplrJS/ts-extractor.svg?style=flat-square" alt="devDependencies" />
13+
</a>
14+
<a href="https://npmjs.org/package/ts-extractor">
15+
<img src="https://img.shields.io/npm/l/ts-extractor.svg?style=flat-square" alt="license" />
16+
</a>
17+
</p>
18+
19+
<h1 align="center">ts-extractor</h1>
20+
221
TypeScript AST extractor to useful structs.
322

423
The purpose of this package is to extract AST into flat JSON structures.

examples/simple/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
// }
1212

1313
// export * from "./exported-functions";
14-
export { Kintamasis as Pakeistas } from "./exported-const-variables";
14+
// export { Kintamasis as Pakeistas } from "./exported-const-variables";
1515
// export type A<TValue> = number & { ok(): TValue };
1616

1717
// Two types have a one common field
@@ -91,6 +91,10 @@ export { Kintamasis as Pakeistas } from "./exported-const-variables";
9191
// Type: TType;
9292
// }
9393

94+
export async function GetFoo(): Promise<void> {
95+
return;
96+
}
97+
9498
// export interface Bar extends Foo<number>, Boo {
9599
// OtherStuff: string[];
96100
// }

package.json

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ts-extractor",
3-
"version": "0.1.1",
3+
"version": "1.0.0",
44
"description": "",
55
"main": "index.js",
66
"types": "./dist/index.d.ts",
@@ -25,22 +25,22 @@
2525
],
2626
"license": "AGPL",
2727
"dependencies": {
28-
"@types/fs-extra": "^4.0.2",
28+
"@types/fs-extra": "^4.0.5",
2929
"fs-extra": "^4.0.2",
30-
"read-package-json": "^2.0.10",
31-
"simplr-logger": "^0.1.1",
30+
"read-package-json": "^2.0.12",
31+
"simplr-logger": "^0.3.0",
3232
"tslint": "^5.8.0",
3333
"typescript": "^2.6.1"
3434
},
3535
"devDependencies": {
3636
"@types/globby": "^6.1.0",
37-
"@types/jest": "^20.0.5",
38-
"@types/sinon": "^2.3.3",
39-
"globby": "^6.1.0",
40-
"jest": "^20.0.4",
37+
"@types/jest": "^21.1.6",
38+
"@types/sinon": "^4.0.0",
39+
"globby": "^7.0.0",
40+
"jest": "^21.2.1",
4141
"rimraf": "^2.6.2",
42-
"sinon": "^2.4.1",
43-
"ts-jest": "^20.0.7",
42+
"sinon": "^4.1.2",
43+
"ts-jest": "^21.2.3",
4444
"ts-node": "^3.3.0"
4545
},
4646
"files": [

src/abstractions/api-callable-base.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { ApiItem, ApiItemOptions } from "../abstractions/api-item";
44
import { TSHelpers } from "../ts-helpers";
55
import { ApiHelpers } from "../api-helpers";
66
import { ApiFunctionDto } from "../contracts/definitions/api-function-dto";
7-
import { ApiItemReferenceDictionary } from "../contracts/api-item-reference-dictionary";
7+
import { ApiItemReferenceTuple } from "../contracts/api-item-reference-tuple";
88
import { ApiItemKinds } from "../contracts/api-item-kinds";
99
import { TypeDto } from "../contracts/type-dto";
1010
import { ApiMetadataDto } from "../contracts/api-metadata-dto";
@@ -19,8 +19,8 @@ export abstract class ApiCallableBase<
1919
>
2020
extends ApiItem<TDeclaration, TExtractDto> {
2121

22-
protected Parameters: ApiItemReferenceDictionary = {};
23-
protected TypeParameters: ApiItemReferenceDictionary = {};
22+
protected Parameters: ApiItemReferenceTuple = [];
23+
protected TypeParameters: ApiItemReferenceTuple = [];
2424
protected ReturnType: TypeDto | undefined;
2525

2626
protected OnGatherData(): void {

src/abstractions/api-item.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export interface ApiItemOptions {
1010
Program: ts.Program;
1111
ExtractorOptions: ExtractorOptions;
1212
Registry: ReadonlyRegistry<ApiItem>;
13-
AddItemToRegistry: (item: ApiItem) => string;
13+
AddItemToRegistry(item: ApiItem): string;
1414
}
1515

1616
export enum ApiItemStatus {

src/api-helpers.ts

Lines changed: 47 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { LogLevel } from "simplr-logger";
44

55
import { ApiItem, ApiItemOptions } from "./abstractions/api-item";
66

7-
import { ApiItemReferenceDictionary } from "./contracts/api-item-reference-dictionary";
7+
import { ApiItemReferenceTuple } from "./contracts/api-item-reference-tuple";
88
import {
99
TypeDto,
1010
TypeBasicDto,
@@ -111,18 +111,43 @@ export namespace ApiHelpers {
111111
}
112112

113113
export function ShouldVisit(declaration: ts.Declaration, options: ApiItemOptions): boolean {
114-
const declarationFileName = declaration.getSourceFile().fileName;
115-
if (PathIsInside(declarationFileName, options.ExtractorOptions.ProjectDirectory)) {
116-
return true;
114+
const declarationSourceFile = declaration.getSourceFile();
115+
const declarationFileName = declarationSourceFile.fileName;
116+
117+
if (!PathIsInside(declarationFileName, options.ExtractorOptions.ProjectDirectory)) {
118+
return false;
117119
}
118-
return false;
120+
121+
if (options.Program.isSourceFileFromExternalLibrary(declarationSourceFile)) {
122+
return false;
123+
}
124+
125+
return true;
126+
}
127+
128+
export function GetItemId(declaration: ts.Declaration, symbol: ts.Symbol, options: ApiItemOptions): string | undefined {
129+
if (!ShouldVisit(declaration, options)) {
130+
return undefined;
131+
}
132+
133+
if (options.Registry.HasDeclaration(declaration)) {
134+
return options.Registry.GetDeclarationId(declaration);
135+
}
136+
137+
const resolveRealSymbol = TSHelpers.FollowSymbolAliases(symbol, options.Program.getTypeChecker());
138+
const apiItem = VisitApiItem(declaration, resolveRealSymbol, options);
139+
if (apiItem == null) {
140+
return undefined;
141+
}
142+
143+
return options.AddItemToRegistry(apiItem);
119144
}
120145

121146
export function GetItemsIdsFromSymbols(
122147
symbols: ts.UnderscoreEscapedMap<ts.Symbol> | undefined,
123148
options: ApiItemOptions
124-
): ApiItemReferenceDictionary {
125-
const items: ApiItemReferenceDictionary = {};
149+
): ApiItemReferenceTuple {
150+
const items: ApiItemReferenceTuple = [];
126151
if (symbols == null) {
127152
return items;
128153
}
@@ -134,27 +159,13 @@ export namespace ApiHelpers {
134159
const symbolItems: string[] = [];
135160

136161
symbol.declarations.forEach(declaration => {
137-
// Check if declaration already exists in the registry.
138-
if (options.Registry.HasDeclaration(declaration)) {
139-
const declarationId = options.Registry.GetDeclarationId(declaration);
140-
if (declarationId == null) {
141-
throw new Error(`Declaration id cannot be undefined.`);
142-
}
143-
symbolItems.push(declarationId);
144-
return;
162+
const itemId = GetItemId(declaration, symbol, options);
163+
if (itemId != null) {
164+
symbolItems.push(itemId);
145165
}
146-
147-
const resolveRealSymbol = TSHelpers.FollowSymbolAliases(symbol, options.Program.getTypeChecker());
148-
149-
const visitedItem = VisitApiItem(declaration, resolveRealSymbol, options);
150-
if (visitedItem == null || !ShouldVisit(declaration, options)) {
151-
return;
152-
}
153-
154-
symbolItems.push(options.AddItemToRegistry(visitedItem));
155166
});
156167

157-
items[symbol.name] = symbolItems.length === 1 ? symbolItems.toString() : symbolItems;
168+
items.push([symbol.name, symbolItems]);
158169
});
159170

160171
return items;
@@ -163,38 +174,27 @@ export namespace ApiHelpers {
163174
export function GetItemsIdsFromDeclarations(
164175
declarations: ts.NodeArray<ts.Declaration>,
165176
options: ApiItemOptions
166-
): ApiItemReferenceDictionary {
167-
const items: ApiItemReferenceDictionary = {};
177+
): ApiItemReferenceTuple {
178+
const items: ApiItemReferenceTuple = [];
168179
const typeChecker = options.Program.getTypeChecker();
169180

170181
declarations.forEach(declaration => {
171182
const symbol = TSHelpers.GetSymbolFromDeclaration(declaration, typeChecker);
172183
if (symbol == null) {
173184
return;
174185
}
175-
const name = symbol.name;
176186

177-
let declarationId = options.Registry.GetDeclarationId(declaration);
178-
if (declarationId == null) {
179-
const resolveRealSymbol = TSHelpers.FollowSymbolAliases(symbol, options.Program.getTypeChecker());
180-
181-
const visitedItem = VisitApiItem(declaration, resolveRealSymbol, options);
182-
if (visitedItem == null || !ShouldVisit(declaration, options)) {
183-
return;
184-
}
185-
186-
declarationId = options.AddItemToRegistry(visitedItem);
187+
const itemId = GetItemId(declaration, symbol, options);
188+
if (itemId == null) {
189+
return;
187190
}
188191

189-
if (items[name] == null) {
190-
items[name] = declarationId;
192+
const index = items.findIndex(x => x != null && x.length === 2 && x[0] === symbol.name);
193+
194+
if (index === -1) {
195+
items.push([symbol.name, [itemId]]);
191196
} else {
192-
const refs = items[name];
193-
if (Array.isArray(refs)) {
194-
refs.push(declarationId);
195-
} else {
196-
items[name] = [refs, declarationId];
197-
}
197+
items[index][1].push(itemId);
198198
}
199199
});
200200

@@ -270,17 +270,7 @@ export namespace ApiHelpers {
270270
if (symbol.declarations != null && symbol.declarations.length > 0) {
271271
const declaration: ts.Declaration = symbol.declarations[0];
272272

273-
let declarationId = options.Registry.GetDeclarationId(declaration);
274-
275-
if (declarationId == null) {
276-
const resolveRealSymbol = TSHelpers.FollowSymbolAliases(symbol, typeChecker);
277-
278-
const apiItem = VisitApiItem(declaration, resolveRealSymbol, options);
279-
if (apiItem != null) {
280-
declarationId = options.AddItemToRegistry(apiItem);
281-
}
282-
}
283-
273+
const declarationId = GetItemId(declaration, symbol, options);
284274
if (declarationId != null) {
285275
return {
286276
ApiTypeKind: TypeKinds.Reference,

src/api-registry.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import * as ts from "typescript";
22
import { ApiItem } from "./abstractions/api-item";
33
import { Dictionary } from "./contracts/dictionary";
44
import { Registry } from "./contracts/registry";
5-
import { ApiBaseItemDto } from "./contracts/api-base-item-dto";
5+
import { ApiItemDto } from "./contracts/api-item-dto";
66

7-
export type ExtractedApiRegistry = Dictionary<ApiBaseItemDto>;
7+
export type ExtractedApiRegistry = Dictionary<ApiItemDto>;
88

99
export class ApiRegistry implements Registry<ApiItem> {
1010
protected registry: Map<string, ApiItem> = new Map<string, ApiItem>();
@@ -21,7 +21,7 @@ export class ApiRegistry implements Registry<ApiItem> {
2121
const [key, apiItem] = item;
2222
const extractedData = apiItem.Extract(forceExtract);
2323

24-
this.ExtractedData[key] = extractedData;
24+
this.ExtractedData[key] = extractedData as ApiItemDto;
2525
}
2626

2727
this.IsDataExtracted = true;

src/contracts.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ export * from "./contracts/access-modifier";
22
export * from "./contracts/api-base-item-dto";
33
export * from "./contracts/api-callable-dto";
44
export * from "./contracts/api-item-kinds";
5-
export * from "./contracts/api-item-reference-dictionary";
5+
export * from "./contracts/api-item-reference-tuple";
66
export * from "./contracts/api-metadata-dto";
77
export * from "./contracts/config";
88
export * from "./contracts/definitions/api-call-dto";
@@ -33,3 +33,4 @@ export * from "./contracts/extractor-options";
3333
export * from "./contracts/registry";
3434
export * from "./contracts/type-dto";
3535
export * from "./contracts/type-kinds";
36+
export * from "./contracts/api-item-dto";

src/contracts/api-callable-dto.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { ApiBaseItemDto } from "./api-base-item-dto";
2-
import { ApiItemReferenceDictionary } from "./api-item-reference-dictionary";
2+
import { ApiItemReferenceTuple } from "./api-item-reference-tuple";
33
import { TypeDto } from "./type-dto";
44
import { ApiItemKinds } from "./api-item-kinds";
55

66
export interface ApiCallableDto extends ApiBaseItemDto {
7-
TypeParameters: ApiItemReferenceDictionary;
8-
Parameters: ApiItemReferenceDictionary;
7+
TypeParameters: ApiItemReferenceTuple;
8+
Parameters: ApiItemReferenceTuple;
99
ReturnType?: TypeDto;
1010
}

src/contracts/api-item-dto.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { ApiCallDto } from "./definitions/api-call-dto";
2+
import { ApiClassConstructorDto } from "./definitions/api-class-constructor-dto";
3+
import { ApiClassDto } from "./definitions/api-class-dto";
4+
import { ApiClassMethodDto } from "./definitions/api-class-method-dto";
5+
import { ApiClassPropertyDto } from "./definitions/api-class-property-dto";
6+
import { ApiConstructDto } from "./definitions/api-construct-dto";
7+
import { ApiEnumDto } from "./definitions/api-enum-dto";
8+
import { ApiEnumMemberDto } from "./definitions/api-enum-member-dto";
9+
import { ApiExportDto } from "./definitions/api-export-dto";
10+
import { ApiExportSpecifierDto } from "./definitions/api-export-specifier-dto";
11+
import { ApiFunctionDto } from "./definitions/api-function-dto";
12+
import { ApiFunctionTypeDto } from "./definitions/api-function-type-dto";
13+
import { ApiIndexDto } from "./definitions/api-index-dto";
14+
import { ApiInterfaceDto } from "./definitions/api-interface-dto";
15+
import { ApiMethodDto } from "./definitions/api-method-dto";
16+
import { ApiNamespaceDto } from "./definitions/api-namespace-dto";
17+
import { ApiParameterDto } from "./definitions/api-parameter-dto";
18+
import { ApiPropertyDto } from "./definitions/api-property-dto";
19+
import { ApiSourceFileDto } from "./definitions/api-source-file-dto";
20+
import { ApiTypeDto } from "./definitions/api-type-dto";
21+
import { ApiTypeLiteralDto } from "./definitions/api-type-literal-dto";
22+
import { ApiTypeParameterDto } from "./definitions/api-type-parameter-dto";
23+
import { ApiVariableDto } from "./definitions/api-variable-dto";
24+
25+
export type ApiItemDto = ApiCallDto |
26+
ApiClassConstructorDto |
27+
ApiClassDto |
28+
ApiClassMethodDto |
29+
ApiClassPropertyDto |
30+
ApiConstructDto |
31+
ApiEnumDto |
32+
ApiEnumMemberDto |
33+
ApiExportDto |
34+
ApiExportSpecifierDto |
35+
ApiFunctionDto |
36+
ApiFunctionTypeDto |
37+
ApiIndexDto |
38+
ApiInterfaceDto |
39+
ApiMethodDto |
40+
ApiNamespaceDto |
41+
ApiParameterDto |
42+
ApiPropertyDto |
43+
ApiSourceFileDto |
44+
ApiTypeDto |
45+
ApiTypeLiteralDto |
46+
ApiTypeParameterDto |
47+
ApiVariableDto;

0 commit comments

Comments
 (0)