Skip to content

Commit

Permalink
0.90.0 - #27 - Ability to add/insert get & set accessors.
Browse files Browse the repository at this point in the history
  • Loading branch information
dsherret committed Nov 12, 2017
1 parent f8bd3ab commit 7c30fe6
Show file tree
Hide file tree
Showing 38 changed files with 345 additions and 49 deletions.
7 changes: 4 additions & 3 deletions code-generation/ensureOverloadStructuresMatch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ for (const overloadVM of overloadVMs) {
}

for (const remainingOverloadExtension of flattenedOverloadExtensions) {
problems.push(`Overload extension of ${remainingOverloadExtension.name} does not exist on main structure.`);
problems.push(`${overloadVM.name}: Overload extension of ${remainingOverloadExtension.name} does not exist on main structure.`);
}

for (const remainingStructureExtension of flattenedStructureExtensions) {
problems.push(`Structure extension of ${remainingStructureExtension.name} does not exist on overload structure.`);
problems.push(`${overloadVM.name}: Structure extension of ${remainingStructureExtension.name} does not exist on overload structure.`);
}
}

Expand All @@ -39,7 +39,8 @@ if (problems.length > 0) {

function isAllowedStructure(vm: InterfaceViewModel) {
switch (vm.name) {
case "NamedStructure":
case "NamedNodeStructure":
case "PropertyNamedNodeStructure":
case "FunctionLikeDeclarationStructure":
case "BodiedNodeStructure":
case "BodyableNodeStructure":
Expand Down
5 changes: 0 additions & 5 deletions code-generation/ensureStructuresMatchClasses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,6 @@ function getStructureName(vm: ClassViewModel | MixinViewModel) {
}

function isStructureToIgnore(structure: InterfaceViewModel) {
switch (structure.name) {
case "NamedStructure":
return true;
}

if (/SpecificStructure$/.test(structure.name))
return true;

Expand Down
12 changes: 12 additions & 0 deletions docs/details/classes.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,18 @@ Add or insert properties by using `insertProperties()`, `insertProperty`, `addPr
const property = classDeclaration.addProperty({ isStatic: true, name: "prop", type: "string" });
```

Add or insert get accessors by using `insertGetAccessors()`, `insertGetAccessor`, `addGetAccessor`, or `addGetAccessors`:

```typescript
const getAccessor = classDeclaration.addGetAccessor({ name: "someNumber", returnType: "number", body: "return 5;" });
```

Add or insert set accessors by using `insertSetAccessors()`, `insertSetAccessor`, `addSetAccessor`, or `addSetAccessors`:

```typescript
const setAccessor = classDeclaration.addSetAccessor({ name: "someNumber", parameters: [{ name: "value", type: "number" }], body: "_someNumber = value;" });
```

#### Remove

Call `.remove()`:
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ts-simple-ast",
"version": "0.89.0",
"version": "0.90.0",
"description": "TypeScript compiler wrapper for AST navigation and code generation.",
"main": "dist/main.js",
"typings": "dist/main.d.ts",
Expand Down
11 changes: 11 additions & 0 deletions src/compiler/base/name/NamedNode.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import * as ts from "typescript";
import {Constructor} from "./../../../Constructor";
import * as errors from "./../../../errors";
import {NamedNodeStructure} from "./../../../structures";
import {Node, Identifier} from "./../../common";
import {callBaseFill} from "./../../callBaseFill";

// todo: make name optional, but in a different class because TypeParameterDeclaration expects a name
// (maybe NameableNode and rename some of the other "-ed" classes)
Expand Down Expand Up @@ -41,5 +43,14 @@ export function NamedNode<T extends Constructor<NamedNodeExtensionType>>(Base: T
this.getNameIdentifier().rename(newName);
return this;
}

fill(structure: Partial<NamedNodeStructure>) {
callBaseFill(Base.prototype, this, structure);

if (structure.name != null)
this.rename(structure.name);

return this;
}
};
}
11 changes: 11 additions & 0 deletions src/compiler/base/name/PropertyNamedNode.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import * as ts from "typescript";
import {Constructor} from "./../../../Constructor";
import * as errors from "./../../../errors";
import {PropertyNamedNodeStructure} from "./../../../structures";
import {Node, Identifier} from "./../../common";
import {callBaseFill} from "./../../callBaseFill";

export type PropertyNamedNodeExtensionType = Node<ts.Node & { name: ts.PropertyName; }>;

Expand Down Expand Up @@ -34,5 +36,14 @@ export function PropertyNamedNode<T extends Constructor<PropertyNamedNodeExtensi
this.getNameIdentifier().rename(text);
return this;
}

fill(structure: Partial<PropertyNamedNodeStructure>) {
callBaseFill(Base.prototype, this, structure);

if (structure.name != null)
this.rename(structure.name);

return this;
}
};
}
131 changes: 130 additions & 1 deletion src/compiler/class/ClassDeclaration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import * as errors from "./../../errors";
import {insertIntoCreatableSyntaxList, insertIntoParent, getEndIndexFromArray, insertIntoBracesOrSourceFileWithFillAndGetChildren, verifyAndGetIndex,
removeStatementedNodeChild} from "./../../manipulation";
import {getNamedNodeByNameOrFindFunction, getNotFoundErrorMessageForNameOrFindFunction, TypeGuards, StringUtils} from "./../../utils";
import {PropertyDeclarationStructure, MethodDeclarationStructure, ConstructorDeclarationStructure, ClassDeclarationStructure} from "./../../structures";
import {PropertyDeclarationStructure, MethodDeclarationStructure, ConstructorDeclarationStructure, GetAccessorDeclarationStructure,
SetAccessorDeclarationStructure, ClassDeclarationStructure} from "./../../structures";
import {Node} from "./../common";
import {NamedNode, ExportableNode, ModifierableNode, AmbientableNode, DocumentationableNode, TypeParameteredNode, DecoratableNode, HeritageClauseableNode,
ImplementsClauseableNode, TextInsertableNode} from "./../base";
Expand Down Expand Up @@ -43,6 +44,10 @@ export class ClassDeclaration extends ClassDeclarationBase<ts.ClassDeclaration>
this.addConstructor(structure.ctor);
if (structure.properties != null)
this.addProperties(structure.properties);
if (structure.getAccessors != null)
this.addGetAccessors(structure.getAccessors);
if (structure.setAccessors != null)
this.addSetAccessors(structure.setAccessors);
if (structure.methods != null)
this.addMethods(structure.methods);

Expand Down Expand Up @@ -166,6 +171,130 @@ export class ClassDeclaration extends ClassDeclarationBase<ts.ClassDeclaration>
return this.getAllMembers().filter(m => TypeGuards.isConstructorDeclaration(m)) as ConstructorDeclaration[];
}

/**
* Add get accessor.
* @param structure - Structure representing the get accessor.
*/
addGetAccessor(structure: GetAccessorDeclarationStructure) {
return this.addGetAccessors([structure])[0];
}

/**
* Add properties.
* @param structures - Structures representing the properties.
*/
addGetAccessors(structures: GetAccessorDeclarationStructure[]) {
return this.insertGetAccessors(getEndIndexFromArray(this.getBodyMembers()), structures);
}

/**
* Insert get accessor.
* @param index - Index to insert at.
* @param structure - Structure representing the get accessor.
*/
insertGetAccessor(index: number, structure: GetAccessorDeclarationStructure) {
return this.insertGetAccessors(index, [structure])[0];
}

/**
* Insert properties.
* @param index - Index to insert at.
* @param structures - Structures representing the properties.
*/
insertGetAccessors(index: number, structures: GetAccessorDeclarationStructure[]) {
const indentationText = this.getChildIndentationText();
const newLineKind = this.global.manipulationSettings.getNewLineKind();

// create code
const codes: string[] = [];
for (const structure of structures) {
let code = `${indentationText}`;
if (structure.isStatic)
code += "static ";
code += `get ${structure.name}()`;
if (structure.returnType != null && structure.returnType.length > 0)
code += `: ${structure.returnType}`;
code += " {" + newLineKind + indentationText + "}";
codes.push(code);
}

return insertIntoBracesOrSourceFileWithFillAndGetChildren<GetAccessorDeclaration, GetAccessorDeclarationStructure>({
getIndexedChildren: () => this.getBodyMembers(),
sourceFile: this.getSourceFile(),
parent: this,
index,
childCodes: codes,
structures,
previousBlanklineWhen: () => true,
separatorNewlineWhen: () => true,
nextBlanklineWhen: () => true,
expectedKind: ts.SyntaxKind.GetAccessor,
fillFunction: (node, structure) => node.fill(structure)
});
}

