redhat-developer / redhat-developer/yaml-language-server

Can specify static resolved value for custom tags

Open
#767 3 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
TypeScript
Stars
1.5k
Forks
352
Avg merge
2d 7h
Merged PRs (30d)
11

Description

Is your enhancement related to a problem? Please describe.

Related issue:

The key point of my scenario

The customized resolver I defined for such custom tag changes the data type and value dynamically at runtime.

So how could I do validation on it?

Current behavior

I can only specify the rough shape (scalar, mapping or sequence) of data with some custom tag. After that, the parser will just return the data as is with a simple shape check.

But it doesn't make sense in my scenario right? My expected resolved data is definitely not the original one, but I have to accept it when writing schema.

Describe the solution you would like

To solve it, there are several directions in theory:

  1. Best: Can do a validation on the final result dynamically. But it's impossible when only uses JSON schema.
  2. Secondary: Can do a customized schema validation on the fragments with custom tag by its tag value. But it's not supported now.
  3. At least: There is a way that can ignore/bypass the fragments with some custom tag during validation.

Here I propose a solution under direction 3 because it is simplest:

Allow to specify static resolved values (stubs) for custom tags
Specification

Extends the yaml.customTags setting to accept object type values with a new property resolvedValue (property name can be discussed further).

Example
{
  // ......
  "yaml.customTags": [
    {
      "tag": "!TagName",
      "type": "mapping",

      // new property `resolvedValue` to define a stub, can give any valid json data here
      "resolvedValue": {
        "anything": "you want to be"
      }
    }
  ]
}

Then every fragment with tag !TagName will be replaced by the resolvedValue before doing validation.

Use cases
1. Force to use specific custom tag

Settings:

{
  // ......
  "yaml.customTags": [
    {
      "tag": "!regex",
      "type": "scalar",
      "resolvedValue":  "This must be a regex type value!!!"
    }
  ]
}

Schema:

{
  // ......
  "properties": {
    "matcher": {
      "type": "string",
      "const": "This must be a regex type value!!!"
    }
  },
  "required": [ "productId" ]
  // ......
}

Correct:

---
matcher: !regex '([A-Z])\w+'

Incorrect:

---
matcher: '([A-Z])\w+'
2. Ignore merging of objects with custom tag

Settings:

{
  // ......
  "yaml.customTags": [
    {
      "tag": "!include",
      "type": "mapping",
      "resolvedValue":  {}
    }
  ]
}

Yaml:

---
object:
  <<: !include
    source: './abc/xyz'
    path: 'any-path'
  path: 'may be seen as a duplicate key'

Result with resolvedValue setting:

{
  "object": {
    "path": "may be seen as a duplicate key"
  }
}

Result without resolvedValue setting:

{
  "object": {
    "source": "./abc/xyz",
    "path": "any-path",
    "path": "may be seen as a duplicate key"  // error!
  }
}
Describe alternatives you have considered

Can also choose another solution under direction 1 which is a little more risky than above one:

Allow to specify a dynamic resolver function for custom tags
Specification

Extends yaml.customTags setting to accept object type values with new property resolver.

Settings:

{
  "yaml.customTags": [
    {
      "tag": "!TagName",
      "type": "mapping",
      "resolver": "./path/to/js/file/.../resolverFunction.js"
    }
  ]
}

resolverFunction.js: Exports a function that will be invoked to resolve the inputs tagged by such custom tag.

Note

The resolver property is better to also accept raw JavaScript code string so that extension developers can pass their functions directly without creating a temporary js file.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing how the yaml.customTags setting is parsed and how custom-tag fragments participate in schema validation. Compare the proposed resolvedValue behavior with the dynamic resolver alternative and define which option is in scope. Done means custom-tag fragments use the configured static value during validation without breaking existing tag handling, with coverage for the scalar and mapping examples.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript, yaml
Domain
devtools
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.