Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/compiler/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1231,6 +1231,8 @@ namespace ts {

export interface ObjectAllocator {
getNodeConstructor(): new (kind: SyntaxKind, pos?: number, end?: number) => Node;
getTokenConstructor(): new (kind: SyntaxKind, pos?: number, end?: number) => Token;
getIdentifierConstructor(): new (kind: SyntaxKind, pos?: number, end?: number) => Token;
getSourceFileConstructor(): new (kind: SyntaxKind, pos?: number, end?: number) => SourceFile;
getSymbolConstructor(): new (flags: SymbolFlags, name: string) => Symbol;
getTypeConstructor(): new (checker: TypeChecker, flags: TypeFlags) => Type;
Expand Down Expand Up @@ -1260,6 +1262,8 @@ namespace ts {

export let objectAllocator: ObjectAllocator = {
getNodeConstructor: () => <any>Node,
getTokenConstructor: () => <any>Node,
getIdentifierConstructor: () => <any>Node,
getSourceFileConstructor: () => <any>Node,
getSymbolConstructor: () => <any>Symbol,
getTypeConstructor: () => <any>Type,
Expand Down
22 changes: 18 additions & 4 deletions src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,20 @@ namespace ts {
/* @internal */ export let parseTime = 0;

let NodeConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
let TokenConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
let IdentifierConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
let SourceFileConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;

export function createNode(kind: SyntaxKind, pos?: number, end?: number): Node {
if (kind === SyntaxKind.SourceFile) {
return new (SourceFileConstructor || (SourceFileConstructor = objectAllocator.getSourceFileConstructor()))(kind, pos, end);
}
else if (kind === SyntaxKind.Identifier) {
return new (IdentifierConstructor || (IdentifierConstructor = objectAllocator.getIdentifierConstructor()))(kind, pos, end);
}
else if (kind < SyntaxKind.FirstNode) {
return new (TokenConstructor || (TokenConstructor = objectAllocator.getTokenConstructor()))(kind, pos, end);
}
else {
return new (NodeConstructor || (NodeConstructor = objectAllocator.getNodeConstructor()))(kind, pos, end);
}
Expand Down Expand Up @@ -466,6 +474,8 @@ namespace ts {

// capture constructors in 'initializeState' to avoid null checks
let NodeConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
let TokenConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
let IdentifierConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
let SourceFileConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;

let sourceFile: SourceFile;
Expand Down Expand Up @@ -576,6 +586,8 @@ namespace ts {

function initializeState(fileName: string, _sourceText: string, languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor, scriptKind: ScriptKind) {
NodeConstructor = objectAllocator.getNodeConstructor();
TokenConstructor = objectAllocator.getTokenConstructor();
IdentifierConstructor = objectAllocator.getIdentifierConstructor();
SourceFileConstructor = objectAllocator.getSourceFileConstructor();

sourceText = _sourceText;
Expand Down Expand Up @@ -1018,13 +1030,15 @@ namespace ts {
}

// note: this function creates only node
function createNode(kind: SyntaxKind, pos?: number): Node {
function createNode(kind: SyntaxKind, pos?: number): Node | Token | Identifier {
nodeCount++;
if (!(pos >= 0)) {
pos = scanner.getStartPos();
}

return new NodeConstructor(kind, pos, pos);
return kind >= SyntaxKind.FirstNode ? new NodeConstructor(kind, pos, pos) :
kind === SyntaxKind.Identifier ? new IdentifierConstructor(kind, pos, pos) :
new TokenConstructor(kind, pos, pos);
}

function finishNode<T extends Node>(node: T, end?: number): T {
Expand Down Expand Up @@ -5095,7 +5109,7 @@ namespace ts {
}

flags |= modifierToFlag(modifierKind);
modifiers.push(finishNode(createNode(modifierKind, modifierStart)));
modifiers.push(finishNode(<Modifier>createNode(modifierKind, modifierStart)));
}
if (modifiers) {
modifiers.flags = flags;
Expand All @@ -5114,7 +5128,7 @@ namespace ts {
modifiers = <ModifiersArray>[];
modifiers.pos = modifierStart;
flags |= modifierToFlag(modifierKind);
modifiers.push(finishNode(createNode(modifierKind, modifierStart)));
modifiers.push(finishNode(<Modifier>createNode(modifierKind, modifierStart)));
modifiers.flags = flags;
modifiers.end = scanner.getStartPos();
}
Expand Down
6 changes: 5 additions & 1 deletion src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,10 @@ namespace ts {
flags: NodeFlags;
}

export interface Token extends Node {
__tokenTag: any;
}

// @kind(SyntaxKind.AbstractKeyword)
// @kind(SyntaxKind.AsyncKeyword)
// @kind(SyntaxKind.ConstKeyword)
Expand All @@ -482,7 +486,7 @@ namespace ts {
// @kind(SyntaxKind.PrivateKeyword)
// @kind(SyntaxKind.ProtectedKeyword)
// @kind(SyntaxKind.StaticKeyword)
export interface Modifier extends Node { }
export interface Modifier extends Token { }

// @kind(SyntaxKind.Identifier)
export interface Identifier extends PrimaryExpression {
Expand Down
104 changes: 98 additions & 6 deletions src/services/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,10 @@ namespace ts {
];
let jsDocCompletionEntries: CompletionEntry[];

function createNode(kind: SyntaxKind, pos: number, end: number, flags: NodeFlags, parent?: Node): NodeObject {
const node = new NodeObject(kind, pos, end);
node.flags = flags;
function createNode(kind: SyntaxKind, pos: number, end: number, parent?: Node): NodeObject | TokenObject | IdentifierObject {
const node = kind >= SyntaxKind.FirstNode ? new NodeObject(kind, pos, end) :
kind === SyntaxKind.Identifier ? new IdentifierObject(kind, pos, end) :
new TokenObject(kind, pos, end);
node.parent = parent;
return node;
}
Expand All @@ -197,11 +198,11 @@ namespace ts {
private _children: Node[];

constructor(kind: SyntaxKind, pos: number, end: number) {
this.kind = kind;
this.pos = pos;
this.end = end;
this.flags = NodeFlags.None;
this.parent = undefined;
this.kind = kind;
}

public getSourceFile(): SourceFile {
Expand Down Expand Up @@ -246,15 +247,15 @@ namespace ts {
const token = useJSDocScanner ? scanner.scanJSDocToken() : scanner.scan();
const textPos = scanner.getTextPos();
if (textPos <= end) {
nodes.push(createNode(token, pos, textPos, 0, this));
nodes.push(createNode(token, pos, textPos, this));
}
pos = textPos;
}
return pos;
}

private createSyntaxList(nodes: NodeArray<Node>): Node {
const list = createNode(SyntaxKind.SyntaxList, nodes.pos, nodes.end, 0, this);
const list = <NodeObject>createNode(SyntaxKind.SyntaxList, nodes.pos, nodes.end, this);
list._children = [];
let pos = nodes.pos;

Expand Down Expand Up @@ -345,6 +346,95 @@ namespace ts {
}
}

class TokenOrIdentifierObject implements Token {
public kind: SyntaxKind;
public pos: number;
public end: number;
public flags: NodeFlags;
public parent: Node;
public jsDocComments: JSDocComment[];
public __tokenTag: any;

constructor(pos: number, end: number) {
// Set properties in same order as NodeObject
this.pos = pos;
this.end = end;
this.flags = NodeFlags.None;
this.parent = undefined;
}

public getSourceFile(): SourceFile {
return getSourceFileOfNode(this);
}

public getStart(sourceFile?: SourceFile, includeJsDocComment?: boolean): number {
return getTokenPosOfNode(this, sourceFile, includeJsDocComment);
}

public getFullStart(): number {
return this.pos;
}

public getEnd(): number {
return this.end;
}

public getWidth(sourceFile?: SourceFile): number {
return this.getEnd() - this.getStart(sourceFile);
}

public getFullWidth(): number {
return this.end - this.pos;
}

public getLeadingTriviaWidth(sourceFile?: SourceFile): number {
return this.getStart(sourceFile) - this.pos;
}

public getFullText(sourceFile?: SourceFile): string {
return (sourceFile || this.getSourceFile()).text.substring(this.pos, this.end);
}

public getText(sourceFile?: SourceFile): string {
return (sourceFile || this.getSourceFile()).text.substring(this.getStart(), this.getEnd());
}

public getChildCount(sourceFile?: SourceFile): number {
return 0;
}

public getChildAt(index: number, sourceFile?: SourceFile): Node {
return undefined;
}

public getChildren(sourceFile?: SourceFile): Node[] {
return emptyArray;
}

public getFirstToken(sourceFile?: SourceFile): Node {
return undefined;
}

public getLastToken(sourceFile?: SourceFile): Node {
return undefined;
}
}

class TokenObject extends TokenOrIdentifierObject {
public kind: SyntaxKind;
constructor(kind: SyntaxKind, pos: number, end: number) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

public kind

super(pos, end);
this.kind = kind;
}
}

class IdentifierObject extends TokenOrIdentifierObject {
constructor(kind: SyntaxKind, pos: number, end: number) {
super(pos, end);
}
}
IdentifierObject.prototype.kind = SyntaxKind.Identifier;

class SymbolObject implements Symbol {
flags: SymbolFlags;
name: string;
Expand Down Expand Up @@ -8696,6 +8786,8 @@ namespace ts {
function initializeServices() {
objectAllocator = {
getNodeConstructor: () => NodeObject,
getTokenConstructor: () => TokenObject,
getIdentifierConstructor: () => IdentifierObject,
getSourceFileConstructor: () => SourceFileObject,
getSymbolConstructor: () => SymbolObject,
getTypeConstructor: () => TypeObject,
Expand Down