/**
* Add set accessor.
* @param structure - Structure representing the set accessor.
*/
addSetAccessor(structure: SetAccessorDeclarationStructure) {
return this.addSetAccessors([structure])[0];
}

/**
* Add properties.
* @param structures - Structures representing the properties.
*/
addSetAccessors(structures: SetAccessorDeclarationStructure[]) {
return this.insertSetAccessors(getEndIndexFromArray(this.getBodyMembers()), structures);
}

/**
* Insert set accessor.
* @param index - Index to insert at.
* @param structure - Structure representing the set accessor.
*/
insertSetAccessor(index: number, structure: SetAccessorDeclarationStructure) {
return this.insertSetAccessors(index, [structure])[0];
}

/**
* Insert properties.
* @param index - Index to insert at.
* @param structures - Structures representing the properties.
*/
insertSetAccessors(index: number, structures: SetAccessorDeclarationStructure[]) {
const indentationText = this.getChildIndentationText();
const newLineKind = this.global.manipulationSettings.getNewLineKind();

// create code
const codes: string[] = [];
for (const structure of structures) {
let code = `${indentationText}`;
if (structure.isStatic)
code += "static ";
code += `set ${structure.name}()`;
if (structure.returnType != null && structure.returnType.length > 0)
code += `: ${structure.returnType}`;
code += " {" + newLineKind + indentationText + "}";
codes.push(code);
}

return insertIntoBracesOrSourceFileWithFillAndGetChildren<SetAccessorDeclaration, SetAccessorDeclarationStructure>({
getIndexedChildren: () => this.getBodyMembers(),
sourceFile: this.getSourceFile(),
parent: this,
index,
childCodes: codes,
structures,
previousBlanklineWhen: () => true,
separatorNewlineWhen: () => true,
nextBlanklineWhen: () => true,
expectedKind: ts.SyntaxKind.SetAccessor,
fillFunction: (node, structure) => node.fill(structure)
});
}

/**
* Add property.
* @param structure - Structure representing the property.
Expand Down
11 changes: 11 additions & 0 deletions src/compiler/class/GetAccessorDeclaration.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import * as ts from "typescript";
import * as errors from "./../../errors";
import {removeClassMember} from "./../../manipulation";
import {GetAccessorDeclarationStructure} from "./../../structures";
import {callBaseFill} from "./../callBaseFill";
import {Node} from "./../common";
import {PropertyNamedNode, StaticableNode, ScopedNode, DecoratableNode, BodiedNode, TextInsertableNode} from "./../base";
import {FunctionLikeDeclaration} from "./../function";
Expand All @@ -12,6 +14,15 @@ export const GetAccessorDeclarationBase = TextInsertableNode(DecoratableNode(Abs
BodiedNode(FunctionLikeDeclaration(PropertyNamedNode(Node)))
)))));
export class GetAccessorDeclaration extends GetAccessorDeclarationBase<ts.GetAccessorDeclaration> {
/**
* Fills the node from a structure.
* @param structure - Structure to fill.
*/
fill(structure: Partial<GetAccessorDeclarationStructure>) {
callBaseFill(GetAccessorDeclarationBase.prototype, this, structure);
return this;
}

/**
* Gets the corresponding set accessor if one exists.
*/
Expand Down
11 changes: 11 additions & 0 deletions src/compiler/class/SetAccessorDeclaration.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import * as ts from "typescript";
import * as errors from "./../../errors";
import {removeClassMember} from "./../../manipulation";
import {SetAccessorDeclarationStructure} from "./../../structures";
import {callBaseFill} from "./../callBaseFill";
import {Node} from "./../common";
import {PropertyNamedNode, StaticableNode, ScopedNode, DecoratableNode, BodiedNode, TextInsertableNode} from "./../base";
import {FunctionLikeDeclaration} from "./../function";
Expand All @@ -12,6 +14,15 @@ export const SetAccessorDeclarationBase = TextInsertableNode(DecoratableNode(Abs
BodiedNode(FunctionLikeDeclaration(PropertyNamedNode(Node))
))))));
export class SetAccessorDeclaration extends SetAccessorDeclarationBase<ts.SetAccessorDeclaration> {
/**
* Fills the node from a structure.
* @param structure - Structure to fill.
*/
fill(structure: Partial<SetAccessorDeclarationStructure>) {
callBaseFill(SetAccessorDeclarationBase.prototype, this, structure);
return this;
}

/**
* Gets the corresponding get accessor if one exists.
*/
Expand Down
2 changes: 1 addition & 1 deletion src/manipulation/getMixinStructureFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export function fromInitializerExpressionableNode(node: compiler.InitializerExpr
};
}

