package printer import ( "strings" "unicode/utf8" "efprojects.com/kitten-ipc/kitcom/internal/tsgo/ast" "efprojects.com/kitten-ipc/kitcom/internal/tsgo/core" "efprojects.com/kitten-ipc/kitcom/internal/tsgo/stringutil" ) var _ EmitTextWriter = &textWriter{} type textWriter struct { newLine string builder strings.Builder lastWritten string indent int lineStart bool lineCount int linePos int hasTrailingCommentState bool } func (w *textWriter) Clear() { *w = textWriter{newLine: w.newLine, lineStart: true} } func (w *textWriter) DecreaseIndent() { w.indent-- } func (w *textWriter) GetColumn() int { if w.lineStart { return w.indent * 4 } return w.builder.Len() - w.linePos } func (w *textWriter) GetIndent() int { return w.indent } func (w *textWriter) GetLine() int { return w.lineCount } func (w *textWriter) String() string { return w.builder.String() } func (w *textWriter) GetTextPos() int { return w.builder.Len() } func (w textWriter) HasTrailingComment() bool { return w.hasTrailingCommentState } func (w *textWriter) HasTrailingWhitespace() bool { if w.builder.Len() == 0 { return false } ch, _ := utf8.DecodeLastRuneInString(w.lastWritten) if ch == utf8.RuneError { return false } return stringutil.IsWhiteSpaceLike(ch) } func (w *textWriter) IncreaseIndent() { w.indent++ } func (w *textWriter) IsAtStartOfLine() bool { return w.lineStart } func (w *textWriter) RawWrite(s string) { if s != "" { w.builder.WriteString(s) w.lastWritten = s w.updateLineCountAndPosFor(s) w.hasTrailingCommentState = false } } func (w *textWriter) updateLineCountAndPosFor(s string) { var count int var lastLineStart core.TextPos for lineStart := range core.ComputeECMALineStartsSeq(s) { count++ lastLineStart = lineStart } if count > 1 { w.lineCount += count - 1 curLen := w.builder.Len() w.linePos = curLen - len(s) + int(lastLineStart) w.lineStart = (w.linePos - curLen) == 0 return } w.lineStart = false } func getIndentString(indent int) string { switch indent { case 0: return "" case 1: return " " default: // TODO: This is cached in tsc - should it be cached here? return strings.Repeat(" ", indent) } } func (w *textWriter) writeText(s string) { if s != "" { if w.lineStart { w.builder.WriteString(getIndentString(w.indent)) w.lineStart = false } w.builder.WriteString(s) w.lastWritten = s w.updateLineCountAndPosFor(s) } } func (w *textWriter) Write(s string) { if s != "" { w.hasTrailingCommentState = false } w.writeText(s) } func (w *textWriter) WriteComment(text string) { if text != "" { w.hasTrailingCommentState = true } w.writeText(text) } func (w *textWriter) WriteKeyword(text string) { w.Write(text) } func (w *textWriter) writeLineRaw() { w.builder.WriteString(w.newLine) w.lastWritten = w.newLine w.lineCount++ w.linePos = w.builder.Len() w.lineStart = true w.hasTrailingCommentState = false } func (w *textWriter) WriteLine() { if !w.lineStart { w.writeLineRaw() } } func (w *textWriter) WriteLineForce(force bool) { if !w.lineStart || force { w.writeLineRaw() } } func (w *textWriter) WriteLiteral(s string) { w.Write(s) } func (w *textWriter) WriteOperator(text string) { w.Write(text) } func (w *textWriter) WriteParameter(text string) { w.Write(text) } func (w *textWriter) WriteProperty(text string) { w.Write(text) } func (w *textWriter) WritePunctuation(text string) { w.Write(text) } func (w *textWriter) WriteSpace(text string) { w.Write(text) } func (w *textWriter) WriteStringLiteral(text string) { w.Write(text) } func (w *textWriter) WriteSymbol(text string, symbol *ast.Symbol) { w.Write(text) } func (w *textWriter) WriteTrailingSemicolon(text string) { w.Write(text) } func NewTextWriter(newLine string) EmitTextWriter { var w textWriter w.newLine = newLine w.Clear() return &w }