Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/build/lib/formatter.ts
3520 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
import fs from 'fs';
6
import path from 'path';
7
import ts from 'typescript';
8
9
10
class LanguageServiceHost implements ts.LanguageServiceHost {
11
files: ts.MapLike<ts.IScriptSnapshot> = {};
12
addFile(fileName: string, text: string) {
13
this.files[fileName] = ts.ScriptSnapshot.fromString(text);
14
}
15
16
fileExists(path: string): boolean {
17
return !!this.files[path];
18
}
19
20
readFile(path: string): string | undefined {
21
return this.files[path]?.getText(0, this.files[path]!.getLength());
22
}
23
24
// for ts.LanguageServiceHost
25
26
getCompilationSettings = () => ts.getDefaultCompilerOptions();
27
getScriptFileNames = () => Object.keys(this.files);
28
getScriptVersion = (_fileName: string) => '0';
29
getScriptSnapshot = (fileName: string) => this.files[fileName];
30
getCurrentDirectory = () => process.cwd();
31
getDefaultLibFileName = (options: ts.CompilerOptions) => ts.getDefaultLibFilePath(options);
32
}
33
34
const defaults: ts.FormatCodeSettings = {
35
baseIndentSize: 0,
36
indentSize: 4,
37
tabSize: 4,
38
indentStyle: ts.IndentStyle.Smart,
39
newLineCharacter: '\r\n',
40
convertTabsToSpaces: false,
41
insertSpaceAfterCommaDelimiter: true,
42
insertSpaceAfterSemicolonInForStatements: true,
43
insertSpaceBeforeAndAfterBinaryOperators: true,
44
insertSpaceAfterConstructor: false,
45
insertSpaceAfterKeywordsInControlFlowStatements: true,
46
insertSpaceAfterFunctionKeywordForAnonymousFunctions: false,
47
insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false,
48
insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false,
49
insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true,
50
insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false,
51
insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces: false,
52
insertSpaceAfterTypeAssertion: false,
53
insertSpaceBeforeFunctionParenthesis: false,
54
placeOpenBraceOnNewLineForFunctions: false,
55
placeOpenBraceOnNewLineForControlBlocks: false,
56
insertSpaceBeforeTypeAnnotation: false,
57
};
58
59
const getOverrides = (() => {
60
let value: ts.FormatCodeSettings | undefined;
61
return () => {
62
value ??= JSON.parse(fs.readFileSync(path.join(__dirname, '..', '..', 'tsfmt.json'), 'utf8'));
63
return value;
64
};
65
})();
66
67
export function format(fileName: string, text: string) {
68
69
const host = new LanguageServiceHost();
70
host.addFile(fileName, text);
71
72
const languageService = ts.createLanguageService(host);
73
const edits = languageService.getFormattingEditsForDocument(fileName, { ...defaults, ...getOverrides() });
74
edits
75
.sort((a, b) => a.span.start - b.span.start)
76
.reverse()
77
.forEach(edit => {
78
const head = text.slice(0, edit.span.start);
79
const tail = text.slice(edit.span.start + edit.span.length);
80
text = `${head}${edit.newText}${tail}`;
81
});
82
83
return text;
84
}
85
86