mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-15 11:35:42 -06:00
Added more control over sourcemap/comment emit and fixed a number of source map emit issues.
This commit is contained in:
parent
3ef9ab475d
commit
cee4954090
@ -77,10 +77,15 @@ namespace ts {
|
||||
emitTrailingDetachedComments
|
||||
};
|
||||
|
||||
function getLeadingComments(range: Node, shouldSkipCommentsForNodeCallback?: (node: Node) => boolean, getCustomCommentRangeForNodeCallback?: (node: Node) => TextRange): CommentRange[];
|
||||
function getLeadingComments(range: TextRange): CommentRange[];
|
||||
function getLeadingComments(range: TextRange | Node, shouldSkipCommentsForNodeCallback?: (node: Node) => boolean, getCustomCommentRangeForNodeCallback?: (node: Node) => TextRange) {
|
||||
if (shouldSkipCommentsForNodeCallback && shouldSkipCommentsForNodeCallback(<Node>range)) {
|
||||
function getLeadingComments(node: Node, shouldSkipCommentsForNodeCallback?: (node: Node) => boolean, getCustomCommentRangeForNodeCallback?: (node: Node) => TextRange): CommentRange[];
|
||||
function getLeadingComments(nodeOrRange: TextRange | Node, shouldSkipCommentsForNodeCallback?: (node: Node) => boolean, getCustomCommentRangeForNodeCallback?: (node: Node) => TextRange) {
|
||||
let range = nodeOrRange;
|
||||
if (getCustomCommentRangeForNodeCallback) {
|
||||
range = getCustomCommentRangeForNodeCallback(<Node>nodeOrRange) || range;
|
||||
}
|
||||
|
||||
if (shouldSkipCommentsForNodeCallback && shouldSkipCommentsForNodeCallback(<Node>nodeOrRange)) {
|
||||
// If the node will not be emitted in JS, remove all the comments (normal,
|
||||
// pinned and `///`) associated with the node, unless it is a triple slash
|
||||
// comment at the top of the file.
|
||||
@ -100,10 +105,6 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (getCustomCommentRangeForNodeCallback) {
|
||||
range = getCustomCommentRangeForNodeCallback(<Node>range) || range;
|
||||
}
|
||||
|
||||
return getLeadingCommentsOfPosition(range.pos);
|
||||
}
|
||||
|
||||
@ -123,15 +124,16 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
function getTrailingComments(range: Node, shouldSkipCommentsForNodeCallback?: (node: Node) => boolean, getCustomCommentRangeForNodeCallback?: (node: Node) => TextRange): CommentRange[];
|
||||
function getTrailingComments(range: TextRange): CommentRange[];
|
||||
function getTrailingComments(range: TextRange | Node, shouldSkipCommentsForNodeCallback?: (node: Node) => boolean, getCustomCommentRangeForNodeCallback?: (node: Node) => TextRange) {
|
||||
if (shouldSkipCommentsForNodeCallback && shouldSkipCommentsForNodeCallback(<Node>range)) {
|
||||
function getTrailingComments(node: Node, shouldSkipCommentsForNodeCallback?: (node: Node) => boolean, getCustomCommentRangeForNodeCallback?: (node: Node) => TextRange): CommentRange[];
|
||||
function getTrailingComments(nodeOrRange: TextRange | Node, shouldSkipCommentsForNodeCallback?: (node: Node) => boolean, getCustomCommentRangeForNodeCallback?: (node: Node) => TextRange) {
|
||||
let range = <TextRange>nodeOrRange;
|
||||
if (shouldSkipCommentsForNodeCallback && shouldSkipCommentsForNodeCallback(<Node>nodeOrRange)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (getCustomCommentRangeForNodeCallback) {
|
||||
range = getCustomCommentRangeForNodeCallback(<Node>range) || range;
|
||||
range = getCustomCommentRangeForNodeCallback(<Node>nodeOrRange) || range;
|
||||
}
|
||||
|
||||
return getTrailingCommentsOfPosition(range.end);
|
||||
|
||||
@ -8,7 +8,7 @@ namespace ts {
|
||||
let NodeConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
|
||||
let SourceFileConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
|
||||
|
||||
function createNode(kind: SyntaxKind, location?: TextRange, flags?: NodeFlags): Node {
|
||||
function createNode(kind: SyntaxKind, location?: TextRange, flags?: NodeFlags, emitOptions?: NodeEmitOptions): Node {
|
||||
const ConstructorForKind = kind === SyntaxKind.SourceFile
|
||||
? (SourceFileConstructor || (SourceFileConstructor = objectAllocator.getSourceFileConstructor()))
|
||||
: (NodeConstructor || (NodeConstructor = objectAllocator.getNodeConstructor()));
|
||||
@ -21,6 +21,10 @@ namespace ts {
|
||||
node.flags = flags;
|
||||
}
|
||||
|
||||
if (emitOptions) {
|
||||
node.emitOptions = emitOptions;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -64,11 +68,11 @@ namespace ts {
|
||||
/**
|
||||
* Creates a shallow, memberwise clone of a node with no source map location.
|
||||
*/
|
||||
export function getSynthesizedClone<T extends Node>(node: T): T {
|
||||
export function getSynthesizedClone<T extends Node>(node: T, emitOptions?: NodeEmitOptions): T {
|
||||
// We don't use "clone" from core.ts here, as we need to preserve the prototype chain of
|
||||
// the original node. We also need to exclude specific properties and only include own-
|
||||
// properties (to skip members already defined on the shared prototype).
|
||||
const clone = <T>createNode(node.kind, /*location*/ undefined);
|
||||
const clone = <T>createNode(node.kind, /*location*/ undefined, /*flags*/ undefined, emitOptions);
|
||||
clone.flags = node.flags;
|
||||
clone.original = node;
|
||||
|
||||
@ -86,29 +90,19 @@ namespace ts {
|
||||
/**
|
||||
* Creates a shallow, memberwise clone of a node for mutation.
|
||||
*/
|
||||
export function getMutableClone<T extends Node>(node: T): T {
|
||||
const clone = getSynthesizedClone(node);
|
||||
export function getMutableClone<T extends Node>(node: T, emitOptions?: NodeEmitOptions): T {
|
||||
const clone = getSynthesizedClone(node, emitOptions);
|
||||
clone.pos = node.pos;
|
||||
clone.end = node.end;
|
||||
clone.parent = node.parent;
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a shallow, memberwise clone of a node at the specified source map location.
|
||||
*/
|
||||
export function getRelocatedClone<T extends Node>(node: T, location: TextRange): T {
|
||||
const clone = getSynthesizedClone(node);
|
||||
clone.pos = location.pos;
|
||||
clone.end = location.end;
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a clone of a node with a unique node ID.
|
||||
*/
|
||||
export function getUniqueClone<T extends Node>(node: T): T {
|
||||
const clone = getMutableClone(node);
|
||||
export function getUniqueClone<T extends Node>(node: T, emitOptions?: NodeEmitOptions): T {
|
||||
const clone = getMutableClone(node, emitOptions);
|
||||
clone.id = undefined;
|
||||
getNodeId(clone);
|
||||
return clone;
|
||||
@ -116,26 +110,26 @@ namespace ts {
|
||||
|
||||
// Literals
|
||||
|
||||
export function createLiteral(textSource: StringLiteral | Identifier, location?: TextRange): StringLiteral;
|
||||
export function createLiteral(value: string, location?: TextRange): StringLiteral;
|
||||
export function createLiteral(value: number, location?: TextRange): LiteralExpression;
|
||||
export function createLiteral(value: string | number | boolean, location?: TextRange): PrimaryExpression;
|
||||
export function createLiteral(value: string | number | boolean | StringLiteral | Identifier, location?: TextRange): PrimaryExpression {
|
||||
export function createLiteral(textSource: StringLiteral | Identifier, location?: TextRange, emitOptions?: NodeEmitOptions): StringLiteral;
|
||||
export function createLiteral(value: string, location?: TextRange, emitOptions?: NodeEmitOptions): StringLiteral;
|
||||
export function createLiteral(value: number, location?: TextRange, emitOptions?: NodeEmitOptions): LiteralExpression;
|
||||
export function createLiteral(value: string | number | boolean, location?: TextRange, emitOptions?: NodeEmitOptions): PrimaryExpression;
|
||||
export function createLiteral(value: string | number | boolean | StringLiteral | Identifier, location?: TextRange, emitOptions?: NodeEmitOptions): PrimaryExpression {
|
||||
if (typeof value === "number") {
|
||||
const node = <LiteralExpression>createNode(SyntaxKind.NumericLiteral, location);
|
||||
const node = <LiteralExpression>createNode(SyntaxKind.NumericLiteral, location, /*flags*/ undefined, emitOptions);
|
||||
node.text = value.toString();
|
||||
return node;
|
||||
}
|
||||
else if (typeof value === "boolean") {
|
||||
return <PrimaryExpression>createNode(value ? SyntaxKind.TrueKeyword : SyntaxKind.FalseKeyword, location);
|
||||
return <PrimaryExpression>createNode(value ? SyntaxKind.TrueKeyword : SyntaxKind.FalseKeyword, location, /*flags*/ undefined, emitOptions);
|
||||
}
|
||||
else if (typeof value === "string") {
|
||||
const node = <StringLiteral>createNode(SyntaxKind.StringLiteral, location);
|
||||
const node = <StringLiteral>createNode(SyntaxKind.StringLiteral, location, /*flags*/ undefined, emitOptions);
|
||||
node.text = value;
|
||||
return node;
|
||||
}
|
||||
else {
|
||||
const node = <StringLiteral>createNode(SyntaxKind.StringLiteral, location);
|
||||
const node = <StringLiteral>createNode(SyntaxKind.StringLiteral, location, /*flags*/ undefined, emitOptions);
|
||||
node.textSourceNode = value;
|
||||
node.text = value.text;
|
||||
return node;
|
||||
@ -256,10 +250,14 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function createParameter(name: string | Identifier | BindingPattern, initializer?: Expression, location?: TextRange) {
|
||||
return createParameterWithDotDotDotToken(/*dotDotDotToken*/ undefined, name, initializer, location);
|
||||
}
|
||||
|
||||
export function createParameterWithDotDotDotToken(dotDotDotToken: Node, name: string | Identifier | BindingPattern, initializer?: Expression, location?: TextRange) {
|
||||
const node = <ParameterDeclaration>createNode(SyntaxKind.Parameter, location);
|
||||
node.decorators = undefined;
|
||||
node.modifiers = undefined;
|
||||
node.dotDotDotToken = undefined;
|
||||
node.dotDotDotToken = dotDotDotToken;
|
||||
node.name = typeof name === "string" ? createIdentifier(name) : name;
|
||||
node.questionToken = undefined;
|
||||
node.type = undefined;
|
||||
@ -287,8 +285,8 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createPropertyAccess(expression: Expression, name: string | Identifier, location?: TextRange) {
|
||||
const node = <PropertyAccessExpression>createNode(SyntaxKind.PropertyAccessExpression, location);
|
||||
export function createPropertyAccess(expression: Expression, name: string | Identifier, location?: TextRange, emitOptions?: NodeEmitOptions) {
|
||||
const node = <PropertyAccessExpression>createNode(SyntaxKind.PropertyAccessExpression, location, /*flags*/ undefined, emitOptions);
|
||||
node.expression = parenthesizeForAccess(expression);
|
||||
node.dotToken = createSynthesizedNode(SyntaxKind.DotToken);
|
||||
node.name = typeof name === "string" ? createIdentifier(name) : name;
|
||||
@ -738,7 +736,7 @@ namespace ts {
|
||||
|
||||
export function createMemberAccessForPropertyName(target: Expression, memberName: PropertyName, location?: TextRange): MemberExpression {
|
||||
if (isIdentifier(memberName)) {
|
||||
return createPropertyAccess(target, getSynthesizedClone(memberName), location);
|
||||
return createPropertyAccess(target, memberName, location, { flags: NodeEmitFlags.NoNestedSourceMaps | NodeEmitFlags.Merge });
|
||||
}
|
||||
else if (isComputedPropertyName(memberName)) {
|
||||
return createElementAccess(target, memberName.expression, location);
|
||||
@ -749,8 +747,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function createRestParameter(name: string | Identifier) {
|
||||
const node = createParameter(name, /*initializer*/ undefined);
|
||||
node.dotDotDotToken = createSynthesizedNode(SyntaxKind.DotDotDotToken);
|
||||
const node = createParameterWithDotDotDotToken(createSynthesizedNode(SyntaxKind.DotDotDotToken), name, /*initializer*/ undefined);
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -1279,10 +1276,16 @@ namespace ts {
|
||||
: getSynthesizedClone(node);
|
||||
}
|
||||
|
||||
export function createExpressionForPropertyName(memberName: PropertyName, location?: TextRange): Expression {
|
||||
return isIdentifier(memberName) ? createLiteral(memberName.text, location)
|
||||
: isComputedPropertyName(memberName) ? getRelocatedClone(memberName.expression, location || synthesizedLocation)
|
||||
: getRelocatedClone(memberName, location || synthesizedLocation);
|
||||
export function createExpressionForPropertyName(memberName: PropertyName, emitOptions: NodeEmitOptions): Expression {
|
||||
if (isIdentifier(memberName)) {
|
||||
return createLiteral(memberName, /*location*/ undefined, emitOptions);
|
||||
}
|
||||
else if (isComputedPropertyName(memberName)) {
|
||||
return getMutableClone(memberName.expression, emitOptions);
|
||||
}
|
||||
else {
|
||||
return getMutableClone(memberName, emitOptions);
|
||||
}
|
||||
}
|
||||
|
||||
// Utilities
|
||||
|
||||
@ -172,7 +172,8 @@ const _super = (function (geti, seti) {
|
||||
let context: TransformationContext;
|
||||
let getNodeEmitFlags: (node: Node) => NodeEmitFlags;
|
||||
let setNodeEmitFlags: (node: Node, flags: NodeEmitFlags) => void;
|
||||
let getNodeCustomCommentRange: (node: Node) => TextRange;
|
||||
let getCommentRange: (node: Node) => TextRange;
|
||||
let getSourceMapRange: (node: Node) => TextRange;
|
||||
let isSubstitutionEnabled: (node: Node) => boolean;
|
||||
let isEmitNotificationEnabled: (node: Node) => boolean;
|
||||
let onSubstituteNode: (node: Node, isExpression: boolean) => Node;
|
||||
@ -233,7 +234,8 @@ const _super = (function (geti, seti) {
|
||||
|
||||
getNodeEmitFlags = undefined;
|
||||
setNodeEmitFlags = undefined;
|
||||
getNodeCustomCommentRange = undefined;
|
||||
getCommentRange = undefined;
|
||||
getSourceMapRange = undefined;
|
||||
isSubstitutionEnabled = undefined;
|
||||
isEmitNotificationEnabled = undefined;
|
||||
onSubstituteNode = undefined;
|
||||
@ -253,7 +255,8 @@ const _super = (function (geti, seti) {
|
||||
context = _context;
|
||||
getNodeEmitFlags = context.getNodeEmitFlags;
|
||||
setNodeEmitFlags = context.setNodeEmitFlags;
|
||||
getNodeCustomCommentRange = context.getNodeCustomCommentRange;
|
||||
getCommentRange = context.getCommentRange;
|
||||
getSourceMapRange = context.getSourceMapRange;
|
||||
isSubstitutionEnabled = context.isSubstitutionEnabled;
|
||||
isEmitNotificationEnabled = context.isEmitNotificationEnabled;
|
||||
onSubstituteNode = context.onSubstituteNode;
|
||||
@ -337,12 +340,12 @@ const _super = (function (geti, seti) {
|
||||
|
||||
function emitNodeWithWorker(node: Node, emitWorker: (node: Node) => void) {
|
||||
if (node) {
|
||||
const leadingComments = getLeadingComments(node, shouldSkipLeadingCommentsForNode, getNodeCustomCommentRange);
|
||||
const trailingComments = getTrailingComments(node, shouldSkipTrailingCommentsForNode, getNodeCustomCommentRange);
|
||||
const leadingComments = getLeadingComments(node, shouldSkipLeadingCommentsForNode, getCommentRange);
|
||||
const trailingComments = getTrailingComments(node, shouldSkipTrailingCommentsForNode, getCommentRange);
|
||||
emitLeadingComments(node, leadingComments);
|
||||
emitStart(node, shouldSkipLeadingSourceMapForNode, shouldSkipSourceMapForChildren);
|
||||
emitStart(node, shouldSkipLeadingSourceMapForNode, shouldSkipSourceMapForChildren, getSourceMapRange);
|
||||
emitWorker(node);
|
||||
emitEnd(node, shouldSkipTrailingSourceMapForNode, shouldSkipSourceMapForChildren);
|
||||
emitEnd(node, shouldSkipTrailingSourceMapForNode, shouldSkipSourceMapForChildren, getSourceMapRange);
|
||||
emitTrailingComments(node, trailingComments);
|
||||
}
|
||||
}
|
||||
@ -2429,9 +2432,9 @@ const _super = (function (geti, seti) {
|
||||
|
||||
function writeTokenNode(node: Node) {
|
||||
if (node) {
|
||||
emitStart(node, shouldSkipLeadingSourceMapForNode, shouldSkipSourceMapForChildren);
|
||||
emitStart(node, shouldSkipLeadingSourceMapForNode, shouldSkipSourceMapForChildren, getSourceMapRange);
|
||||
writeTokenText(node.kind);
|
||||
emitEnd(node, shouldSkipTrailingSourceMapForNode, shouldSkipSourceMapForChildren);
|
||||
emitEnd(node, shouldSkipTrailingSourceMapForNode, shouldSkipSourceMapForChildren, getSourceMapRange);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -7,9 +7,9 @@ namespace ts {
|
||||
setSourceFile(sourceFile: SourceFile): void;
|
||||
emitPos(pos: number, contextNode: Node, shouldIgnorePosCallback: (node: Node) => boolean): void;
|
||||
emitPos(pos: number): void;
|
||||
emitStart(node: Node, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean): void;
|
||||
emitStart(node: Node, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean, getCustomSourceMapRangeForNode?: (node: Node) => TextRange): void;
|
||||
emitStart(range: TextRange): void;
|
||||
emitEnd(node: Node, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean): void;
|
||||
emitEnd(node: Node, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean, getCustomSourceMapRangeForNode?: (node: Node) => TextRange): void;
|
||||
emitEnd(range: TextRange): void;
|
||||
/*@deprecated*/ changeEmitSourcePos(): void;
|
||||
/*@deprecated*/ stopOverridingSpan(): void;
|
||||
@ -36,8 +36,8 @@ namespace ts {
|
||||
nullSourceMapWriter = {
|
||||
getSourceMapData(): SourceMapData { return undefined; },
|
||||
setSourceFile(sourceFile: SourceFile): void { },
|
||||
emitStart(range: TextRange | Node, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean): void { },
|
||||
emitEnd(range: TextRange | Node, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean): void { },
|
||||
emitStart(range: TextRange | Node, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean, getCustomSourceMapRangeForNode?: (node: Node) => TextRange): void { },
|
||||
emitEnd(range: TextRange | Node, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean, getCustomSourceMapRangeForNode?: (node: Node) => TextRange): void { },
|
||||
emitPos(pos: number): void { },
|
||||
changeEmitSourcePos(): void { },
|
||||
stopOverridingSpan(): void { },
|
||||
@ -327,26 +327,36 @@ namespace ts {
|
||||
return range.pos !== -1 ? skipTrivia(currentSourceFile.text, rangeHasDecorators ? (range as Node).decorators.end : range.pos) : -1;
|
||||
}
|
||||
|
||||
function emitStart(node: Node, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean): void;
|
||||
function emitStart(range: TextRange): void;
|
||||
function emitStart(range: TextRange | Node, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean) {
|
||||
if (!(shouldIgnoreNodeCallback && shouldIgnoreNodeCallback(<Node>range))) {
|
||||
function emitStart(node: Node, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean, getCustomSourceMapRangeForNode?: (node: Node) => TextRange): void;
|
||||
function emitStart(nodeOrRange: TextRange | Node, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean, getCustomSourceMapRangeForNode?: (node: Node) => TextRange) {
|
||||
let range = <TextRange>nodeOrRange;
|
||||
if (!(shouldIgnoreNodeCallback && shouldIgnoreNodeCallback(<Node>nodeOrRange))) {
|
||||
if (getCustomSourceMapRangeForNode) {
|
||||
range = getCustomSourceMapRangeForNode(<Node>nodeOrRange) || range;
|
||||
}
|
||||
|
||||
emitPos(getStartPos(range));
|
||||
}
|
||||
|
||||
if (shouldIgnoreChildrenCallback && shouldIgnoreChildrenCallback(<Node>range)) {
|
||||
if (shouldIgnoreChildrenCallback && shouldIgnoreChildrenCallback(<Node>nodeOrRange)) {
|
||||
disable();
|
||||
}
|
||||
}
|
||||
|
||||
function emitEnd(node: Node, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean): void;
|
||||
function emitEnd(range: TextRange): void;
|
||||
function emitEnd(range: TextRange, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean) {
|
||||
if (shouldIgnoreChildrenCallback && shouldIgnoreChildrenCallback(<Node>range)) {
|
||||
function emitEnd(node: Node, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean, getCustomSourceMapRangeForNode?: (node: Node) => TextRange): void;
|
||||
function emitEnd(nodeOrRange: TextRange | Node, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean, getCustomSourceMapRangeForNode?: (node: Node) => TextRange) {
|
||||
let range = <TextRange>nodeOrRange;
|
||||
if (shouldIgnoreChildrenCallback && shouldIgnoreChildrenCallback(<Node>nodeOrRange)) {
|
||||
enable();
|
||||
}
|
||||
|
||||
if (!(shouldIgnoreNodeCallback && shouldIgnoreNodeCallback(<Node>range))) {
|
||||
if (!(shouldIgnoreNodeCallback && shouldIgnoreNodeCallback(<Node>nodeOrRange))) {
|
||||
if (getCustomSourceMapRangeForNode) {
|
||||
range = getCustomSourceMapRangeForNode(<Node>nodeOrRange) || range;
|
||||
}
|
||||
|
||||
emitPos(range.end);
|
||||
}
|
||||
|
||||
|
||||
@ -54,8 +54,7 @@ namespace ts {
|
||||
* @param transforms An array of Transformers.
|
||||
*/
|
||||
export function transformFiles(resolver: EmitResolver, host: EmitHost, sourceFiles: SourceFile[], transformers: Transformer[]) {
|
||||
const nodeEmitFlags: NodeEmitFlags[] = [];
|
||||
const nodeCustomCommentRange: TextRange[] = [];
|
||||
const nodeEmitOptions: NodeEmitOptions[] = [];
|
||||
const lexicalEnvironmentVariableDeclarationsStack: VariableDeclaration[][] = [];
|
||||
const lexicalEnvironmentFunctionDeclarationsStack: FunctionDeclaration[][] = [];
|
||||
const enabledSyntaxKindFeatures = new Array<SyntaxKindFeatureFlags>(SyntaxKind.Count);
|
||||
@ -73,8 +72,10 @@ namespace ts {
|
||||
getEmitHost: () => host,
|
||||
getNodeEmitFlags,
|
||||
setNodeEmitFlags,
|
||||
getNodeCustomCommentRange,
|
||||
setNodeCustomCommentRange,
|
||||
getSourceMapRange,
|
||||
setSourceMapRange,
|
||||
getCommentRange,
|
||||
setCommentRange,
|
||||
hoistVariableDeclaration,
|
||||
hoistFunctionDeclaration,
|
||||
startLexicalEnvironment,
|
||||
@ -107,10 +108,16 @@ namespace ts {
|
||||
return transformation(sourceFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables expression substitutions in the pretty printer for the provided SyntaxKind.
|
||||
*/
|
||||
function enableSubstitution(kind: SyntaxKind) {
|
||||
enabledSyntaxKindFeatures[kind] |= SyntaxKindFeatureFlags.Substitution;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether expression substitutions are enabled for the provided node.
|
||||
*/
|
||||
function isSubstitutionEnabled(node: Node) {
|
||||
return (enabledSyntaxKindFeatures[node.kind] & SyntaxKindFeatureFlags.Substitution) !== 0;
|
||||
}
|
||||
@ -126,10 +133,17 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables before/after emit notifications in the pretty printer for the provided SyntaxKind.
|
||||
*/
|
||||
function enableEmitNotification(kind: SyntaxKind) {
|
||||
enabledSyntaxKindFeatures[kind] |= SyntaxKindFeatureFlags.EmitNotifications;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether before/after emit notifications should be raised in the pretty
|
||||
* printer when it emits a node.
|
||||
*/
|
||||
function isEmitNotificationEnabled(node: Node) {
|
||||
return (enabledSyntaxKindFeatures[node.kind] & SyntaxKindFeatureFlags.EmitNotifications) !== 0
|
||||
|| (getNodeEmitFlags(node) & NodeEmitFlags.AdviseOnEmitNode) !== 0;
|
||||
@ -154,51 +168,94 @@ namespace ts {
|
||||
emit(node);
|
||||
}
|
||||
|
||||
function getNodeEmitOptions(node: Node, createIfMissing: boolean) {
|
||||
// Keeps track of the nearest set of options
|
||||
let options: NodeEmitOptions;
|
||||
let currentNode = node;
|
||||
while (currentNode) {
|
||||
const currentOptions = currentNode.emitOptions || nodeEmitOptions[getNodeId(currentNode)];
|
||||
if (currentOptions) {
|
||||
options = currentOptions;
|
||||
break;
|
||||
}
|
||||
|
||||
currentNode = currentNode.original;
|
||||
}
|
||||
|
||||
if (currentNode !== node && createIfMissing) {
|
||||
options = options ? clone(options) : { };
|
||||
if (isSourceTreeNode(node)) {
|
||||
nodeEmitOptions[getNodeId(node)] = options;
|
||||
}
|
||||
else {
|
||||
node.emitOptions = options;
|
||||
}
|
||||
}
|
||||
|
||||
// Merge with previous options on get.
|
||||
if (options && options.flags & NodeEmitFlags.Merge) {
|
||||
const previousOptions = getNodeEmitOptions(currentNode.original, /*createIfMissing*/ false);
|
||||
if (previousOptions) {
|
||||
options.flags = (options.flags | previousOptions.flags) & ~NodeEmitFlags.Merge;
|
||||
if (!options.sourceMapRange && (options.flags & NodeEmitFlags.NoSourceMap) === 0) {
|
||||
options.sourceMapRange = previousOptions.sourceMapRange;
|
||||
}
|
||||
|
||||
if (!options.commentRange && (options.flags & NodeEmitFlags.NoComments) === 0) {
|
||||
options.commentRange = previousOptions.commentRange;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets flags that control emit behavior of a node.
|
||||
*/
|
||||
function getNodeEmitFlags(node: Node) {
|
||||
while (node) {
|
||||
const nodeId = node.id;
|
||||
if (nodeId && nodeEmitFlags[nodeId] !== undefined) {
|
||||
return nodeEmitFlags[nodeId];
|
||||
}
|
||||
|
||||
node = node.original;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
const options = getNodeEmitOptions(node, /*createIfMissing*/ false);
|
||||
return options && options.flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets flags that control emit behavior of a node.
|
||||
*/
|
||||
function setNodeEmitFlags<T extends Node>(node: T, flags: NodeEmitFlags) {
|
||||
nodeEmitFlags[getNodeId(node)] = flags;
|
||||
getNodeEmitOptions(node, /*createIfMissing*/ true).flags = flags;
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a custom text range to use when emitting source maps.
|
||||
*/
|
||||
function getSourceMapRange(node: Node) {
|
||||
const options = getNodeEmitOptions(node, /*createIfMissing*/ false);
|
||||
return options && options.sourceMapRange;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a custom text range to use when emitting source maps.
|
||||
*/
|
||||
function setSourceMapRange<T extends Node>(node: T, range: TextRange) {
|
||||
getNodeEmitOptions(node, /*createIfMissing*/ true).sourceMapRange = range;
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a custom text range to use when emitting comments.
|
||||
*/
|
||||
function getNodeCustomCommentRange(node: Node) {
|
||||
while (node) {
|
||||
const nodeId = node.id;
|
||||
if (nodeId && nodeCustomCommentRange[nodeId] !== undefined) {
|
||||
return nodeCustomCommentRange[nodeId];
|
||||
}
|
||||
|
||||
node = node.original;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
function getCommentRange(node: Node) {
|
||||
const options = getNodeEmitOptions(node, /*createIfMissing*/ false);
|
||||
return options && options.commentRange;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a custom text range to use when emitting comments.
|
||||
*/
|
||||
function setNodeCustomCommentRange(node: Node, range: TextRange) {
|
||||
nodeCustomCommentRange[getNodeId(node)] = range;
|
||||
function setCommentRange<T extends Node>(node: T, range: TextRange) {
|
||||
getNodeEmitOptions(node, /*createIfMissing*/ true).commentRange = range;
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -251,7 +251,7 @@ namespace ts {
|
||||
emitArrayLiteralAssignment(<ArrayLiteralExpression>target, value, location);
|
||||
}
|
||||
else {
|
||||
const name = getRelocatedClone(<Identifier>target, /*location*/ target);
|
||||
const name = getSynthesizedClone(<Identifier>target, { sourceMapRange: target, commentRange: target });
|
||||
emitAssignment(name, value, location, /*original*/ undefined);
|
||||
}
|
||||
}
|
||||
|
||||
@ -145,6 +145,8 @@ namespace ts {
|
||||
hoistVariableDeclaration,
|
||||
getNodeEmitFlags,
|
||||
setNodeEmitFlags,
|
||||
setCommentRange,
|
||||
setSourceMapRange
|
||||
} = context;
|
||||
|
||||
const resolver = context.getEmitResolver();
|
||||
@ -1055,18 +1057,19 @@ namespace ts {
|
||||
function addCaptureThisForNodeIfNeeded(statements: Statement[], node: Node): void {
|
||||
if (node.transformFlags & TransformFlags.ContainsCapturedLexicalThis && node.kind !== SyntaxKind.ArrowFunction) {
|
||||
enableSubstitutionsForCapturedThis();
|
||||
statements.push(
|
||||
createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createVariableDeclarationList([
|
||||
createVariableDeclaration(
|
||||
"_this",
|
||||
createThis()
|
||||
)
|
||||
]),
|
||||
/*location*/ node
|
||||
)
|
||||
const captureThisStatement = createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createVariableDeclarationList([
|
||||
createVariableDeclaration(
|
||||
"_this",
|
||||
createThis()
|
||||
)
|
||||
])
|
||||
);
|
||||
|
||||
setNodeEmitFlags(captureThisStatement, NodeEmitFlags.NoComments);
|
||||
setSourceMapRange(captureThisStatement, node);
|
||||
statements.push(captureThisStatement);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1174,11 +1177,8 @@ namespace ts {
|
||||
function transformAccessorsToExpression(receiver: LeftHandSideExpression, { firstAccessor, getAccessor, setAccessor }: AllAccessorDeclarations): Expression {
|
||||
// To align with source maps in the old emitter, the receiver and property name
|
||||
// arguments are both mapped contiguously to the accessor name.
|
||||
const target = getSynthesizedClone(receiver);
|
||||
target.pos = firstAccessor.name.pos;
|
||||
|
||||
const propertyName = createExpressionForPropertyName(visitNode(firstAccessor.name, visitor, isPropertyName));
|
||||
propertyName.end = firstAccessor.name.end;
|
||||
const target = getMutableClone(receiver, { flags: NodeEmitFlags.Merge | NodeEmitFlags.NoComments, sourceMapRange: moveRangeEnd(firstAccessor.name, -1) });
|
||||
const propertyName = createExpressionForPropertyName(visitNode(firstAccessor.name, visitor, isPropertyName), { flags: NodeEmitFlags.NoComments, sourceMapRange: moveRangePos(firstAccessor.name, -1) });
|
||||
|
||||
let getAccessorExpression: FunctionExpression;
|
||||
if (getAccessor) {
|
||||
|
||||
@ -24,8 +24,10 @@ namespace ts {
|
||||
|
||||
export function transformTypeScript(context: TransformationContext) {
|
||||
const {
|
||||
setNodeEmitFlags,
|
||||
getNodeEmitFlags,
|
||||
setNodeEmitFlags,
|
||||
setCommentRange,
|
||||
setSourceMapRange,
|
||||
startLexicalEnvironment,
|
||||
endLexicalEnvironment,
|
||||
hoistVariableDeclaration,
|
||||
@ -911,16 +913,18 @@ namespace ts {
|
||||
*/
|
||||
function transformParameterWithPropertyAssignment(node: ParameterDeclaration) {
|
||||
Debug.assert(isIdentifier(node.name));
|
||||
|
||||
const name = node.name as Identifier;
|
||||
const propertyName = getMutableClone(name, { flags: NodeEmitFlags.NoComments | NodeEmitFlags.NoSourceMap });
|
||||
const localName = getMutableClone(name, { flags: NodeEmitFlags.NoComments });
|
||||
return startOnNewLine(
|
||||
createStatement(
|
||||
createAssignment(
|
||||
createPropertyAccess(
|
||||
createThis(),
|
||||
getMutableClone(<Identifier>node.name),
|
||||
propertyName,
|
||||
/*location*/ node.name
|
||||
),
|
||||
getUniqueClone(<Identifier>node.name)
|
||||
localName
|
||||
),
|
||||
/*location*/ node
|
||||
)
|
||||
@ -1011,8 +1015,13 @@ namespace ts {
|
||||
function transformInitializedProperty(node: ClassExpression | ClassDeclaration, property: PropertyDeclaration, receiver: LeftHandSideExpression, location?: TextRange) {
|
||||
const propertyName = visitPropertyNameOfClassElement(property);
|
||||
const initializer = visitNode(property.initializer, visitor, isExpression);
|
||||
const memberAccess = createMemberAccessForPropertyName(receiver, propertyName, /*location*/ propertyName);
|
||||
if (!isComputedPropertyName(propertyName)) {
|
||||
setNodeEmitFlags(memberAccess, NodeEmitFlags.NoNestedSourceMaps);
|
||||
}
|
||||
|
||||
return createAssignment(
|
||||
createMemberAccessForPropertyName(receiver, propertyName, /*location*/ propertyName),
|
||||
memberAccess,
|
||||
initializer,
|
||||
location
|
||||
);
|
||||
@ -1910,7 +1919,7 @@ namespace ts {
|
||||
visitPropertyNameOfClassElement(node),
|
||||
visitNodes(node.parameters, visitor, isParameter),
|
||||
transformFunctionBody(node),
|
||||
/*location*/ getUndecoratedRange(node)
|
||||
/*location*/ node
|
||||
);
|
||||
|
||||
setOriginalNode(method, node);
|
||||
@ -1918,7 +1927,8 @@ namespace ts {
|
||||
// While we emit the source map for the node after skipping the decorators,
|
||||
// we need to emit the comments for the original range.
|
||||
if (node.decorators) {
|
||||
context.setNodeCustomCommentRange(method, node);
|
||||
setCommentRange(method, node);
|
||||
setSourceMapRange(method, getUndecoratedRange(node));
|
||||
}
|
||||
|
||||
return method;
|
||||
@ -1952,7 +1962,7 @@ namespace ts {
|
||||
visitNodes(node.modifiers, visitor, isModifier),
|
||||
visitPropertyNameOfClassElement(node),
|
||||
node.body ? visitEachChild(node.body, visitor, context) : createBlock([]),
|
||||
/*location*/ getUndecoratedRange(node)
|
||||
/*location*/ node
|
||||
);
|
||||
|
||||
setOriginalNode(accessor, node);
|
||||
@ -1960,7 +1970,8 @@ namespace ts {
|
||||
// While we emit the source map for the node after skipping the decorators,
|
||||
// we need to emit the comments for the original range.
|
||||
if (node.decorators) {
|
||||
context.setNodeCustomCommentRange(accessor, node);
|
||||
setCommentRange(accessor, node);
|
||||
setSourceMapRange(accessor, getUndecoratedRange(node));
|
||||
}
|
||||
|
||||
return accessor;
|
||||
@ -1985,7 +1996,7 @@ namespace ts {
|
||||
visitPropertyNameOfClassElement(node),
|
||||
visitNode(firstOrUndefined(node.parameters), visitor, isParameter),
|
||||
node.body ? visitEachChild(node.body, visitor, context) : createBlock([]),
|
||||
/*location*/ getUndecoratedRange(node)
|
||||
/*location*/ node
|
||||
);
|
||||
|
||||
setOriginalNode(accessor, node);
|
||||
@ -1993,7 +2004,8 @@ namespace ts {
|
||||
// While we emit the source map for the node after skipping the decorators,
|
||||
// we need to emit the comments for the original range.
|
||||
if (node.decorators) {
|
||||
context.setNodeCustomCommentRange(accessor, node);
|
||||
setCommentRange(accessor, node);
|
||||
setSourceMapRange(accessor, getUndecoratedRange(node));
|
||||
}
|
||||
|
||||
return accessor;
|
||||
@ -2176,21 +2188,27 @@ namespace ts {
|
||||
* @param node The parameter declaration node.
|
||||
*/
|
||||
function visitParameter(node: ParameterDeclaration) {
|
||||
if (node.name && (node.name as Identifier).originalKeywordKind === SyntaxKind.ThisKeyword) {
|
||||
if (node.name && isIdentifier(node.name) && (node.name as Identifier).originalKeywordKind === SyntaxKind.ThisKeyword) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const clone = getMutableClone(node);
|
||||
clone.decorators = undefined;
|
||||
clone.modifiers = undefined;
|
||||
clone.questionToken = undefined;
|
||||
clone.type = undefined;
|
||||
const parameter = createParameterWithDotDotDotToken(
|
||||
node.dotDotDotToken,
|
||||
visitNode(node.name, visitor, isBindingName),
|
||||
visitNode(node.initializer, visitor, isExpression),
|
||||
/*location*/ node
|
||||
);
|
||||
|
||||
setOriginalNode(parameter, node);
|
||||
|
||||
// While we emit the source map for the node after skipping the decorators,
|
||||
// we need to emit the comments for the original range.
|
||||
if (node.decorators) {
|
||||
setTextRange(clone, getUndecoratedRange(node));
|
||||
setCommentRange(parameter, node);
|
||||
setSourceMapRange(parameter, getUndecoratedRange(node));
|
||||
}
|
||||
|
||||
aggregateTransformFlags(clone);
|
||||
return visitEachChild(clone, visitor, context);
|
||||
return parameter;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3097,7 +3115,7 @@ namespace ts {
|
||||
if (declaration) {
|
||||
const classAlias = currentDecoratedClassAliases[getNodeId(declaration)];
|
||||
if (classAlias) {
|
||||
return getRelocatedClone(classAlias, /*location*/ node);
|
||||
return getSynthesizedClone(classAlias, { sourceMapRange: node, commentRange: node });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -469,6 +469,7 @@ namespace ts {
|
||||
/* @internal */ locals?: SymbolTable; // Locals associated with node (initialized by binding)
|
||||
/* @internal */ nextContainer?: Node; // Next container in declaration order (initialized by binding)
|
||||
/* @internal */ localSymbol?: Symbol; // Local symbol declared by node (initialized by binding only for exported nodes)
|
||||
/* @internal */ emitOptions?: NodeEmitOptions; // Options used to control node emit (used by transforms, should never be set directly on a source tree node)
|
||||
}
|
||||
|
||||
export interface NodeArray<T extends Node> extends Array<T>, TextRange {
|
||||
@ -2941,16 +2942,34 @@ namespace ts {
|
||||
ExportName = 1 << 16, // Ensure an export prefix is added for an identifier that points to an exported declaration with a local name (see SymbolFlags.ExportHasLocal).
|
||||
LocalName = 1 << 17, // Ensure an export prefix is not added for an identifier that points to an exported declaration.
|
||||
Indented = 1 << 18, // Adds an explicit extra indentation level for class and function bodies when printing (used to match old emitter).
|
||||
Merge = 1 << 19, // When getting emit options, merge with existing emit options.
|
||||
|
||||
// SourceMap Specialization.
|
||||
// TODO(rbuckton): These should be removed once source maps are aligned with the old
|
||||
// emitter and new baselines are taken. This exists solely to
|
||||
// align with the old emitter.
|
||||
SourceMapEmitOpenBraceAsToken = 1 << 19, // Emits the open brace of a block function body as a source mapped token.
|
||||
SourceMapAdjustRestParameterLoop = 1 << 20, // Emits adjusted source map positions for a ForStatement generated when transforming a rest parameter for ES5/3.
|
||||
SourceMapEmitOpenBraceAsToken = 1 << 20, // Emits the open brace of a block function body as a source mapped token.
|
||||
SourceMapAdjustRestParameterLoop = 1 << 21, // Emits adjusted source map positions for a ForStatement generated when transforming a rest parameter for ES5/3.
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface NodeEmitOptions {
|
||||
/**
|
||||
* Specifies a custom range to use when emitting source maps.
|
||||
*/
|
||||
sourceMapRange?: TextRange;
|
||||
/**
|
||||
* Specifies a custom range to use when emitting comments.
|
||||
*/
|
||||
commentRange?: TextRange;
|
||||
/**
|
||||
* Specifies flags to use to customize emit.
|
||||
*/
|
||||
flags?: NodeEmitFlags;
|
||||
}
|
||||
|
||||
/** Additional context provided to `visitEachChild` */
|
||||
/* @internal */
|
||||
export interface LexicalEnvironment {
|
||||
/** Starts a new lexical environment. */
|
||||
startLexicalEnvironment(): void;
|
||||
@ -2964,22 +2983,54 @@ namespace ts {
|
||||
getCompilerOptions(): CompilerOptions;
|
||||
getEmitResolver(): EmitResolver;
|
||||
getEmitHost(): EmitHost;
|
||||
|
||||
/**
|
||||
* Gets flags used to customize later transformations or emit.
|
||||
*/
|
||||
getNodeEmitFlags(node: Node): NodeEmitFlags;
|
||||
|
||||
/**
|
||||
* Sets flags used to customize later transformations or emit.
|
||||
*/
|
||||
setNodeEmitFlags<T extends Node>(node: T, flags: NodeEmitFlags): T;
|
||||
getNodeCustomCommentRange(node: Node): TextRange;
|
||||
setNodeCustomCommentRange(node: Node, range: TextRange): void;
|
||||
|
||||
/**
|
||||
* Gets the TextRange to use for source maps for the node.
|
||||
*/
|
||||
getSourceMapRange(node: Node): TextRange;
|
||||
|
||||
/**
|
||||
* Sets the TextRange to use for source maps for the node.
|
||||
*/
|
||||
setSourceMapRange<T extends Node>(node: T, range: TextRange): T;
|
||||
|
||||
/**
|
||||
* Gets the TextRange to use for comments for the node.
|
||||
*/
|
||||
getCommentRange(node: Node): TextRange;
|
||||
|
||||
/**
|
||||
* Sets the TextRange to use for comments for the node.
|
||||
*/
|
||||
setCommentRange<T extends Node>(node: T, range: TextRange): T;
|
||||
|
||||
/**
|
||||
* Hoists a function declaration to the containing scope.
|
||||
*/
|
||||
hoistFunctionDeclaration(node: FunctionDeclaration): void;
|
||||
|
||||
/**
|
||||
* Hoists a variable declaration to the containing scope.
|
||||
*/
|
||||
hoistVariableDeclaration(node: Identifier): void;
|
||||
|
||||
/**
|
||||
* Enables expression substitutions in the pretty printer for
|
||||
* the provided SyntaxKind.
|
||||
* Enables expression substitutions in the pretty printer for the provided SyntaxKind.
|
||||
*/
|
||||
enableSubstitution(kind: SyntaxKind): void;
|
||||
|
||||
/**
|
||||
* Determines whether expression substitutions are enabled for the
|
||||
* provided node.
|
||||
* Determines whether expression substitutions are enabled for the provided node.
|
||||
*/
|
||||
isSubstitutionEnabled(node: Node): boolean;
|
||||
|
||||
@ -2990,14 +3041,14 @@ namespace ts {
|
||||
onSubstituteNode?: (node: Node, isExpression: boolean) => Node;
|
||||
|
||||
/**
|
||||
* Enables before/after emit notifications in the pretty printer for
|
||||
* the provided SyntaxKind.
|
||||
* Enables before/after emit notifications in the pretty printer for the provided
|
||||
* SyntaxKind.
|
||||
*/
|
||||
enableEmitNotification(kind: SyntaxKind): void;
|
||||
|
||||
/**
|
||||
* Determines whether before/after emit notifications should be raised
|
||||
* in the pretty printer when it emits a node.
|
||||
* Determines whether before/after emit notifications should be raised in the pretty
|
||||
* printer when it emits a node.
|
||||
*/
|
||||
isEmitNotificationEnabled(node: Node): boolean;
|
||||
|
||||
|
||||
@ -1830,12 +1830,16 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
export function isSourceTreeNode(node: Node): boolean {
|
||||
return node.original === undefined
|
||||
&& (node.parent !== undefined || node.kind === SyntaxKind.SourceFile);
|
||||
}
|
||||
|
||||
export function getSourceTreeNode(node: Node): Node {
|
||||
node = getOriginalNode(node);
|
||||
if (node) {
|
||||
if (node.parent || node.kind === SyntaxKind.SourceFile) {
|
||||
return node;
|
||||
}
|
||||
|
||||
if (node && (node.parent !== undefined || node.kind === SyntaxKind.SourceFile)) {
|
||||
return node;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user