Skip to content
Merged
56 changes: 26 additions & 30 deletions src/compiler/emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5307,10 +5307,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
function emitDecoratorsOfConstructor(node: ClassLikeDeclaration) {
const decorators = node.decorators;
const constructor = getFirstConstructorWithBody(node);
const hasDecoratedParameters = constructor && forEach(constructor.parameters, nodeIsDecorated);
const firstParameterDecorator = constructor && forEach(constructor.parameters, parameter => parameter.decorators);

// skip decoration of the constructor if neither it nor its parameters are decorated
if (!decorators && !hasDecoratedParameters) {
if (!decorators && !firstParameterDecorator) {
return;
}

Expand All @@ -5326,28 +5326,27 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
//

writeLine();
emitStart(node);
emitStart(node.decorators || firstParameterDecorator);
emitDeclarationName(node);
write(" = __decorate([");
increaseIndent();
writeLine();

const decoratorCount = decorators ? decorators.length : 0;
let argumentsWritten = emitList(decorators, 0, decoratorCount, /*multiLine*/ true, /*trailingComma*/ false, /*leadingComma*/ false, /*noTrailingNewLine*/ true, decorator => {
emitStart(decorator);
emit(decorator.expression);
emitEnd(decorator);
});

argumentsWritten += emitDecoratorsOfParameters(constructor, /*leadingComma*/ argumentsWritten > 0);
let argumentsWritten = emitList(decorators, 0, decoratorCount, /*multiLine*/ true, /*trailingComma*/ false, /*leadingComma*/ false, /*noTrailingNewLine*/ true,
decorator => emit(decorator.expression));
if (firstParameterDecorator) {
argumentsWritten += emitDecoratorsOfParameters(constructor, /*leadingComma*/ argumentsWritten > 0);
}
emitSerializedTypeMetadata(node, /*leadingComma*/ argumentsWritten >= 0);

decreaseIndent();
writeLine();
write("], ");
emitDeclarationName(node);
write(");");
emitEnd(node);
write(")");
emitEnd(node.decorators || firstParameterDecorator);
write(";");
writeLine();
}

Expand All @@ -5363,11 +5362,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
continue;
}

// skip a member if it or any of its parameters are not decorated
if (!nodeOrChildIsDecorated(member)) {
continue;
}

// skip an accessor declaration if it is not the first accessor
let decorators: NodeArray<Decorator>;
let functionLikeMember: FunctionLikeDeclaration;
Expand All @@ -5394,6 +5388,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
functionLikeMember = <MethodDeclaration>member;
}
}
const firstParameterDecorator = functionLikeMember && forEach(functionLikeMember.parameters, parameter => parameter.decorators);

// skip a member if it or any of its parameters are not decorated
if (!decorators && !firstParameterDecorator) {
continue;
}

// Emit the call to __decorate. Given the following:
//
Expand Down Expand Up @@ -5427,29 +5427,26 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
//

writeLine();
emitStart(member);
emitStart(decorators || firstParameterDecorator);
write("__decorate([");
increaseIndent();
writeLine();

const decoratorCount = decorators ? decorators.length : 0;
let argumentsWritten = emitList(decorators, 0, decoratorCount, /*multiLine*/ true, /*trailingComma*/ false, /*leadingComma*/ false, /*noTrailingNewLine*/ true, decorator => {
emitStart(decorator);
emit(decorator.expression);
emitEnd(decorator);
});
let argumentsWritten = emitList(decorators, 0, decoratorCount, /*multiLine*/ true, /*trailingComma*/ false, /*leadingComma*/ false, /*noTrailingNewLine*/ true,
decorator => emit(decorator.expression));

argumentsWritten += emitDecoratorsOfParameters(functionLikeMember, argumentsWritten > 0);
if (firstParameterDecorator) {
argumentsWritten += emitDecoratorsOfParameters(functionLikeMember, argumentsWritten > 0);
}
emitSerializedTypeMetadata(member, argumentsWritten > 0);

decreaseIndent();
writeLine();
write("], ");
emitStart(member.name);
emitClassMemberPrefix(node, member);
write(", ");
emitExpressionForPropertyName(member.name);
emitEnd(member.name);

if (languageVersion > ScriptTarget.ES3) {
if (member.kind !== SyntaxKind.PropertyDeclaration) {
Expand All @@ -5464,8 +5461,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
}
}

