Skip to content

Commit

Permalink
🐛 Fix formatting of commands attached to IMP-Doc
Browse files Browse the repository at this point in the history
Fix #751.
  • Loading branch information
SPGoding committed Nov 14, 2020
1 parent 91ae839 commit 202420c
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 27 deletions.
37 changes: 22 additions & 15 deletions src/plugins/builtin/DocCommentPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { CompletionItemKind } from 'vscode-languageserver'
import { arrayToCompletions, arrayToMessage, escapeIdentityPattern, plugins } from '../..'
import { locale } from '../../locales'
import { ArgumentNode, IdentityNode, NodeDescription, NodeRange, NodeType } from '../../nodes'
import { CacheType, CacheVisibility, combineArgumentParserResult, FileTypes, getCacheVisibilities, isFileType, isInRange, ParsingContext, ParsingError, TextRange } from '../../types'
import { CacheType, CacheVisibility, combineArgumentParserResult, CommandComponent, FileTypes, getCacheVisibilities, isFileType, isInRange, ParsingContext, ParsingError, TextRange } from '../../types'
import { StringReader } from '../../utils/StringReader'
import { CommandSyntaxComponentParser } from './McfunctionPlugin'

Expand Down Expand Up @@ -53,7 +53,7 @@ class DocCommentSyntaxComponentParser implements plugins.SyntaxComponentParser {
}

