Cannot Read Property Uri of Null Visual Studio Code

Tree View API

The Tree View API allows extensions to bear witness content in the sidebar in Visual Studio Code. This content is structured every bit a tree and conforms to the mode of the built-in views of VS Code.

For example, the born References Search View extension shows reference search results as a separate view.

References Search View

The Discover All References results are displayed in a References: Results Tree View, which is in the References View Container.

This guide teaches you how to write an extension that contributes Tree Views and View Containers to Visual Studio Code.

Tree View API Nuts

To explain the Tree View API, we are going to build a sample extension called Node Dependencies. This extension will use a treeview to display all Node.js dependencies in the current folder. The steps for calculation a treeview are to contribute the treeview in your bundle.json, create a TreeDataProvider, and register the TreeDataProvider. You lot can find the complete source code of this sample extension in the tree-view-sample in the vscode-extension-samples GitHub repository.

package.json Contribution

First yous have to let VS Lawmaking know that you are contributing a view, using the contributes.views Contribution Point in package.json.

Here's the package.json for the first version of our extension:

                      {                                    "name"            :                        "custom-view-samples"            ,                                    "displayName"            :                        "Custom view Samples"            ,                                    "description"            :                        "Samples for VS Code's view API"            ,                                    "version"            :                        "0.0.i"            ,                                    "publisher"            :                        "alexr00"            ,                                    "engines"            : {                                    "vscode"            :                        "^1.42.0"                          },                                    "activationEvents"            : [            "onView:nodeDependencies"            ],                                    "main"            :                        "./out/extension.js"            ,                                    "contributes"            : {                                    "views"            : {                                    "explorer"            : [                          {                                    "id"            :                        "nodeDependencies"            ,                                    "proper noun"            :                        "Node Dependencies"                          }                          ]                          }                          },                                    "scripts"            : {                                    "vscode:prepublish"            :                        "npm run compile"            ,                                    "compile"            :                        "tsc -p ./"            ,                                    "lookout man"            :                        "tsc -scout -p ./"                          },                                    "devDependencies"            : {                                    "@types/node"            :                        "^x.12.21"            ,                                    "@types/vscode"            :                        "^1.42.0"            ,                                    "typescript"            :                        "^iii.v.one"            ,                                    "tslint"            :                        "^5.12.ane"                          }            }                  

You must specify an identifier and name for the view, and you tin can contribute to following locations:

  • explorer: Explorer view in the Side Bar
  • debug: Run and Debug view in the Side Bar
  • scm: Source Control view in the Side Bar
  • test: Test explorer view in the Side Bar
  • Custom View Containers

Tree Information Provider

The 2nd step is to provide data to the view yous registered and so that VS Code can display the information in the view. To practice so, you should beginning implement the TreeDataProvider. Our TreeDataProvider will provide node dependencies data, merely you can have a data provider that provides other types of data.

There are two necessary methods in this API that you need to implement:

  • getChildren(element?: T): ProviderResult<T[]> - Implement this to return the children for the given element or root (if no element is passed).
  • getTreeItem(element: T): TreeItem | Thenable<TreeItem> - Implement this to render the UI representation (TreeItem) of the element that gets displayed in the view.

When the user opens the Tree View, the getChildren method will be chosen without an element. From there, your TreeDataProvider should return your top-level tree items. In our case, the collapsibleState of the top-level tree items is TreeItemCollapsibleState.Complanate, significant that the meridian-level tree items will prove equally collapsed. Setting the collapsibleState to TreeItemCollapsibleState.Expanded will cause tree items to evidence as expanded. Leaving the collapsibleState as its default of TreeItemCollapsibleState.None indicates that the tree item has no children. getChildren volition not be called for tree items with a collapsibleState of TreeItemCollapsibleState.None.