export function fromNamedNode(node: compiler.NamedNode): MakeRequired<structures.NamedStructure> {
export function fromNamedNode(node: compiler.NamedNode): MakeRequired<structures.NamedNodeStructure> {
return {
name: node.getName()
};
Expand Down
2 changes: 1 addition & 1 deletion src/structures/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export * from "./base/GeneratorableNodeStructure";
export * from "./base/ExtendsClauseableNodeStructure";
export * from "./base/ImplementsClauseableNodeStructure";
export * from "./base/InitializerExpressionableNodeStructure";
export * from "./base/NamedStructure";
export * from "./base/name";
export * from "./base/QuestionTokenableNodeStructure";
export * from "./base/ParameteredNodeStructure";
export * from "./base/ReadonlyableNodeStructure";
Expand Down
3 changes: 0 additions & 3 deletions src/structures/base/NamedStructure.ts

This file was deleted.

4 changes: 4 additions & 0 deletions src/structures/base/name.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from "./name/BindingNamedNodeStructure";
export * from "./name/DeclarationNamedNodeStructure";
export * from "./name/NamedNodeStructure";
export * from "./name/PropertyNamedNodeStructure";
3 changes: 3 additions & 0 deletions src/structures/base/name/BindingNamedNodeStructure.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface BindingNamedNodeStructure {
name: string;
}
3 changes: 3 additions & 0 deletions src/structures/base/name/DeclarationNamedNodeStructure.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface DeclarationNamedNodeStructure {
name: string;
}
3 changes: 3 additions & 0 deletions src/structures/base/name/NamedNodeStructure.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface NamedNodeStructure {
name: string;
}
3 changes: 3 additions & 0 deletions src/structures/base/name/PropertyNamedNodeStructure.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface PropertyNamedNodeStructure {
name: string;
}
2 changes: 2 additions & 0 deletions src/structures/class.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export * from "./class/ClassDeclarationStructure";
export * from "./class/ConstructorDeclarationStructure";
export * from "./class/GetAccessorDeclarationStructure";
export * from "./class/MethodDeclarationStructure";
export * from "./class/PropertyDeclarationStructure";
export * from "./class/SetAccessorDeclarationStructure";
8 changes: 6 additions & 2 deletions src/structures/class/ClassDeclarationStructure.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import {NamedStructure, ImplementsClauseableNodeStructure, DecoratableNodeStructure, TypeParameteredNodeStructure,
import {NamedNodeStructure, ImplementsClauseableNodeStructure, DecoratableNodeStructure, TypeParameteredNodeStructure,
DocumentationableNodeStructure, AmbientableNodeStructure, AbstractableNodeStructure, ExportableNodeStructure} from "./../base";
import {PropertyDeclarationStructure} from "./PropertyDeclarationStructure";
import {MethodDeclarationStructure} from "./MethodDeclarationStructure";
import {ConstructorDeclarationStructure} from "./ConstructorDeclarationStructure";
import {GetAccessorDeclarationStructure} from "./GetAccessorDeclarationStructure";
import {SetAccessorDeclarationStructure} from "./SetAccessorDeclarationStructure";

export interface ClassDeclarationStructure
extends NamedStructure, ClassDeclarationSpecificStructure, ImplementsClauseableNodeStructure, DecoratableNodeStructure,
extends NamedNodeStructure, ClassDeclarationSpecificStructure, ImplementsClauseableNodeStructure, DecoratableNodeStructure,
TypeParameteredNodeStructure, DocumentationableNodeStructure, AmbientableNodeStructure, AbstractableNodeStructure, ExportableNodeStructure
{
}
Expand All @@ -14,5 +16,7 @@ export interface ClassDeclarationSpecificStructure {
extends?: string;
ctor?: ConstructorDeclarationStructure;
properties?: PropertyDeclarationStructure[];
getAccessors?: GetAccessorDeclarationStructure[];
setAccessors?: SetAccessorDeclarationStructure[];
methods?: MethodDeclarationStructure[];
}

0 comments on commit 7c30fe6

Please sign in to comment.