introduce EditorSettings/FormatCodeSettings interfaces

This commit is contained in:
Vladimir Matveev 2016-06-17 14:06:33 -07:00
parent 04d617de8d
commit 6ebc8abea2
8 changed files with 194 additions and 144 deletions

View File

@ -202,7 +202,7 @@ namespace FourSlash {
// Whether or not we should format on keystrokes
public enableFormatting = true;
public formatCodeOptions: ts.FormatCodeOptions;
public formatCodeSettings: ts.FormatCodeSettings;
private inputFiles: ts.Map<string> = {}; // Map between inputFile's fileName and its content for easily looking up when resolving references
@ -309,22 +309,22 @@ namespace FourSlash {
Harness.Compiler.getDefaultLibrarySourceFile().text, /*isRootFile*/ false);
}
this.formatCodeOptions = {
IndentSize: 4,
TabSize: 4,
NewLineCharacter: Harness.IO.newLine(),
ConvertTabsToSpaces: true,
IndentStyle: ts.IndentStyle.Smart,
InsertSpaceAfterCommaDelimiter: true,
InsertSpaceAfterSemicolonInForStatements: true,
InsertSpaceBeforeAndAfterBinaryOperators: true,
InsertSpaceAfterKeywordsInControlFlowStatements: true,
InsertSpaceAfterFunctionKeywordForAnonymousFunctions: false,
InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false,
InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false,
InsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false,
PlaceOpenBraceOnNewLineForFunctions: false,
PlaceOpenBraceOnNewLineForControlBlocks: false,
this.formatCodeSettings = {
indentSize: 4,
tabSize: 4,
newLineCharacter: Harness.IO.newLine(),
convertTabsToSpaces: true,
indentStyle: ts.IndentStyle.Smart,
insertSpaceAfterCommaDelimiter: true,
insertSpaceAfterSemicolonInForStatements: true,
insertSpaceBeforeAndAfterBinaryOperators: true,
insertSpaceAfterKeywordsInControlFlowStatements: true,
insertSpaceAfterFunctionKeywordForAnonymousFunctions: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false,
insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false,
placeOpenBraceOnNewLineForFunctions: false,
placeOpenBraceOnNewLineForControlBlocks: false,
};
// Open the first file by default
@ -1278,7 +1278,7 @@ namespace FourSlash {
// Handle post-keystroke formatting
if (this.enableFormatting) {
const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeOptions);
const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeSettings);
if (edits.length) {
offset += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
// this.checkPostEditInvariants();
@ -1316,7 +1316,7 @@ namespace FourSlash {
// Handle post-keystroke formatting
if (this.enableFormatting) {
const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeOptions);
const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeSettings);
if (edits.length) {
offset += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
}
@ -1369,7 +1369,7 @@ namespace FourSlash {
// Handle post-keystroke formatting
if (this.enableFormatting) {
const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeOptions);
const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeSettings);
if (edits.length) {
offset += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
// this.checkPostEditInvariants();
@ -1395,7 +1395,7 @@ namespace FourSlash {
// Handle formatting
if (this.enableFormatting) {
const edits = this.languageService.getFormattingEditsForRange(this.activeFile.fileName, start, offset, this.formatCodeOptions);
const edits = this.languageService.getFormattingEditsForRange(this.activeFile.fileName, start, offset, this.formatCodeSettings);
if (edits.length) {
offset += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
this.checkPostEditInvariants();
@ -1469,30 +1469,30 @@ namespace FourSlash {
return runningOffset;
}
public copyFormatOptions(): ts.FormatCodeOptions {
return ts.clone(this.formatCodeOptions);
public copyFormatOptions(): ts.FormatCodeSettings {
return ts.clone(this.formatCodeSettings);
}
public setFormatOptions(formatCodeOptions: ts.FormatCodeOptions): ts.FormatCodeOptions {
const oldFormatCodeOptions = this.formatCodeOptions;
this.formatCodeOptions = formatCodeOptions;
public setFormatOptions(formatCodeOptions: ts.FormatCodeOptions | ts.FormatCodeSettings): ts.FormatCodeSettings {
const oldFormatCodeOptions = this.formatCodeSettings;
this.formatCodeSettings = ts.toEditorSettings(formatCodeOptions);
return oldFormatCodeOptions;
}
public formatDocument() {
const edits = this.languageService.getFormattingEditsForDocument(this.activeFile.fileName, this.formatCodeOptions);
const edits = this.languageService.getFormattingEditsForDocument(this.activeFile.fileName, this.formatCodeSettings);
this.currentCaretPosition += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
this.fixCaretPosition();
}
public formatSelection(start: number, end: number) {
const edits = this.languageService.getFormattingEditsForRange(this.activeFile.fileName, start, end, this.formatCodeOptions);
const edits = this.languageService.getFormattingEditsForRange(this.activeFile.fileName, start, end, this.formatCodeSettings);
this.currentCaretPosition += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
this.fixCaretPosition();
}
public formatOnType(pos: number, key: string) {
const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, pos, key, this.formatCodeOptions);
const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, pos, key, this.formatCodeSettings);
this.currentCaretPosition += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
this.fixCaretPosition();
}
@ -1621,8 +1621,8 @@ namespace FourSlash {
private getIndentation(fileName: string, position: number, indentStyle: ts.IndentStyle): number {
const formatOptions = ts.clone(this.formatCodeOptions);
formatOptions.IndentStyle = indentStyle;
const formatOptions = ts.clone(this.formatCodeSettings);
formatOptions.indentStyle = indentStyle;
return this.languageService.getIndentationAtPosition(fileName, position, formatOptions);
}
@ -3226,7 +3226,7 @@ namespace FourSlashInterface {
this.state.formatDocument();
}
public copyFormatOptions(): ts.FormatCodeOptions {
public copyFormatOptions(): ts.FormatCodeSettings {
return this.state.copyFormatOptions();
}
@ -3246,7 +3246,7 @@ namespace FourSlashInterface {
public setOption(name: string, value: string): void;
public setOption(name: string, value: boolean): void;
public setOption(name: string, value: any): void {
this.state.formatCodeOptions[name] = value;
(<any>this.state.formatCodeSettings)[name] = value;
}
}

View File

@ -16,53 +16,51 @@ namespace ts.server {
msg(s: string, type?: string): void;
}
function getDefaultFormatCodeOptions(host: ServerHost): ts.FormatCodeOptions {
return ts.clone(<ts.FormatCodeOptions>{
IndentSize: 4,
TabSize: 4,
NewLineCharacter: host.newLine || "\n",
ConvertTabsToSpaces: true,
IndentStyle: ts.IndentStyle.Smart,
InsertSpaceAfterCommaDelimiter: true,
InsertSpaceAfterSemicolonInForStatements: true,
InsertSpaceBeforeAndAfterBinaryOperators: true,
InsertSpaceAfterKeywordsInControlFlowStatements: true,
InsertSpaceAfterFunctionKeywordForAnonymousFunctions: false,
InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false,
InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false,
InsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false,
PlaceOpenBraceOnNewLineForFunctions: false,
PlaceOpenBraceOnNewLineForControlBlocks: false,
function getDefaultFormatCodeSettings(host: ServerHost): ts.FormatCodeSettings {
return ts.clone(<ts.FormatCodeSettings>{
indentSize: 4,
tabSize: 4,
newLineCharacter: host.newLine || "\n",
convertTabsToSpaces: true,
indentStyle: ts.IndentStyle.Smart,
insertSpaceAfterCommaDelimiter: true,
insertSpaceAfterSemicolonInForStatements: true,
insertSpaceBeforeAndAfterBinaryOperators: true,
insertSpaceAfterKeywordsInControlFlowStatements: true,
insertSpaceAfterFunctionKeywordForAnonymousFunctions: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false,
insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false,
placeOpenBraceOnNewLineForFunctions: false,
placeOpenBraceOnNewLineForControlBlocks: false,
});
}
function mergeFormatOptions(formatCodeOptions: FormatCodeOptions, formatOptions: protocol.FormatOptions): void {
const hasOwnProperty = Object.prototype.hasOwnProperty;
Object.keys(formatOptions).forEach((key) => {
const codeKey = key.charAt(0).toUpperCase() + key.substring(1);
if (hasOwnProperty.call(formatCodeOptions, codeKey)) {
formatCodeOptions[codeKey] = formatOptions[key];
function mergeMaps(target: Map<any>, source: Map<any>): void {
for (const key in source) {
if (hasProperty(source, key)) {
target[key] = source[key];
}
});
}
}
export class ScriptInfo {
svc: ScriptVersionCache;
defaultProject: Project; // project to use by default for file
fileWatcher: FileWatcher;
formatCodeOptions: ts.FormatCodeOptions;
formatCodeSettings: ts.FormatCodeSettings;
path: Path;
scriptKind: ScriptKind;
constructor(private host: ServerHost, public fileName: string, public content: string, public isOpen = false) {
this.path = toPath(fileName, host.getCurrentDirectory(), createGetCanonicalFileName(host.useCaseSensitiveFileNames));
this.svc = ScriptVersionCache.fromString(host, content);
this.formatCodeOptions = getDefaultFormatCodeOptions(this.host);
this.formatCodeSettings = getDefaultFormatCodeSettings(this.host);
}
setFormatOptions(formatOptions: protocol.FormatOptions): void {
if (formatOptions) {
mergeFormatOptions(this.formatCodeOptions, formatOptions);
setFormatOptions(formatSettings: protocol.FormatOptions): void {
if (formatSettings) {
mergeMaps(this.formatCodeSettings, formatSettings);
}
}
@ -603,7 +601,7 @@ namespace ts.server {
}
export interface HostConfiguration {
formatCodeOptions: ts.FormatCodeOptions;
formatCodeOptions: ts.FormatCodeSettings;
hostInfo: string;
}
@ -665,7 +663,7 @@ namespace ts.server {
private setDefaultHostConfiguration() {
this.hostConfiguration = {
formatCodeOptions: getDefaultFormatCodeOptions(this.host),
formatCodeOptions: getDefaultFormatCodeSettings(this.host),
hostInfo: "Unknown host"
};
}
@ -693,7 +691,7 @@ namespace ts.server {
if (file) {
const info = this.filenameToScriptInfo[file];
if (info) {
return info.formatCodeOptions;
return info.formatCodeSettings;
}
}
return this.hostConfiguration.formatCodeOptions;
@ -1286,7 +1284,7 @@ namespace ts.server {
if (content !== undefined) {
info = new ScriptInfo(this.host, fileName, content, openedByClient);
info.scriptKind = scriptKind;
info.setFormatOptions(this.getFormatCodeOptions());
info.setFormatOptions(toEditorSettings(this.getFormatCodeOptions()));
this.filenameToScriptInfo[fileName] = info;
if (!info.isOpen) {
info.fileWatcher = this.host.watchFile(fileName, _ => { this.onSourceFileChanged(fileName); });
@ -1322,7 +1320,7 @@ namespace ts.server {
this.log("Host information " + args.hostInfo, "Info");
}
if (args.formatOptions) {
mergeFormatOptions(this.hostConfiguration.formatCodeOptions, args.formatOptions);
mergeMaps(this.hostConfiguration.formatCodeOptions, args.formatOptions);
this.log("Format host information updated", "Info");
}
}

View File

@ -544,9 +544,6 @@ declare namespace ts.server.protocol {
/** Defines whether an open brace is put onto a new line for control blocks or not. Default value is false. */
placeOpenBraceOnNewLineForControlBlocks?: boolean;
/** Index operator */
[key: string]: string | number | boolean;
}
/**

View File

@ -778,10 +778,10 @@ namespace ts.server {
if (lineText.search("\\S") < 0) {
// TODO: get these options from host
const editorOptions: ts.EditorOptions = {
IndentSize: formatOptions.IndentSize,
TabSize: formatOptions.TabSize,
NewLineCharacter: formatOptions.NewLineCharacter,
ConvertTabsToSpaces: formatOptions.ConvertTabsToSpaces,
IndentSize: formatOptions.indentSize,
TabSize: formatOptions.tabSize,
NewLineCharacter: formatOptions.newLineCharacter,
ConvertTabsToSpaces: formatOptions.convertTabsToSpaces,
IndentStyle: ts.IndentStyle.Smart,
};
const preferredIndent = project.languageService.getIndentationAtPosition(file, position, editorOptions);

View File

@ -67,7 +67,7 @@ namespace ts.formatting {
delta: number;
}
export function formatOnEnter(position: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeOptions): TextChange[] {
export function formatOnEnter(position: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeSettings): TextChange[] {
const line = sourceFile.getLineAndCharacterOfPosition(position).line;
if (line === 0) {
return [];
@ -96,15 +96,15 @@ namespace ts.formatting {
return formatSpan(span, sourceFile, options, rulesProvider, FormattingRequestKind.FormatOnEnter);
}
export function formatOnSemicolon(position: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeOptions): TextChange[] {
export function formatOnSemicolon(position: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeSettings): TextChange[] {
return formatOutermostParent(position, SyntaxKind.SemicolonToken, sourceFile, options, rulesProvider, FormattingRequestKind.FormatOnSemicolon);
}
export function formatOnClosingCurly(position: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeOptions): TextChange[] {
export function formatOnClosingCurly(position: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeSettings): TextChange[] {
return formatOutermostParent(position, SyntaxKind.CloseBraceToken, sourceFile, options, rulesProvider, FormattingRequestKind.FormatOnClosingCurlyBrace);
}
export function formatDocument(sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeOptions): TextChange[] {
export function formatDocument(sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeSettings): TextChange[] {
const span = {
pos: 0,
end: sourceFile.text.length
@ -112,7 +112,7 @@ namespace ts.formatting {
return formatSpan(span, sourceFile, options, rulesProvider, FormattingRequestKind.FormatDocument);
}
export function formatSelection(start: number, end: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeOptions): TextChange[] {
export function formatSelection(start: number, end: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeSettings): TextChange[] {
// format from the beginning of the line
const span = {
pos: getLineStartPositionForPosition(start, sourceFile),
@ -121,7 +121,7 @@ namespace ts.formatting {
return formatSpan(span, sourceFile, options, rulesProvider, FormattingRequestKind.FormatSelection);
}
function formatOutermostParent(position: number, expectedLastToken: SyntaxKind, sourceFile: SourceFile, options: FormatCodeOptions, rulesProvider: RulesProvider, requestKind: FormattingRequestKind): TextChange[] {
function formatOutermostParent(position: number, expectedLastToken: SyntaxKind, sourceFile: SourceFile, options: FormatCodeSettings, rulesProvider: RulesProvider, requestKind: FormattingRequestKind): TextChange[] {
const parent = findOutermostParent(position, expectedLastToken, sourceFile);
if (!parent) {
return [];
@ -294,7 +294,7 @@ namespace ts.formatting {
* if parent is on the different line - its delta was already contributed
* to the initial indentation.
*/
function getOwnOrInheritedDelta(n: Node, options: FormatCodeOptions, sourceFile: SourceFile): number {
function getOwnOrInheritedDelta(n: Node, options: FormatCodeSettings, sourceFile: SourceFile): number {
let previousLine = Constants.Unknown;
let child: Node;
while (n) {
@ -304,7 +304,7 @@ namespace ts.formatting {
}
if (SmartIndenter.shouldIndentChildNode(n, child)) {
return options.IndentSize;
return options.indentSize;
}
previousLine = line;
@ -316,7 +316,7 @@ namespace ts.formatting {
function formatSpan(originalRange: TextRange,
sourceFile: SourceFile,
options: FormatCodeOptions,
options: FormatCodeSettings,
rulesProvider: RulesProvider,
requestKind: FormattingRequestKind): TextChange[] {
@ -410,7 +410,7 @@ namespace ts.formatting {
effectiveParentStartLine: number): Indentation {
let indentation = inheritedIndentation;
let delta = SmartIndenter.shouldIndentChildNode(node) ? options.IndentSize : 0;
let delta = SmartIndenter.shouldIndentChildNode(node) ? options.indentSize : 0;
if (effectiveParentStartLine === startLine) {
// if node is located on the same line with the parent
@ -419,7 +419,7 @@ namespace ts.formatting {
indentation = startLine === lastIndentedLine
? indentationOnLastIndentedLine
: parentDynamicIndentation.getIndentation();
delta = Math.min(options.IndentSize, parentDynamicIndentation.getDelta(node) + delta);
delta = Math.min(options.indentSize, parentDynamicIndentation.getDelta(node) + delta);
}
else if (indentation === Constants.Unknown) {
if (SmartIndenter.childStartsOnTheSameLineWithElseInIfStatement(parent, node, startLine, sourceFile)) {
@ -503,14 +503,14 @@ namespace ts.formatting {
recomputeIndentation: lineAdded => {
if (node.parent && SmartIndenter.shouldIndentChildNode(node.parent, node)) {
if (lineAdded) {
indentation += options.IndentSize;
indentation += options.indentSize;
}
else {
indentation -= options.IndentSize;
indentation -= options.indentSize;
}
if (SmartIndenter.shouldIndentChildNode(node)) {
delta = options.IndentSize;
delta = options.indentSize;
}
else {
delta = 0;
@ -1036,7 +1036,7 @@ namespace ts.formatting {
// edit should not be applied only if we have one line feed between elements
const lineDelta = currentStartLine - previousStartLine;
if (lineDelta !== 1) {
recordReplace(previousRange.end, currentRange.pos - previousRange.end, options.NewLineCharacter);
recordReplace(previousRange.end, currentRange.pos - previousRange.end, options.newLineCharacter);
}
break;
case RuleAction.Space:
@ -1102,19 +1102,19 @@ namespace ts.formatting {
let internedTabsIndentation: string[];
let internedSpacesIndentation: string[];
export function getIndentationString(indentation: number, options: FormatCodeOptions): string {
export function getIndentationString(indentation: number, options: EditorSettings): string {
// reset interned strings if FormatCodeOptions were changed
const resetInternedStrings =
!internedSizes || (internedSizes.tabSize !== options.TabSize || internedSizes.indentSize !== options.IndentSize);
!internedSizes || (internedSizes.tabSize !== options.tabSize || internedSizes.indentSize !== options.indentSize);
if (resetInternedStrings) {
internedSizes = { tabSize: options.TabSize, indentSize: options.IndentSize };
internedSizes = { tabSize: options.tabSize, indentSize: options.indentSize };
internedTabsIndentation = internedSpacesIndentation = undefined;
}
if (!options.ConvertTabsToSpaces) {
const tabs = Math.floor(indentation / options.TabSize);
const spaces = indentation - tabs * options.TabSize;
if (!options.convertTabsToSpaces) {
const tabs = Math.floor(indentation / options.tabSize);
const spaces = indentation - tabs * options.tabSize;
let tabString: string;
if (!internedTabsIndentation) {
@ -1132,14 +1132,14 @@ namespace ts.formatting {
}
else {
let spacesString: string;
const quotient = Math.floor(indentation / options.IndentSize);
const remainder = indentation % options.IndentSize;
const quotient = Math.floor(indentation / options.indentSize);
const remainder = indentation % options.indentSize;
if (!internedSpacesIndentation) {
internedSpacesIndentation = [];
}
if (internedSpacesIndentation[quotient] === undefined) {
spacesString = repeat(" ", options.IndentSize * quotient);
spacesString = repeat(" ", options.indentSize * quotient);
internedSpacesIndentation[quotient] = spacesString;
}
else {

View File

@ -4,7 +4,7 @@
namespace ts.formatting {
export class RulesProvider {
private globalRules: Rules;
private options: ts.FormatCodeOptions;
private options: ts.FormatCodeSettings;
private activeRules: Rule[];
private rulesMap: RulesMap;
@ -24,7 +24,7 @@ namespace ts.formatting {
return this.rulesMap;
}
public ensureUpToDate(options: ts.FormatCodeOptions) {
public ensureUpToDate(options: ts.FormatCodeSettings) {
if (!this.options || !ts.compareDataObjects(this.options, options)) {
const activeRules = this.createActiveRules(options);
const rulesMap = RulesMap.create(activeRules);
@ -35,31 +35,31 @@ namespace ts.formatting {
}
}
private createActiveRules(options: ts.FormatCodeOptions): Rule[] {
private createActiveRules(options: ts.FormatCodeSettings): Rule[] {
let rules = this.globalRules.HighPriorityCommonRules.slice(0);
if (options.InsertSpaceAfterCommaDelimiter) {
if (options.insertSpaceAfterCommaDelimiter) {
rules.push(this.globalRules.SpaceAfterComma);
}
else {
rules.push(this.globalRules.NoSpaceAfterComma);
}
if (options.InsertSpaceAfterFunctionKeywordForAnonymousFunctions) {
if (options.insertSpaceAfterFunctionKeywordForAnonymousFunctions) {
rules.push(this.globalRules.SpaceAfterAnonymousFunctionKeyword);
}
else {
rules.push(this.globalRules.NoSpaceAfterAnonymousFunctionKeyword);
}
if (options.InsertSpaceAfterKeywordsInControlFlowStatements) {
if (options.insertSpaceAfterKeywordsInControlFlowStatements) {
rules.push(this.globalRules.SpaceAfterKeywordInControl);
}
else {
rules.push(this.globalRules.NoSpaceAfterKeywordInControl);
}
if (options.InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis) {
if (options.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis) {
rules.push(this.globalRules.SpaceAfterOpenParen);
rules.push(this.globalRules.SpaceBeforeCloseParen);
rules.push(this.globalRules.NoSpaceBetweenParens);
@ -70,7 +70,7 @@ namespace ts.formatting {
rules.push(this.globalRules.NoSpaceBetweenParens);
}
if (options.InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets) {
if (options.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets) {
rules.push(this.globalRules.SpaceAfterOpenBracket);
rules.push(this.globalRules.SpaceBeforeCloseBracket);
rules.push(this.globalRules.NoSpaceBetweenBrackets);
@ -81,7 +81,7 @@ namespace ts.formatting {
rules.push(this.globalRules.NoSpaceBetweenBrackets);
}
if (options.InsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces) {
if (options.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces) {
rules.push(this.globalRules.SpaceAfterTemplateHeadAndMiddle);
rules.push(this.globalRules.SpaceBeforeTemplateMiddleAndTail);
}
@ -90,14 +90,14 @@ namespace ts.formatting {
rules.push(this.globalRules.NoSpaceBeforeTemplateMiddleAndTail);
}
if (options.InsertSpaceAfterSemicolonInForStatements) {
if (options.insertSpaceAfterSemicolonInForStatements) {
rules.push(this.globalRules.SpaceAfterSemicolonInFor);
}
else {
rules.push(this.globalRules.NoSpaceAfterSemicolonInFor);
}
if (options.InsertSpaceBeforeAndAfterBinaryOperators) {
if (options.insertSpaceBeforeAndAfterBinaryOperators) {
rules.push(this.globalRules.SpaceBeforeBinaryOperator);
rules.push(this.globalRules.SpaceAfterBinaryOperator);
}
@ -106,11 +106,11 @@ namespace ts.formatting {
rules.push(this.globalRules.NoSpaceAfterBinaryOperator);
}
if (options.PlaceOpenBraceOnNewLineForControlBlocks) {
if (options.placeOpenBraceOnNewLineForControlBlocks) {
rules.push(this.globalRules.NewLineBeforeOpenBraceInControl);
}
if (options.PlaceOpenBraceOnNewLineForFunctions) {
if (options.placeOpenBraceOnNewLineForFunctions) {
rules.push(this.globalRules.NewLineBeforeOpenBraceInFunction);
rules.push(this.globalRules.NewLineBeforeOpenBraceInTypeScriptDeclWithBlock);
}

View File

@ -8,14 +8,14 @@ namespace ts.formatting {
Unknown = -1
}
export function getIndentation(position: number, sourceFile: SourceFile, options: EditorOptions): number {
export function getIndentation(position: number, sourceFile: SourceFile, options: EditorSettings): number {
if (position > sourceFile.text.length) {
return 0; // past EOF
}
// no indentation when the indent style is set to none,
// so we can return fast
if (options.IndentStyle === IndentStyle.None) {
if (options.indentStyle === IndentStyle.None) {
return 0;
}
@ -35,7 +35,7 @@ namespace ts.formatting {
// 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) {
if (options.indentStyle === IndentStyle.Block) {
// move backwards until we find a line with a non-whitespace character,
// then find the first non-whitespace character for that line.
@ -75,7 +75,7 @@ namespace ts.formatting {
indentationDelta = 0;
}
else {
indentationDelta = lineAtPosition !== currentStart.line ? options.IndentSize : 0;
indentationDelta = lineAtPosition !== currentStart.line ? options.indentSize : 0;
}
break;
@ -88,7 +88,7 @@ namespace ts.formatting {
}
actualIndentation = getLineIndentationWhenExpressionIsInMultiLine(current, sourceFile, options);
if (actualIndentation !== Value.Unknown) {
return actualIndentation + options.IndentSize;
return actualIndentation + options.indentSize;
}
previous = current;
@ -103,7 +103,7 @@ namespace ts.formatting {
return getIndentationForNodeWorker(current, currentStart, /*ignoreActualIndentationRange*/ undefined, indentationDelta, sourceFile, options);
}
export function getIndentationForNode(n: Node, ignoreActualIndentationRange: TextRange, sourceFile: SourceFile, options: FormatCodeOptions): number {
export function getIndentationForNode(n: Node, ignoreActualIndentationRange: TextRange, sourceFile: SourceFile, options: EditorSettings): number {
const start = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile));
return getIndentationForNodeWorker(n, start, ignoreActualIndentationRange, /*indentationDelta*/ 0, sourceFile, options);
}
@ -114,7 +114,7 @@ namespace ts.formatting {
ignoreActualIndentationRange: TextRange,
indentationDelta: number,
sourceFile: SourceFile,
options: EditorOptions): number {
options: EditorSettings): number {
let parent: Node = current.parent;
let parentStart: LineAndCharacter;
@ -154,7 +154,7 @@ namespace ts.formatting {
// increase indentation if parent node wants its content to be indented and parent and child nodes don't start on the same line
if (shouldIndentChildNode(parent, current) && !parentAndChildShareLine) {
indentationDelta += options.IndentSize;
indentationDelta += options.indentSize;
}
current = parent;
@ -178,7 +178,7 @@ namespace ts.formatting {
/*
* Function returns Value.Unknown if indentation cannot be determined
*/
function getActualIndentationForListItemBeforeComma(commaToken: Node, sourceFile: SourceFile, options: EditorOptions): number {
function getActualIndentationForListItemBeforeComma(commaToken: Node, sourceFile: SourceFile, options: EditorSettings): number {
// previous token is comma that separates items in list - find the previous item and try to derive indentation from it
const commaItemInfo = findListItemInfo(commaToken);
if (commaItemInfo && commaItemInfo.listItemIndex > 0) {
@ -198,7 +198,7 @@ namespace ts.formatting {
currentLineAndChar: LineAndCharacter,
parentAndChildShareLine: boolean,
sourceFile: SourceFile,
options: EditorOptions): number {
options: EditorSettings): number {
// actual indentation is used for statements\declarations if one of cases below is true:
// - parent is SourceFile - by default immediate children of SourceFile are not indented except when user indents them manually
@ -305,7 +305,7 @@ namespace ts.formatting {
return undefined;
}
function getActualIndentationForListItem(node: Node, sourceFile: SourceFile, options: EditorOptions): number {
function getActualIndentationForListItem(node: Node, sourceFile: SourceFile, options: EditorSettings): number {
const containingList = getContainingList(node, sourceFile);
return containingList ? getActualIndentationFromList(containingList) : Value.Unknown;
@ -315,7 +315,7 @@ namespace ts.formatting {
}
}
function getLineIndentationWhenExpressionIsInMultiLine(node: Node, sourceFile: SourceFile, options: EditorOptions): number {
function getLineIndentationWhenExpressionIsInMultiLine(node: Node, sourceFile: SourceFile, options: EditorSettings): number {
// actual indentation should not be used when:
// - node is close parenthesis - this is the end of the expression
if (node.kind === SyntaxKind.CloseParenToken) {
@ -363,7 +363,7 @@ namespace ts.formatting {
}
}
function deriveActualIndentationFromList(list: Node[], index: number, sourceFile: SourceFile, options: EditorOptions): number {
function deriveActualIndentationFromList(list: Node[], index: number, sourceFile: SourceFile, options: EditorSettings): number {
Debug.assert(index >= 0 && index < list.length);
const node = list[index];
@ -385,7 +385,7 @@ namespace ts.formatting {
return Value.Unknown;
}
function findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter: LineAndCharacter, sourceFile: SourceFile, options: EditorOptions): number {
function findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter: LineAndCharacter, sourceFile: SourceFile, options: EditorSettings): number {
const lineStart = sourceFile.getPositionOfLineAndCharacter(lineAndCharacter.line, 0);
return findFirstNonWhitespaceColumn(lineStart, lineStart + lineAndCharacter.character, sourceFile, options);
}
@ -397,7 +397,7 @@ namespace ts.formatting {
value of 'character' for '$' is 3
value of 'column' for '$' is 6 (assuming that tab size is 4)
*/
export function findFirstNonWhitespaceCharacterAndColumn(startPos: number, endPos: number, sourceFile: SourceFile, options: EditorOptions) {
export function findFirstNonWhitespaceCharacterAndColumn(startPos: number, endPos: number, sourceFile: SourceFile, options: EditorSettings) {
let character = 0;
let column = 0;
for (let pos = startPos; pos < endPos; pos++) {
@ -407,7 +407,7 @@ namespace ts.formatting {
}
if (ch === CharacterCodes.tab) {
column += options.TabSize + (column % options.TabSize);
column += options.tabSize + (column % options.tabSize);
}
else {
column++;
@ -418,7 +418,7 @@ namespace ts.formatting {
return { column, character };
}
export function findFirstNonWhitespaceColumn(startPos: number, endPos: number, sourceFile: SourceFile, options: EditorOptions): number {
export function findFirstNonWhitespaceColumn(startPos: number, endPos: number, sourceFile: SourceFile, options: EditorSettings): number {
return findFirstNonWhitespaceCharacterAndColumn(startPos, endPos, sourceFile, options).column;
}

View File

@ -1154,11 +1154,11 @@ namespace ts {
getOutliningSpans(fileName: string): OutliningSpan[];
getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[];
getBraceMatchingAtPosition(fileName: string, position: number): TextSpan[];
getIndentationAtPosition(fileName: string, position: number, options: EditorOptions): number;
getIndentationAtPosition(fileName: string, position: number, options: EditorOptions | EditorSettings): number;
getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions): TextChange[];
getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions): TextChange[];
getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions): TextChange[];
getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions | FormatCodeSettings): TextChange[];
getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[];
getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[];
getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion;
@ -1258,6 +1258,7 @@ namespace ts {
containerKind: string;
}
/* @deprecated - consider using EditorSettings instead */
export interface EditorOptions {
IndentSize: number;
TabSize: number;
@ -1266,12 +1267,21 @@ namespace ts {
IndentStyle: IndentStyle;
}
export interface EditorSettings {
indentSize: number;
tabSize: number;
newLineCharacter: string;
convertTabsToSpaces: boolean;
indentStyle: IndentStyle;
}
export enum IndentStyle {
None = 0,
Block = 1,
Smart = 2,
}
/* @deprecated - consider using FormatCodeSettings instead */
export interface FormatCodeOptions extends EditorOptions {
InsertSpaceAfterCommaDelimiter: boolean;
InsertSpaceAfterSemicolonInForStatements: boolean;
@ -1283,9 +1293,50 @@ namespace ts {
InsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: boolean;
PlaceOpenBraceOnNewLineForFunctions: boolean;
PlaceOpenBraceOnNewLineForControlBlocks: boolean;
[s: string]: boolean | number | string;
}
export interface FormatCodeSettings extends EditorSettings {
insertSpaceAfterCommaDelimiter: boolean;
insertSpaceAfterSemicolonInForStatements: boolean;
insertSpaceBeforeAndAfterBinaryOperators: boolean;
insertSpaceAfterKeywordsInControlFlowStatements: boolean;
insertSpaceAfterFunctionKeywordForAnonymousFunctions: boolean;
insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: boolean;
insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: boolean;
insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: boolean;
placeOpenBraceOnNewLineForFunctions: boolean;
placeOpenBraceOnNewLineForControlBlocks: boolean;
}
/* @internal */
export function toEditorSettings(options: FormatCodeOptions | FormatCodeSettings): FormatCodeSettings;
export function toEditorSettings(options: EditorOptions | EditorSettings): EditorSettings;
export function toEditorSettings(optionsAsMap: Map<any>): Map<any> {
let allPropertiesAreCamelCased = true;
for (const key in optionsAsMap) {
if (hasProperty(optionsAsMap, key) && !isCamelCase(key)) {
allPropertiesAreCamelCased = false;
break;
}
}
if (allPropertiesAreCamelCased) {
return optionsAsMap;
}
const settings: Map<any> = {};
for (const key in optionsAsMap) {
if (hasProperty(optionsAsMap, key)) {
const newKey = isCamelCase(key) ? key : key.charAt(0).toLowerCase() + key.substr(1);
settings[newKey] = optionsAsMap[key];
}
}
return settings;
}
function isCamelCase(s: string) {
return !s.length || s.charAt(0) === s.charAt(0).toLowerCase();
}
export interface DefinitionInfo {
fileName: string;
textSpan: TextSpan;
@ -2949,7 +3000,7 @@ namespace ts {
return sourceFile;
}
function getRuleProvider(options: FormatCodeOptions) {
function getRuleProvider(options: FormatCodeSettings) {
// Ensure rules are initialized and up to date wrt to formatting options
if (!ruleProvider) {
ruleProvider = new formatting.RulesProvider();
@ -7632,40 +7683,44 @@ namespace ts {
}
}
function getIndentationAtPosition(fileName: string, position: number, editorOptions: EditorOptions) {
function getIndentationAtPosition(fileName: string, position: number, optionsOrSettings: EditorOptions | EditorSettings) {
let start = new Date().getTime();
const settings = toEditorSettings(optionsOrSettings);
const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
log("getIndentationAtPosition: getCurrentSourceFile: " + (new Date().getTime() - start));
start = new Date().getTime();
const result = formatting.SmartIndenter.getIndentation(position, sourceFile, editorOptions);
const result = formatting.SmartIndenter.getIndentation(position, sourceFile, settings);
log("getIndentationAtPosition: computeIndentation : " + (new Date().getTime() - start));
return result;
}
function getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions): TextChange[] {
function getFormattingEditsForRange(fileName: string, start: number, end: number, optionsOrSettings: FormatCodeOptions | FormatCodeSettings): TextChange[] {
const settings = toEditorSettings(optionsOrSettings);
const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
return formatting.formatSelection(start, end, sourceFile, getRuleProvider(options), options);
return formatting.formatSelection(start, end, sourceFile, getRuleProvider(settings), settings);
}
function getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions): TextChange[] {
function getFormattingEditsForDocument(fileName: string, optionsOrSettings: FormatCodeOptions | FormatCodeSettings): TextChange[] {
const settings = toEditorSettings(optionsOrSettings);
const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
return formatting.formatDocument(sourceFile, getRuleProvider(options), options);
return formatting.formatDocument(sourceFile, getRuleProvider(settings), settings);
}
function getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions): TextChange[] {
function getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, optionsOrSettings: FormatCodeOptions | FormatCodeSettings): TextChange[] {
const settings = toEditorSettings(optionsOrSettings);
const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
if (key === "}") {
return formatting.formatOnClosingCurly(position, sourceFile, getRuleProvider(options), options);
return formatting.formatOnClosingCurly(position, sourceFile, getRuleProvider(settings), settings);
}
else if (key === ";") {
return formatting.formatOnSemicolon(position, sourceFile, getRuleProvider(options), options);
return formatting.formatOnSemicolon(position, sourceFile, getRuleProvider(settings), settings);
}
else if (key === "\n") {
return formatting.formatOnEnter(position, sourceFile, getRuleProvider(options), options);
return formatting.formatOnEnter(position, sourceFile, getRuleProvider(settings), settings);
}
return [];