Hither is an example of a TreeDataProvider implementation that provides node dependencies data:

                      import                                    *                                    as                                    vscode                                    from                                    'vscode'            ;            import                                    *                                    as                                    fs                                    from                                    'fs'            ;            import                                    *                                    as                                    path                                    from                                    'path'            ;            export                                    form                                    NodeDependenciesProvider                                    implements                                    vscode            .            TreeDataProvider            <            Dependency            > {                                    constructor            (            private                                    workspaceRoot            :                        string            ) {}                                    getTreeItem            (            element            :                        Dependency            ):                        vscode            .            TreeItem                          {                                    return                                    element            ;                          }                                    getChildren            (            element            ?:                        Dependency            ):                        Thenable            <            Dependency            []> {                                    if                          (!            this            .            workspaceRoot            ) {                                    vscode            .            window            .            showInformationMessage            (            'No dependency in empty workspace'            );                                    return                                    Promise            .            resolve            ([]);                          }                                    if                          (            chemical element            ) {                                    return                                    Promise            .            resolve            (                                    this            .            getDepsInPackageJson            (                          path.            bring together            (            this            .            workspaceRoot            ,                        'node_modules'            ,                        element            .            label            ,                        'package.json'            )                          )                          );                          }                        else                          {                                    const                                    packageJsonPath                          = path.            join            (            this            .            workspaceRoot            ,                        'package.json'            );                                    if                          (            this            .            pathExists            (            packageJsonPath            )) {                                    return                                    Promise            .            resolve            (            this            .            getDepsInPackageJson            (            packageJsonPath            ));                          }                        else                          {                                    vscode            .            window            .            showInformationMessage            (            'Workspace has no package.json'            );                                    return                                    Promise            .            resolve            ([]);                          }                          }                          }                                    /**                          * Given the path to bundle.json, read all its dependencies and devDependencies.                          */                                    private                                    getDepsInPackageJson            (            packageJsonPath            :                        string            ):                        Dependency            [] {                                    if                          (            this            .            pathExists            (            packageJsonPath            )) {                                    const                                    packageJson                          =                        JSON            .            parse            (fs.            readFileSync            (            packageJsonPath            ,                        'utf-8'            ));                                    const                                    toDep                          = (            moduleName            :                        cord            ,                        version            :                        string            ):                        Dependency                                    =>                          {                                    if                          (            this            .            pathExists            (path.            join            (            this            .            workspaceRoot            ,                        'node_modules'            ,                        moduleName            ))) {                                    render                                    new                                    Dependency            (                                    moduleName            ,                                    version            ,                                    vscode            .            TreeItemCollapsibleState            .            Collapsed                          );                          }                        else                          {                                    return                                    new                                    Dependency            (            moduleName            ,                        version            ,                        vscode            .            TreeItemCollapsibleState            .            None            );                          }                          };                                    const                                    deps                          =                        packageJson            .            dependencies                          ?                        Object            .            keys            (            packageJson            .            dependencies            ).            map            (            dep                                    =>                                    toDep            (            dep            ,                        packageJson            .            dependencies            [            dep            ])                          )                          : [];                                    const                                    devDeps                          =                        packageJson            .            devDependencies                          ?                        Object            .            keys            (            packageJson            .            devDependencies            ).            map            (            dep                                    =>                                    toDep            (            dep            ,                        packageJson            .            devDependencies            [            dep            ])                          )                          : [];                                    render                                    deps            .            concat            (            devDeps            );                          }                        else                          {                                    render                          [];                          }                          }                                    private                                    pathExists            (            p            :                        string            ):                        boolean                          {                                    endeavour                          {                          fs.            accessSync            (            p            );                          }                        catch                          (            err            ) {                                    render                                    false            ;                          }                                    return                                    true            ;                          }            }            form                                    Dependency                                    extends                                    vscode            .            TreeItem                          {                                    constructor            (                                    public                                    readonly                                    characterization            :                        cord            ,                                    individual                                    version            :                        cord            ,                                    public                                    readonly                                    collapsibleState            :                        vscode            .            TreeItemCollapsibleState                          ) {                                    super            (            label            ,                        collapsibleState            );                                    this            .            tooltip                          =                        `            ${this            .            label            }            -            ${this            .            version            }            `            ;                                    this            .            description                          =                        this            .            version            ;                          }                                    iconPath                          = {                                    light:                          path.            join            (            __filename            ,                        '..'            ,                        '..'            ,                        'resources'            ,                        'light'            ,                        'dependency.svg'            ),                                    dark:                          path.            join            (            __filename            ,                        '..'            ,                        '..'            ,                        'resources'            ,                        'dark'            ,                        'dependency.svg'            )                          };            }                  

