• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/* @internal */
2namespace ts.formatting {
3    export const enum FormattingRequestKind {
4        FormatDocument,
5        FormatSelection,
6        FormatOnEnter,
7        FormatOnSemicolon,
8        FormatOnOpeningCurlyBrace,
9        FormatOnClosingCurlyBrace
10    }
11
12    export class FormattingContext {
13        public currentTokenSpan!: TextRangeWithKind;
14        public nextTokenSpan!: TextRangeWithKind;
15        public contextNode!: Node;
16        public currentTokenParent!: Node;
17        public nextTokenParent!: Node;
18
19        private contextNodeAllOnSameLine: boolean | undefined;
20        private nextNodeAllOnSameLine: boolean | undefined;
21        private tokensAreOnSameLine: boolean | undefined;
22        private contextNodeBlockIsOnOneLine: boolean | undefined;
23        private nextNodeBlockIsOnOneLine: boolean | undefined;
24
25        constructor(public readonly sourceFile: SourceFileLike, public formattingRequestKind: FormattingRequestKind, public options: FormatCodeSettings) {
26        }
27
28        public updateContext(currentRange: TextRangeWithKind, currentTokenParent: Node, nextRange: TextRangeWithKind, nextTokenParent: Node, commonParent: Node) {
29            this.currentTokenSpan = Debug.checkDefined(currentRange);
30            this.currentTokenParent = Debug.checkDefined(currentTokenParent);
31            this.nextTokenSpan = Debug.checkDefined(nextRange);
32            this.nextTokenParent = Debug.checkDefined(nextTokenParent);
33            this.contextNode = Debug.checkDefined(commonParent);
34
35            // drop cached results
36            this.contextNodeAllOnSameLine = undefined;
37            this.nextNodeAllOnSameLine = undefined;
38            this.tokensAreOnSameLine = undefined;
39            this.contextNodeBlockIsOnOneLine = undefined;
40            this.nextNodeBlockIsOnOneLine = undefined;
41        }
42
43        public ContextNodeAllOnSameLine(): boolean {
44            if (this.contextNodeAllOnSameLine === undefined) {
45                this.contextNodeAllOnSameLine = this.NodeIsOnOneLine(this.contextNode);
46            }
47
48            return this.contextNodeAllOnSameLine;
49        }
50
51        public NextNodeAllOnSameLine(): boolean {
52            if (this.nextNodeAllOnSameLine === undefined) {
53                this.nextNodeAllOnSameLine = this.NodeIsOnOneLine(this.nextTokenParent);
54            }
55
56            return this.nextNodeAllOnSameLine;
57        }
58
59        public TokensAreOnSameLine(): boolean {
60            if (this.tokensAreOnSameLine === undefined) {
61                const startLine = this.sourceFile.getLineAndCharacterOfPosition(this.currentTokenSpan.pos).line;
62                const endLine = this.sourceFile.getLineAndCharacterOfPosition(this.nextTokenSpan.pos).line;
63                this.tokensAreOnSameLine = (startLine === endLine);
64            }
65
66            return this.tokensAreOnSameLine;
67        }
68
69        public ContextNodeBlockIsOnOneLine() {
70            if (this.contextNodeBlockIsOnOneLine === undefined) {
71                this.contextNodeBlockIsOnOneLine = this.BlockIsOnOneLine(this.contextNode);
72            }
73
74            return this.contextNodeBlockIsOnOneLine;
75        }
76
77        public NextNodeBlockIsOnOneLine() {
78            if (this.nextNodeBlockIsOnOneLine === undefined) {
79                this.nextNodeBlockIsOnOneLine = this.BlockIsOnOneLine(this.nextTokenParent);
80            }
81
82            return this.nextNodeBlockIsOnOneLine;
83        }
84
85        private NodeIsOnOneLine(node: Node): boolean {
86            const startLine = this.sourceFile.getLineAndCharacterOfPosition(node.getStart(this.sourceFile)).line;
87            const endLine = this.sourceFile.getLineAndCharacterOfPosition(node.getEnd()).line;
88            return startLine === endLine;
89        }
90
91        private BlockIsOnOneLine(node: Node): boolean {
92            const openBrace = findChildOfKind(node, SyntaxKind.OpenBraceToken, this.sourceFile);
93            const closeBrace = findChildOfKind(node, SyntaxKind.CloseBraceToken, this.sourceFile);
94            if (openBrace && closeBrace) {
95                const startLine = this.sourceFile.getLineAndCharacterOfPosition(openBrace.getEnd()).line;
96                const endLine = this.sourceFile.getLineAndCharacterOfPosition(closeBrace.getStart(this.sourceFile)).line;
97                return startLine === endLine;
98            }
99            return false;
100        }
101    }
102}
103