Skip to content

Commit

Permalink
feat: Add ImportTypeNode.
Browse files Browse the repository at this point in the history
  • Loading branch information
dsherret committed Jun 3, 2018
1 parent db00f18 commit 3d0203c
Show file tree
Hide file tree
Showing 15 changed files with 132 additions and 108 deletions.
69 changes: 8 additions & 61 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
"source-map-support": "^0.5.5",
"ts-nameof": "^1.0.0",
"ts-node": "^6.0.2",
"ts-simple-ast": "11.2.0",
"ts-simple-ast": "12.0.0",
"tslint": "^5.8.0",
"ttypescript": "1.4.6"
},
Expand Down
2 changes: 1 addition & 1 deletion scripts/common/typeHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export function hasDescendantBaseType(type: Type, isMatch: (type: Type) => boole
}

export function getDescendantBaseType(type: Type, isMatch: (type: Type) => boolean): Type | undefined {
if (type.isIntersectionType()) {
if (type.isIntersection()) {
for (const intersectionType of type.getIntersectionTypes()) {
const descendantType = getDescendantBaseType(intersectionType, isMatch);
if (descendantType != null)
Expand Down
2 changes: 2 additions & 0 deletions scripts/createCompilerNodeBrandPropertyNamesType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ export function createCompilerNodeBrandPropertyNamesType(tsInspector: TsInspecto

if (existingTypeAlias != null)
existingTypeAlias.remove();
if (brandNames.length === 0)
throw new Error("Unexpected! For some reason there were no brand names.");

sourceFile.addTypeAlias({
isExported: true,
Expand Down
12 changes: 7 additions & 5 deletions scripts/createDeclarationFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,10 @@ import { getDefinitionProject } from "./common";
import { flattenDeclarationFiles } from "./flattenDeclarationFiles";

const project = getDefinitionProject();
// temporary until I can upgrade this project to 2.9
for (const sourceFile of project.getSourceFiles()) {
// remove all import type expressions
sourceFile.replaceText([0, sourceFile.getEnd()], sourceFile.getFullText().replace(/import\([^\)]+\).([A-Za-z]+)/g, "$1"));
}
const mainFile = project.getSourceFileOrThrow("main.d.ts");

flattenDeclarationFiles(project, mainFile);
removeImportTypes();
hideBaseDeclarations();

project.save();
Expand All @@ -35,3 +31,9 @@ function hideBaseDeclarations() {
variableStatement.setIsExported(false);
}
}

function removeImportTypes() {
for (const type of mainFile.getDescendantsOfKind(SyntaxKind.ImportType)) {
type.replaceWithText(type.getNodeProperty("qualifier" as any).getText());
}
}
4 changes: 2 additions & 2 deletions scripts/inspectors/TsInspector.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Project, { InterfaceDeclaration, SourceFile, SyntaxKind } from "ts-simple-ast";
import { Memoize, ArrayUtils } from "../../src/utils";
import { Memoize, ArrayUtils, StringUtils } from "../../src/utils";
import { hasDescendantBaseType } from "../common";
import { TsNode } from "./ts";
import { WrapperFactory } from "./WrapperFactory";
Expand All @@ -21,7 +21,7 @@ export class TsInspector {
const compilerApiFile = this.project.getSourceFileOrThrow("src/typescript/typescript.ts");
const interfaces: InterfaceDeclaration[] = [];
for (const interfaceDec of ArrayUtils.flatten(compilerApiFile.getNamespaces().map(n => n.getInterfaces()))) {
if (interfaceDec.getBaseTypes().some(t => hasDescendantBaseType(t, checkingType => checkingType.getText() === "ts.Node")))
if (interfaceDec.getBaseTypes().some(t => hasDescendantBaseType(t, checkingType => StringUtils.endsWith(checkingType.getText(), "ts.Node"))))
interfaces.push(interfaceDec);
}
return ArrayUtils.sortByProperty(interfaces.map(i => this.wrapperFactory.getTsNode(i)), item => item.getName());
Expand Down
2 changes: 1 addition & 1 deletion scripts/inspectors/tsSimpleAst/WrappedNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export class WrappedNode {
if (extendsExpr == null)
return undefined;
const extendsType = extendsExpr.getType();
const possibleTypes = extendsType.isIntersectionType() ? extendsType.getIntersectionTypes() : [extendsType];
const possibleTypes = extendsType.isIntersection() ? extendsType.getIntersectionTypes() : [extendsType];
const nodeType = ArrayUtils.find(possibleTypes, t => hasDescendantNodeType(t));
if (nodeType == null)
return undefined;
Expand Down
1 change: 1 addition & 0 deletions src/compiler/CompilerNodeToWrappedType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ export type CompilerNodeToWrappedType<T extends ts.Node> = [T] extends [ts.Class
[T] extends [ts.ConstructorTypeNode] ? compiler.ConstructorTypeNode :
[T] extends [ts.ExpressionWithTypeArguments] ? compiler.ExpressionWithTypeArguments :
[T] extends [ts.FunctionTypeNode] ? compiler.FunctionTypeNode :
[T] extends [ts.ImportTypeNode] ? compiler.ImportTypeNode :
[T] extends [ts.IntersectionTypeNode] ? compiler.IntersectionTypeNode :
[T] extends [ts.LiteralTypeNode] ? compiler.LiteralTypeNode :
[T] extends [ts.TupleTypeNode] ? compiler.TupleTypeNode :
Expand Down
3 changes: 2 additions & 1 deletion src/compiler/kindToNodeMappings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ export interface KindToNodeMappings {
[SyntaxKind.ImportDeclaration]: compiler.ImportDeclaration;
[SyntaxKind.ImportEqualsDeclaration]: compiler.ImportEqualsDeclaration;
[SyntaxKind.ImportSpecifier]: compiler.ImportSpecifier;
[SyntaxKind.ImportType]: compiler.ImportTypeNode;
[SyntaxKind.LastTypeNode]: compiler.ImportTypeNode;
[SyntaxKind.IndexSignature]: compiler.IndexSignatureDeclaration;
[SyntaxKind.InterfaceDeclaration]: compiler.InterfaceDeclaration;
[SyntaxKind.IntersectionType]: compiler.IntersectionTypeNode;
Expand Down Expand Up @@ -83,7 +85,6 @@ export interface KindToNodeMappings {
[SyntaxKind.JsxText]: compiler.JsxText;
[SyntaxKind.LabeledStatement]: compiler.LabeledStatement;
[SyntaxKind.LiteralType]: compiler.LiteralTypeNode;
[SyntaxKind.LastTypeNode]: compiler.LiteralTypeNode;
[SyntaxKind.MetaProperty]: compiler.MetaProperty;
[SyntaxKind.MethodDeclaration]: compiler.MethodDeclaration;
[SyntaxKind.MethodSignature]: compiler.MethodSignature;
Expand Down
29 changes: 29 additions & 0 deletions src/compiler/type/ImportTypeNode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { ts } from "../../typescript";
import * as errors from "../../errors";
import { TypeArgumentedNode } from "../base";
import { QualifiedName } from "../common";
import { TypeNode } from "./TypeNode";

export const ImportTypeNodeBase = TypeArgumentedNode(TypeNode);
export class ImportTypeNode extends ImportTypeNodeBase<ts.ImportTypeNode> {
/**
* Gets the argument passed into the import type.
*/
getArgument() {
return this.getNodeFromCompilerNode<TypeNode>(this.compilerNode.argument)
}

/**
* Gets the qualifier of the import type if it exists or throws
*/
getQualifierOrThrow() {
return errors.throwIfNullOrUndefined(this.getQualifier(), () => `Expected to find a qualifier for the import type: ${this.getText()}`);
}

/**
* Gets the qualifier of the import type if it exists or returns undefined.
*/
getQualifier() {
return this.getNodeFromCompilerNodeIfExists<QualifiedName>(this.compilerNode.qualifier)
}
}
1 change: 1 addition & 0 deletions src/compiler/type/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export * from "./ArrayTypeNode";
export * from "./ConstructorTypeNode";
export * from "./ExpressionWithTypeArguments";
export * from "./FunctionTypeNode";
export * from "./ImportTypeNode";
export * from "./IntersectionTypeNode";
export * from "./LiteralTypeNode";
export * from "./TupleTypeNode";
Expand Down
1 change: 1 addition & 0 deletions src/factories/kindToWrapperMappings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export const kindToWrapperMappings: { [key: number]: any } = {
[SyntaxKind.ImportDeclaration]: compiler.ImportDeclaration,
[SyntaxKind.ImportEqualsDeclaration]: compiler.ImportEqualsDeclaration,
[SyntaxKind.ImportSpecifier]: compiler.ImportSpecifier,
[SyntaxKind.ImportType]: compiler.ImportTypeNode,
[SyntaxKind.IndexSignature]: compiler.IndexSignatureDeclaration,
[SyntaxKind.InterfaceDeclaration]: compiler.InterfaceDeclaration,
[SyntaxKind.IntersectionType]: compiler.IntersectionTypeNode,
Expand Down
57 changes: 57 additions & 0 deletions src/tests/compiler/type/importTypeNodeTests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { expect } from "chai";
import { ts, SyntaxKind } from "../../../typescript";
import { ImportTypeNode } from "../../../compiler";
import { getInfoFromTextWithDescendant } from "../testHelpers";

describe(nameof(ImportTypeNode), () => {
function getNode(text: string) {
return getInfoFromTextWithDescendant<ImportTypeNode>(text, SyntaxKind.ImportType);
}

describe(nameof<ImportTypeNode>(d => d.getArgument), () => {
function doTest(text: string, expected: string) {
const {descendant} = getNode(text);
expect(descendant.getArgument().getText()).to.equal(expected);
}

it("should get the argument", () => {
doTest("var t: import('testing');", "'testing'");
});
});

describe(nameof<ImportTypeNode>(d => d.getQualifier), () => {
function doTest(text: string, expected: string | undefined) {
const {descendant} = getNode(text);
if (expected == null)
expect(descendant.getQualifier()).to.be.undefined;
else
expect(descendant.getQualifier()!.getText()).to.equal(expected);
}

it("should get the qualifier when it exists", () => {
doTest("var t: import('testing').Test;", "Test");
});

it("should be undefined when it doesn't exist", () => {
doTest("var t: import('testing');", undefined);
});
});

describe(nameof<ImportTypeNode>(d => d.getQualifierOrThrow), () => {
function doTest(text: string, expected: string | undefined) {
const {descendant} = getNode(text);
if (expected == null)
expect(() => descendant.getQualifierOrThrow()).to.throw();
else
expect(descendant.getQualifierOrThrow().getText()).to.equal(expected);
}

it("should get the qualifier when it exists", () => {
doTest("var t: import('testing').Test;", "Test");
});

it("should be undefined when it doesn't exist", () => {
doTest("var t: import('testing');", undefined);
});
});
});
10 changes: 10 additions & 0 deletions src/utils/TypeGuards.ts
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,14 @@ export class TypeGuards {
return node.getKind() === SyntaxKind.ImportSpecifier;
}

/**
* Gets if the node is a ImportTypeNode.
* @param node - Node to check.
*/
static isImportTypeNode(node: compiler.Node): node is compiler.ImportTypeNode {
return node.getKind() === SyntaxKind.ImportType;
}

/**
* Gets if the node is a IndexSignatureDeclaration.
* @param node - Node to check.
Expand Down Expand Up @@ -2189,6 +2197,7 @@ export class TypeGuards {
switch (node.getKind()) {
case SyntaxKind.CallExpression:
case SyntaxKind.NewExpression:
case SyntaxKind.ImportType:
return true;
default:
return false;
Expand Down Expand Up @@ -2253,6 +2262,7 @@ export class TypeGuards {
case SyntaxKind.ConstructorType:
case SyntaxKind.ExpressionWithTypeArguments:
case SyntaxKind.FunctionType:
case SyntaxKind.ImportType:
case SyntaxKind.IntersectionType:
case SyntaxKind.LiteralType:
case SyntaxKind.TupleType:
Expand Down

0 comments on commit 3d0203c

Please sign in to comment.