Registering the TreeDataProvider

The tertiary step is to register the above data provider to your view.

This can be done in the post-obit two ways:

  • vscode.window.registerTreeDataProvider - Register the tree data provider by providing the registered view ID and above information provider.

                                  const                                                rootPath                                  =                                                vscode                .                workspace                .                workspaceFolders                                  &&                                vscode                .                workspace                .                workspaceFolders                .                length                                  >                                0                                  ?                                vscode                .                workspace                .                workspaceFolders                [                0                ].                uri                .                fsPath                                  :                                undefined                ;                vscode                .                window                .                registerTreeDataProvider                (                                                'nodeDependencies'                ,                                                new                                                NodeDependenciesProvider                (                rootPath                )                );                          
  • vscode.window.createTreeView - Create the Tree View by providing the registered view ID and higher up data provider. This will give access to the TreeView, which you tin use for performing other view operations. Utilise createTreeView, if you demand the TreeView API.

                                  vscode                .                window                .                createTreeView                (                'nodeDependencies'                , {                                                treeDataProvider:                                                new                                                NodeDependenciesProvider                (                rootPath                )                });                          

Hither's the extension in action:

View

Updating Tree View content

Our node dependencies view is simple, and one time the data is shown, it isn't updated. However, it would be useful to take a refresh button in the view and update the node dependencies view with the electric current contents of the parcel.json. To do this, nosotros tin use the onDidChangeTreeData event.

  • onDidChangeTreeData?: Event<T | undefined | null | void> - Implement this if your tree data can change and yous want to update the treeview.

Add the following to your NodeDependenciesProvider.

                                              private                                    _onDidChangeTreeData            :                        vscode            .            EventEmitter            <            Dependency                          |                        undefined                          |                        null                          |                        void            > =                        new                                    vscode            .            EventEmitter            <            Dependency                          |                        undefined                          |                        zip                          |                        void            >();                                    readonly                                    onDidChangeTreeData            :                        vscode            .            Event            <            Dependency                          |                        undefined                          |                        null                          |                        void            > =                        this            .            _onDidChangeTreeData            .            issue            ;                                    refresh            ():                        void                          {                                    this            .            _onDidChangeTreeData            .            fire            ();                          }                  

At present nosotros have a refresh method, but no one is calling it. We can add a control to call refresh.

In the contributes department of your package.json, add:

                                              "commands"            : [                          {                                    "command"            :                        "nodeDependencies.refreshEntry"            ,                                    "title"            :                        "Refresh"            ,                                    "icon"            : {                                    "light"            :                        "resources/light/refresh.svg"            ,                                    "night"            :                        "resources/nighttime/refresh.svg"                          }                          },                          ]                  

And register the command in your extension activation:

                      import                                    *                                    as                                    vscode                                    from                                    'vscode'            ;            import                          {                        NodeDependenciesProvider                          }                        from                                    './nodeDependencies'            ;            export                                    function                                    activate            (            context            :                        vscode            .            ExtensionContext            ) {                                    const                                    rootPath                          =                                    vscode            .            workspace            .            workspaceFolders                          &&                        vscode            .            workspace            .            workspaceFolders            .            length                          >                        0                          ?                        vscode            .            workspace            .            workspaceFolders            [            0            ].            uri            .            fsPath                          :                        undefined            ;                                    const                                    nodeDependenciesProvider                          =                        new                                    NodeDependenciesProvider            (            rootPath            );                                    vscode            .            window            .            registerTreeDataProvider            (            'nodeDependencies'            ,                        nodeDependenciesProvider            );                                    vscode            .            commands            .            registerCommand            (            'nodeDependencies.refreshEntry'            , ()                        =>                                    nodeDependenciesProvider            .            refresh            ()                          );            }                  

