unspoof call expression start in iife

This commit is contained in:
Arthur Ozga
2017-06-21 15:03:20 -07:00
parent 47c1563649
commit 0bd3d8c2eb
4 changed files with 41 additions and 21 deletions

View File

@@ -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 && (<IfStatement>parent).elseStatement === child) {
const elseKeyword = findChildOfKind(parent, SyntaxKind.ElseKeyword, sourceFile);

View File

@@ -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;

View File

@@ -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

View File

@@ -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 {