-
Notifications
You must be signed in to change notification settings - Fork 189
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: #204 - Add IterationStatement, Do, ForIn, ForOf, For, While
- Loading branch information
Showing
28 changed files
with
1,065 additions
and
64 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
import * as ts from "typescript"; | ||
import {Constructor} from "./../../Constructor"; | ||
import * as errors from "./../../errors"; | ||
import {AwaitableNodeStructure} from "./../../structures"; | ||
import {callBaseFill} from "./../callBaseFill"; | ||
import {insertIntoParent, removeChildren, FormattingKind} from "./../../manipulation"; | ||
import {Node} from "./../common"; | ||
import {NamedNode} from "./../base"; | ||
|
||
export type AwaitableNodeExtensionType = Node<ts.Node & { awaitModifier?: ts.AwaitKeywordToken; }>; | ||
|
||
export interface AwaitableNode { | ||
/** | ||
* If it's an awaited node. | ||
*/ | ||
isAwaited(): boolean; | ||
/** | ||
* Gets the await token or undefined if none exists. | ||
*/ | ||
getAwaitKeyword(): Node<ts.AwaitKeywordToken> | undefined; | ||
/** | ||
* Gets the await token or throws if none exists. | ||
*/ | ||
getAwaitKeywordOrThrow(): Node<ts.AwaitKeywordToken>; | ||
/** | ||
* Sets if the node is awaited. | ||
* @param value - If it should be awaited or not. | ||
*/ | ||
setIsAwaited(value: boolean): this; | ||
} | ||
|
||
export function AwaitableNode<T extends Constructor<AwaitableNodeExtensionType>>(Base: T): Constructor<AwaitableNode> & T { | ||
return class extends Base implements AwaitableNode { | ||
isAwaited() { | ||
return this.compilerNode.awaitModifier != null; | ||
} | ||
|
||
getAwaitKeyword(): Node<ts.AwaitKeywordToken> | undefined { | ||
const awaitModifier = this.compilerNode.awaitModifier; | ||
return awaitModifier == null ? undefined : (this.getNodeFromCompilerNode(awaitModifier) as Node<ts.AwaitKeywordToken>); | ||
} | ||
|
||
getAwaitKeywordOrThrow(): Node<ts.AwaitKeywordToken> { | ||
return errors.throwIfNullOrUndefined(this.getAwaitKeyword(), "Expected to find an await token."); | ||
} | ||
|
||
setIsAwaited(value: boolean) { | ||
const awaitModifier = this.getAwaitKeyword(); | ||
const isSet = awaitModifier != null; | ||
|
||
if (isSet === value) | ||
return this; | ||
|
||
if (awaitModifier == null) { | ||
const info = getAwaitInsertInfo(this); | ||
insertIntoParent({ | ||
insertPos: info.pos, | ||
childIndex: info.childIndex, | ||
insertItemsCount: 1, | ||
parent: this, | ||
newText: " await" | ||
}); | ||
} | ||
else { | ||
removeChildren({ | ||
children: [awaitModifier], | ||
removePrecedingSpaces: true | ||
}); | ||
} | ||
|
||
return this; | ||
} | ||
|
||
fill(structure: Partial<AwaitableNodeStructure>) { | ||
callBaseFill(Base.prototype, this, structure); | ||
|
||
if (structure.isAwaited != null) | ||
this.setIsAwaited(structure.isAwaited); | ||
|
||
return this; | ||
} | ||
}; | ||
} | ||
|
||
function getAwaitInsertInfo(node: Node) { | ||
if (node.getKind() === ts.SyntaxKind.ForOfStatement) { | ||
const forKeyword = node.getFirstChildByKindOrThrow(ts.SyntaxKind.ForKeyword); | ||
return { | ||
pos: forKeyword.getEnd(), | ||
childIndex: forKeyword.getChildIndex() + 1 | ||
}; | ||
} | ||
|
||
throw new errors.NotImplementedError("Expected a for of statement node."); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import * as ts from "typescript"; | ||
import {Expression} from "./../common"; | ||
import {IterationStatement} from "./IterationStatement"; | ||
|
||
export const DoStatementBase = IterationStatement; | ||
export class DoStatement extends DoStatementBase<ts.DoStatement> { | ||
/** | ||
* Gets this do statement's expression. | ||
*/ | ||
getExpression() { | ||
return this.getNodeFromCompilerNode(this.compilerNode.expression) as Expression; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import * as ts from "typescript"; | ||
import {Expression} from "./../common"; | ||
import {IterationStatement} from "./IterationStatement"; | ||
import {VariableDeclarationList} from "./VariableDeclarationList"; | ||
|
||
export const ForInStatementBase = IterationStatement; | ||
export class ForInStatement extends ForInStatementBase<ts.ForInStatement> { | ||
|
||
/** | ||
* Gets this for in statement's initializer. | ||
*/ | ||
getInitializer() { | ||
return this.getNodeFromCompilerNode(this.compilerNode.initializer) as (VariableDeclarationList | Expression); | ||
} | ||
|
||
/** | ||
* Gets this for in statement's expression. | ||
*/ | ||
getExpression() { | ||
return this.getNodeFromCompilerNode(this.compilerNode.expression) as Expression; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import * as ts from "typescript"; | ||
import {callBaseFill} from "./../callBaseFill"; | ||
import {Expression} from "./../common"; | ||
import {ForOfStatementStructure} from "./../../structures"; | ||
import {IterationStatement} from "./IterationStatement"; | ||
import {VariableDeclarationList} from "./VariableDeclarationList"; | ||
import {AwaitableNode} from "../base"; | ||
|
||
export const ForOfStatementBase = AwaitableNode(IterationStatement); | ||
export class ForOfStatement extends ForOfStatementBase<ts.ForOfStatement> { | ||
/** | ||
* Gets this for of statement's initializer. | ||
*/ | ||
getInitializer() { | ||
return this.getNodeFromCompilerNode(this.compilerNode.initializer) as (VariableDeclarationList | Expression); | ||
} | ||
|
||
/** | ||
* Gets this for of statement's expression. | ||
*/ | ||
getExpression() { | ||
return this.getNodeFromCompilerNode(this.compilerNode.expression) as Expression; | ||
} | ||
|
||
/** | ||
* Fills the node from a structure. | ||
* @param structure - Structure to fill. | ||
*/ | ||
fill(structure: Partial<ForOfStatementStructure>) { | ||
callBaseFill(ForOfStatementBase.prototype, this, structure); | ||
return this; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import * as ts from "typescript"; | ||
import * as errors from "./../../errors"; | ||
import {Expression} from "./../common"; | ||
import {IterationStatement} from "./IterationStatement"; | ||
import {VariableDeclarationList} from "./VariableDeclarationList"; | ||
|
||
export const ForStatementBase = IterationStatement; | ||
export class ForStatement extends ForStatementBase<ts.ForStatement> { | ||
|
||
/** | ||
* Gets this for statement's initializer or undefined if none exists. | ||
*/ | ||
getInitializer() { | ||
return this.compilerNode.initializer == null | ||
? undefined | ||
: this.getNodeFromCompilerNode(this.compilerNode.initializer) as (VariableDeclarationList | Expression); | ||
} | ||
|
||
/** | ||
* Gets this for statement's initializer or throws if none exists. | ||
*/ | ||
getInitializerOrThrow() { | ||
return errors.throwIfNullOrUndefined(this.getInitializer(), "Expected to find an initializer."); | ||
} | ||
|
||
/** | ||
* Gets this for statement's condition or undefined if none exists. | ||
*/ | ||
getCondition() { | ||
return this.compilerNode.condition == null | ||
? undefined | ||
: this.getNodeFromCompilerNode(this.compilerNode.condition) as Expression; | ||
} | ||
|
||
/** | ||
* Gets this for statement's condition or throws if none exists. | ||
*/ | ||
getConditionOrThrow() { | ||
return errors.throwIfNullOrUndefined(this.getCondition(), "Expected to find a condition."); | ||
} | ||
|
||
/** | ||
* Gets this for statement's incrementor. | ||
*/ | ||
getIncrementor() { | ||
return this.compilerNode.incrementor == null | ||
? undefined | ||
: this.getNodeFromCompilerNode(this.compilerNode.incrementor) as Expression; | ||
} | ||
|
||
/** | ||
* Gets this for statement's incrementor or throws if none exists. | ||
*/ | ||
getIncrementorOrThrow() { | ||
return errors.throwIfNullOrUndefined(this.getIncrementor(), "Expected to find an incrementor."); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import * as ts from "typescript"; | ||
import {removeStatementedNodeChild} from "./../../manipulation"; | ||
import {ChildOrderableNode} from "./../base"; | ||
import {Statement} from "./Statement"; | ||
|
||
export const IterationStatementBase = ChildOrderableNode(Statement); | ||
export class IterationStatement<T extends ts.IterationStatement = ts.IterationStatement> extends IterationStatementBase<T> { | ||
/** | ||
* Gets this iteration statement's statement. | ||
*/ | ||
getStatement() { | ||
return this.getNodeFromCompilerNode(this.compilerNode.statement) as Statement; | ||
} | ||
|
||
/** | ||
* Removes this iteration statement. | ||
*/ | ||
remove() { | ||
removeStatementedNodeChild(this); | ||
} | ||
} |
Oops, something went wrong.