Now we take a command that will refresh the node dependencies view, but a push button on the view would be fifty-fifty meliorate. Nosotros already added an icon to the command, so information technology will show upwardly with that icon when we add it to the view.

In the contributes section of your package.json, add together:

                      "menus"            : {                                    "view/championship"            : [                          {                                    "control"            :                        "nodeDependencies.refreshEntry"            ,                                    "when"            :                        "view == nodeDependencies"            ,                                    "grouping"            :                        "navigation"                          },                          ]            }                  

Activation

Information technology is of import that your extension is activated simply when user needs the functionality that your extension provides. In this case, you lot should consider activating your extension when the user starts using the view. VS Lawmaking emits an activationEvent onView:${viewId} (onView:nodeDependencies for the example above) when the user opens the view.

You can register to this activation event in bundle.json and VS Lawmaking will actuate your extension on this event:

                      "activationEvents"            : [                                    "onView:nodeDependencies"            ,            ],                  

View Container

A View Container contains a list of views that are displayed in the Activeness Bar or Panel forth with the built-in View Containers. Examples of built-in View Containers are Source Control and Explorer.

View Container

To contribute a View Container, y'all should beginning register it using contributes.viewsContainers Contribution Bespeak in bundle.json.

You lot have to specify the following required fields:

  • id - The name of the new view container you're creating.
  • title - The name that will testify up at the top of the view container.
  • icon - An image that volition be displayed for the view container when in the Activity Bar.
                      "contributes"            : {                                    "viewsContainers"            : {                                    "activitybar"            : [                          {                                    "id"            :                        "package-explorer"            ,                                    "title"            :                        "Package Explorer"            ,                                    "icon"            :                        "media/dep.svg"                          }                          ]                          }            }                  

Alternatively, you lot could contribute this view to the panel past placing it under the panel node.

                      "contributes"            : {                                    "viewsContainers"            : {                                    "panel"            : [                          {                                    "id"            :                        "package-explorer"            ,                                    "championship"            :                        "Package Explorer"            ,                                    "icon"            :                        "media/dep.svg"                          }                          ]                          }            }                  

Contributing views to View Containers

In one case you've created a View Container, you can utilise the contributes.views Contribution Signal in packet.json.

                      "contributes"            : {                                    "views"            : {                                    "package-explorer"            : [                          {                                    "id"            :                        "nodeDependencies"            ,                                    "name"            :                        "Node Dependencies"            ,                                    "icon"            :                        "media/dep.svg"            ,                                    "contextualTitle"            :                        "Package Explorer"                          }                          ]                          }            }                  

A view tin can also have an optional visibility holding which can be set to visible, complanate, or hidden. This holding is only respected by VS Code the outset time a workspace is opened with this view. After that, the visibility is fix to whatever the user has chosen. If y'all take a view container with many views, or if your view will not exist useful to every user of your extension, consider setting the view the complanate or hidden. A hidden view volition appear in the view containers "Views" menu:

Views Menu

View Actions

Actions are available as inline icons on your individual tree items, in tree detail context menus, and at the height of your view in the view title. Actions are commands that you set to show up in these locations by adding contributions to your package.json.

To contribute to these three places, you can employ the post-obit menu contribution points in your parcel.json:

  • view/title - Location to show deportment in the view title. Principal or inline deportment use "grouping": "navigation" and rest are secondary deportment, which are in ... carte du jour.
  • view/item/context - Location to evidence actions for the tree item. Inline actions utilize "grouping": "inline" and rest are secondary deportment, which are in ... menu.

