Skip to content
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions src/EditorConfigDiagnosticsProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import {
Diagnostic,
DiagnosticCollection,
DiagnosticSeverity,
Disposable,
languages,
Range,
TextDocument,
workspace,
} from 'vscode'

/**
* Matches an inline comment: any line that contains non-whitespace content
* followed by required whitespace and then an unquoted `#` or `;`.
* Lines where `#` or `;` is the first non-whitespace character are proper
* standalone comments and are excluded before this regex is applied.
*/
const INLINE_COMMENT_RE = /\S.*[ \t]+([#;].*)$/
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Do we need to use a regex here? Can't we use invalid.illegal.inline-comment.editorconfig?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately no — VS Code's extension API doesn't expose TextMate grammar token scopes at runtime. The invalid.illegal.inline-comment.editorconfig scope lives entirely inside VS Code's syntax highlighting engine and there's no public API to query what scope a given document position has. So the detection logic must be reimplemented in TypeScript.

I've added a comment (commit 9efd460) directly above the regex to explain this and cross-reference the grammar rule, so it's clear the two are intentionally in sync.


export default class EditorConfigDiagnosticsProvider {
private collection: DiagnosticCollection
private disposable: Disposable

public constructor() {
this.collection = languages.createDiagnosticCollection('editorconfig')

const subscriptions: Disposable[] = []

// Analyze documents that are already open when the extension activates
for (const doc of workspace.textDocuments) {
this.analyze(doc)
}

subscriptions.push(
workspace.onDidOpenTextDocument(doc => this.analyze(doc)),
)
subscriptions.push(
workspace.onDidChangeTextDocument(e => this.analyze(e.document)),
)
subscriptions.push(
workspace.onDidCloseTextDocument(doc =>
this.collection.delete(doc.uri),
),
)

this.disposable = Disposable.from(...subscriptions)
}

private analyze(doc: TextDocument) {
if (doc.languageId !== 'editorconfig') {
return
}

const diagnostics: Diagnostic[] = []

for (let i = 0; i < doc.lineCount; i++) {
const { text } = doc.lineAt(i)

// Skip blank lines and proper standalone comment lines
const trimmed = text.trimStart()
if (
trimmed.length === 0 ||
trimmed.startsWith('#') ||
trimmed.startsWith(';')
) {
continue
}

const match = INLINE_COMMENT_RE.exec(text)
if (match) {
const commentStart = text.length - match[1].length
const range = new Range(i, commentStart, i, text.length)
diagnostics.push(
new Diagnostic(
range,
'Inline comments are not supported in EditorConfig. Move this comment to its own line.',
DiagnosticSeverity.Warning,
),
)
}
}

this.collection.set(doc.uri, diagnostics)
}

public dispose() {
this.collection.dispose()
this.disposable.dispose()
}
}
2 changes: 2 additions & 0 deletions src/editorConfigMain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ import {
import { generateEditorConfig } from './commands/generateEditorConfig'
import DocumentWatcher from './DocumentWatcher'
import EditorConfigCompletionProvider from './EditorConfigCompletionProvider'
import EditorConfigDiagnosticsProvider from './EditorConfigDiagnosticsProvider'

/**
* Main entry
*/
export function activate(ctx: ExtensionContext) {
ctx.subscriptions.push(new DocumentWatcher())
ctx.subscriptions.push(new EditorConfigDiagnosticsProvider())

// register .editorconfig file completion provider
const editorConfigFileSelector: DocumentSelector = {
Expand Down
10 changes: 10 additions & 0 deletions syntaxes/editorconfig.tmLanguage.json
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,10 @@
}
]
},
"inlineComment": {
"name": "invalid.illegal.inline-comment.editorconfig",
"match": "\\s*[#;].*$"
},
"section": {
"name": "meta.section.editorconfig",
"begin": "^\\s*(?=\\[.*?\\])",
Expand All @@ -286,6 +290,9 @@
},
{
"include": "#rule"
},
{
"include": "#inlineComment"
}
]
},
Expand Down Expand Up @@ -374,6 +381,9 @@
},
{
"include": "#string"
},
{
"include": "#inlineComment"
}
]
}
Expand Down