skip to Main Content

I have this contribution:

{
  "contributes": {
    "configuration": {
      "title": "mytool",
      "properties": {
        "args": {
          "description": "Command line arguments, passed to mytool",
          "type": "list",
          "default": [],
          "items": {
            "type": "string"
          }
        }
      }
    }
}

Inside the extension code, I can grab the args like this:

const workspaceFolder = vscode.workspace.getWorkspaceFolder(document.uri);
const config = vscode.workspace.getConfiguration("mytool", workspaceFolder || null);
const args = config.get("args", []);

That works as expected when setting this via settings.json

{
  "mytool.args": ["--foo"] 
}

However, I noticed that VS Code does not recognize this as valid configuration. It is grayed out. Instead, it knows about top level args, and shows the description for it.

{
  "args": [] 
}

I tried several combinations to have it recognize it. The documentation suggests naming the property mytool.args, in the package.json. However, if I do this, I am not able to pick up the config in my extension code anymore.

What is the proper way to configure this?

2

Answers


  1. Chosen as BEST ANSWER

    I was able to solve it by doing 2 things.

    1. Define the property as mytool.args, in the package.json and set its scope to resource.
    {
      "contributes": {
        "configuration": {
          "title": "mytool",
          "properties": {
            // use full dotted name
            "mytool.args": {
              "scope": "resource", // this one is important
              "description": "Command line arguments, passed to mytool",
              "type": "array",
              "default": [],
              "items": {
                "type": "string"
              }
            }
          }
        }
      }
    }
    
    1. Then resolve the config like this:
    const config = vscode.workspace.getConfiguration("mytool", document.uri);
    const args = config.get("args", []);
    

    Or alternatively, like this

    const config = vscode.workspace.getConfiguration("", document.uri);
    const args = config.get("mytool.args", []);
    

    Note how the document.uri is passed as scope.

    Under the hood, resource settings are resolved with simple logic: We try to find a WorkspaceFolder for the resource that is passed into the getConfiguration API. If such a folder exists, and that folder defines the setting, it will be returned. Otherwise, the normal logic applies for finding the setting on a parent level: it could be defined within the workspace file or on the user level.


    I had already the suspicion that it has to do work of my attempt to handle mutli-root workspaces. While my idea was ok, the execution was not 100% correct.

    The proper way to do it is documented here. It took quite some time to find that page. https://github.com/Microsoft/vscode/wiki/Adopting-Multi-Root-Workspace-APIs#settings


  2. In your package.json contribution, the title field should match the namespace you want to use for your configuration keys. In your case, this should be "mytool". Here’s how the contribution in your package.json should look:

    {
      "contributes": {
        "configuration": {
          "title": "mytool",
          "properties": {
            "mytool.args": {
              "description": "Command line arguments, passed to mytool",
              "type": "array",
              "default": [],
              "items": {
                "type": "string"
              }
            }
          }
        }
      }
    }
    

    Note: The type field should be "array" instead of "list".

    Now, the setting "mytool.args" should be recognized in your settings.json and can be read in your extension as you’ve shown:

    const workspaceFolder = vscode.workspace.getWorkspaceFolder(document.uri);
    const config = vscode.workspace.getConfiguration("mytool", workspaceFolder || null);
    const args = config.get("args", []);
    

    Here, getConfiguration("mytool") is getting all configuration settings that start with "mytool.", and get("args") is getting the "args" part of the "mytool.args" setting.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search