Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Config for files to be treated as JSON Schema files #39

Closed
14 changes: 6 additions & 8 deletions language-server/src/features/document-settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ import { publish } from "../pubsub.js";
import { clearSchemaDocuments } from "./schema-documents.js";


export const isSchema = RegExp.prototype.test.bind(/(?:\.|\/|^)schema\.json$/);

let hasConfigurationCapability = false;
let hasDidChangeConfigurationCapability = false;

Expand All @@ -21,12 +19,10 @@ export default {
connection.client.register(DidChangeConfigurationNotification.type);
}

connection.onDidChangeConfiguration((change) => {
connection.onDidChangeConfiguration(() => {
if (hasConfigurationCapability) {
documentSettings.clear();
clearSchemaDocuments();
} else {
globalSettings = change.settings.jsonSchemaLanguageServer ?? globalSettings;
}

publish("workspaceChanged", { changes: [] });
Expand All @@ -39,19 +35,21 @@ export default {
};

const documentSettings = new Map();
let globalSettings = {};
const defaultSettings = {
schemaFilePatterns: ["**/*.schema.json", "**/schema.json"]
};

export const getDocumentSettings = async (connection, uri) => {
if (!hasConfigurationCapability) {
return globalSettings;
return defaultSettings;
}

if (!documentSettings.has(uri)) {
const result = await connection.workspace.getConfiguration({
scopeUri: uri,
section: "jsonSchemaLanguageServer"
});
documentSettings.set(uri, result ?? globalSettings);
documentSettings.set(uri, result ?? defaultSettings);
jdesrosiers marked this conversation as resolved.
Show resolved Hide resolved
}

return documentSettings.get(uri);
Expand Down
9 changes: 7 additions & 2 deletions language-server/src/features/semantic-tokens.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import { getKeywordId } from "@hyperjump/json-schema/experimental";
import * as Instance from "../json-instance.js";
import { getSchemaDocument } from "./schema-documents.js";
import { toAbsoluteUri } from "../util.js";
import { isSchema } from "./document-settings.js";
import { isMatchedFile } from "./workspace.js";
import { fileURLToPath } from "node:url";
import { getDocumentSettings } from "./document-settings.js";


export default {
Expand Down Expand Up @@ -51,7 +53,10 @@ export default {
};

connection.languages.semanticTokens.on(async ({ textDocument }) => {
if (!isSchema(textDocument.uri)) {
const filePath = fileURLToPath(textDocument.uri);
const settings = await getDocumentSettings(connection);
const schemaFilePatterns = settings.schemaFilePatterns;
if (!isMatchedFile(filePath, schemaFilePatterns)) {
return { data: [] };
}

Expand Down
33 changes: 26 additions & 7 deletions language-server/src/features/workspace.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import {
import { TextDocument } from "vscode-languageserver-textdocument";
import { publish, publishAsync, subscribe } from "../pubsub.js";
import { getSchemaDocument } from "./schema-documents.js";
import { isSchema } from "./document-settings.js";
import { getDocumentSettings } from "./document-settings.js";
import picomatch from "picomatch";


let hasWorkspaceFolderCapability = false;
Expand Down Expand Up @@ -62,7 +63,9 @@ export default {
reporter.begin("JSON Schema: Indexing workspace");

// Re/validate all schemas
for await (const uri of workspaceSchemas()) {
const settings = await getDocumentSettings(connection);
const schemaFilePatterns = settings.schemaFilePatterns;
for await (const uri of workspaceSchemas(schemaFilePatterns)) {
let textDocument = documents.get(uri);
if (!textDocument) {
const instanceJson = await readFile(fileURLToPath(uri), "utf8");
Expand Down Expand Up @@ -130,7 +133,10 @@ export default {
connection.onDidChangeWatchedFiles(onWorkspaceChange);

documents.onDidChangeContent(async ({ document }) => {
if (isSchema(document.uri)) {
const settings = await getDocumentSettings(connection);
const schemaFilePatterns = settings.schemaFilePatterns;
const filePath = fileURLToPath(document.uri);
if (isMatchedFile(filePath, schemaFilePatterns)) {
validateSchema(document);
}
});
Expand All @@ -139,6 +145,19 @@ export default {
}
};

export const isMatchedFile = (uri, patterns) => {
patterns = patterns.map((pattern) => `**/${pattern}`);
const matchers = patterns.map((pattern) => {
return picomatch(pattern, {
noglobstar: false,
matchBase: false,
dot: true,
nonegate: true
});
});
return matchers.some((matcher) => matcher(uri));
};

const workspaceFolders = new Set();

const addWorkspaceFolders = (folders) => {
Expand All @@ -159,7 +178,7 @@ const removeWorkspaceFolders = (folders) => {

const watchers = {};

const watchWorkspace = (handler) => {
const watchWorkspace = (handler, schemaFilePatterns) => {
for (const { uri } of workspaceFolders) {
const path = fileURLToPath(uri);

Expand All @@ -168,19 +187,19 @@ const watchWorkspace = (handler) => {
}

watchers[path] = watch(path, { recursive: true }, (eventType, filename) => {
if (isSchema(filename)) {
if (isMatchedFile(filename, schemaFilePatterns)) {
handler(eventType, filename);
}
});
}
};

const workspaceSchemas = async function* () {
const workspaceSchemas = async function* (schemaFilePatterns) {
for (const { uri } of workspaceFolders) {
const path = fileURLToPath(uri);

for (const filename of await readdir(path, { recursive: true })) {
if (isSchema(filename)) {
if (isMatchedFile(filename, schemaFilePatterns)) {
const schemaPath = resolve(path, filename);

yield pathToFileURL(schemaPath).toString();
Expand Down
14 changes: 13 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"@hyperjump/json-pointer": "^1.0.1",
"@hyperjump/json-schema": "github:hyperjump-io/json-schema#lsp",
"@hyperjump/pact": "^1.3.0",
"@hyperjump/uri": "^1.2.2"
"@hyperjump/uri": "^1.2.2",
"picomatch": "^4.0.2"
}
}
5 changes: 5 additions & 0 deletions vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@
"jsonSchemaLanguageServer.defaultDialect": {
"type": "string",
"description": "The default JSON Schema dialect to use if none is specified in the schema document"
},
"jsonSchemaLanguageServer.schemaFilePatterns": {
"type": "array",
"description": "The glob pattern for identifying JSON Schema files.",
"default": ["**/*.schema.json", "**/schema.json"]
}
}
}
Expand Down