From 0bd3d8c2eb01a0e881177c59e1f3a9136533de05 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Wed, 21 Jun 2017 15:03:20 -0700 Subject: [PATCH] unspoof call expression start in iife --- src/services/formatting/smartIndenter.ts | 53 ++++++++++++++++-------- src/services/services.ts | 2 +- src/services/textChanges.ts | 2 +- src/services/utilities.ts | 5 ++- 4 files changed, 41 insertions(+), 21 deletions(-) diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index 18b0479c85a..7609296ccf5 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -9,18 +9,21 @@ namespace ts.formatting { } /** - * Computed indentation for a given position in source file - * @param position - position in file - * @param sourceFile - target source file - * @param options - set of editor options that control indentation - * @param assumeNewLineBeforeCloseBrace - false when getIndentation is called on the text from the real source file. - * true - when we need to assume that position is on the newline. This is usefult for codefixes, i.e. + * @param assumeNewLineBeforeCloseBrace + * `false` when called on text from a real source file. + * `true` when we need to assume `position` is on a newline. + * + * This is useful for codefixes. Consider + * ``` * function f() { * |} - * when inserting some text after open brace we would like to get the value of indentation as if newline was already there. - * However by default indentation at position | will be 0 so 'assumeNewLineBeforeCloseBrace' allows to override this behavior, + * ``` + * with `position` at `|`. + * + * When inserting some text after an open brace, we would like to get indentation as if a newline was already there. + * By default indentation at `position` will be 0 so 'assumeNewLineBeforeCloseBrace' overrides this behavior, */ - export function getIndentation(position: number, sourceFile: SourceFile, options: EditorSettings, assumeNewLineBeforeCloseBrace = false): number { + export function getIndentationAtPosition(position: number, sourceFile: SourceFile, options: EditorSettings, assumeNewLineBeforeCloseBrace = false): number { if (position > sourceFile.text.length) { return getBaseIndentation(options); // past EOF } @@ -136,8 +139,10 @@ namespace ts.formatting { let parent: Node = current.parent; let parentStart: LineAndCharacter; - // walk upwards and collect indentations for pairs of parent-child nodes - // indentation is not added if parent and child nodes start on the same line or if parent is IfStatement and child starts on the same line with 'else clause' + // Walk up the tree and collect indentation for pairs of parent-child nodes. + // indentation is not added if + // * parent and child nodes start on the same line + // * parent is IfStatement and child starts on the same line with 'else clause' while (parent) { let useActualIndentation = true; if (ignoreActualIndentationRange) { @@ -174,22 +179,24 @@ namespace ts.formatting { indentationDelta += options.indentSize; } + // Update current and parent. + + const callExpressionUsesTrueStart = + isParameterAndStartLineOverlapsExpressionBeingCalled(parent, current, currentStart.line, sourceFile); + current = parent; - currentStart = parentStart; parent = current.parent; + currentStart = callExpressionUsesTrueStart ? sourceFile.getLineAndCharacterOfPosition(current.getStart()) : parentStart; + parentStart = undefined; } return indentationDelta + getBaseIndentation(options); } - function getParentStart(parent: Node, child: Node, sourceFile: SourceFile): LineAndCharacter { const containingList = getContainingList(child, sourceFile); - if (containingList) { - return sourceFile.getLineAndCharacterOfPosition(containingList.pos); - } - - return sourceFile.getLineAndCharacterOfPosition(parent.getStart(sourceFile)); + const startPos = containingList ? containingList.pos : parent.getStart(sourceFile); + return sourceFile.getLineAndCharacterOfPosition(startPos); } /* @@ -268,6 +275,16 @@ namespace ts.formatting { return sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)); } + export function isParameterAndStartLineOverlapsExpressionBeingCalled(parent: Node, child: Node, childStartLine: number, sourceFile: SourceFileLike): boolean { + if (!(isCallExpression(parent) && contains(parent.arguments, child))) { + return false; + } + + const callExpressionEnd = parent.expression.getEnd(); + const expressionEndLine = getLineAndCharacterOfPosition(sourceFile, callExpressionEnd).line; + return expressionEndLine === childStartLine; + } + export function childStartsOnTheSameLineWithElseInIfStatement(parent: Node, child: TextRangeWithKind, childStartLine: number, sourceFile: SourceFileLike): boolean { if (parent.kind === SyntaxKind.IfStatement && (parent).elseStatement === child) { const elseKeyword = findChildOfKind(parent, SyntaxKind.ElseKeyword, sourceFile); diff --git a/src/services/services.ts b/src/services/services.ts index b508285b182..13e6e2a2e4b 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1742,7 +1742,7 @@ namespace ts { start = timestamp(); - const result = formatting.SmartIndenter.getIndentation(position, sourceFile, settings); + const result = formatting.SmartIndenter.getIndentationAtPosition(position, sourceFile, settings); log("getIndentationAtPosition: computeIndentation : " + (timestamp() - start)); return result; diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index 5aa4ebca7d0..e0d96d26a55 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -465,7 +465,7 @@ namespace ts.textChanges { change.options.indentation !== undefined ? change.options.indentation : change.useIndentationFromFile - ? formatting.SmartIndenter.getIndentation(change.range.pos, sourceFile, formatOptions, posStartsLine || (change.options.prefix === this.newLineCharacter)) + ? formatting.SmartIndenter.getIndentationAtPosition(change.range.pos, sourceFile, formatOptions, posStartsLine || (change.options.prefix === this.newLineCharacter)) : 0; const delta = change.options.delta !== undefined diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 78c71403736..f0a0c3ee758 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -402,8 +402,11 @@ namespace ts { return start < end; } + /** + * Assumes `candidate.start <= position` holds. + */ export function positionBelongsToNode(candidate: Node, position: number, sourceFile: SourceFile): boolean { - return candidate.end > position || !isCompletedNode(candidate, sourceFile); + return position < candidate.end || !isCompletedNode(candidate, sourceFile); } export function isCompletedNode(n: Node, sourceFile: SourceFile): boolean {