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

customTags utilizing regex/pattern matching

Open
#996 0 comments 4 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

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.

Currently there is no way to provide support for matching tags based on a prefix or regex pattern.
A trivial example being straight from pyyaml:

x: !!python/object:__main__.Hero
  name: Welthyr Syxgon
  hp: 1200
  sp: 0

This will make VSCode always complain about the !!python/object tag simply because its not an exact match. I have tried several values for yaml.customTags including:

"tag:yaml.org,2002:python/object"
"!!python/object"
"tag:yaml.org,2002:python/object*"
"!!python/object*"
"tag:yaml.org,2002:python/object.*"
"!!python/object.*"

but none work due to the CommonTagImpl not utilizing the test field that ScalarTag provides in the yaml module used by this module. Unfortunately CollectionTag doesnt support test, but if we had a custom Composer class that overrides the next generator to look at the token that is passed in and add the value of the tag to our options.customTags if it matches then that would be sufficient I think. A crude and incomplete example being:

class CustomComposer extends Composer {
  regexTags: RegexTag[]
  schema: Schema // yaml.Schema, should be the same schema used in the private option options.schema
  *next(token: Token) {
    // check token tag and if it matches our internal list of regexTags
    // if it matches add it to schema.tags
    super.next(token);
  }
}
Describe the solution you would like

Some way to allow a user to specify that a custom tag is using a prefix/regex. I have looked briefly at the code and it seems that most cases just do simple tag parsing like:

const typeInfo = tag.split(' ');
const tagName = typeInfo[0];
const tagType = (typeInfo[1] && typeInfo[1].toLowerCase()) || 'scalar';

which given the use of .split(' ') could mean that there could be code that checks for options after [1] and does some additional parsing for it. A simple example being:

// assuming a tag of "!!python/object:.* mapping regex"
const typeInfo = tag.split(' ');
const tagName = typeInfo[0];
const tagType = (typeInfo[1] && typeInfo[1].toLowerCase()) || 'scalar';
const options = typeInfo.slice(2);
if (options.includes("regex")) {
  // some code to handle regex tags here
}

Im not saying this is 100% the best solution, but it is backwards compatible with how custom tags have been working. Some alternatives might involve changing the structure of yaml.customTags entirely to accept mappings or similar which is also valid, albeit more work.

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 with src/languageservice/parser/custom-tag-provider.ts and compare CommonTagImpl with the ScalarTag definition referenced from the yaml module. Trace how yaml.customTags is parsed and how tags reach the schema, then define and verify the intended prefix or regex behavior while preserving existing custom-tag handling.

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
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.