You tin can control the visibility of these actions using a when clause.

View Actions

Examples:

                      "contributes"            : {                                    "commands"            : [                          {                                    "command"            :                        "nodeDependencies.refreshEntry"            ,                                    "championship"            :                        "Refresh"            ,                                    "icon"            : {                                    "light"            :                        "resource/light/refresh.svg"            ,                                    "night"            :                        "resources/dark/refresh.svg"                          }                          },                          {                                    "command"            :                        "nodeDependencies.addEntry"            ,                                    "title"            :                        "Add"                          },                          {                                    "control"            :                        "nodeDependencies.editEntry"            ,                                    "title"            :                        "Edit"            ,                                    "icon"            : {                                    "light"            :                        "resources/low-cal/edit.svg"            ,                                    "night"            :                        "resource/dark/edit.svg"                          }                          },                          {                                    "command"            :                        "nodeDependencies.deleteEntry"            ,                                    "title"            :                        "Delete"                          }                          ],                                    "menus"            : {                                    "view/title"            : [                          {                                    "command"            :                        "nodeDependencies.refreshEntry"            ,                                    "when"            :                        "view == nodeDependencies"            ,                                    "grouping"            :                        "navigation"                          },                          {                                    "command"            :                        "nodeDependencies.addEntry"            ,                                    "when"            :                        "view == nodeDependencies"                          }                          ],                                    "view/item/context"            : [                          {                                    "command"            :                        "nodeDependencies.editEntry"            ,                                    "when"            :                        "view == nodeDependencies && viewItem == dependency"            ,                                    "group"            :                        "inline"                          },                          {                                    "command"            :                        "nodeDependencies.deleteEntry"            ,                                    "when"            :                        "view == nodeDependencies && viewItem == dependency"                          }                          ]                          }            }                  

Note: If y'all desire to show an action for specific tree items, y'all can do so past defining the context of a tree item using TreeItem.contextValue and you can specify the context value for key viewItem in when expression.

Examples:

                      "contributes"            : {                                    "menus"            : {                                    "view/item/context"            : [                          {                                    "command"            :                        "nodeDependencies.deleteEntry"            ,                                    "when"            :                        "view == nodeDependencies && viewItem == dependency"                          }                          ]                          }            }                  

Welcome content

If your view tin can exist empty, or if you want to add Welcome content to another extension'due south empty view, y'all can contribute viewsWelcome content. An empty view is a view that has no message and an empty tree.

                      "contributes"            : {                                    "viewsWelcome"            : [                          {                                    "view"            :                        "nodeDependencies"            ,                                    "contents"            :                        "No node dependencies found [learn more than](https://www.npmjs.com/).            \n            [Add Dependency](command:nodeDependencies.addEntry)"                          }                          ]            }                  

Welcome Content

Links are supported in Welcome content. By convention, a link on a line past itself is a button. Each Welcome content tin can also incorporate a when clause. For more examples, come across the built-in Git extension.

TreeDataProvider

Extension writers should register a TreeDataProvider programmatically to populate data in the view.

                      vscode            .            window            .            registerTreeDataProvider            (            'nodeDependencies'            ,                        new                                    DepNodeProvider            ());                  

See nodeDependencies.ts in the tree-view-sample for the implementation.

TreeView

If you would like to perform some UI operations on the view programmatically, yous can use window.createTreeView instead of window.registerTreeDataProvider. This will give access to the view, which you can utilize for performing view operations.

                      vscode            .            window            .            createTreeView            (            'ftpExplorer'            , {                                    treeDataProvider:                                    new                                    FtpTreeDataProvider            ()            });                  

See ftpExplorer.ts in the tree-view-sample for the implementation.

wellsadow1956.blogspot.com

Source: https://code.visualstudio.com/api/extension-guides/tree-view

0 Response to "Cannot Read Property Uri of Null Visual Studio Code"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel