Skip to content

Commit c3023e7

Browse files
authored
Add configuration option requireConfig (#43)
1 parent dd63b00 commit c3023e7

12 files changed

+268
-5
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
coverage/
22
node_modules/
3+
/test/.testremarkrc.json
34
*.log
45
*.d.ts
56
*.tgz

lib/index.js

Lines changed: 88 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,18 @@
2424
* This can be used to ship a processor with your package, to be used if no
2525
* processor is found locally.
2626
* If this isn’t passed, a warning is shown if `processorName` can’t be found.
27+
* @property {string} configurationSection
28+
* This option will be used to give the client a hint of which configuration
29+
* section to use.
30+
* For example VSCode extensions use this to pick only settings that use this
31+
* as a prefix in order to prevent conflicts and reduce the amount of data
32+
* sent to the language server.
2733
*
2834
* @typedef {EngineFields & LanguageServerFields} Options
35+
*
36+
* @typedef UnifiedLanguageServerSettings
37+
* @property {boolean} [requireConfig=false]
38+
* If true, files will only be checked if a configuration file is present.
2939
*/
3040

3141
import path from 'node:path'
@@ -42,6 +52,7 @@ import {
4252
CodeActionKind,
4353
Diagnostic,
4454
DiagnosticSeverity,
55+
DidChangeConfigurationNotification,
4556
Position,
4657
ProposedFeatures,
4758
Range,
@@ -122,6 +133,7 @@ function lspDocumentToVfile(document, cwd) {
122133
* Configuration for `unified-engine` and the language server.
123134
*/
124135
export function createUnifiedLanguageServer({
136+
configurationSection,
125137
ignoreName,
126138
packageField,
127139
pluginPrefix,
@@ -135,14 +147,49 @@ export function createUnifiedLanguageServer({
135147
const documents = new TextDocuments(TextDocument)
136148
/** @type {Set<string>} */
137149
const workspaces = new Set()
150+
/** @type {UnifiedLanguageServerSettings} */
151+
const globalSettings = {requireConfig: false}
152+
/** @type {Map<string, Promise<UnifiedLanguageServerSettings>>} */
153+
const documentSettings = new Map()
138154
let hasWorkspaceFolderCapability = false
155+
let hasConfigurationCapability = false
156+
157+
/**
158+
* @param {string} scopeUri
159+
* @returns {Promise<UnifiedLanguageServerSettings>}
160+
*/
161+
async function getDocumentSettings(scopeUri) {
162+
if (!hasConfigurationCapability) {
163+
return globalSettings
164+
}
165+
166+
let result = documentSettings.get(scopeUri)
167+
if (!result) {
168+
result = connection.workspace
169+
.getConfiguration({scopeUri, section: configurationSection})
170+
.then(
171+
/** @param {Record<string, unknown>} raw */
172+
(raw) => ({requireConfig: Boolean(raw.requireConfig)})
173+
)
174+
documentSettings.set(scopeUri, result)
175+
}
176+
177+
return result
178+
}
139179

140180
/**
141181
* @param {string} cwd
142182
* @param {VFile[]} files
143183
* @param {boolean} alwaysStringify
184+
* @param {boolean} ignoreUnconfigured
185+
* @returns {Promise<VFile[]>}
144186
*/
145-
async function processWorkspace(cwd, files, alwaysStringify) {
187+
async function processWorkspace(
188+
cwd,
189+
files,
190+
alwaysStringify,
191+
ignoreUnconfigured
192+
) {
146193
/** @type {EngineOptions['processor']} */
147194
let processor
148195

@@ -190,6 +237,7 @@ export function createUnifiedLanguageServer({
190237
cwd,
191238
files,
192239
ignoreName,
240+
ignoreUnconfigured,
193241
packageField,
194242
pluginPrefix,
195243
plugins,
@@ -233,6 +281,8 @@ export function createUnifiedLanguageServer({
233281
.sort((a, b) => b.length - a.length)
234282
/** @type {Map<string, Array<VFile>>} */
235283
const workspacePathToFiles = new Map()
284+
/** @type {Map<string, Array<VFile>>} */
285+
const workspacePathToFilesRequireConfig = new Map()
236286

237287
await Promise.all(
238288
textDocuments.map(async (textDocument) => {
@@ -269,18 +319,28 @@ export function createUnifiedLanguageServer({
269319

270320
if (!cwd) return
271321

322+
const configuration = await getDocumentSettings(textDocument.uri)
323+
272324
const file = lspDocumentToVfile(textDocument, cwd)
273325

274-
const files = workspacePathToFiles.get(cwd) || []
275-
workspacePathToFiles.set(cwd, [...files, file])
326+
const filesMap = configuration.requireConfig
327+
? workspacePathToFilesRequireConfig
328+
: workspacePathToFiles
329+
const files = filesMap.get(cwd) || []
330+
files.push(file)
331+
filesMap.set(cwd, files)
276332
})
277333
)
278334

279335
/** @type {Array<Promise<Array<VFile>>>} */
280336
const promises = []
281337

282338
for (const [cwd, files] of workspacePathToFiles) {
283-
promises.push(processWorkspace(cwd, files, alwaysStringify))
339+
promises.push(processWorkspace(cwd, files, alwaysStringify, false))
340+
}
341+
342+
for (const [cwd, files] of workspacePathToFilesRequireConfig) {
343+
promises.push(processWorkspace(cwd, files, alwaysStringify, true))
284344
}
285345

286346
const listsOfFiles = await Promise.all(promises)
@@ -324,6 +384,9 @@ export function createUnifiedLanguageServer({
324384
workspaces.add(event.rootUri)
325385
}
326386

387+
hasConfigurationCapability = Boolean(
388+
event.capabilities.workspace && event.capabilities.workspace.configuration
389+
)
327390
hasWorkspaceFolderCapability = Boolean(
328391
event.capabilities.workspace &&
329392
event.capabilities.workspace.workspaceFolders
@@ -345,6 +408,10 @@ export function createUnifiedLanguageServer({
345408
})
346409

347410
connection.onInitialized(() => {
411+
if (hasConfigurationCapability) {
412+
connection.client.register(DidChangeConfigurationNotification.type)
413+
}
414+
348415
if (hasWorkspaceFolderCapability) {
349416
connection.workspace.onDidChangeWorkspaceFolders((event) => {
350417
for (const workspace of event.removed) {
@@ -399,13 +466,30 @@ export function createUnifiedLanguageServer({
399466
version,
400467
diagnostics: []
401468
})
469+
documentSettings.delete(uri)
402470
})
403471

404472
// Check everything again if the file system watched by the client changes.
405473
connection.onDidChangeWatchedFiles(() => {
406474
checkDocuments(...documents.all())
407475
})
408476

477+
connection.onDidChangeConfiguration((change) => {
478+
if (hasConfigurationCapability) {
479+
// Reset all cached document settings
480+
documentSettings.clear()
481+
} else {
482+
globalSettings.requireConfig = Boolean(
483+
/** @type {Omit<typeof change, 'settings'> & { settings: Record<string, unknown> }} */ (
484+
change
485+
).settings.requireConfig
486+
)
487+
}
488+
489+
// Revalidate all open text documents
490+
checkDocuments(...documents.all())
491+
})
492+
409493
connection.onCodeAction((event) => {
410494
/** @type {CodeAction[]} */
411495
const codeActions = []

readme.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Create a **[language server][]** based on **[unified][]** ecosystems.
2121
* [Examples](#examples)
2222
* [Types](#types)
2323
* [Language Server features](#language-server-features)
24+
* [Configuration](#configuration)
2425
* [Compatibility](#compatibility)
2526
* [Related](#related)
2627
* [Contribute](#contribute)
@@ -205,6 +206,11 @@ server features:
205206
Any messages collected are published to the client using
206207
`textDocument/publishDiagnostics`.
207208

209+
### Configuration
210+
211+
* `requireConfig` (default: `false`)
212+
— If true, files will only be checked if a configuration file is present.
213+
208214
## Compatibility
209215

210216
Projects maintained by the unified collective are compatible with all maintained

test/code-actions.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {createUnifiedLanguageServer} from 'unified-language-server'
22

33
createUnifiedLanguageServer({
4+
configurationSection: 'remark',
45
processorName: 'remark',
56
processorSpecifier: 'remark',
67
plugins: [warn]

test/folder/remark-with-cwd.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {createUnifiedLanguageServer} from 'unified-language-server'
22

33
createUnifiedLanguageServer({
4+
configurationSection: 'remark',
45
processorName: 'remark',
56
processorSpecifier: 'remark',
67
plugins: [warn]

0 commit comments

Comments
 (0)