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

New JSON mode with autocompletion, etc. #2883

Closed
mkosieradzki opened this issue Feb 8, 2016 · 7 comments
Closed

New JSON mode with autocompletion, etc. #2883

mkosieradzki opened this issue Feb 8, 2016 · 7 comments

Comments

@mkosieradzki
Copy link

I have nearly completed my reimplementation of JSON mode with:

  1. Support for multiple errors in code (instead of failing after first error)
  2. JSON Schema validation support
  3. Auto-completion support according to a provided JSON Schema
  4. Contributions support: allowing insertion of code based on complex scenarios - for example downloading values from external data source
  5. Custom validation - allowing to provide second level of logical validation of JSON document
    All operations are properly executed in web worker.

I would be happy to share my code, but there are two problems:

  1. Major one: I am utilizing some JSON parsers from a different large project coming with an MIT license. This might be a dealbreaker.
  2. Minor one: I am far too lazy to write tests for trivial code :-(
  3. Would you like to accept such a PR (should I create one)?
  4. How should I handle license headers for such a PR?

BTW. Great job implementing the ACE editor! :)

@nightwing
Copy link
Member

That sounds interesting. Please submit a pr or give a link to the repository with the code, and we can decide how to proceed. If it's not possible to include in ace, we can still maintain json tooling in a separate repository. I actually want to move other workers into their own repositories too.

@mkosieradzki
Copy link
Author

It is currently in my private repository so the action plan:
I will

  1. complete my code (excluding contributions (4) and custom validation (5) mechanism - I will explain below why)
  2. fork ace repo on GH
  3. Move and cleanup code to this forker repo
  4. Create a PR

I am going to

  • keep all third pirty code in modes/json subdir after removing legacy parser. I am going to keep all the original MIT headers in this dir and also add LICENSE to this dir.
  • push only the javascript files with proper simplified common js module stylings (I will not push the original typescript files). I will provide links to the original typescript files for reference in some documentation file.
  • Apply my own modifications to the existing modes/json_worker, modes/json keeping BSD header

Regarding contributions and custom schema validation - I would need to create yet another extensibility kinds (like for modes, themes, etc) for plugable contributions and custom schema validation: this is something requiring more discussion - as for my own private fork I planned hardcoding of those mechanisms. Such plugins should be loadable into worker using standard ACE mechanisms.

Does this all sound reasonable?

@yanlantao
Copy link

Any update on this?Is this feature supported now?

@gerardojbaez
Copy link

Is this repository still maintained? 👀

@tslater
Copy link

tslater commented Jul 23, 2021

@mkosieradzki is this DOA?

@sadnub
Copy link
Contributor

sadnub commented Dec 12, 2022

I was able to get vscode-json-languageservice to work with schema validation in ace editor. I'm not sure how to go about making a plugin for ace, but here is my code.

run npm install vscode-json-languageservice

import ace from "ace-builds";
import type { Ace } from "ace-builds";
import modeJsonUrl from "ace-builds/src-noconflict/mode-json?url";
import themeLightUrl from "ace-builds/src-noconflict/theme-chrome?url";
import extLangToolsUrl from "ace-builds/src-noconflict/ext-language_tools?url";

import {
  getLanguageService,
  TextDocument,
  type JSONSchema,
  type JSONDocument,
} from "vscode-json-languageservice";

ace.config.setModuleUrl("ace/theme/chrome", themeLightUrl);
ace.config.setModuleUrl("ace/mode/json", modeJsonUrl);
ace.config.setModuleUrl("ace/ext/language_tools", extLangToolsUrl);
ace.config.loadModule("ace/ext/language_tools");

// import and use this function in your other js files
export const useJsonLanguageService = (
  editor: Ace.Editor,
  schema: JSONSchema
) => {
  let textDocument: TextDocument;
  let jsonDocument: JSONDocument;

  const schemaUri = "local:https://data.schema.json";

  const languageService = getLanguageService({
    schemaRequestService: (uri) => {
      console.log(uri);
      if (uri === schemaUri) {
        console.log("schema resolved");
        return Promise.resolve(JSON.stringify(schema));
      }
      return Promise.reject(`Unabled to load schema at ${uri}`);
    },
  });
  languageService.configure({
    allowComments: false,
    schemas: [{ fileMatch: ["*data.json"], uri: schemaUri }],
  });

  function setContent(content: string) {
    textDocument = TextDocument.create("local:https://data.json", "json", 1, content);
    jsonDocument = languageService.parseJSONDocument(textDocument);
  }

  async function validate() {
    const diagnostics = await languageService.doValidation(
      textDocument,
      jsonDocument
    );

    // create annotations to to mark line numbers for errors
    const annotations = [] as Ace.Annotation[];
    diagnostics.forEach((error) => {
      annotations.push({
        row: error.range.start.line,
        text: error.message,
        type: "error",
      });
    });
    editor.session.setAnnotations(annotations);
  }

  function getAceCompleter() {
    return {
      getCompletions: async (editor, session, position, prefix, callback) => {
        const completionResult = await languageService.doComplete(
          textDocument,
          { line: position.row, character: position.column },
          jsonDocument
        );

        if (completionResult) {
          callback(
            null,
            completionResult.items.map((item) => ({
              value: item.insertText ? item.insertText : item.label,
              score: item.kind ? item.kind : 10,
              meta: "schema",
              caption: item.detail,
            }))
          );
        }
      },
    } as Ace.Completer;
  }

  // set initial content
  setContent(editor.session.getValue());

  // create listeners
  editor.session.on("change", () => {
    setContent(editor.session.getValue());
    validate();
  });

  // add completer
  editor.completers = [getAceCompleter()];

  // can use these to manually validate or setContent
  return {
    setContent,
    validate,
  };
};

Then in your file that initializes the editor

  import { useJsonLanguageService } from "file"
  let editor = ace.edit("editor")
  editor.setTheme("ace/theme/chrome");
  editor.session.setMode("ace/mode/json");
  editor.setOptions({
    enableBasicAutocompletion: true,
    enableLiveAutocompletion: true
  })

  const schema = {
    type: "object",
    properties: {
      name: {
        type: "string",
      },
      country: {
        type: "string",
        enum: ["Ireland", "Iceland"],
      },
    },
  };

  const {setContent, validate} = useJsonLanguageService(editor, schema);

I'm sure there is a better way to do this, but it does work!

@whazor
Copy link
Contributor

whazor commented Jul 29, 2024

Ace linters supports auto-complete and error checking based on a JSON schema.

After setting up the ace-linters JsonService, you can set the service.setGlobalOptions() that allows you to set a custom schema:

    schemas?: {
        uri: string,
        fileMatch?: string[],
        schema?: string,
    }[],

Source: https://github.com/mkslanc/ace-linters/blob/v1.2.3/packages/ace-linters/src/types/language-service.ts#L89-L93

We don't see JSON schema's going to be directly integrated with ACE.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants