122 lines
4.2 KiB
Go
122 lines
4.2 KiB
Go
package format
|
|
|
|
import (
|
|
"github.com/microsoft/typescript-go/internal/ast"
|
|
"github.com/microsoft/typescript-go/internal/astnav"
|
|
"github.com/microsoft/typescript-go/internal/core"
|
|
"github.com/microsoft/typescript-go/internal/ls/lsutil"
|
|
"github.com/microsoft/typescript-go/internal/scanner"
|
|
)
|
|
|
|
type FormattingContext struct {
|
|
currentTokenSpan TextRangeWithKind
|
|
nextTokenSpan TextRangeWithKind
|
|
contextNode *ast.Node
|
|
currentTokenParent *ast.Node
|
|
nextTokenParent *ast.Node
|
|
|
|
contextNodeAllOnSameLine core.Tristate
|
|
nextNodeAllOnSameLine core.Tristate
|
|
tokensAreOnSameLine core.Tristate
|
|
contextNodeBlockIsOnOneLine core.Tristate
|
|
nextNodeBlockIsOnOneLine core.Tristate
|
|
|
|
SourceFile *ast.SourceFile
|
|
FormattingRequestKind FormatRequestKind
|
|
Options lsutil.FormatCodeSettings
|
|
}
|
|
|
|
func NewFormattingContext(file *ast.SourceFile, kind FormatRequestKind, options lsutil.FormatCodeSettings) *FormattingContext {
|
|
res := &FormattingContext{
|
|
SourceFile: file,
|
|
FormattingRequestKind: kind,
|
|
Options: options,
|
|
}
|
|
return res
|
|
}
|
|
|
|
func (this *FormattingContext) UpdateContext(cur TextRangeWithKind, curParent *ast.Node, next TextRangeWithKind, nextParent *ast.Node, commonParent *ast.Node) {
|
|
if curParent == nil {
|
|
panic("nil current range node parent in update context")
|
|
}
|
|
if nextParent == nil {
|
|
panic("nil next range node parent in update context")
|
|
}
|
|
if commonParent == nil {
|
|
panic("nil common parent node in update context")
|
|
}
|
|
this.currentTokenSpan = cur
|
|
this.currentTokenParent = curParent
|
|
this.nextTokenSpan = next
|
|
this.nextTokenParent = nextParent
|
|
this.contextNode = commonParent
|
|
|
|
// drop cached results
|
|
this.contextNodeAllOnSameLine = core.TSUnknown
|
|
this.nextNodeAllOnSameLine = core.TSUnknown
|
|
this.tokensAreOnSameLine = core.TSUnknown
|
|
this.contextNodeBlockIsOnOneLine = core.TSUnknown
|
|
this.nextNodeBlockIsOnOneLine = core.TSUnknown
|
|
}
|
|
|
|
func (this *FormattingContext) rangeIsOnOneLine(node core.TextRange) core.Tristate {
|
|
if rangeIsOnOneLine(node, this.SourceFile) {
|
|
return core.TSTrue
|
|
}
|
|
return core.TSFalse
|
|
}
|
|
|
|
func (this *FormattingContext) nodeIsOnOneLine(node *ast.Node) core.Tristate {
|
|
return this.rangeIsOnOneLine(withTokenStart(node, this.SourceFile))
|
|
}
|
|
|
|
func withTokenStart(loc *ast.Node, file *ast.SourceFile) core.TextRange {
|
|
startPos := scanner.GetTokenPosOfNode(loc, file, false)
|
|
return core.NewTextRange(startPos, loc.End())
|
|
}
|
|
|
|
func (this *FormattingContext) blockIsOnOneLine(node *ast.Node) core.Tristate {
|
|
openBrace := astnav.FindChildOfKind(node, ast.KindOpenBraceToken, this.SourceFile)
|
|
closeBrace := astnav.FindChildOfKind(node, ast.KindCloseBraceToken, this.SourceFile)
|
|
if openBrace != nil && closeBrace != nil {
|
|
closeBraceStart := scanner.GetTokenPosOfNode(closeBrace, this.SourceFile, false)
|
|
return this.rangeIsOnOneLine(core.NewTextRange(openBrace.End(), closeBraceStart))
|
|
}
|
|
return core.TSFalse
|
|
}
|
|
|
|
func (this *FormattingContext) ContextNodeAllOnSameLine() bool {
|
|
if this.contextNodeAllOnSameLine == core.TSUnknown {
|
|
this.contextNodeAllOnSameLine = this.nodeIsOnOneLine(this.contextNode)
|
|
}
|
|
return this.contextNodeAllOnSameLine == core.TSTrue
|
|
}
|
|
|
|
func (this *FormattingContext) NextNodeAllOnSameLine() bool {
|
|
if this.nextNodeAllOnSameLine == core.TSUnknown {
|
|
this.nextNodeAllOnSameLine = this.nodeIsOnOneLine(this.nextTokenParent)
|
|
}
|
|
return this.nextNodeAllOnSameLine == core.TSTrue
|
|
}
|
|
|
|
func (this *FormattingContext) TokensAreOnSameLine() bool {
|
|
if this.tokensAreOnSameLine == core.TSUnknown {
|
|
this.tokensAreOnSameLine = this.rangeIsOnOneLine(core.NewTextRange(this.currentTokenSpan.Loc.Pos(), this.nextTokenSpan.Loc.End()))
|
|
}
|
|
return this.tokensAreOnSameLine == core.TSTrue
|
|
}
|
|
|
|
func (this *FormattingContext) ContextNodeBlockIsOnOneLine() bool {
|
|
if this.contextNodeBlockIsOnOneLine == core.TSUnknown {
|
|
this.contextNodeBlockIsOnOneLine = this.blockIsOnOneLine(this.contextNode)
|
|
}
|
|
return this.contextNodeBlockIsOnOneLine == core.TSTrue
|
|
}
|
|
|
|
func (this *FormattingContext) NextNodeBlockIsOnOneLine() bool {
|
|
if this.nextNodeBlockIsOnOneLine == core.TSUnknown {
|
|
this.nextNodeBlockIsOnOneLine = this.blockIsOnOneLine(this.nextTokenParent)
|
|
}
|
|
return this.nextNodeBlockIsOnOneLine == core.TSTrue
|
|
}
|