diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 7ab46fc689e..436b97821cc 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1177,6 +1177,7 @@ namespace ts.server { TabSize: 4, NewLineCharacter: ts.sys ? ts.sys.newLine : '\n', ConvertTabsToSpaces: true, + IndentStyle: ts.IndentStyle.Smart, InsertSpaceAfterCommaDelimiter: true, InsertSpaceAfterSemicolonInForStatements: true, InsertSpaceBeforeAndAfterBinaryOperators: true, @@ -1187,7 +1188,6 @@ namespace ts.server { PlaceOpenBraceOnNewLineForFunctions: false, PlaceOpenBraceOnNewLineForControlBlocks: false, } - } export interface LineCollection { diff --git a/src/server/session.ts b/src/server/session.ts index da044e7b4c6..f3d3826409e 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -606,6 +606,7 @@ namespace ts.server { TabSize: formatOptions.TabSize, NewLineCharacter: "\n", ConvertTabsToSpaces: formatOptions.ConvertTabsToSpaces, + IndentStyle: ts.IndentStyle.Smart, }; var indentPosition = compilerService.languageService.getIndentationAtPosition(file, position, editorOptions); diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index 8355fac03f5..6daeca5eacc 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -13,6 +13,12 @@ namespace ts.formatting { return 0; // past EOF } + // no indentation when the indent style is set to none, + // so we can return fast + if (options.IndentStyle === IndentStyle.None) { + return 0; + } + let precedingToken = findPrecedingToken(position, sourceFile); if (!precedingToken) { return 0; @@ -32,6 +38,26 @@ namespace ts.formatting { let lineAtPosition = sourceFile.getLineAndCharacterOfPosition(position).line; + // indentation is first non-whitespace character in a previous line + // for block indentation, we should look for a line which contains something that's not + // whitespace. + if (options.IndentStyle === IndentStyle.Block) { + + // move backwards untill we find a line with a non-whitespace character, + // then find the first non-whitespace character for that line. + let current = position; + while (current > 0){ + let char = sourceFile.text.charCodeAt(current); + if (!isWhiteSpace(char) && !isLineBreak(char)) { + break; + } + current--; + } + + let lineStart = ts.getLineStartPositionForPosition(current, sourceFile); + return SmartIndenter.findFirstNonWhitespaceColumn(lineStart, current, sourceFile, options); + } + if (precedingToken.kind === SyntaxKind.CommaToken && precedingToken.parent.kind !== SyntaxKind.BinaryExpression) { // previous token is comma that separates items in list - find the previous item and try to derive indentation from it let actualIndentation = getActualIndentationForListItemBeforeComma(precedingToken, sourceFile, options); @@ -224,7 +250,7 @@ namespace ts.formatting { function getStartLineAndCharacterForNode(n: Node, sourceFile: SourceFile): LineAndCharacter { return sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)); } - + export function childStartsOnTheSameLineWithElseInIfStatement(parent: Node, child: TextRangeWithKind, childStartLine: number, sourceFile: SourceFile): boolean { if (parent.kind === SyntaxKind.IfStatement && (parent).elseStatement === child) { let elseKeyword = findChildOfKind(parent, SyntaxKind.ElseKeyword, sourceFile); @@ -325,7 +351,7 @@ namespace ts.formatting { } return Value.Unknown; - + function getStartingExpression(node: PropertyAccessExpression | CallExpression | ElementAccessExpression) { while (true) { switch (node.kind) { diff --git a/src/services/services.ts b/src/services/services.ts index 87cca1fe0f1..bc60f5f3eb8 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1189,6 +1189,13 @@ namespace ts { TabSize: number; NewLineCharacter: string; ConvertTabsToSpaces: boolean; + IndentStyle: IndentStyle; + } + + export enum IndentStyle { + None = 0, + Block = 1, + Smart = 2, } export interface FormatCodeOptions extends EditorOptions {