Skip to content

Commit 1520cf8

Browse files
committed
feat(tsfmt): using Language Service API instead of Old Compiler API
1 parent 74f7eb9 commit 1520cf8

File tree

1 file changed

+29
-39
lines changed

1 file changed

+29
-39
lines changed

lib/formatter.ts

+29-39
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,37 @@
11
import * as ts from "typescript";
2-
import { createDefaultFormatCodeSettings } from "./utils";
3-
4-
// from https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#pretty-printer-using-the-ls-formatter
5-
6-
// Note: this uses ts.formatting which is part of the typescript 1.4 package but is not currently
7-
// exposed in the public typescript.d.ts. The typings should be exposed in the next release.
8-
export default function format(fileName: string, text: string, options = createDefaultFormatCodeSettings()) {
9-
10-
// Parse the source text
11-
let sourceFile = ts.createSourceFile(fileName, text, ts.ScriptTarget.Latest, true);
122

13-
// Get the formatting edits on the input sources
14-
let edits = (ts as any).formatting.formatDocument(sourceFile, getRuleProvider(options), options);
15-
16-
// Apply the edits on the input code
17-
return applyEdits(text, edits);
3+
import { createDefaultFormatCodeSettings } from "./utils";
184

19-
function getRuleProvider(settings: ts.FormatCodeSettings) {
20-
// Share this between multiple formatters using the same options.
21-
// This represents the bulk of the space the formatter uses.
22-
let ruleProvider = new (ts as any).formatting.RulesProvider();
23-
ruleProvider.ensureUpToDate(settings);
24-
return ruleProvider;
5+
class LanguageServiceHost implements ts.LanguageServiceHost {
6+
files: { [fileName: string]: ts.IScriptSnapshot; } = {};
7+
addFile(fileName: string, text: string) {
8+
this.files[fileName] = ts.ScriptSnapshot.fromString(text);
259
}
2610

27-
function applyEdits(text: string, edits: ts.TextChange[]): string {
28-
// Apply edits in reverse on the existing text
29-
let result = text;
11+
// for ts.LanguageServiceHost
3012

31-
// An issue with `ts.formatting.formatDocument` is that it does
32-
// not always give the edits array in ascending order of change start
33-
// point. This can result that we add or remove some character in
34-
// the begining of the document, making the all the other edits
35-
// offsets invalid.
13+
getCompilationSettings = () => ts.getDefaultCompilerOptions();
14+
getScriptFileNames = () => Object.keys(this.files);
15+
getScriptVersion = (_fileName: string) => "1";
16+
getScriptSnapshot = (fileName: string) => this.files[fileName];
17+
getCurrentDirectory = () => process.cwd();
18+
getDefaultLibFileName = (_options: ts.CompilerOptions) => "lib";
19+
}
3620

37-
// We resolve this by sorting edits by ascending start point
38-
edits.sort((a, b) => a.span.start - b.span.start);
39-
for (let i = edits.length - 1; i >= 0; i--) {
40-
let change = edits[i];
41-
let head = result.slice(0, change.span.start);
42-
let tail = result.slice(change.span.start + change.span.length);
43-
result = head + change.newText + tail;
44-
}
45-
return result;
46-
}
21+
export default function format(fileName: string, text: string, options = createDefaultFormatCodeSettings()) {
22+
const host = new LanguageServiceHost();
23+
host.addFile(fileName, text);
24+
25+
const languageService = ts.createLanguageService(host, ts.createDocumentRegistry());
26+
const edits = languageService.getFormattingEditsForDocument(fileName, options);
27+
edits
28+
.sort((a, b) => a.span.start - b.span.start)
29+
.reverse()
30+
.forEach(edit => {
31+
const head = text.slice(0, edit.span.start);
32+
const tail = text.slice(edit.span.start + edit.span.length);
33+
text = `${head}${edit.newText}${tail}`;
34+
});
35+
36+
return text;
4737
}

0 commit comments

Comments
 (0)