From 5a424d202a4533d3bfbba4ae92c55e2e4dce90f9 Mon Sep 17 00:00:00 2001 From: Predrag Date: Tue, 24 Dec 2019 20:15:51 +0100 Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=91=8C=20IMPROVE:=20Add=20jsonc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit closes #2 --- LSP-json.sublime-settings | 5 +++++ plugin.py | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/LSP-json.sublime-settings b/LSP-json.sublime-settings index a946be5..ff08487 100644 --- a/LSP-json.sublime-settings +++ b/LSP-json.sublime-settings @@ -9,6 +9,11 @@ "Packages/JavaScript/JSON.sublime-syntax", "Packages/JSON/JSON.sublime-syntax" ] + }, + { + "languageId": "jsonc", + "scopes": ["source.json.sublime.settings"], + "syntaxes": ["Packages/PackageDev/Package/Sublime Text Settings/Sublime Text Settings.sublime-syntax"] } ], "initializationOptions": { diff --git a/plugin.py b/plugin.py index 4b8ce84..c6c7aea 100644 --- a/plugin.py +++ b/plugin.py @@ -88,6 +88,11 @@ def config(self) -> ClientConfig: "Packages/JavaScript/JSON.sublime-syntax", "Packages/JSON/JSON.sublime-syntax" ] + }, + { + "languageId": "jsonc", + "scopes": ["source.json.sublime.settings"], + "syntaxes": ["Packages/PackageDev/Package/Sublime Text Settings/Sublime Text Settings.sublime-syntax"] } ] } From b1def5129bc2783002411f348921a0d4ea2a080e Mon Sep 17 00:00:00 2001 From: Predrag Date: Tue, 24 Dec 2019 20:35:37 +0100 Subject: [PATCH 2/3] add keymaps syntax --- LSP-json.sublime-settings | 10 ++++++++-- plugin.py | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/LSP-json.sublime-settings b/LSP-json.sublime-settings index ff08487..b329ff5 100644 --- a/LSP-json.sublime-settings +++ b/LSP-json.sublime-settings @@ -12,8 +12,14 @@ }, { "languageId": "jsonc", - "scopes": ["source.json.sublime.settings"], - "syntaxes": ["Packages/PackageDev/Package/Sublime Text Settings/Sublime Text Settings.sublime-syntax"] + "scopes": [ + "source.json.sublime.settings", + "source.json.sublime.keymap" + ], + "syntaxes": [ + "Packages/PackageDev/Package/Sublime Text Settings/Sublime Text Settings.sublime-syntax", + "Packages/PackageDev/Package/Sublime Text Keymap/Sublime Text Keymap.sublime-syntax" + ] } ], "initializationOptions": { diff --git a/plugin.py b/plugin.py index c6c7aea..c2759bf 100644 --- a/plugin.py +++ b/plugin.py @@ -91,8 +91,14 @@ def config(self) -> ClientConfig: }, { "languageId": "jsonc", - "scopes": ["source.json.sublime.settings"], - "syntaxes": ["Packages/PackageDev/Package/Sublime Text Settings/Sublime Text Settings.sublime-syntax"] + "scopes": [ + "source.json.sublime.settings", + "source.json.sublime.keymap" + ], + "syntaxes": [ + "Packages/PackageDev/Package/Sublime Text Settings/Sublime Text Settings.sublime-syntax", + "Packages/PackageDev/Package/Sublime Text Keymap/Sublime Text Keymap.sublime-syntax" + ] } ] } From 2bedce3af6ceb540e80af553ae26ac50419efc5d Mon Sep 17 00:00:00 2001 From: Predrag Date: Mon, 17 Feb 2020 15:55:31 +0100 Subject: [PATCH 3/3] Add JSONC support with json schemas --- LSP-json.schema.json | 58 +++++++++++++++ LSP-json.sublime-settings | 6 +- plugin.py | 46 ++++++++++-- syntax/JSONC.sublime-syntax | 143 ++++++++++++++++++++++++++++++++++++ 4 files changed, 242 insertions(+), 11 deletions(-) create mode 100644 LSP-json.schema.json create mode 100644 syntax/JSONC.sublime-syntax diff --git a/LSP-json.schema.json b/LSP-json.schema.json new file mode 100644 index 0000000..aa1fbb8 --- /dev/null +++ b/LSP-json.schema.json @@ -0,0 +1,58 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "http://example.com/product.schema.json", + "title": "LSP-json settings", + "description": "Configure the LSP-json settings", + "type": "object", + "definitions": { + "language": { + "type": "object", + "additionalProperties": false, + "properties": { + "languageId": { + "type": "string", + "description": "See a list of available languages Ids in https://code.visualstudio.com/docs/languages/identifiers#_known-language-identifiers" + }, + "scopes": { + "description": "Array of scopes that will trigger the activation of the language server. Open `Tools/Developer/Show scope name` menu to get the scope name.", + "type": "array", + "items": { + "description": "Open `Tools/Developer/Show scope name` menu to get the scope name", + "type": "string" + } + }, + "syntaxes": { + "description": "Array of sublime-syntaxt strings. Run `view.settings().get('syntax')` in sublime console to get the syntax.", + "type": "array", + "items": { + "description": "Run `view.settings().get('syntax')` in sublime console to get the syntax.", + "type": "string" + } + } + }, + "required": ["languageId", "scopes", "syntaxes"] + } + }, + "properties": { + "client": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "languages": { + "type": "array", + "items": { + "$ref": "#/definitions/language" + } + }, + "initializationOptions": { + "type": "object" + }, + "settings": { + "type": "object" + } + } + } + } +} diff --git a/LSP-json.sublime-settings b/LSP-json.sublime-settings index b329ff5..afd45b1 100644 --- a/LSP-json.sublime-settings +++ b/LSP-json.sublime-settings @@ -13,12 +13,10 @@ { "languageId": "jsonc", "scopes": [ - "source.json.sublime.settings", - "source.json.sublime.keymap" + "source.jsonc" ], "syntaxes": [ - "Packages/PackageDev/Package/Sublime Text Settings/Sublime Text Settings.sublime-syntax", - "Packages/PackageDev/Package/Sublime Text Keymap/Sublime Text Keymap.sublime-syntax" + "Packages/LSP-json/syntax/JSONC.sublime-syntax" ] } ], diff --git a/plugin.py b/plugin.py index c2759bf..8b57114 100644 --- a/plugin.py +++ b/plugin.py @@ -3,6 +3,7 @@ import sublime import threading import subprocess +import json from LSP.plugin.core.handlers import LanguageHandler from LSP.plugin.core.settings import ClientConfig, LanguageConfig, read_client_config @@ -12,7 +13,36 @@ server_path = os.path.join(package_path, 'node_modules', 'vscode-json-languageserver', 'bin', 'vscode-json-languageserver') +def get_plugin_schemas(): + plugin_schemas = [] + added_schemas = [] + + for schema in sublime.find_resources("*.schema.json"): + schema_content = sublime.load_resource(schema) + schema_file_name = os.path.basename(schema) + + # Associate a `LSP-json.schema.json` file to `LSP-json.sublime-settings` + settings_file_name = schema_file_name.replace(".schema.json", ".sublime-settings") + try: + if schema_file_name in added_schemas: + continue + + added_schemas.append(schema_file_name) + plugin_schemas.append({ + "name": schema_file_name, + "fileMatch": [ + settings_file_name + ], + "schema": json.loads(schema_content) + }) + except Exception as e: + pass + + return plugin_schemas + + def plugin_loaded(): + get_plugin_schemas() is_server_installed = os.path.isfile(server_path) print('LSP-json: Server {}.'.format('installed' if is_server_installed else 'is not installed' )) @@ -74,6 +104,12 @@ def name(self) -> str: def config(self) -> ClientConfig: settings = sublime.load_settings("LSP-json.sublime-settings") client_configuration = settings.get('client') + + all_schemas = [] + plugin_schemas = get_plugin_schemas() + all_schemas.extend(plugin_schemas) + all_schemas.extend(schemas) + default_configuration = { "command": [ 'node', @@ -91,19 +127,15 @@ def config(self) -> ClientConfig: }, { "languageId": "jsonc", - "scopes": [ - "source.json.sublime.settings", - "source.json.sublime.keymap" - ], + "scopes": ["source.jsonc"], "syntaxes": [ - "Packages/PackageDev/Package/Sublime Text Settings/Sublime Text Settings.sublime-syntax", - "Packages/PackageDev/Package/Sublime Text Keymap/Sublime Text Keymap.sublime-syntax" + "Packages/LSP-json/syntax/JSONC.sublime-syntax" ] } ] } default_configuration.update(client_configuration) - default_configuration['settings']['json']['schemas'] = schemas + default_configuration['settings']['json']['schemas'] = all_schemas return read_client_config('lsp-json', default_configuration) def on_start(self, window) -> bool: diff --git a/syntax/JSONC.sublime-syntax b/syntax/JSONC.sublime-syntax new file mode 100644 index 0000000..0623562 --- /dev/null +++ b/syntax/JSONC.sublime-syntax @@ -0,0 +1,143 @@ +%YAML 1.2 +--- +name: JSONC +file_extensions: + - jsonc + - sublime-settings + - sublime-menu + - sublime-keymap + - sublime-mousemap + - sublime-theme + - sublime-build + - sublime-project + - sublime-completions + - sublime-commands + - sublime-macro + - sublime-color-scheme + - ipynb + - Pipfile.lock +scope: source.jsonc +contexts: + prototype: + - include: comments + main: + - include: value + value: + - include: constant + - include: number + - include: string + - include: array + - include: object + array: + - match: '\[' + scope: punctuation.section.sequence.begin.jsonc + push: + - meta_scope: meta.sequence.jsonc + - match: '\]' + scope: punctuation.section.sequence.end.jsonc + pop: true + - include: value + - match: "," + scope: punctuation.separator.sequence.jsonc + - match: '[^\s\]]' + scope: invalid.illegal.expected-sequence-separator.jsonc + comments: + - match: /\*\*(?!/) + scope: punctuation.definition.comment.jsonc + push: + - meta_scope: comment.block.documentation.jsonc + - meta_include_prototype: false + - match: \*/ + pop: true + - match: ^\s*(\*)(?!/) + captures: + 1: punctuation.definition.comment.jsonc + - match: /\* + scope: punctuation.definition.comment.jsonc + push: + - meta_scope: comment.block.jsonc + - meta_include_prototype: false + - match: \*/ + pop: true + - match: (//).*$\n? + scope: comment.line.double-slash.js + captures: + 1: punctuation.definition.comment.jsonc + constant: + - match: \b(?:true|false|null)\b + scope: constant.language.jsonc + number: + # handles integer and decimal numbers + - match: -?(?:0|[1-9]\d*)(?:(?:(\.)\d+)(?:[eE][-+]?\d+)?|(?:[eE][-+]?\d+)) + scope: constant.numeric.float.decimal.jsonc + captures: + 1: punctuation.separator.decimal.jsonc + - match: -?(?:0|[1-9]\d*) + scope: constant.numeric.integer.decimal.jsonc + object: + # a jsonc object + - match: '\{' + scope: punctuation.section.mapping.begin.jsonc + push: + - meta_scope: meta.mapping.jsonc + - match: '\}' + scope: punctuation.section.mapping.end.jsonc + pop: true + - match: '"' + scope: punctuation.definition.string.begin.jsonc + push: + - clear_scopes: 1 + - meta_scope: meta.mapping.key.jsonc string.quoted.double.jsonc + - meta_include_prototype: false + - include: inside-string + - match: ":" + scope: punctuation.separator.mapping.key-value.jsonc + push: + - match: ',|\s?(?=\})' + scope: invalid.illegal.expected-mapping-value.jsonc + pop: true + - match: (?=\S) + set: + - clear_scopes: 1 + - meta_scope: meta.mapping.value.jsonc + - include: value + - match: '' + set: + - match: ',' + scope: punctuation.separator.mapping.pair.jsonc + pop: true + - match: \s*(?=\}) + pop: true + - match: \s(?!/[/*])(?=[^\s,])|[^\s,] + scope: invalid.illegal.expected-mapping-separator.jsonc + pop: true + - match: '[^\s\}]' + scope: invalid.illegal.expected-mapping-key.jsonc + string: + - match: '"' + scope: punctuation.definition.string.begin.jsonc + push: inside-string + inside-string: + - meta_scope: string.quoted.double.jsonc + - meta_include_prototype: false + - match: '"' + scope: punctuation.definition.string.end.jsonc + pop: true + - include: string-escape + - match: $\n? + scope: invalid.illegal.unclosed-string.jsonc + pop: true + string-escape: + - match: |- + (?x: # turn on extended mode + \\ # a literal backslash + (?: # ...followed by... + ["\\/bfnrt] # one of these characters + | # ...or... + u # a u + [0-9a-fA-F]{4} # and four hex digits + ) + ) + scope: constant.character.escape.jsonc + - match: \\. + scope: invalid.illegal.unrecognized-string-escape.jsonc