write(");");
emitEnd(member);
write(")");
emitEnd(decorators || firstParameterDecorator);
write(";");
writeLine();
}
}
Expand All @@ -5478,11 +5476,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
if (nodeIsDecorated(parameter)) {
const decorators = parameter.decorators;
argumentsWritten += emitList(decorators, 0, decorators.length, /*multiLine*/ true, /*trailingComma*/ false, /*leadingComma*/ leadingComma, /*noTrailingNewLine*/ true, decorator => {
emitStart(decorator);
write(`__param(${parameterIndex}, `);
emit(decorator.expression);
write(")");
emitEnd(decorator);
});
leadingComma = true;
}
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4902,7 +4902,7 @@ namespace ts {

if (!decorators) {
decorators = <NodeArray<Decorator>>[];
decorators.pos = scanner.getStartPos();
decorators.pos = decoratorStart;
}

const decorator = <Decorator>createNode(SyntaxKind.Decorator, decoratorStart);
Expand Down
3 changes: 2 additions & 1 deletion src/compiler/sourcemap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,8 @@ namespace ts {
}

function emitStart(range: TextRange) {
emitPos(range.pos !== -1 ? skipTrivia(currentSourceFile.text, range.pos) : -1);
const rangeHasDecorators = !!(range as Node).decorators;
emitPos(range.pos !== -1 ? skipTrivia(currentSourceFile.text, rangeHasDecorators ? (range as Node).decorators.end : range.pos) : -1);
}

function emitEnd(range: TextRange) {
Expand Down
17 changes: 0 additions & 17 deletions src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -906,23 +906,6 @@ namespace ts {
return false;
}

export function childIsDecorated(node: Node): boolean {
switch (node.kind) {
case SyntaxKind.ClassDeclaration:
return forEach((<ClassDeclaration>node).members, nodeOrChildIsDecorated);

case SyntaxKind.MethodDeclaration:
case SyntaxKind.SetAccessor:
return forEach((<FunctionLikeDeclaration>node).parameters, nodeIsDecorated);
}

return false;
}

export function nodeOrChildIsDecorated(node: Node): boolean {
return nodeIsDecorated(node) || childIsDecorated(node);
}

export function isPropertyAccessExpression(node: Node): node is PropertyAccessExpression {
return node.kind === SyntaxKind.PropertyAccessExpression;
}
Expand Down
21 changes: 18 additions & 3 deletions src/services/breakpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace ts.BreakpointResolver {

let tokenAtLocation = getTokenAtPosition(sourceFile, position);
let lineOfPosition = sourceFile.getLineAndCharacterOfPosition(position).line;
if (sourceFile.getLineAndCharacterOfPosition(tokenAtLocation.getStart()).line > lineOfPosition) {
if (sourceFile.getLineAndCharacterOfPosition(tokenAtLocation.getStart(sourceFile)).line > lineOfPosition) {
// Get previous token if the token is returned starts on new line
// eg: let x =10; |--- cursor is here
// let y = 10;
Expand All @@ -39,16 +39,23 @@ namespace ts.BreakpointResolver {
return spanInNode(tokenAtLocation);

function textSpan(startNode: Node, endNode?: Node) {
return createTextSpanFromBounds(startNode.getStart(), (endNode || startNode).getEnd());
const start = startNode.decorators ?
skipTrivia(sourceFile.text, startNode.decorators.end) :
startNode.getStart(sourceFile);
return createTextSpanFromBounds(start, (endNode || startNode).getEnd());
}

function spanInNodeIfStartsOnSameLine(node: Node, otherwiseOnNode?: Node): TextSpan {
if (node && lineOfPosition === sourceFile.getLineAndCharacterOfPosition(node.getStart()).line) {
if (node && lineOfPosition === sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line) {
return spanInNode(node);
}
return spanInNode(otherwiseOnNode);
}

function spanInNodeArray<T>(nodeArray: NodeArray<T>) {
return createTextSpanFromBounds(skipTrivia(sourceFile.text, nodeArray.pos), nodeArray.end);
}

function spanInPreviousNode(node: Node): TextSpan {
return spanInNode(findPrecedingToken(node.pos, sourceFile));
}
Expand All @@ -65,6 +72,11 @@ namespace ts.BreakpointResolver {
return spanInPreviousNode(node);
}

if (node.parent.kind === SyntaxKind.Decorator) {
// Set breakpoint on the decorator emit
return spanInNode(node.parent);
}

if (node.parent.kind === SyntaxKind.ForStatement) {
// For now lets set the span on this expression, fix it later
return textSpan(node);
Expand Down Expand Up @@ -207,6 +219,9 @@ namespace ts.BreakpointResolver {
// span in statement
return spanInNode((<WithStatement>node).statement);

case SyntaxKind.Decorator:
return spanInNodeArray(node.parent.decorators);

// No breakpoint in interface, type alias
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.TypeAliasDeclaration:
Expand Down
Loading