parse(reader: StringReader, ctx: ParsingContext): plugins.SyntaxComponent<DocCommentData> {
const ans = plugins.SyntaxComponent.create<DocCommentData>(this.identity, [])
const ans = plugins.SyntaxComponent.create<DocCommentData>(this.identity, { doc: new DocCommentNode() })
reader.skipSpace()
const start = reader.cursor
this.parseComment(ans, reader, ctx)
Expand All @@ -64,8 +64,7 @@ class DocCommentSyntaxComponentParser implements plugins.SyntaxComponentParser {
private parseComment(ans: plugins.SyntaxComponent<DocCommentData>, reader: StringReader, ctx: ParsingContext): void {
const start = reader.cursor
const isFunctionDoc = /^[ \t]*$/.test(reader.passedString)
const docComment = new DocCommentNode()
ans.data.push({ data: docComment })
const docComment = ans.data.doc
const currentID = ctx.id?.toString()
try {
reader
Expand Down Expand Up @@ -95,6 +94,7 @@ class DocCommentSyntaxComponentParser implements plugins.SyntaxComponentParser {
docComment.plainText += reader.readLine() + '\n'
}
let indentBeforeLastHash = 0
let endOfDocComment = reader.cursor
while (reader.nextLine(ctx.textDoc), reader.canRead()) {
const lineStart = reader.cursor
reader.skipSpace()
Expand All @@ -110,10 +110,15 @@ class DocCommentSyntaxComponentParser implements plugins.SyntaxComponentParser {
docComment.plainText += reader.readLine() + '\n'
}
} else {
endOfDocComment = reader
.clone()
.lastLine(ctx.textDoc)
.skipLine()
.cursor
if (!isFunctionDoc) {
// Attach the next command to this doc comment component.
const commandIndent = reader.cursor - lineStart
this.parseCommand(ans, reader, ctx, indentBeforeLastHash, commandIndent)
this.parseCommand(ans, reader, ctx, indentBeforeLastHash, commandIndent, reader.string.slice(lineStart, reader.cursor))
} else {
reader
.lastLine(ctx.textDoc)
Expand All @@ -122,8 +127,8 @@ class DocCommentSyntaxComponentParser implements plugins.SyntaxComponentParser {
break
}
}
docComment[NodeRange] = { start, end: reader.cursor }
docComment.raw = reader.string.slice(start, reader.cursor)
docComment[NodeRange] = { start, end: endOfDocComment }
docComment.raw = reader.string.slice(start, endOfDocComment)
} catch (p) {
ans.errors.push(p)
}
Expand Down Expand Up @@ -228,21 +233,21 @@ class DocCommentSyntaxComponentParser implements plugins.SyntaxComponentParser {
return visibilities
}

private parseCommand(ans: plugins.SyntaxComponent<DocCommentData>, reader: StringReader, ctx: ParsingContext, indentBeforeLastHash: number, commandIndent: number) {
private parseCommand(ans: plugins.SyntaxComponent<DocCommentData>, reader: StringReader, ctx: ParsingContext, indentBeforeLastHash: number, commandIndent: number, indent: string) {
const parser = new CommandSyntaxComponentParser()
const cmdResult = parser.parse(reader, ctx)
ans.data.push(...cmdResult.data)
const cmdResult = parser.parse(reader, ctx);
(ans.data.commands = ans.data.commands ?? []).push({ component: cmdResult, indent })
combineArgumentParserResult(ans, cmdResult)
if (commandIndent - indentBeforeLastHash >= 2) {
if (commandIndent - indentBeforeLastHash >= 1) {
const clonedReader = reader
.clone()
.nextLine(ctx.textDoc)
const nextLineStart = clonedReader.cursor
clonedReader.skipSpace()
const nextSkippedSpaces = clonedReader.readSpace()
const nextCommandIndent = clonedReader.cursor - nextLineStart
if (nextCommandIndent - indentBeforeLastHash >= 2) {
if (nextCommandIndent - indentBeforeLastHash >= 1) {
reader.cursor = clonedReader.cursor
this.parseCommand(ans, reader, ctx, indentBeforeLastHash, nextCommandIndent)
this.parseCommand(ans, reader, ctx, indentBeforeLastHash, nextCommandIndent, nextSkippedSpaces)
}
}
}
Expand All @@ -261,14 +266,16 @@ class DocCommentSyntaxComponentParser implements plugins.SyntaxComponentParser {
}
}

type DocCommentData = { data: ArgumentNode }[]
type DocCommentData = { doc: DocCommentNode, commands?: { component: CommandComponent, indent: string }[] }

type AnnotationValue = { raw: string, range: TextRange }
type Annotation = {
value: AnnotationValue,
children?: Annotation[]
}

export type DocCommentComponent = plugins.SyntaxComponent<DocCommentData>

class DocCommentNode extends ArgumentNode {
[NodeType] = 'builtin:doc_comment'

Expand Down
10 changes: 3 additions & 7 deletions src/services/onDocumentFormatting.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,21 @@
import { DiagnosticSeverity, TextEdit } from 'vscode-languageserver'
import { TextDocument } from 'vscode-languageserver-textdocument'
import { Config, SyntaxComponent } from '../types'
import { commandToLintedString } from '../types/CommandComponent'
import { componentToLintedString } from '../types/CommandComponent'
import { McfunctionDocument } from '../types/DatapackDocument'
import { getLspRange } from './common'

export function onDocumentFormatting({ doc, textDoc, config }: { doc: McfunctionDocument, textDoc: TextDocument, config: Config }) {
const ans: TextEdit[] = []

doc.nodes.forEach(node => {
if (isLintable(node) && node.errors.filter(v => v.severity === DiagnosticSeverity.Error).length === 0) {
if (node.errors.filter(v => v.severity === DiagnosticSeverity.Error).length === 0) {
ans.push({
range: getLspRange(textDoc, node.range),
newText: commandToLintedString(node, config.lint)
newText: componentToLintedString(node, config.lint)
})
}
})

return ans
}

function isLintable(value: SyntaxComponent): value is SyntaxComponent<{ data: unknown }[]> {
return value.data instanceof Array && value.data.every(v => v.data != null)
}
14 changes: 10 additions & 4 deletions src/types/CommandComponent.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { TextRange } from '.'
import { plugins } from '..'
import { SyntaxComponent, TextRange } from '.'
import { getEol, plugins } from '..'
import { DocCommentComponent } from '../plugins/builtin/DocCommentPlugin'
import { toFormattedString } from '../utils'
import { combineCache } from './ClientCache'
import { LintConfig } from './Config'
Expand Down Expand Up @@ -39,6 +40,11 @@ export function combineCommand(base: CommandComponent, override: CommandComponen
return base
}

export function commandToLintedString(cmd: { data: { data: unknown }[] }, lint: LintConfig) {
return cmd.data.map(v => toFormattedString(v.data, lint)).join(' ')
export function componentToLintedString(com: SyntaxComponent<unknown>, lint: LintConfig): string {
if (com.type === 'spgoding:doc_comment/doc_comment') {
const docCom = com as DocCommentComponent
return toFormattedString(docCom.data.doc, lint) + getEol(lint) + docCom.data.commands?.map(v => v.indent + componentToLintedString(v.component, lint)).join(getEol(lint))
}
const cmdCom = com as CommandComponent
return cmdCom.data.map(v => toFormattedString(v.data, lint)).join(' ')
}
2 changes: 1 addition & 1 deletion src/types/Formattable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ export interface Formattable {
}

export function isFormattable(value: unknown): value is Formattable {
return value && (value as any)[GetFormattedString] instanceof Function
return !!value && (value as any)[GetFormattedString] instanceof Function
}
13 changes: 13 additions & 0 deletions src/utils/StringReader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,23 @@ export class StringReader {
return this
}

skipLine() {
this.readUntilOrEnd('\r', '\n')
return this
}

read() {
return this.string.charAt(this.cursor++)
}

readSpace() {
const start = this.cursor
while (this.canRead() && StringReader.isSpace(this.peek())) {
this.skip()
}
return this.string.slice(start, this.cursor)
}

skipSpace() {
while (this.canRead() && StringReader.isSpace(this.peek())) {
this.skip()
Expand Down

0 comments on commit 202420c

Please sign in to comment.