Showing preview only (318K chars total). Download the full file or copy to clipboard to get everything.
Repository: vivekmalneedi/veridian
Branch: master
Commit: 0c5776a4a4e0
Files: 50
Total size: 301.9 KB
Directory structure:
gitextract_lil_lsx1/
├── .github/
│ └── workflows/
│ └── ci.yml
├── .gitignore
├── Cargo.toml
├── LICENSE
├── README.md
├── extensions/
│ └── vscode/
│ ├── .eslintignore
│ ├── .eslintrc.js
│ ├── .eslintrc.json
│ ├── .gitignore
│ ├── .vscodeignore
│ ├── LICENSE
│ ├── README.md
│ ├── package.json
│ ├── src/
│ │ └── extension.ts
│ ├── syntaxes/
│ │ └── systemverilog.tmLanguage.json
│ ├── tsconfig.json
│ └── tsconfig.tsbuildinfo
├── rustfmt.toml
├── src/
│ ├── completion/
│ │ └── keyword.rs
│ ├── completion.rs
│ ├── definition/
│ │ ├── def_types.rs
│ │ └── extract_defs.rs
│ ├── definition.rs
│ ├── diagnostics.rs
│ ├── format.rs
│ ├── lib.rs
│ ├── main.rs
│ ├── server.rs
│ ├── sources.rs
│ └── support.rs
├── test_data/
│ ├── complete.sv
│ ├── definition_test.sv
│ ├── diag/
│ │ └── diag_test.sv
│ ├── ind.sv
│ ├── interface_obj.sv
│ ├── simple_bus.svh
│ ├── test_inter.sv
│ ├── top.sv
│ ├── top_inc.sv
│ └── verilator_errors.txt
└── veridian-slang/
├── Cargo.toml
├── build.rs
├── slang_wrapper/
│ ├── CMakeLists.txt
│ └── src/
│ ├── BasicClient.h
│ ├── FormatBuffer.h
│ ├── basic_client.cpp
│ ├── slang_lib.cpp
│ └── slang_wrapper.h
└── src/
├── lib.rs
└── wrapper.rs
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/workflows/ci.yml
================================================
on:
push:
pull_request:
workflow_dispatch:
schedule:
- cron: '0 0 * * 0'
name: CI
jobs:
test:
name: Test Suite
runs-on: ubuntu-22.04
steps:
- name: Checkout sources
uses: actions/checkout@v6
with:
submodules: true
- name: Install stable toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: 1.91.1
override: true
- name: cache cargo dirs
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Install Deps
run: |
wget 'https://github.com/chipsalliance/verible/releases/download/v0.0-3607-g46de0f64/verible-v0.0-3607-g46de0f64-linux-static-x86_64.tar.gz' -O verible.tar.gz
tar -xf verible.tar.gz
sudo cp verible-v0.0-3607-g46de0f64/bin/* /usr/bin
sudo apt update
sudo apt-get install -y verilator perl
- name: Run cargo test
uses: actions-rs/cargo@v1
with:
command: test
args: --all-features
#todo: vscode extensions tests
- uses: actions/setup-node@v6
with:
node-version: "24"
- name: build extension
working-directory: extensions/vscode
run: |
npm install
npm install -g @vscode/vsce
vsce package -o veridian.vsix
lints:
name: Lints
runs-on: ubuntu-22.04
steps:
- name: Checkout sources
uses: actions/checkout@v6
with:
submodules: true
- name: Install stable toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: 1.91.1
override: true
components: rustfmt, clippy
- name: cache cargo dirs
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Run cargo fmt
uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check
- uses: actions-rs/clippy-check@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --all-features -- -D warnings
build_ubuntu:
name: Build Ubuntu
runs-on: ubuntu-22.04
if: ${{ github.ref == 'refs/heads/master' && ( github.event_name == 'workflow_dispatch' || github.event_name == 'schedule' ) }}
steps:
- name: Checkout sources
uses: actions/checkout@v6
- name: Install stable toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: 1.91.1
override: true
- name: cache cargo dirs
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-release-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Run cargo build
uses: actions-rs/cargo@v1
with:
command: build
args: --all-features --release
- name: Create archive
run: |
strip target/release/veridian
cp target/release/veridian .
tar -czvf veridian-ubuntu-22.04.tar.gz veridian
- uses: actions/upload-artifact@v4
with:
name: veridian-ubuntu-22.04.tar.gz
path: veridian-ubuntu-22.04.tar.gz
if-no-files-found: error
build_vscode:
name: Build vscode extension
runs-on: ubuntu-latest
if: ${{ ( github.event_name == 'workflow_dispatch' || github.event_name == 'schedule' ) }}
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: "24"
- name: build extension
working-directory: extensions/vscode
run: |
npm install
npm install -g @vscode/vsce
vsce package -o veridian.vsix
- uses: actions/upload-artifact@v4
with:
name: veridian.vsix
path: extensions/vscode/veridian.vsix
if-no-files-found: error
publish:
name: Create Release
needs: [build_ubuntu, build_vscode]
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v4
with:
name: veridian-ubuntu-22.04.tar.gz
- uses: actions/download-artifact@v4
with:
name: veridian.vsix
- uses: marvinpinto/action-automatic-releases@latest
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
automatic_release_tag: nightly
prerelease: true
title: nightly
files: |
veridian-ubuntu-22.04.tar.gz
veridian.vsix
================================================
FILE: .gitignore
================================================
# Generated by Cargo
# will have compiled files and executables
debug/
target/
# These are backup files generated by rustfmt
**/*.rs.bk
tests_rtl
log_files
test.txt
.vscode/
veridian-slang/slang_wrapper/slang/
================================================
FILE: Cargo.toml
================================================
[package]
name = "veridian"
version = "0.1.0"
authors = ["Vivek Malneedi <vivekmalneedi@gmail.com>"]
edition = "2018"
[features]
slang = ["veridian_slang"]
[dependencies]
sv-parser = "0.8.2"
log = "0.4.19"
tower-lsp = "0.20.0"
flexi_logger = "0.29.8"
ropey = "1.6.0"
tokio = { version = "1.29.1", features = ["macros", "io-std", "rt-multi-thread"] }
path-clean = "1.0.1"
pathdiff = "0.2.1"
walkdir = "2.3.3"
serde_yaml = "0.9.25"
anyhow = "1.0.72"
serde = "1.0.179"
which = "7.0.1"
regex = "1.9.1"
structopt = "0.3.26"
strum = "0.26.1"
strum_macros = "0.26.1"
[dev-dependencies]
tempdir = "0.3.7"
[dependencies.veridian_slang]
optional = true
path = "veridian-slang"
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2021 Vivek Malneedi
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# veridian


A SystemVerilog Language Server\
<a href="https://asciinema.org/a/374859" target="_blank"><img src="https://asciinema.org/a/374859.svg" width="500"/></a>
## Installation
### Pre-Installation
- It is recommended to install the [verible](https://github.com/google/verible) tools for
- formatting support with `verible-verilog-format`
- syntax checking support with `verible-verilog-syntax`
- It is recommended to install [verilator](https://www.veripool.org/verilator/) for additional linting
### Install from Release
- Download the latest release for your OS from the [releases page](https://github.com/vivekmalneedi/veridian/releases)
- The nightly release contains the last successful build, and is not guaranteed to be stable
- The ubuntu build also includes [slang](https://github.com/MikePopoloski/slang) for linting
### Install from Source
- Build dependencies: Rust toolchain (Install through system package manager or through [rustup](https://rustup.rs/]))
- optional: C++17 compatible compiler (for linting with slang)
```bash
# install with slang feature, if C++17 compiler is available
cargo install --git https://github.com/vivekmalneedi/veridian.git --all-features
# install if C++17 compiler is not available
cargo install --git https://github.com/vivekmalneedi/veridian.git
```
## Usage
### [neovim](https://github.com/neovim/nvim-lspconfig)
```lua
local lspconfutil = require 'lspconfig/util'
local root_pattern = lspconfutil.root_pattern("veridian.yml", ".git")
require('lspconfig').veridian.setup {
cmd = { 'veridian' },
root_dir = function(fname)
local filename = lspconfutil.path.is_absolute(fname) and fname
or lspconfutil.path.join(vim.loop.cwd(), fname)
return root_pattern(filename) or lspconfutil.path.dirname(filename)
end;
}
````
### [vscode](https://github.com/vivekmalneedi/veridian/tree/master/extensions/vscode)
- download veridian.vsix from the latest release
- install the extension using one of the two following methods
- In the extensions tab, click on the 3 dots, then click `Install from VSIX` and choose `veridian.vsix`
- Run `code --install-extension veridian.vsix`
### [coc.nvim](https://github.com/neoclide/coc.nvim)
In `coc-settings.json`:
```json
{
"languageserver": {
"veridian": {
"command": "veridian",
"filetypes": ["systemverilog", "verilog"]
}
}
```
### Emacs
- Install the [`verilog-ext`](https://github.com/gmlarumbe/verilog-ext/) package
- Copy the following snippet into your init file:
```elisp
(require 'verilog-ext)
(verilog-ext-mode-setup)
(verilog-ext-eglot-set-server 've-veridian) ;`eglot' config
(verilog-ext-lsp-set-server 've-veridian) ; `lsp' config
```
The [full list](https://github.com/vivekmalneedi/veridian/wiki/Usage-Instructions-for-various-LSP-Clients) is on the wiki
## Configuration
- Specify source directories and include directories using a yaml project config
- All settings have defaults so your config file should only specify custom values
In `veridian.yml`:
```yaml
# list of directories with header files
include_dirs:
- inc1
- inc2
# list of directories to recursively search for SystemVerilog/Verilog sources
source_dirs:
- src
- src2
# if true, recursively search the working directory for files to run diagnostics on
# default: true
auto_search_workdir: true|false,
# verible tool configuration
verible:
# verible-verilog-syntax configuration
syntax:
# default: true if in path
enabled: true|false,
path: "verible-verilog-syntax"
# default: none
args:
- arg1
- arg2
# verible-verilog-format configuration
format:
# default: true if in path
enabled: true|false,
path: "verible-verilog-format"
# default: none
args:
- arg1
- arg2
verilator:
# verilator configuration
syntax:
# default: true if in path
enabled: true|false,
path: "verilator"
# default: specified below
args:
- --lint-only
- --sv
- -Wall
# set log level
# default: Info
log_level: Error|Warn|Info|Debug|Trace
```
## LSP Support
See the [LSP Specification](https://microsoft.github.io/language-server-protocol/specifications/specification-current/) for more details
- diagnostics (using [slang](https://github.com/MikePopoloski/slang) or [verible](https://github.com/google/verible))
- completion
- identifier completion
- dot completion
- keywords & snippets
- system task/function and compiler directives
- hover (documentation)
- definition
- documentSymbol
- documentHighlight
- formatting (using [verible](https://github.com/google/verible))
- rangeFormatting (using [verible](https://github.com/google/verible))
## Alternatives
The Verible project is working on a language server for SystemVerilog, check it out [here](https://github.com/chipsalliance/verible/tree/master/verilog/tools/ls)
================================================
FILE: extensions/vscode/.eslintignore
================================================
node_modules/**
out/**
================================================
FILE: extensions/vscode/.eslintrc.js
================================================
/**@type {import('eslint').Linter.Config} */
// eslint-disable-next-line no-undef
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
plugins: [
'@typescript-eslint',
],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
],
rules: {
'semi': [2, "always"],
'@typescript-eslint/no-unused-vars': 0,
'@typescript-eslint/no-explicit-any': 0,
'@typescript-eslint/explicit-module-boundary-types': 0,
'@typescript-eslint/no-non-null-assertion': 0,
}
};
================================================
FILE: extensions/vscode/.eslintrc.json
================================================
{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module"
},
"env": {
"node": true
},
"rules": {
"semi": "error",
"no-extra-semi": "warn",
"curly": "warn",
"quotes": ["error", "single", { "allowTemplateLiterals": true } ],
"eqeqeq": "error",
"indent": ["warn", "tab", { "SwitchCase": 1 } ]
}
}
================================================
FILE: extensions/vscode/.gitignore
================================================
out
node_modules
.vscode-test
*.vsix
================================================
FILE: extensions/vscode/.vscodeignore
================================================
.vscode/**
**/*.ts
**/*.map
.gitignore
**/tsconfig.json
**/tsconfig.base.json
contributing.md
.travis.yml
================================================
FILE: extensions/vscode/LICENSE
================================================
MIT License
Copyright (c) 2021 Vivek Malneedi
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: extensions/vscode/README.md
================================================
# veridian
a vscode client extension for the veridian language server.
- veridian must be installed seperately, see https://github.com/vivekmalneedi/veridian for details
- provides syntax highlighting, the grammar for which is borrowed from https://github.com/TheClams/SystemVerilog and is under the Apache 2.0 License
================================================
FILE: extensions/vscode/package.json
================================================
{
"name": "veridian",
"description": "A client for the Veridian Language Server for SystemVerilog/Verilog",
"author": "Vivek Malneedi",
"publisher": "vivekmalneedi",
"license": "MIT",
"version": "0.1.0",
"categories": [
"Programming Languages",
"Snippets",
"Linters"
],
"keywords": [
"SystemVerilog",
"Verilog"
],
"repository": {
"type": "git",
"url": "https://github.com/vivekmalneedi/veridian"
},
"activationEvents": [
"onLanguage:systemverilog",
"onLanguage:verilog"
],
"main": "./out/extension",
"scripts": {
"vscode:prepublish": "npm run compile",
"compile": "tsc -b",
"watch": "tsc -b -w"
},
"contributes": {
"languages": [
{
"id": "systemverilog",
"extensions": [
".sv",
".svh",
".v",
".vh",
".verilog"
],
"aliases": [
"SystemVerilog",
"verilog",
"Verilog"
]
}
],
"grammars": [
{
"language": "systemverilog",
"scopeName": "source.systemverilog",
"path": "./syntaxes/systemverilog.tmLanguage.json"
}
],
"configuration": {
"type": "object",
"title": "veridian",
"properties": {
"veridian.serverPath": {
"scope": "window",
"type": "string",
"default": "veridian",
"description": "path of the veridian binary"
},
"veridian.trace.server": {
"scope": "window",
"type": "string",
"enum": [
"off",
"messages",
"verbose"
],
"default": "off",
"description": "Traces the communication between VS Code and the language server."
}
}
}
},
"engines": {
"vscode": "^1.100.0"
},
"dependencies": {
"glob": "^11.0.0",
"vscode-languageclient": "^9.0.1"
},
"devDependencies": {
"@eslint/js": "^9.13.0",
"@stylistic/eslint-plugin": "^2.9.0",
"@types/mocha": "^10.0.6",
"@types/node": "^22",
"eslint": "^9.13.0",
"mocha": "^10.3.0",
"typescript": "^5.9.2",
"typescript-eslint": "^8.39.0",
"@types/vscode": "^1.100.0"
}
}
================================================
FILE: extensions/vscode/src/extension.ts
================================================
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import { workspace, ExtensionContext } from "vscode";
import {
LanguageClient,
LanguageClientOptions,
ServerOptions,
Executable,
} from "vscode-languageclient/node";
let client: LanguageClient;
const workSpaceFolder = workspace.workspaceFolders?.[0];
let cwd: string = workSpaceFolder.uri.fsPath;
const serverPath: string = workspace.getConfiguration().get("veridian.serverPath");
export function activate(context: ExtensionContext) {
const run: Executable = {
command: serverPath,
// options: { cwd },
};
// If the extension is launched in debug mode then the debug server options are used
// Otherwise the run options are used
let serverOptions: ServerOptions = {
run,
debug: run,
};
// Options to control the language client
let clientOptions: LanguageClientOptions = {
// Register the server for plain text documents
documentSelector: [{ scheme: "file", language: "systemverilog" }],
};
// Create the language client and start the client.
client = new LanguageClient(
"veridian",
"veridian",
serverOptions,
clientOptions
);
// Start the client. This will also launch the server
client.start();
}
export function deactivate(): Thenable<void> | undefined {
if (!client) {
return undefined;
}
return client.stop();
}
================================================
FILE: extensions/vscode/syntaxes/systemverilog.tmLanguage.json
================================================
{
"$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
"fileTypes": [
"sv",
"SV",
"v",
"V",
"svh",
"SVH",
"vh",
"VH"
],
"hidden": true,
"foldingStartMarker": "(begin)\\s*(//.*)?$",
"foldingStopMarker": "^\\s*(begin)$",
"name": "systemverilog",
"patterns": [
{
"begin": "\\s*\\b(function|task)\\b(\\s+automatic)?",
"beginCaptures": {
"1": {
"name": "keyword.control.systemverilog"
},
"2": {
"name": "keyword.control.systemverilog"
}
},
"end": ";",
"patterns": [
{
"match": "\\b([a-zA-Z_][a-zA-Z0-9_]*\\s+)?([a-zA-Z_][a-zA-Z0-9_:]*)\\s*(?=\\(|;)",
"captures": {
"1": {
"name": "storage.type.systemverilog"
},
"2": {
"name": "entity.name.function.systemverilog"
}
}
},
{
"include": "#port-dir"
},
{
"include": "#base-grammar"
}
],
"name": "meta.function.systemverilog"
},
{
"match": "\\s*\\b(task)\\s+(automatic)?\\s*(\\w+)\\s*;",
"captures": {
"1": {
"name": "keyword.control.systemverilog"
},
"2": {
"name": "keyword.control.systemverilog"
},
"3": {
"name": "entity.name.function.systemverilog"
}
},
"name": "meta.task.simple.systemverilog"
},
{
"begin": "\\s*\\b(typedef\\s+(struct|enum|union)\\b)\\s*(packed)?\\s*([a-zA-Z_][a-zA-Z0-9_]*)?",
"beginCaptures": {
"1": {
"name": "keyword.control.systemverilog"
},
"2": {
"name": "keyword.control.systemverilog"
},
"3": {
"name": "keyword.control.systemverilog"
},
"4": {
"name": "storage.type.systemverilog"
}
},
"end": "(})\\s*([a-zA-Z_][a-zA-Z0-9_]*)\\s*;",
"endCaptures": {
"1": {
"name": "keyword.operator.other.systemverilog"
},
"2": {
"name": "entity.name.function.systemverilog"
}
},
"patterns": [
{
"include": "#struct-anonymous"
},
{
"include": "#base-grammar"
}
],
"name": "meta.typedef.struct.systemverilog"
},
{
"match": "\\s*\\b(typedef\\s+class)\\s+([a-zA-Z_][a-zA-Z0-9_]*)\\s*;",
"captures": {
"1": {
"name": "keyword.control.systemverilog"
},
"2": {
"name": "entity.name.declaration.systemverilog"
}
},
"name": "meta.typedef.class.systemverilog"
},
{
"begin": "\\s*\\b(typedef)\\b",
"beginCaptures": {
"1": {
"name": "keyword.control.systemverilog"
}
},
"end": "([a-zA-Z_][a-zA-Z0-9_]*)\\s*(?=(\\[[a-zA-Z0-9_:\\$\\-\\+]*\\])?;)",
"endCaptures": {
"1": {
"name": "entity.name.function.systemverilog"
}
},
"patterns": [
{
"match": "\\b([a-zA-Z_]\\w*)\\s*(#)\\(",
"captures": {
"1": {
"name": "storage.type.userdefined.systemverilog"
},
"2": {
"name": "keyword.operator.param.systemverilog"
}
},
"name": "meta.typedef.class.systemverilog"
},
{
"include": "#base-grammar"
},
{
"include": "#module-binding"
}
],
"name": "meta.typedef.simple.systemverilog"
},
{
"begin": "\\s*(module)\\s+\\b([a-zA-Z_][a-zA-Z0-9_]*)\\b",
"beginCaptures": {
"1": {
"name": "keyword.control.systemverilog"
},
"2": {
"name": "entity.name.type.module.systemverilog"
}
},
"end": ";",
"endCaptures": {
"1": {
"name": "entity.name.function.systemverilog"
}
},
"patterns": [
{
"include": "#port-dir"
},
{
"match": "\\s*(parameter)",
"name": "keyword.other.systemverilog"
},
{
"include": "#base-grammar"
},
{
"include": "#ifmodport"
}
],
"name": "meta.module.systemverilog"
},
{
"captures": {
"1": {
"name": "keyword.control.systemverilog"
},
"2": {
"name": "entity.name.function.systemverilog"
}
},
"match": "\\b(sequence)\\s+([a-zA-Z_][a-zA-Z0-9_]*)",
"name": "meta.sequence.systemverilog"
},
{
"match": "\\b(bind)\\s+([a-zA-Z_][a-zA-Z0-9_\\.]*)\\b",
"captures": {
"1": {
"name": "keyword.control.systemverilog"
}
}
},
{
"captures": {
"0": {
"name": "meta.section.begin.systemverilog"
},
"1": {
"name": "keyword.other.block.systemverilog"
},
"3": {
"name": "keyword.operator.systemverilog"
},
"4": {
"name": "entity.name.section.systemverilog"
}
},
"match": "\\s*(begin|fork)\\s*((:)\\s*([a-zA-Z_][a-zA-Z0-9_]*))\\b",
"name": "meta.definition.systemverilog"
},
{
"match": "\\b(property)\\s+(\\w+)",
"captures": {
"1": {
"name": "keyword.sva.systemverilog"
},
"2": {
"name": "entity.name.sva.systemverilog"
}
}
},
{
"match": "\\b(\\w+)\\s*(:)\\s*(assert)\\b",
"captures": {
"1": {
"name": "entity.name.sva.systemverilog"
},
"2": {
"name": "keyword.operator.systemverilog"
},
"3": {
"name": "keyword.sva.systemverilog"
}
}
},
{
"begin": "\\s*(//)\\s*(psl)\\s+((\\w+)\\s*(:))?\\s*(default|assert|assume)",
"beginCaptures": {
"0": {
"name": "meta.psl.systemverilog"
},
"1": {
"name": "comment.line.double-slash.systemverilog"
},
"2": {
"name": "keyword.psl.systemverilog"
},
"4": {
"name": "entity.psl.name.systemverilog"
},
"5": {
"name": "keyword.operator.systemverilog"
},
"6": {
"name": "keyword.psl.systemverilog"
}
},
"end": ";",
"patterns": [
{
"match": "\\b(never|always|default|clock|within|rose|fell|stable|until|before|next|eventually|abort|posedge)\\b",
"name": "keyword.psl.systemverilog"
},
{
"include": "#operators"
},
{
"include": "#functions"
},
{
"include": "#constants"
}
],
"name": "meta.psl.systemverilog"
},
{
"begin": "\\s*(/\\*)\\s*(psl)",
"beginCaptures": {
"0": {
"name": "meta.psl.systemverilog"
},
"1": {
"name": "comment.block.systemverilog"
},
"2": {
"name": "keyword.psl.systemverilog"
}
},
"end": "(\\*/)",
"endCaptures": {
"1": {
"name": "comment.block.systemverilog"
}
},
"patterns": [
{
"match": "^\\s*((\\w+)\\s*(:))?\\s*(default|assert|assume)",
"captures": {
"0": {
"name": "meta.psl.systemverilog"
},
"2": {
"name": "entity.psl.name.systemverilog"
},
"3": {
"name": "keyword.operator.systemverilog"
},
"4": {
"name": "keyword.psl.systemverilog"
}
}
},
{
"match": "\\b(property)\\s+(\\w+)",
"captures": {
"1": {
"name": "keyword.psl.systemverilog"
},
"2": {
"name": "entity.psl.name.systemverilog"
}
}
},
{
"match": "\\b(never|always|default|clock|within|rose|fell|stable|until|before|next|eventually|abort|posedge|negedge)\\b",
"name": "keyword.psl.systemverilog"
},
{
"include": "#operators"
},
{
"include": "#functions"
},
{
"include": "#constants"
}
],
"name": "meta.psl.systemverilog"
},
{
"match": "\\s*\\b(automatic|cell|config|deassign|defparam|design|disable|edge|endconfig|endgenerate|endspecify|endtable|event|generate|genvar|ifnone|incdir|instance|liblist|library|macromodule|negedge|noshowcancelled|posedge|pulsestyle_onevent|pulsestyle_ondetect|scalared|showcancelled|specify|specparam|table|use|vectored)\\b",
"captures": {
"1": {
"name": "keyword.other.systemverilog"
}
}
},
{
"match": "\\s*\\b(initial|always|wait|force|release|assign|always_comb|always_ff|always_latch|forever|repeat|while|for|if|iff|else|case|casex|casez|default|endcase|return|break|continue|do|foreach|with|inside|dist|clocking|cover|coverpoint|property|bins|binsof|illegal_bins|ignore_bins|randcase|modport|matches|solve|static|assert|assume|before|expect|cross|ref|first_match|srandom|struct|packed|final|chandle|alias|tagged|extern|throughout|timeprecision|timeunit|priority|type|union|uwire|wait_order|triggered|randsequence|import|export|context|pure|intersect|wildcard|within|new|typedef|enum|this|super|begin|fork|forkjoin|unique|unique0|priority)\\b",
"captures": {
"1": {
"name": "keyword.control.systemverilog"
}
}
},
{
"match": "\\s*\\b(end|endtask|endmodule|endfunction|endprimitive|endclass|endpackage|endsequence|endprogram|endclocking|endproperty|endgroup|endinterface|join|join_any|join_none)\\b(\\s*(:)\\s*(\\w+))?",
"captures": {
"1": {
"name": "keyword.control.systemverilog"
},
"3": {
"name": "keyword.operator.systemverilog"
},
"4": {
"name": "entity.label.systemverilog"
}
},
"name": "meta.object.end.systemverilog"
},
{
"match": "\\b(std)\\b::",
"name": "support.class.systemverilog"
},
{
"captures": {
"1": {
"name": "constant.other.define.systemverilog"
},
"2": {
"name": "entity.name.type.define.systemverilog"
}
},
"match": "^\\s*(`define)\\s+([a-zA-Z_][a-zA-Z0-9_]*)",
"name": "meta.define.systemverilog"
},
{
"include": "#comments"
},
{
"captures": {
"1": {
"name": "keyword.control.systemverilog"
},
"2": {
"name": "entity.name.type.class.systemverilog"
}
},
"match": "\\s*(primitive|package|constraint|interface|covergroup|program)\\s+\\b([a-zA-Z_][a-zA-Z0-9_]*)\\b",
"name": "meta.definition.systemverilog"
},
{
"captures": {
"2": {
"name": "entity.name.type.class.systemverilog"
},
"3": {
"name": "keyword.operator.other.systemverilog"
},
"4": {
"name": "keyword.control.systemverilog"
}
},
"match": "(([a-zA-Z_][a-zA-Z0-9_]*)\\s*(:))?\\s*(coverpoint|cross)\\s+([a-zA-Z_][a-zA-Z0-9_]*)",
"name": "meta.definition.systemverilog"
},
{
"captures": {
"1": {
"name": "keyword.control.systemverilog"
},
"2": {
"name": "keyword.control.systemverilog"
},
"3": {
"name": "entity.name.type.class.systemverilog"
}
},
"match": "\\b(virtual\\s+)?(class)\\s+\\b([a-zA-Z_][a-zA-Z0-9_]*)\\b",
"name": "meta.definition.class.systemverilog"
},
{
"captures": {
"1": {
"name": "keyword.control.systemverilog"
},
"2": {
"name": "entity.other.inherited-class.systemverilog"
}
},
"match": "\\b(extends)\\s+([a-zA-Z_][a-zA-Z0-9_]*)\\b",
"name": "meta.definition.systemverilog"
},
{
"include": "#all-types"
},
{
"include": "#operators"
},
{
"include": "#port-dir"
},
{
"match": "\\b(and|nand|nor|or|xor|xnor|buf|not|bufif[01]|notif[01]|r?[npc]mos|tran|r?tranif[01]|pullup|pulldown)\\b",
"name": "support.type.systemverilog"
},
{
"include": "#strings"
},
{
"match": "\\$\\b([a-zA-Z_][a-zA-Z0-9_]*)\\b",
"name": "support.function.systemverilog"
},
{
"match": "\\b([a-zA-Z_][a-zA-Z0-9_]*)(')(?=\\()",
"name": "meta.cast.systemverilog",
"captures": {
"1": {
"name": "storage.type.systemverilog"
},
"2": {
"name": "keyword.operator.cast.systemverilog"
}
}
},
{
"match": "^\\s*(localparam|parameter)\\s+([A-Z_][A-Z0-9_]*)\\b\\s*(?=(=))",
"name": "meta.param.systemverilog",
"captures": {
"1": {
"name": "keyword.other.systemverilog"
},
"2": {
"name": "constant.other.systemverilog"
}
}
},
{
"match": "^\\s*(localparam|parameter)\\s+([a-zA-Z_][a-zA-Z0-9_]*)\\b\\s*(?=(=))",
"name": "meta.param.systemverilog",
"captures": {
"1": {
"name": "keyword.other.systemverilog"
}
}
},
{
"match": "^\\s*(local\\s+|protected\\s+|localparam\\s+|parameter\\s+)?(const\\s+|virtual\\s+)?(rand\\s+|randc\\s+)?(([a-zA-Z_][a-zA-Z0-9_]*)(::))?([a-zA-Z_][a-zA-Z0-9_]*)\\b\\s*(?=(#\\s*\\([\\w,]+\\)\\s*)?([a-zA-Z][a-zA-Z0-9_\\s\\[\\]']*)(;|,|=|'\\{))",
"name": "meta.userdefined.systemverilog",
"captures": {
"1": {
"name": "keyword.other.systemverilog"
},
"2": {
"name": "keyword.other.systemverilog"
},
"3": {
"name": "storage.type.rand.systemverilog"
},
"5": {
"name": "support.type.scope.systemverilog"
},
"6": {
"name": "keyword.operator.scope.systemverilog"
},
"7": {
"name": "storage.type.userdefined.systemverilog"
}
}
},
{
"match": "\\s*\\b(option)\\.",
"captures": {
"1": {
"name": "keyword.cover.systemverilog"
}
}
},
{
"match": "\\s*\\b(local|const|protected|virtual|localparam|parameter)\\b",
"captures": {
"1": {
"name": "keyword.other.systemverilog"
}
}
},
{
"match": "\\s*\\b(rand|randc)\\b",
"name": "storage.type.rand.systemverilog"
},
{
"begin": "^(\\s*(bind)\\s+([a-zA-Z_][\\w\\.]*))?\\s*([a-zA-Z_][a-zA-Z0-9_]*)\\s*(?=#[^#])",
"beginCaptures": {
"2": {
"name": "keyword.control.systemverilog"
},
"4": {
"name": "storage.module.systemverilog"
}
},
"end": "(?=;|=|:)",
"patterns": [
{
"include": "#module-binding"
},
{
"include": "#module-param"
},
{
"include": "#comments"
},
{
"include": "#operators"
},
{
"include": "#constants"
},
{
"include": "#strings"
},
{
"match": "\\b([a-zA-Z_][a-zA-Z0-9_]*)\\b(?=\\s*(\\(|$))",
"name": "entity.name.type.module.systemverilog"
}
],
"name": "meta.module.inst.param.systemverilog"
},
{
"begin": "\\b([a-zA-Z_][a-zA-Z0-9_]*)\\s+(?!intersect|and|or|throughout|within)([a-zA-Z_][a-zA-Z0-9_]*)\\s*(\\[(\\d+)(\\:(\\d+))?\\])?\\s*(\\(|$)",
"beginCaptures": {
"1": {
"name": "storage.module.systemverilog"
},
"2": {
"name": "entity.name.type.module.systemverilog"
},
"4": {
"name": "constant.numeric.systemverilog"
},
"6": {
"name": "constant.numeric.systemverilog"
}
},
"end": ";",
"patterns": [
{
"include": "#module-binding"
},
{
"include": "#comments"
},
{
"include": "#strings"
},
{
"include": "#operators"
},
{
"include": "#constants"
}
],
"name": "meta.module.inst.systemverilog"
},
{
"name": "meta.struct.assign.systemverilog",
"begin": "\\b\\s+(<?=)\\s*(\\'{)",
"beginCaptures": {
"1": {
"name": "keyword.operator.other.systemverilog"
},
"2": {
"name": "keyword.operator.other.systemverilog"
},
"3": {
"name": "keyword.operator.other.systemverilog"
}
},
"end": ";",
"patterns": [
{
"match": "\\b(\\w+)\\s*(:)(?!:)",
"captures": {
"1": {
"name": "support.function.field.systemverilog"
},
"2": {
"name": "keyword.operator.other.systemverilog"
}
}
},
{
"include": "#comments"
},
{
"include": "#strings"
},
{
"include": "#operators"
},
{
"include": "#constants"
},
{
"include": "#storage-scope-systemverilog"
}
]
},
{
"include": "#storage-scope-systemverilog"
},
{
"include": "#functions"
},
{
"include": "#constants"
}
],
"repository": {
"functions": {
"match": "\\b(\\w+)(?=\\s*\\()",
"name": "support.function.generic.systemverilog"
},
"all-types": {
"patterns": [
{
"include": "#storage-type-systemverilog"
},
{
"include": "#storage-modifier-systemverilog"
}
]
},
"constants": {
"patterns": [
{
"match": "(\\b\\d+)?'(s?[bB]\\s*[0-1xXzZ?][0-1_xXzZ?]*|s?[oO]\\s*[0-7xXzZ?][0-7_xXzZ?]*|s?[dD]\\s*[0-9xXzZ?][0-9_xXzZ?]*|s?[hH]\\s*[0-9a-fA-FxXzZ?][0-9a-fA-F_xXzZ?]*)((e|E)(\\+|-)?[0-9]+)?(?!'|\\w)",
"name": "constant.numeric.systemverilog"
},
{
"match": "'[01xXzZ]",
"name": "constant.numeric.bit.systemverilog"
},
{
"match": "\\b((\\d[\\d_]*)(e|E)(\\+|-)?[0-9]+)\\b",
"name": "constant.numeric.exp.systemverilog"
},
{
"match": "\\b(\\d[\\d_]*)\\b",
"name": "constant.numeric.decimal.systemverilog"
},
{
"match": "\\b(\\d+(fs|ps|ns|us|ms|s)?)\\b",
"name": "constant.numeric.time.systemverilog"
},
{
"match": "\\b([A-Z][A-Z0-9_]*)\\b",
"name": "constant.other.net.systemverilog"
},
{
"match": "(`ifdef|`ifndef|`default_nettype)\\s+(\\w+)",
"captures": {
"1": {
"name": "constant.other.preprocessor.systemverilog"
},
"2": {
"name": "support.variable.systemverilog"
}
}
},
{
"match": "`(celldefine|else|elsif|endcelldefine|endif|include|line|nounconnected_drive|resetall|timescale|unconnected_drive|undef|begin_\\w+|end_\\w+|remove_\\w+|restore_\\w+)\\b",
"name": "constant.other.preprocessor.systemverilog"
},
{
"match": "`\\b([a-zA-Z_][a-zA-Z0-9_]*)\\b",
"name": "constant.other.define.systemverilog"
},
{
"match": "\\b(null)\\b",
"name": "support.constant.systemverilog"
}
]
},
"operators": {
"patterns": [
{
"match": "(=|==|===|!=|!==|<=|>=|<|>)",
"name": "keyword.operator.comparison.systemverilog"
},
{
"match": "(\\-|\\+|\\*|\\/|%)",
"name": "keyword.operator.arithmetic.systemverilog"
},
{
"match": "(!|&&|\\|\\||\\bor\\b)",
"name": "keyword.operator.logical.systemverilog"
},
{
"match": "(&|\\||\\^|~|{|'{|}|<<|>>|\\?|:)",
"name": "keyword.operator.bitwise.systemverilog"
},
{
"match": "(#|@)",
"name": "keyword.operator.other.systemverilog"
}
]
},
"comments": {
"patterns": [
{
"begin": "/\\*",
"captures": {
"0": {
"name": "punctuation.definition.comment.systemverilog"
}
},
"end": "\\*/",
"name": "comment.block.systemverilog"
},
{
"captures": {
"1": {
"name": "punctuation.definition.comment.systemverilog"
}
},
"match": "(//).*$\\n?",
"name": "comment.line.double-slash.systemverilog"
}
]
},
"port-dir": {
"patterns": [
{
"match": "\\s*\\b(output|input|inout|ref)\\s+(([a-zA-Z_][a-zA-Z0-9_]*)(::))?([a-zA-Z_][a-zA-Z0-9_]*)?\\s+(?=\\[[a-zA-Z0-9_\\-\\+]*:[a-zA-Z0-9_\\-\\+]*\\]\\s+[a-zA-Z_][a-zA-Z0-9_\\s]*)",
"captures": {
"1": {
"name": "support.type.systemverilog"
},
"3": {
"name": "support.type.scope.systemverilog"
},
"4": {
"name": "keyword.operator.scope.systemverilog"
},
"5": {
"name": "storage.type.interface.systemverilog"
}
}
},
{
"match": "\\s*\\b(output|input|inout|ref)\\s+(([a-zA-Z_][a-zA-Z0-9_]*)(::))?([a-zA-Z_][a-zA-Z0-9_]*)?\\s+(?=[a-zA-Z_][a-zA-Z0-9_\\s]*)",
"captures": {
"1": {
"name": "support.type.systemverilog"
},
"3": {
"name": "support.type.scope.systemverilog"
},
"4": {
"name": "keyword.operator.scope.systemverilog"
},
"5": {
"name": "storage.type.interface.systemverilog"
}
}
},
{
"match": "\\s*\\b(output|input|inout|ref)\\b",
"name": "support.type.systemverilog"
}
]
},
"base-grammar": {
"patterns": [
{
"include": "#all-types"
},
{
"include": "#comments"
},
{
"include": "#operators"
},
{
"include": "#constants"
},
{
"include": "#strings"
},
{
"match": "^\\s*([a-zA-Z_][a-zA-Z0-9_]*)\\s+[a-zA-Z_][a-zA-Z0-9_,=\\s]*",
"captures": {
"1": {
"name": "storage.type.interface.systemverilog"
}
}
},
{
"include": "#storage-scope-systemverilog"
}
]
},
"storage-type-systemverilog": {
"patterns": [
{
"match": "\\s*\\b(var|wire|tri|tri[01]|supply[01]|wand|triand|wor|trior|trireg|reg|integer|int|longint|shortint|logic|bit|byte|shortreal|string|time|realtime|real|process|void)\\b",
"name": "storage.type.systemverilog"
},
{
"match": "\\s*\\b(uvm_transaction|uvm_component|uvm_monitor|uvm_driver|uvm_test|uvm_env|uvm_object|uvm_agent|uvm_sequence_base|uvm_sequence|uvm_sequence_item|uvm_sequence_state|uvm_sequencer|uvm_sequencer_base|uvm_component_registry|uvm_analysis_imp|uvm_analysis_port|uvm_analysis_export|uvm_config_db|uvm_active_passive_enum|uvm_phase|uvm_verbosity|uvm_tlm_analysis_fifo|uvm_tlm_fifo|uvm_report_server|uvm_objection|uvm_recorder|uvm_domain|uvm_reg_field|uvm_reg|uvm_reg_block|uvm_bitstream_t|uvm_radix_enum|uvm_printer|uvm_packer|uvm_comparer|uvm_scope_stack)\\b",
"name": "storage.type.uvm.systemverilog"
}
]
},
"storage-scope-systemverilog": {
"match": "\\b([a-zA-Z_][a-zA-Z0-9_]*)(::)",
"captures": {
"1": {
"name": "support.type.systemverilog"
},
"2": {
"name": "keyword.operator.scope.systemverilog"
}
},
"name": "meta.scope.systemverilog"
},
"storage-modifier-systemverilog": {
"match": "\\b(signed|unsigned|small|medium|large|supply[01]|strong[01]|pull[01]|weak[01]|highz[01])\\b",
"name": "storage.modifier.systemverilog"
},
"ifmodport": {
"match": "\\b([a-zA-Z_][a-zA-Z0-9_]*)\\.([a-zA-Z_][a-zA-Z0-9_]*)\\s+([a-zA-Z_][a-zA-Z0-9_]*)\\b",
"captures": {
"1": {
"name": "storage.type.interface.systemverilog"
},
"2": {
"name": "support.modport.systemverilog"
}
}
},
"strings": {
"patterns": [
{
"begin": "\"",
"beginCaptures": {
"0": {
"name": "punctuation.definition.string.begin.systemverilog"
}
},
"end": "\"",
"endCaptures": {
"0": {
"name": "punctuation.definition.string.end.systemverilog"
}
},
"name": "string.quoted.double.systemverilog",
"patterns": [
{
"match": "\\\\.",
"name": "constant.character.escape.systemverilog"
},
{
"match": "(?x)%\n\t\t\t\t\t\t\t\t\t\t(\\d+\\$)? # field (argument #)\n\t\t\t\t\t\t\t\t\t\t[#0\\- +']* # flags\n\t\t\t\t\t\t\t\t\t\t[,;:_]? # separator character (AltiVec)\n\t\t\t\t\t\t\t\t\t\t((-?\\d+)|\\*(-?\\d+\\$)?)? # minimum field width\n\t\t\t\t\t\t\t\t\t\t(\\.((-?\\d+)|\\*(-?\\d+\\$)?)?)? # precision\n\t\t\t\t\t\t\t\t\t\t(hh|h|ll|l|j|t|z|q|L|vh|vl|v|hv|hl)? # length modifier\n\t\t\t\t\t\t\t\t\t\t[bdiouxXhHDOUeEfFgGaACcSspnmt%] # conversion type\n\t\t\t\t\t\t\t\t\t",
"name": "constant.other.placeholder.systemverilog"
},
{
"match": "%",
"name": "invalid.illegal.placeholder.systemverilog"
}
]
}
]
},
"module-binding": {
"begin": "\\.([a-zA-Z_][a-zA-Z0-9_]*)\\s*\\(",
"beginCaptures": {
"1": {
"name": "support.function.port.systemverilog"
}
},
"end": "\\)",
"patterns": [
{
"include": "#constants"
},
{
"include": "#comments"
},
{
"include": "#operators"
},
{
"include": "#strings"
},
{
"include": "#constants"
},
{
"match": "\\b([a-zA-Z_]\\w*)(::)",
"captures": {
"1": {
"name": "support.type.scope.systemverilog"
},
"2": {
"name": "keyword.operator.scope.systemverilog"
}
}
},
{
"match": "\\b([a-zA-Z_]\\w*)(')",
"captures": {
"1": {
"name": "storage.type.interface.systemverilog"
},
"2": {
"name": "keyword.operator.cast.systemverilog"
}
}
},
{
"match": "\\$\\b([a-zA-Z_][a-zA-Z0-9_]*)\\b",
"name": "support.function.systemverilog"
},
{
"match": "\\b(virtual)\\b",
"name": "keyword.control.systemverilog"
}
],
"match": "\\.([a-zA-Z_][a-zA-Z0-9_]*)\\s*",
"captures": {
"1": {
"name": "support.function.port.implicit.systemverilog"
}
}
},
"module-param": {
"name": "meta.module-param.systemverilog",
"begin": "(#)\\s*\\(",
"beginCaptures": {
"1": {
"name": "keyword.operator.param.systemverilog"
}
},
"end": "\\)",
"patterns": [
{
"include": "#comments"
},
{
"include": "#constants"
},
{
"include": "#operators"
},
{
"include": "#strings"
},
{
"include": "#module-binding"
},
{
"match": "\\b(virtual)\\b",
"name": "keyword.control.systemverilog"
}
]
},
"struct-anonymous": {
"begin": "\\s*\\b(struct|union)\\s*(packed)?\\s*",
"beginCaptures": {
"1": {
"name": "keyword.control.systemverilog"
},
"2": {
"name": "keyword.control.systemverilog"
}
},
"end": "(})\\s*([a-zA-Z_]\\w*)\\s*;",
"endCaptures": {
"1": {
"name": "keyword.operator.other.systemverilog"
}
},
"patterns": [
{
"include": "#base-grammar"
}
],
"name": "meta.struct.anonymous.systemverilog"
}
},
"scopeName": "source.systemverilog",
"uuid": "789be04c-8b74-352e-8f37-63d336001277"
}
================================================
FILE: extensions/vscode/tsconfig.json
================================================
{
"compilerOptions": {
"module": "commonjs",
"target": "es2019",
"lib": ["ES2019"],
"outDir": "out",
"rootDir": "src",
"sourceMap": true
},
"include": ["src"],
"exclude": ["node_modules", ".vscode-test"]
}
================================================
FILE: extensions/vscode/tsconfig.tsbuildinfo
================================================
{"root":["./src/extension.ts"],"version":"5.9.3"}
================================================
FILE: rustfmt.toml
================================================
edition = "2018"
max_width = 100
================================================
FILE: src/completion/keyword.rs
================================================
use tower_lsp::lsp_types::*;
pub fn keyword_completions(keywords: &[(&str, &str)]) -> Vec<CompletionItem> {
let mut items: Vec<CompletionItem> = Vec::new();
for key in keywords {
if key.1.is_empty() {
items.push(CompletionItem {
label: key.0.to_string(),
kind: Some(CompletionItemKind::KEYWORD),
..CompletionItem::default()
});
} else {
items.push(CompletionItem {
label: key.0.to_string(),
kind: Some(CompletionItemKind::KEYWORD),
insert_text: Some(key.1.to_string()),
insert_text_format: Some(InsertTextFormat::SNIPPET),
..CompletionItem::default()
})
}
}
items
}
pub fn other_completions(tasks: &[&str]) -> Vec<CompletionItem> {
tasks
.iter()
.map(|x| CompletionItem {
label: x.to_string(),
kind: Some(CompletionItemKind::FUNCTION),
..CompletionItem::default()
})
.collect()
}
pub const KEYWORDS: &[(&str, &str)] = &[
("accept_on", ""),
("alias", ""),
("always", "always @($1) begin\nend"),
("always_comb", "always_comb begin\n\t$1\nend"),
("always_ff", "always_ff @($1) begin\nend"),
("always_latch", "always_latch begin\n\t$1\nend"),
("and", ""),
("assert", ""),
("assign", ""),
("assume", ""),
("automatic", ""),
("before", ""),
("begin", "begin\n\t$1\nend"),
("bind", ""),
("bins", ""),
("binsof", ""),
("bit", ""),
("break", ""),
("buf", ""),
("bufif0", ""),
("bufif1", ""),
("byte", ""),
("case", "case $1;\nendcase"),
("casex", "casex $1;\nendcase"),
("casez", "casez $1;\nendcase"),
("cell", ""),
("chandle", ""),
("checker", "checker $1;\nendchecker"),
("class", "class $1;\nendclass"),
("clocking", "clocking $1;\nendclocking"),
("cmos", ""),
("config", "config $1;\nendconfig"),
("const", ""),
("constraint", ""),
("context", ""),
("continue", ""),
("cover", ""),
("covergroup", ""),
("coverpoint", ""),
("cross", ""),
("deassign", ""),
("default", ""),
("defparam", ""),
("design", ""),
("disable", ""),
("dist", ""),
("do", ""),
("edge", ""),
("else", ""),
("end", ""),
("endcase", ""),
("endchecker", ""),
("endclass", ""),
("endclocking", ""),
("endconfig", ""),
("endfunction", ""),
("endgenerate", ""),
("endgroup", ""),
("endinterface", ""),
("endmodule", ""),
("endpackage", ""),
("endprimitive", ""),
("endprogram", ""),
("endproperty", ""),
("endspecify", ""),
("endsequence", ""),
("endtable", ""),
("endtask", ""),
("enum", ""),
("event", ""),
("eventually", ""),
("expect", ""),
("export", ""),
("extends", ""),
("extern", ""),
("final", ""),
("first_match", ""),
("for", ""),
("force", ""),
("foreach", ""),
("forever", ""),
("fork", ""),
("forkjoin", ""),
("function", "function $1;\nendfunction"),
("generate", "generate\n\t$1\nendgenerate"),
("genvar", ""),
("global", ""),
("highz0", ""),
("highz1", ""),
("if", ""),
("iff", ""),
("ifnone", ""),
("ignore_bins", ""),
("illegal_bins", ""),
("implements", ""),
("implies", ""),
("import", ""),
("incdir", ""),
("include", ""),
("initial", ""),
("inout", ""),
("input", ""),
("inside", ""),
("instance", ""),
("int", ""),
("integer", ""),
("interconnect", ""),
("interface", "interface $1;\nendinterface"),
("intersect", ""),
("join", ""),
("join_any", ""),
("join_none", ""),
("large", ""),
("let", ""),
("liblist", ""),
("library", ""),
("local", ""),
("localparam", ""),
("logic", ""),
("longint", ""),
("macromodule", ""),
("matches", ""),
("medium", ""),
("modport", ""),
("module", "module $1 ($2);\nendmodule"),
("nand", ""),
("negedge", ""),
("nettype", ""),
("new", ""),
("nexttime", ""),
("nmos", ""),
("nor", ""),
("noshowcancelled", ""),
("not", ""),
("notif0", ""),
("notif1", ""),
("null", ""),
("or", ""),
("output", ""),
("package", "package $1;\nendpackage"),
("packed", ""),
("parameter", ""),
("pmos", ""),
("posedge", ""),
("primitive", "primitive $1;\nendprimitive"),
("priority", ""),
("program", "program $1;\nendprogram"),
("property", "property $1;\nendproperty"),
("protected", ""),
("pull0", ""),
("pull1", ""),
("pulldown", ""),
("pullup", ""),
("pulsestyle_ondetect", ""),
("pulsestyle_onevent", ""),
("pure", ""),
("rand", ""),
("randc", ""),
("randcase", ""),
("randsequence", ""),
("rcmos", ""),
("real", ""),
("realtime", ""),
("ref", ""),
("reg", ""),
("reject_on", ""),
("release", ""),
("repeat", ""),
("restrict", ""),
("return", ""),
("rnmos", ""),
("rpmos", ""),
("rtran", ""),
("rtranif0", ""),
("rtranif1", ""),
("s_always", ""),
("s_eventually", ""),
("s_nexttime", ""),
("s_until", ""),
("s_until_with", ""),
("scalared", ""),
("sequence", "sequence $1;\nendsequence"),
("shortint", ""),
("shortreal", ""),
("showcancelled", ""),
("signed", ""),
("small", ""),
("soft", ""),
("solve", ""),
("specify", "specify $1;\nendspecify"),
("specparam", ""),
("static", ""),
("string", ""),
("strong", ""),
("strong0", ""),
("strong1", ""),
("struct", ""),
("super", ""),
("supply0", ""),
("supply1", ""),
("sync_accept_on", ""),
("sync_reject_on", ""),
("table", "table $1;\nendtable"),
("tagged", ""),
("task", "task $1;\nendtask"),
("this", ""),
("throughout", ""),
("time", ""),
("timeprecision", ""),
("timeunit", ""),
("tran", ""),
("tranif0", ""),
("tranif1", ""),
("tri", ""),
("tri0", ""),
("tri1", ""),
("triand", ""),
("trior", ""),
("trireg", ""),
("type", ""),
("typedef", ""),
("union", ""),
("unique", ""),
("unique0", ""),
("unsigned", ""),
("until", ""),
("until_with", ""),
("untyped", ""),
("use", ""),
("uwire", ""),
("var", ""),
("vectored", ""),
("virtual", ""),
("void", ""),
("wait", ""),
("wait_order", ""),
("wand", ""),
("weak", ""),
("weak0", ""),
("weak1", ""),
("while", ""),
("wildcard", ""),
("wire", ""),
("with", ""),
("within", ""),
("wor", ""),
("xnor", ""),
("xor", ""),
];
pub const SYS_TASKS: &[&str] = &[
"finish",
"exit",
"fatal",
"warning",
"stop",
"error",
"info",
"realtime",
"time",
"asserton",
"assertkill",
"assertpasson",
"assertfailon",
"assertnonvacuouson",
"stime",
"printtimescale",
"timeformat",
"bitstoreal",
"bitstoshortreal",
"itor",
"signed",
"cast",
"realtobits",
"shortrealtobits",
"rtoi",
"unsigned",
"sampled",
"fell",
"changed",
"past_gclk",
"fell_gclk",
"changed_gclk",
"rising_gclk",
"steady_gclk",
"bits",
"typename",
"isunbounded",
"coverage_control",
"coverage_get",
"coverage_save",
"set_coverage_db_name",
"dimensions",
"right",
"high",
"size",
"random",
"dist_erlang",
"dist_normal",
"dist_t",
"asin",
"acos",
"atan",
"atan2",
"hypot",
"sinh",
"cosh",
"tanh",
"asinh",
"acosh",
"atanh",
"q_initialize",
"q_remove",
"q_exam",
"q_add",
"q_full",
"async$and$array",
"async$nand$array",
"async$or$array",
"async$nor$array",
"sync$and$array",
"sync$nand$array",
"sync$or$array",
"sync$nor$array",
"countones",
"onehot0",
"fatal",
"warning",
"dist_chi_square",
"dist_exponential",
"dist_poisson",
"dist_uniform",
"countbits",
"onehot",
"isunknown",
"coverage_get_max",
"coverage_merge",
"get_coverage",
"load_coverage_db",
"clog2",
"ln",
"log10",
"exp",
"sqrt",
"pow",
"floor",
"ceil",
"sin",
"cos",
"tan",
"rose",
"stable",
"past",
"rose_gclk",
"stable_gclk",
"future_gclk",
"falling_gclk",
"changing_gclk",
"unpacked_dimensions",
"left",
"low",
"increment",
"assertoff",
"assertcontrol",
"assertpassoff",
"assertfailoff",
"assertvacuousoff",
"error",
"info",
"async$and$plane",
"async$nand$plane",
"async$or$plane",
"async$nor$plane",
"sync$and$plane",
"sync$nand$plane",
"sync$or$plane",
"sync$nor$plane",
"system",
"countdrivers",
"getpattern",
"incsave",
"input",
"key",
"list",
"log",
"nokey",
"nolog",
"reset",
"reset_count",
"reset_value",
"restart",
"save",
"scale",
"scope",
"showscopes",
"showvars",
"sreadmemb",
"sreadmemh",
];
pub const DIRECTIVES: &[&str] = &[
"__FILE__",
"__LINE__",
"begin_keywords",
"celldefine",
"default_nettype",
"define",
"else",
"elsif",
"end_keywords",
"endcelldefine",
"endif",
"ifdef",
"ifndef",
"include",
"line",
"nounconnected_drive",
"pragma",
"resetall",
"timescale",
"unconnected_drive",
"undef",
"undefineall",
"default_decay_time",
"default_trireg_strength",
"delay_mode_distributed",
"delay_mode_path",
"delay_mode_unit",
"delay_mode_zero",
];
================================================
FILE: src/completion.rs
================================================
use crate::server::LSPServer;
use crate::sources::LSPSupport;
use log::{debug, trace};
use ropey::{Rope, RopeSlice};
use std::time::Instant;
use tower_lsp::lsp_types::*;
pub mod keyword;
impl LSPServer {
pub fn completion(&self, params: CompletionParams) -> Option<CompletionResponse> {
debug!("completion requested");
trace!("{:#?}", ¶ms);
let now = Instant::now();
let doc = params.text_document_position;
let file_id = self.srcs.get_id(&doc.text_document.uri).to_owned();
self.srcs.wait_parse_ready(file_id, false);
trace!("comp wait parse: {}", now.elapsed().as_millis());
let file = self.srcs.get_file(file_id)?;
let file = file.read().ok()?;
trace!("comp read: {}", now.elapsed().as_millis());
let token = get_completion_token(
&file.text,
file.text.line(doc.position.line as usize),
doc.position,
);
let response = match params.context {
Some(context) => match context.trigger_kind {
CompletionTriggerKind::TRIGGER_CHARACTER => {
debug!(
"trigger char completion: {}",
context.trigger_character.clone()?.as_str()
);
match context.trigger_character?.as_str() {
"." => Some(self.srcs.get_dot_completions(
token.trim_end_matches('.'),
file.text.pos_to_byte(&doc.position),
&doc.text_document.uri,
)?),
"$" => Some(CompletionList {
is_incomplete: false,
items: self.sys_tasks.clone(),
}),
"`" => Some(CompletionList {
is_incomplete: false,
items: self.directives.clone(),
}),
_ => None,
}
}
CompletionTriggerKind::TRIGGER_FOR_INCOMPLETE_COMPLETIONS => None,
CompletionTriggerKind::INVOKED => {
debug!("Invoked Completion");
let mut comps = self.srcs.get_completions(
&token,
file.text.pos_to_byte(&doc.position),
&doc.text_document.uri,
)?;
// complete keywords
comps.items.extend::<Vec<CompletionItem>>(
self.key_comps
.iter()
.filter(|x| x.label.starts_with(&token))
.cloned()
.collect(),
);
Some(comps)
}
_ => None,
},
None => {
let trigger = prev_char(&file.text, &doc.position);
match trigger {
'.' => Some(self.srcs.get_dot_completions(
token.trim_end_matches('.'),
file.text.pos_to_byte(&doc.position),
&doc.text_document.uri,
)?),
'$' => Some(CompletionList {
is_incomplete: false,
items: self.sys_tasks.clone(),
}),
'`' => Some(CompletionList {
is_incomplete: false,
items: self.directives.clone(),
}),
_ => {
let mut comps = self.srcs.get_completions(
&token,
file.text.pos_to_byte(&doc.position),
&doc.text_document.uri,
)?;
comps.items.extend::<Vec<CompletionItem>>(
self.key_comps
.iter()
.filter(|x| x.label.starts_with(&token))
.cloned()
.collect(),
);
Some(comps)
}
}
}
};
// eprintln!("comp response: {}", now.elapsed().as_millis());
Some(CompletionResponse::List(response?))
}
}
/// get the previous non-whitespace character
fn prev_char(text: &Rope, pos: &Position) -> char {
let char_idx = text.pos_to_char(pos);
if char_idx > 0 {
for i in (0..char_idx).rev() {
let res = text.char(i);
if !res.is_whitespace() {
return res;
}
}
' '
} else {
' '
}
}
/// attempt to get the token the user was trying to complete, by
/// filtering out characters unneeded for name resolution
fn get_completion_token(text: &Rope, line: RopeSlice, pos: Position) -> String {
let mut token = String::new();
let mut line_iter = line.chars();
for _ in 0..(line.utf16_cu_to_char(pos.character as usize)) {
line_iter.next();
}
let mut c = line_iter.prev();
//TODO: make this a regex
while c.is_some()
&& (c.unwrap().is_alphanumeric()
|| c.unwrap() == '_'
|| c.unwrap() == '.'
|| c.unwrap() == '['
|| c.unwrap() == ']')
{
token.push(c.unwrap());
c = line_iter.prev();
}
let mut result: String = token.chars().rev().collect();
if result.contains('[') {
let l_bracket_offset = result.find('[').unwrap_or(result.len());
result.replace_range(l_bracket_offset.., "");
}
if &result == "." {
// probably a instantiation, the token should be what we're instatiating
let mut char_iter = text.chars();
let mut token = String::new();
for _ in 0..text.pos_to_char(&pos) {
char_iter.next();
}
let mut c = char_iter.prev();
// go to the last semicolon
while c.is_some() && (c.unwrap() != ';') {
c = char_iter.prev();
}
// go the the start of the next symbol
while c.is_some() && !(c.unwrap().is_alphanumeric() || c.unwrap() == '_') {
c = char_iter.next();
}
// then extract the next symbol
while c.is_some() && (c.unwrap().is_alphanumeric() || c.unwrap() == '_') {
token.push(c.unwrap());
c = char_iter.next();
}
token
} else {
result
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::definition::def_types::Scope;
use crate::definition::get_scopes;
use crate::sources::{parse, LSPSupport};
use crate::support::test_init;
use ropey::Rope;
#[test]
fn test_get_completion_token() {
test_init();
let text = Rope::from_str("abc abc.cba de_fg cde[4]");
let mut result = get_completion_token(
&text,
text.line(0),
Position {
line: 0,
character: 3,
},
);
assert_eq!(&result, "abc");
result = get_completion_token(
&text,
text.line(0),
Position {
line: 0,
character: 11,
},
);
assert_eq!(&result, "abc.cba");
result = get_completion_token(
&text,
text.line(0),
Position {
line: 0,
character: 16,
},
);
assert_eq!(&result, "de_f");
result = get_completion_token(
&text,
text.line(0),
Position {
line: 0,
character: 23,
},
);
assert_eq!(&result, "cde");
}
#[test]
fn test_completion() {
test_init();
let server = LSPServer::new(None);
let uri = Url::parse("file:///test.sv").unwrap();
let text = r#"module test;
logic abc;
logic abcd;
endmodule
"#;
let open_params = DidOpenTextDocumentParams {
text_document: TextDocumentItem {
uri: uri.clone(),
language_id: "systemverilog".to_owned(),
version: 0,
text: text.to_owned(),
},
};
server.did_open(open_params);
let fid = server.srcs.get_id(&uri);
server.srcs.wait_parse_ready(fid, true);
let change_params = DidChangeTextDocumentParams {
text_document: VersionedTextDocumentIdentifier {
uri: uri.clone(),
version: 3,
},
content_changes: vec![
TextDocumentContentChangeEvent {
range: Some(Range {
start: Position {
line: 3,
character: 0,
},
end: Position {
line: 3,
character: 0,
},
}),
range_length: None,
text: "\n".to_owned(),
},
TextDocumentContentChangeEvent {
range: Some(Range {
start: Position {
line: 4,
character: 0,
},
end: Position {
line: 4,
character: 0,
},
}),
range_length: None,
text: " ".to_owned(),
},
TextDocumentContentChangeEvent {
range: Some(Range {
start: Position {
line: 4,
character: 2,
},
end: Position {
line: 4,
character: 2,
},
}),
range_length: None,
text: "a".to_owned(),
},
],
};
server.did_change(change_params);
server.srcs.wait_parse_ready(fid, true);
let completion_params = CompletionParams {
text_document_position: TextDocumentPositionParams {
text_document: TextDocumentIdentifier { uri },
position: Position {
line: 4,
character: 3,
},
},
work_done_progress_params: WorkDoneProgressParams::default(),
partial_result_params: PartialResultParams::default(),
context: Some(CompletionContext {
trigger_kind: CompletionTriggerKind::INVOKED,
trigger_character: None,
}),
};
let response: CompletionResponse = server.completion(completion_params).unwrap();
let item1 = CompletionItem {
label: "abc".to_owned(),
kind: Some(CompletionItemKind::VARIABLE),
detail: Some("logic".to_string()),
..CompletionItem::default()
};
let item2 = CompletionItem {
label: "abcd".to_owned(),
kind: Some(CompletionItemKind::VARIABLE),
detail: Some("logic".to_string()),
..CompletionItem::default()
};
if let CompletionResponse::List(item) = response {
assert!(item.items.contains(&item1));
assert!(item.items.contains(&item2));
} else {
panic!();
}
}
#[test]
fn test_nested_completion() {
test_init();
let server = LSPServer::new(None);
let uri = Url::parse("file:///test.sv").unwrap();
let text = r#"module test;
logic aouter;
function func1();
logic abc;
func1 = abc;
endfunction
function func2();
logic abcd;
func2 = abcd;
endfunction
endmodule
"#;
let open_params = DidOpenTextDocumentParams {
text_document: TextDocumentItem {
uri: uri.clone(),
language_id: "systemverilog".to_owned(),
version: 0,
text: text.to_owned(),
},
};
server.did_open(open_params);
let fid = server.srcs.get_id(&uri);
server.srcs.wait_parse_ready(fid, true);
let change_params = DidChangeTextDocumentParams {
text_document: VersionedTextDocumentIdentifier {
uri: uri.clone(),
version: 3,
},
content_changes: vec![
TextDocumentContentChangeEvent {
range: Some(Range {
start: Position {
line: 4,
character: 0,
},
end: Position {
line: 4,
character: 0,
},
}),
range_length: None,
text: "\n".to_owned(),
},
TextDocumentContentChangeEvent {
range: Some(Range {
start: Position {
line: 4,
character: 0,
},
end: Position {
line: 4,
character: 0,
},
}),
range_length: None,
text: " ".to_owned(),
},
TextDocumentContentChangeEvent {
range: Some(Range {
start: Position {
line: 4,
character: 2,
},
end: Position {
line: 4,
character: 2,
},
}),
range_length: None,
text: "a".to_owned(),
},
],
};
server.did_change(change_params);
server.srcs.wait_parse_ready(fid, true);
let completion_params = CompletionParams {
text_document_position: TextDocumentPositionParams {
text_document: TextDocumentIdentifier { uri },
position: Position {
line: 4,
character: 3,
},
},
work_done_progress_params: WorkDoneProgressParams::default(),
partial_result_params: PartialResultParams::default(),
context: Some(CompletionContext {
trigger_kind: CompletionTriggerKind::INVOKED,
trigger_character: None,
}),
};
let response: CompletionResponse = server.completion(completion_params).unwrap();
let item1 = CompletionItem {
label: "abc".to_owned(),
kind: Some(CompletionItemKind::VARIABLE),
detail: Some("logic".to_string()),
..CompletionItem::default()
};
let item3 = CompletionItem {
label: "aouter".to_owned(),
kind: Some(CompletionItemKind::VARIABLE),
detail: Some("logic".to_string()),
..CompletionItem::default()
};
if let CompletionResponse::List(item) = response {
eprintln!("{:#?}", item);
assert!(item.items.contains(&item1));
for comp in &item.items {
assert!(comp.label != "abcd");
}
assert!(item.items.contains(&item3));
} else {
panic!();
}
}
#[test]
fn test_dot_completion() {
test_init();
let server = LSPServer::new(None);
let uri = Url::parse("file:///test.sv").unwrap();
let text = r#"interface test_inter;
wire abcd;
endinterface
module test(
test_inter abc
);
abc.
test_inter.
endmodule
"#;
let open_params = DidOpenTextDocumentParams {
text_document: TextDocumentItem {
uri: uri.clone(),
language_id: "systemverilog".to_owned(),
version: 0,
text: text.to_owned(),
},
};
server.did_open(open_params);
let fid = server.srcs.get_id(&uri);
server.srcs.wait_parse_ready(fid, true);
let file = server.srcs.get_file(fid).unwrap();
let file = file.read().unwrap();
eprintln!("{}", file.syntax_tree.as_ref().unwrap());
eprintln!(
"{:#?}",
server.srcs.scope_tree.read().unwrap().as_ref().unwrap()
);
let completion_params = CompletionParams {
text_document_position: TextDocumentPositionParams {
text_document: TextDocumentIdentifier { uri: uri.clone() },
position: Position {
line: 6,
character: 8,
},
},
work_done_progress_params: WorkDoneProgressParams::default(),
partial_result_params: PartialResultParams::default(),
context: Some(CompletionContext {
trigger_kind: CompletionTriggerKind::TRIGGER_CHARACTER,
trigger_character: Some(".".to_string()),
}),
};
let response: CompletionResponse = server.completion(completion_params).unwrap();
dbg!(&response);
let item1 = CompletionItem {
label: "abcd".to_owned(),
kind: Some(CompletionItemKind::VARIABLE),
detail: Some("wire".to_string()),
..CompletionItem::default()
};
if let CompletionResponse::List(item) = response {
eprintln!("{:#?}", item);
assert!(item.items.contains(&item1));
assert!(item.items.len() == 1);
} else {
panic!();
}
let completion_params = CompletionParams {
text_document_position: TextDocumentPositionParams {
text_document: TextDocumentIdentifier { uri },
position: Position {
line: 7,
character: 14,
},
},
work_done_progress_params: WorkDoneProgressParams::default(),
partial_result_params: PartialResultParams::default(),
context: Some(CompletionContext {
trigger_kind: CompletionTriggerKind::TRIGGER_CHARACTER,
trigger_character: Some(".".to_string()),
}),
};
let response: CompletionResponse = server.completion(completion_params).unwrap();
if let CompletionResponse::List(item) = response {
eprintln!("{:#?}", item);
assert!(item.items.contains(&item1));
assert!(item.items.len() == 1);
} else {
panic!();
}
}
#[test]
fn test_trigger_dot_nocontext() {
test_init();
let server = LSPServer::new(None);
let uri = Url::parse("file:///test.sv").unwrap();
let text = r#"interface test_inter;
wire abcd;
endinterface
module test(
test_inter abc
);
abc.
test_inter.
endmodule
"#;
let open_params = DidOpenTextDocumentParams {
text_document: TextDocumentItem {
uri: uri.clone(),
language_id: "systemverilog".to_owned(),
version: 0,
text: text.to_owned(),
},
};
server.did_open(open_params);
let fid = server.srcs.get_id(&uri);
server.srcs.wait_parse_ready(fid, true);
let file = server.srcs.get_file(fid).unwrap();
let file = file.read().unwrap();
eprintln!("{}", file.syntax_tree.as_ref().unwrap());
eprintln!(
"{:#?}",
server.srcs.scope_tree.read().unwrap().as_ref().unwrap()
);
let completion_params = CompletionParams {
text_document_position: TextDocumentPositionParams {
text_document: TextDocumentIdentifier { uri: uri.clone() },
position: Position {
line: 6,
character: 8,
},
},
work_done_progress_params: WorkDoneProgressParams::default(),
partial_result_params: PartialResultParams::default(),
context: None,
};
let response: CompletionResponse = server.completion(completion_params).unwrap();
dbg!(&response);
let item1 = CompletionItem {
label: "abcd".to_owned(),
kind: Some(CompletionItemKind::VARIABLE),
detail: Some("wire".to_string()),
..CompletionItem::default()
};
if let CompletionResponse::List(item) = response {
eprintln!("{:#?}", item);
assert!(item.items.contains(&item1));
assert!(item.items.len() == 1);
} else {
panic!();
}
let completion_params = CompletionParams {
text_document_position: TextDocumentPositionParams {
text_document: TextDocumentIdentifier { uri },
position: Position {
line: 7,
character: 14,
},
},
work_done_progress_params: WorkDoneProgressParams::default(),
partial_result_params: PartialResultParams::default(),
context: Some(CompletionContext {
trigger_kind: CompletionTriggerKind::TRIGGER_CHARACTER,
trigger_character: Some(".".to_string()),
}),
};
let response: CompletionResponse = server.completion(completion_params).unwrap();
if let CompletionResponse::List(item) = response {
eprintln!("{:#?}", item);
assert!(item.items.contains(&item1));
assert!(item.items.len() == 1);
} else {
panic!();
}
}
#[test]
fn test_dot_completion_instantiation() {
test_init();
let text = r#"interface test_inter;
wire wrong;
logic clk;
endinterface
module test;
logic clk;
test_inter2 t (
.clk(clk),
.
)
endmodule
interface test_inter2;
wire abcd;
logic clk;
endinterface
"#;
let doc = Rope::from_str(text);
let url = Url::parse("file:///test.sv").unwrap();
let syntax_tree = parse(&doc, &url, &None, &Vec::new()).unwrap();
let scope_tree = get_scopes(&syntax_tree, &url).unwrap();
let pos = Position::new(8, 9);
let token = get_completion_token(&doc, doc.line(pos.line as usize), pos);
let completions = scope_tree.get_dot_completion(
token.trim_end_matches('.'),
doc.pos_to_byte(&pos),
&url,
&scope_tree,
);
let labels: Vec<String> = completions.iter().map(|x| x.label.clone()).collect();
assert_eq!(labels, vec!["abcd", "clk"]);
}
/*
#[test]
fn test_package_completion() {
test_init();
let text = r#"package p;
struct {int x;} s1;
struct {int x;} s2;
function void f();
int x;
endfunction
endpackage
module m;
import p::*;
if (1) begin : s1
initial begin
s1.x = 1;
f.x = 1;
end
int x;
end
endmodule
"#;
let doc = Rope::from_str(&text);
let url = Url::parse("file:///test.sv").unwrap();
let syntax_tree = parse(&doc, &url, &None, &Vec::new()).unwrap();
let scope_tree = get_scopes(&syntax_tree, &url).unwrap();
dbg!(&scope_tree);
/*
let pos = Position::new(8, 9);
let token = get_completion_token(&doc, doc.line(pos.line as usize), pos);
let completions = scope_tree.get_dot_completion(
token.trim_end_matches('.'),
doc.pos_to_byte(&pos),
&url,
&scope_tree,
);
let labels: Vec<String> = completions.iter().map(|x| x.label.clone()).collect();
assert_eq!(labels, vec!["abcd", "clk"]);
*/
panic!();
}
*/
#[test]
fn test_inter_file_completion() {
test_init();
let server = LSPServer::new(None);
let uri = Url::parse("file:///test.sv").unwrap();
let uri2 = Url::parse("file:///test2.sv").unwrap();
let text = r#"module test;
s
endmodule
"#;
let text2 = r#"interface simple_bus;
logic clk;
endinterface"#;
let open_params = DidOpenTextDocumentParams {
text_document: TextDocumentItem {
uri: uri.clone(),
language_id: "systemverilog".to_owned(),
version: 0,
text: text.to_owned(),
},
};
let open_params2 = DidOpenTextDocumentParams {
text_document: TextDocumentItem {
uri: uri2.clone(),
language_id: "systemverilog".to_owned(),
version: 0,
text: text2.to_owned(),
},
};
server.did_open(open_params);
server.did_open(open_params2);
let fid = server.srcs.get_id(&uri);
let fid2 = server.srcs.get_id(&uri2);
server.srcs.wait_parse_ready(fid, true);
server.srcs.wait_parse_ready(fid2, true);
let completion_params = CompletionParams {
text_document_position: TextDocumentPositionParams {
text_document: TextDocumentIdentifier { uri },
position: Position {
line: 1,
character: 5,
},
},
work_done_progress_params: WorkDoneProgressParams::default(),
partial_result_params: PartialResultParams::default(),
context: Some(CompletionContext {
trigger_kind: CompletionTriggerKind::INVOKED,
trigger_character: None,
}),
};
let response: CompletionResponse = server.completion(completion_params).unwrap();
let scope_tree = server.srcs.scope_tree.read().unwrap();
dbg!(scope_tree.as_ref().unwrap());
if let CompletionResponse::List(item) = response {
// eprintln!("{:#?}", item);
let names: Vec<&String> = item.items.iter().map(|x| &x.label).collect();
assert!(names.contains(&&"simple_bus".to_string()));
} else {
panic!();
}
}
}
================================================
FILE: src/definition/def_types.rs
================================================
use crate::sources::LSPSupport;
use log::trace;
use ropey::Rope;
use tower_lsp::lsp_types::*;
/// cleanup the text of a definition so it can be included in completions
pub fn clean_type_str(type_str: &str, ident: &str) -> String {
let endings: &[_] = &[';', ','];
// remove anything after an equals sign
let eq_offset = type_str.find('=').unwrap_or(type_str.len());
let mut result = type_str.to_string();
result.replace_range(eq_offset.., "");
result
.trim_start()
.trim_end()
.trim_end_matches(endings)
.trim_end_matches(ident)
.split_whitespace()
.collect::<Vec<&str>>()
.join(" ")
.replace("[ ", "[")
.replace(" ]", "]")
.replace(" : ", ":")
}
pub fn copy_defs(defs: &[Box<dyn Definition>]) -> Vec<Box<dyn Definition>> {
let mut decs: Vec<Box<dyn Definition>> = Vec::new();
for def in defs {
decs.push(Box::new(GenericDec {
ident: def.ident(),
byte_idx: def.byte_idx(),
url: def.url(),
type_str: def.type_str(),
completion_kind: def.completion_kind(),
symbol_kind: def.symbol_kind(),
def_type: def.def_type(),
}))
}
decs
}
pub fn copy_scopes(scopes: &[Box<dyn Scope>]) -> Vec<Box<dyn Scope>> {
let mut scope_decs: Vec<Box<dyn Scope>> = Vec::new();
for scope in scopes {
let mut scope_copy = GenericScope {
ident: scope.ident(),
byte_idx: scope.byte_idx(),
start: scope.start(),
end: scope.end(),
url: scope.url(),
type_str: scope.type_str(),
completion_kind: scope.completion_kind(),
symbol_kind: scope.symbol_kind(),
def_type: scope.def_type(),
defs: Vec::new(),
scopes: Vec::new(),
};
scope_copy.defs.extend(copy_defs(scope.defs()));
scope_copy.scopes.extend(copy_scopes(scope.scopes()));
scope_decs.push(Box::new(scope_copy))
}
scope_decs
}
/// A definition of any SystemVerilog variable or construct
pub trait Definition: std::fmt::Debug + Sync + Send {
// identifier
fn ident(&self) -> String;
// byte index in file of definition
fn byte_idx(&self) -> usize;
// url pointing to the file the definition is in
fn url(&self) -> Url;
// cleaned up text of the definition
fn type_str(&self) -> String;
// the kind of this definition, for use in completions
fn completion_kind(&self) -> CompletionItemKind;
// the kind of this definition, for use in showing document symbols
// for some reason this kind is different than CompletionItemKind
fn symbol_kind(&self) -> SymbolKind;
// the kind of this definition, simplified for internal use
fn def_type(&self) -> DefinitionType;
// whether the definition identifier starts with the given token
fn starts_with(&self, token: &str) -> bool;
// constructs the completion for this definition
fn completion(&self) -> CompletionItem;
fn dot_completion(&self, scope_tree: &GenericScope) -> Vec<CompletionItem>;
}
pub trait Scope: std::fmt::Debug + Definition + Sync + Send {
// the start byte of this scope
fn start(&self) -> usize;
// the end byte of this scope
fn end(&self) -> usize;
// all the within this scope
fn defs(&self) -> &Vec<Box<dyn Definition>>;
// all the scopes within this scope, ex. task inside a module
fn scopes(&self) -> &Vec<Box<dyn Scope>>;
// the definition of this scope
fn definition(&self) -> GenericDec {
GenericDec {
ident: self.ident(),
byte_idx: self.byte_idx(),
url: self.url(),
type_str: self.type_str(),
completion_kind: self.completion_kind(),
symbol_kind: self.symbol_kind(),
def_type: DefinitionType::GenericScope,
}
}
/// return a completion from the scope tree, this function should be called on the global scope
fn get_completion(&self, token: &str, byte_idx: usize, url: &Url) -> Vec<CompletionItem> {
let mut completions: Vec<CompletionItem> = Vec::new();
// first we need to go down the scope tree, to the scope the user is invoking a completion
// in
for scope in self.scopes() {
if &scope.url() == url && scope.start() <= byte_idx && byte_idx <= scope.end() {
completions = scope.get_completion(token, byte_idx, url);
break;
}
}
// now that we are in the users scope, we can attempt to find a relevant completion
// we proceed back upwards through the scope tree, adding any definitions that match
// the users token
let completion_idents: Vec<String> = completions.iter().map(|x| x.label.clone()).collect();
for def in self.defs() {
if !completion_idents.contains(&def.ident()) && def.starts_with(token) {
completions.push(def.completion());
}
}
for scope in self.scopes() {
if scope.starts_with(token) {
completions.push(scope.completion());
}
}
completions
}
/// return a dot completion from the scope tree, this function should be called on the global
/// scope
fn get_dot_completion(
&self,
token: &str,
byte_idx: usize,
url: &Url,
scope_tree: &GenericScope,
) -> Vec<CompletionItem> {
trace!("dot entering: {}, token: {}", self.ident(), token);
trace!("{:?}", self.scopes());
// first we need to go down the scope tree, to the scope the user is invoking a completion
// in
for scope in self.scopes() {
trace!(
"{}, {}, {}, {}",
scope.ident(),
byte_idx,
scope.start(),
scope.end()
);
if &scope.url() == url && scope.start() <= byte_idx && byte_idx <= scope.end() {
eprintln!("checking dot completion: {}", scope.ident());
let result = scope.get_dot_completion(token, byte_idx, url, scope_tree);
if !result.is_empty() {
return result;
}
}
}
// now that we are in the users scope, we can attempt to find the relevant definition
// we proceed back upwards through the scope tree, and if a definition matches our token,
// we invoke dot completion on that definition and pass it the syntax tree
for def in self.defs() {
trace!("def: {:?}", def);
if def.starts_with(token) {
trace!("complete def: {:?}", def);
return def.dot_completion(scope_tree);
}
}
for scope in self.scopes() {
if scope.starts_with(token) {
trace!("found dot-completion scope: {}", scope.ident());
return scope.dot_completion(scope_tree);
}
}
Vec::new()
}
/// return a definition from the scope tree, this function should be called on the global
/// scope
fn get_definition(&self, token: &str, byte_idx: usize, url: &Url) -> Option<GenericDec> {
let mut definition: Option<GenericDec> = None;
for scope in self.scopes() {
if &scope.url() == url && scope.start() <= byte_idx && byte_idx <= scope.end() {
definition = scope.get_definition(token, byte_idx, url);
break;
}
}
if definition.is_none() {
for def in self.defs() {
if def.ident() == token {
return Some(GenericDec {
ident: def.ident(),
byte_idx: def.byte_idx(),
url: def.url(),
type_str: def.type_str(),
completion_kind: def.completion_kind(),
symbol_kind: def.symbol_kind(),
def_type: DefinitionType::Net,
});
}
}
for scope in self.scopes() {
if scope.ident() == token {
return Some(scope.definition());
}
}
}
definition
}
/// returns all symbols in a document
fn document_symbols(&self, uri: &Url, doc: &Rope) -> Vec<DocumentSymbol> {
let mut symbols: Vec<DocumentSymbol> = Vec::new();
for scope in self.scopes() {
if &scope.url() == uri {
#[allow(deprecated)]
symbols.push(DocumentSymbol {
name: scope.ident(),
detail: Some(scope.type_str()),
kind: scope.symbol_kind(),
deprecated: None,
range: Range::new(doc.byte_to_pos(scope.start()), doc.byte_to_pos(scope.end())),
selection_range: Range::new(
doc.byte_to_pos(scope.byte_idx()),
doc.byte_to_pos(scope.byte_idx() + scope.ident().len()),
),
children: Some(scope.document_symbols(uri, doc)),
tags: None,
})
}
}
for def in self.defs() {
#[allow(deprecated)]
symbols.push(DocumentSymbol {
name: def.ident(),
detail: Some(def.type_str()),
kind: def.symbol_kind(),
deprecated: None,
range: Range::new(
doc.byte_to_pos(def.byte_idx()),
doc.byte_to_pos(def.byte_idx() + def.ident().len()),
),
selection_range: Range::new(
doc.byte_to_pos(def.byte_idx()),
doc.byte_to_pos(def.byte_idx() + def.ident().len()),
),
children: None,
tags: None,
})
}
symbols
}
/// highlight all references of a symbol
fn document_highlights(
&self,
uri: &Url,
doc: &Rope,
// all references in the doc's syntax tree
references: Vec<(String, usize)>,
// byte_idx of symbol definition
byte_idx: usize,
) -> Vec<DocumentHighlight> {
// to find references we need to grab references from locations downward from the
// definition
for scope in self.scopes() {
if &scope.url() == uri && scope.start() <= byte_idx && byte_idx <= scope.end() {
return scope.document_highlights(uri, doc, references, byte_idx);
}
}
// we should now be in the scope of the definition, so we can grab all references
// in this scope. This also grabs references below this scope.
references
.iter()
.filter(|x| self.start() <= x.1 && x.1 <= self.end())
.map(|x| DocumentHighlight {
range: Range::new(doc.byte_to_pos(x.1), doc.byte_to_pos(x.1 + x.0.len())),
kind: None,
})
.collect()
}
}
#[derive(Debug, Clone, Copy)]
pub enum DefinitionType {
Port,
Net,
Data,
Modport,
Subroutine,
ModuleInstantiation,
GenericScope,
Class,
}
#[derive(Debug)]
pub struct PortDec {
pub ident: String,
pub byte_idx: usize,
pub url: Url,
pub type_str: String,
pub completion_kind: CompletionItemKind,
pub symbol_kind: SymbolKind,
pub def_type: DefinitionType,
pub interface: Option<String>,
pub modport: Option<String>,
}
impl PortDec {
pub fn new(url: &Url) -> Self {
Self {
ident: String::new(),
byte_idx: 0,
type_str: String::new(),
completion_kind: CompletionItemKind::PROPERTY,
symbol_kind: SymbolKind::PROPERTY,
def_type: DefinitionType::Port,
interface: None,
modport: None,
url: url.clone(),
}
}
}
impl Definition for PortDec {
fn ident(&self) -> String {
self.ident.clone()
}
fn byte_idx(&self) -> usize {
self.byte_idx
}
fn url(&self) -> Url {
self.url.clone()
}
fn type_str(&self) -> String {
self.type_str.clone()
}
fn completion_kind(&self) -> CompletionItemKind {
self.completion_kind
}
fn symbol_kind(&self) -> SymbolKind {
self.symbol_kind
}
fn def_type(&self) -> DefinitionType {
self.def_type
}
fn starts_with(&self, token: &str) -> bool {
self.ident.starts_with(token)
}
fn completion(&self) -> CompletionItem {
CompletionItem {
label: self.ident.clone(),
detail: Some(clean_type_str(&self.type_str, &self.ident)),
kind: Some(self.completion_kind),
..CompletionItem::default()
}
}
fn dot_completion(&self, scope_tree: &GenericScope) -> Vec<CompletionItem> {
for scope in &scope_tree.scopes {
if let Some(interface) = &self.interface {
if &scope.ident() == interface {
return match &self.modport {
Some(modport) => {
for def in scope.defs() {
if def.starts_with(modport) {
return def.dot_completion(scope_tree);
}
}
Vec::new()
}
None => scope
.defs()
.iter()
.filter(|x| !x.starts_with(&scope.ident()))
.map(|x| x.completion())
.collect(),
};
}
}
}
Vec::new()
}
}
#[derive(Debug)]
pub struct GenericDec {
pub ident: String,
pub byte_idx: usize,
pub url: Url,
pub type_str: String,
pub completion_kind: CompletionItemKind,
pub symbol_kind: SymbolKind,
pub def_type: DefinitionType,
}
impl GenericDec {
pub fn new(url: &Url) -> Self {
Self {
ident: String::new(),
byte_idx: 0,
url: url.clone(),
type_str: String::new(),
completion_kind: CompletionItemKind::VARIABLE,
// FIXME: check if this replacement is correct
symbol_kind: SymbolKind::NULL,
def_type: DefinitionType::Net,
}
}
}
impl Definition for GenericDec {
fn ident(&self) -> String {
self.ident.clone()
}
fn byte_idx(&self) -> usize {
self.byte_idx
}
fn url(&self) -> Url {
self.url.clone()
}
fn type_str(&self) -> String {
self.type_str.clone()
}
fn completion_kind(&self) -> CompletionItemKind {
self.completion_kind
}
fn symbol_kind(&self) -> SymbolKind {
self.symbol_kind
}
fn def_type(&self) -> DefinitionType {
self.def_type
}
fn starts_with(&self, token: &str) -> bool {
self.ident.starts_with(token)
}
fn completion(&self) -> CompletionItem {
CompletionItem {
label: self.ident.clone(),
detail: Some(clean_type_str(&self.type_str, &self.ident)),
kind: Some(self.completion_kind),
..CompletionItem::default()
}
}
fn dot_completion(&self, _: &GenericScope) -> Vec<CompletionItem> {
Vec::new()
}
}
#[derive(Debug)]
pub struct PackageImport {
pub ident: String,
pub byte_idx: usize,
pub url: Url,
pub type_str: String,
pub completion_kind: CompletionItemKind,
pub symbol_kind: SymbolKind,
pub def_type: DefinitionType,
pub asterisk: bool,
pub import_ident: Option<String>,
}
impl PackageImport {
pub fn new(url: &Url) -> Self {
Self {
ident: String::new(),
byte_idx: 0,
url: url.clone(),
type_str: String::new(),
completion_kind: CompletionItemKind::TEXT,
symbol_kind: SymbolKind::NAMESPACE,
def_type: DefinitionType::Data,
asterisk: false,
import_ident: None,
}
}
}
impl Definition for PackageImport {
fn ident(&self) -> String {
self.ident.clone()
}
fn byte_idx(&self) -> usize {
self.byte_idx
}
fn url(&self) -> Url {
self.url.clone()
}
fn type_str(&self) -> String {
self.type_str.clone()
}
fn completion_kind(&self) -> CompletionItemKind {
self.completion_kind
}
fn symbol_kind(&self) -> SymbolKind {
self.symbol_kind
}
fn def_type(&self) -> DefinitionType {
self.def_type
}
fn starts_with(&self, token: &str) -> bool {
self.ident.starts_with(token)
}
fn completion(&self) -> CompletionItem {
CompletionItem {
label: self.ident.clone(),
detail: Some(clean_type_str(&self.type_str, &self.ident.clone())),
kind: Some(self.completion_kind),
..CompletionItem::default()
}
}
fn dot_completion(&self, _: &GenericScope) -> Vec<CompletionItem> {
Vec::new()
}
}
#[derive(Debug)]
pub struct SubDec {
pub ident: String,
pub byte_idx: usize,
pub url: Url,
pub type_str: String,
pub completion_kind: CompletionItemKind,
pub symbol_kind: SymbolKind,
pub def_type: DefinitionType,
pub start: usize,
pub end: usize,
pub defs: Vec<Box<dyn Definition>>,
pub scopes: Vec<Box<dyn Scope>>,
}
impl SubDec {
pub fn new(url: &Url) -> Self {
Self {
ident: String::new(),
byte_idx: 0,
url: url.clone(),
type_str: String::new(),
completion_kind: CompletionItemKind::FUNCTION,
symbol_kind: SymbolKind::FUNCTION,
def_type: DefinitionType::Subroutine,
start: 0,
end: 0,
defs: Vec::new(),
scopes: Vec::new(),
}
}
}
impl Definition for SubDec {
fn ident(&self) -> String {
self.ident.clone()
}
fn byte_idx(&self) -> usize {
self.byte_idx
}
fn url(&self) -> Url {
self.url.clone()
}
fn type_str(&self) -> String {
self.type_str.clone()
}
fn completion_kind(&self) -> CompletionItemKind {
self.completion_kind
}
fn symbol_kind(&self) -> SymbolKind {
self.symbol_kind
}
fn def_type(&self) -> DefinitionType {
self.def_type
}
fn starts_with(&self, token: &str) -> bool {
self.ident.starts_with(token)
}
fn completion(&self) -> CompletionItem {
CompletionItem {
label: self.ident.clone(),
detail: Some(clean_type_str(&self.type_str, &self.ident)),
kind: Some(self.completion_kind),
..CompletionItem::default()
}
}
fn dot_completion(&self, _: &GenericScope) -> Vec<CompletionItem> {
Vec::new()
}
}
impl Scope for SubDec {
fn start(&self) -> usize {
self.start
}
fn end(&self) -> usize {
self.end
}
fn defs(&self) -> &Vec<Box<dyn Definition>> {
&self.defs
}
fn scopes(&self) -> &Vec<Box<dyn Scope>> {
&self.scopes
}
}
#[derive(Debug)]
pub struct ModportDec {
pub ident: String,
pub byte_idx: usize,
pub url: Url,
pub type_str: String,
pub completion_kind: CompletionItemKind,
pub symbol_kind: SymbolKind,
pub def_type: DefinitionType,
pub ports: Vec<Box<dyn Definition>>,
}
impl ModportDec {
pub fn new(url: &Url) -> Self {
Self {
ident: String::new(),
byte_idx: 0,
url: url.clone(),
type_str: String::new(),
completion_kind: CompletionItemKind::INTERFACE,
symbol_kind: SymbolKind::INTERFACE,
def_type: DefinitionType::Modport,
ports: Vec::new(),
}
}
}
impl Definition for ModportDec {
fn ident(&self) -> String {
self.ident.clone()
}
fn byte_idx(&self) -> usize {
self.byte_idx
}
fn url(&self) -> Url {
self.url.clone()
}
fn type_str(&self) -> String {
self.type_str.clone()
}
fn completion_kind(&self) -> CompletionItemKind {
self.completion_kind
}
fn symbol_kind(&self) -> SymbolKind {
self.symbol_kind
}
fn def_type(&self) -> DefinitionType {
self.def_type
}
fn starts_with(&self, token: &str) -> bool {
self.ident.starts_with(token)
}
fn completion(&self) -> CompletionItem {
CompletionItem {
label: self.ident.clone(),
detail: Some(clean_type_str(&self.type_str, &self.ident)),
kind: Some(self.completion_kind),
..CompletionItem::default()
}
}
fn dot_completion(&self, _: &GenericScope) -> Vec<CompletionItem> {
self.ports.iter().map(|x| x.completion()).collect()
}
}
#[derive(Debug)]
pub struct ModInst {
pub ident: String,
pub byte_idx: usize,
pub url: Url,
pub type_str: String,
pub completion_kind: CompletionItemKind,
pub symbol_kind: SymbolKind,
pub def_type: DefinitionType,
pub mod_ident: String,
}
impl ModInst {
pub fn new(url: &Url) -> Self {
Self {
ident: String::new(),
byte_idx: 0,
url: url.clone(),
type_str: String::new(),
completion_kind: CompletionItemKind::MODULE,
symbol_kind: SymbolKind::MODULE,
def_type: DefinitionType::ModuleInstantiation,
mod_ident: String::new(),
}
}
}
impl Definition for ModInst {
fn ident(&self) -> String {
self.ident.clone()
}
fn byte_idx(&self) -> usize {
self.byte_idx
}
fn url(&self) -> Url {
self.url.clone()
}
fn type_str(&self) -> String {
self.type_str.clone()
}
fn completion_kind(&self) -> CompletionItemKind {
self.completion_kind
}
fn symbol_kind(&self) -> SymbolKind {
self.symbol_kind
}
fn def_type(&self) -> DefinitionType {
self.def_type
}
fn starts_with(&self, token: &str) -> bool {
self.ident.starts_with(token)
}
fn completion(&self) -> CompletionItem {
CompletionItem {
label: self.ident.clone(),
detail: Some(clean_type_str(&self.type_str, &self.ident)),
kind: Some(self.completion_kind),
..CompletionItem::default()
}
}
fn dot_completion(&self, scope_tree: &GenericScope) -> Vec<CompletionItem> {
for scope in &scope_tree.scopes {
if scope.ident() == self.mod_ident {
return scope
.defs()
.iter()
.filter(|x| !x.starts_with(&scope.ident()))
.map(|x| x.completion())
.collect();
}
}
Vec::new()
}
}
#[derive(Debug)]
pub struct GenericScope {
pub ident: String,
pub byte_idx: usize,
pub start: usize,
pub end: usize,
pub url: Url,
pub type_str: String,
pub completion_kind: CompletionItemKind,
pub symbol_kind: SymbolKind,
pub def_type: DefinitionType,
pub defs: Vec<Box<dyn Definition>>,
pub scopes: Vec<Box<dyn Scope>>,
}
impl GenericScope {
pub fn new(url: &Url) -> Self {
Self {
ident: String::new(),
byte_idx: 0,
start: 0,
end: 0,
url: url.clone(),
type_str: String::new(),
completion_kind: CompletionItemKind::MODULE,
symbol_kind: SymbolKind::MODULE,
def_type: DefinitionType::GenericScope,
defs: Vec::new(),
scopes: Vec::new(),
}
}
#[cfg(test)]
pub fn contains_scope(&self, scope_ident: &str) -> bool {
for scope in &self.scopes {
if scope.starts_with(scope_ident) {
return true;
}
}
false
}
}
impl Definition for GenericScope {
fn ident(&self) -> String {
self.ident.clone()
}
fn byte_idx(&self) -> usize {
self.byte_idx
}
fn url(&self) -> Url {
self.url.clone()
}
fn type_str(&self) -> String {
self.type_str.clone()
}
fn completion_kind(&self) -> CompletionItemKind {
self.completion_kind
}
fn symbol_kind(&self) -> SymbolKind {
self.symbol_kind
}
fn def_type(&self) -> DefinitionType {
self.def_type
}
fn starts_with(&self, token: &str) -> bool {
self.ident.starts_with(token)
}
fn completion(&self) -> CompletionItem {
CompletionItem {
label: self.ident.clone(),
detail: Some(clean_type_str(&self.type_str, &self.ident)),
kind: Some(self.completion_kind),
..CompletionItem::default()
}
}
fn dot_completion(&self, scope_tree: &GenericScope) -> Vec<CompletionItem> {
for scope in scope_tree.scopes() {
if scope.ident() == self.ident {
return scope
.defs()
.iter()
.filter(|x| !x.starts_with(&scope.ident()))
.map(|x| x.completion())
.collect();
}
}
Vec::new()
}
}
impl Scope for GenericScope {
fn start(&self) -> usize {
self.start
}
fn end(&self) -> usize {
self.end
}
fn defs(&self) -> &Vec<Box<dyn Definition>> {
&self.defs
}
fn scopes(&self) -> &Vec<Box<dyn Scope>> {
&self.scopes
}
}
#[derive(Debug)]
pub struct ClassDec {
pub ident: String,
pub byte_idx: usize,
pub start: usize,
pub end: usize,
pub url: Url,
pub type_str: String,
pub completion_kind: CompletionItemKind,
pub symbol_kind: SymbolKind,
pub def_type: DefinitionType,
pub defs: Vec<Box<dyn Definition>>,
pub scopes: Vec<Box<dyn Scope>>,
// class, package
pub extends: (Vec<String>, Option<String>),
// class, package
pub implements: Vec<(String, Option<String>)>,
}
impl ClassDec {
pub fn new(url: &Url) -> Self {
Self {
ident: String::new(),
byte_idx: 0,
start: 0,
end: 0,
url: url.clone(),
type_str: String::new(),
completion_kind: CompletionItemKind::CLASS,
symbol_kind: SymbolKind::CLASS,
def_type: DefinitionType::Class,
defs: Vec::new(),
scopes: Vec::new(),
extends: (Vec::new(), None),
implements: Vec::new(),
}
}
}
impl Definition for ClassDec {
fn ident(&self) -> String {
self.ident.clone()
}
fn byte_idx(&self) -> usize {
self.byte_idx
}
fn url(&self) -> Url {
self.url.clone()
}
fn type_str(&self) -> String {
self.type_str.clone()
}
fn completion_kind(&self) -> CompletionItemKind {
self.completion_kind
}
fn symbol_kind(&self) -> SymbolKind {
self.symbol_kind
}
fn def_type(&self) -> DefinitionType {
self.def_type
}
fn starts_with(&self, token: &str) -> bool {
self.ident.starts_with(token)
}
fn completion(&self) -> CompletionItem {
CompletionItem {
label: self.ident.clone(),
detail: Some(clean_type_str(&self.type_str, &self.ident)),
kind: Some(self.completion_kind),
..CompletionItem::default()
}
}
fn dot_completion(&self, scope_tree: &GenericScope) -> Vec<CompletionItem> {
for scope in scope_tree.scopes() {
if scope.ident() == self.ident {
return scope
.defs()
.iter()
.filter(|x| !x.starts_with(&scope.ident()))
.map(|x| x.completion())
.collect();
}
}
Vec::new()
}
}
impl Scope for ClassDec {
fn start(&self) -> usize {
self.start
}
fn end(&self) -> usize {
self.end
}
fn defs(&self) -> &Vec<Box<dyn Definition>> {
&self.defs
}
fn scopes(&self) -> &Vec<Box<dyn Scope>> {
&self.scopes
}
}
================================================
FILE: src/definition/extract_defs.rs
================================================
use crate::definition::def_types::*;
use crate::definition::match_definitions;
use sv_parser::*;
use tower_lsp::lsp_types::*;
pub fn get_ident(tree: &SyntaxTree, node: RefNode) -> (String, usize) {
let loc = unwrap_locate!(node).unwrap();
let ident_str = tree.get_str(loc).unwrap().to_string();
let byte_idx = tree.get_origin(loc).unwrap().1;
(ident_str, byte_idx)
}
fn get_loc(tree: &SyntaxTree, node: RefNode) -> usize {
let loc = unwrap_locate!(node).unwrap();
tree.get_origin(loc).unwrap().1
}
macro_rules! advance_until_leave {
($tokens:ident, $tree:ident, $event_iter:ident, $node:path) => {{
let mut result: Option<RefNode> = None;
while let Some(event) = $event_iter.next() {
match event {
NodeEvent::Leave(x) => match x {
$node(node) => {
result = Some($node(node));
break;
}
RefNode::Locate(node) => {
$tokens.push(' ');
$tokens.push_str($tree.get_str(node)?);
}
_ => (),
},
NodeEvent::Enter(_) => (),
}
}
result
}};
}
macro_rules! advance_until_enter {
($tokens:ident, $tree:ident, $event_iter:ident, $node:path, $type:ty) => {{
let mut result: Option<$type> = None;
while let Some(event) = $event_iter.next() {
match event {
NodeEvent::Enter(x) => match x {
$node(node) => {
result = Some(node);
break;
}
RefNode::Locate(node) => {
$tokens.push(' ');
$tokens.push_str($tree.get_str(node)?);
}
_ => (),
},
NodeEvent::Leave(_) => (),
}
}
result
}};
}
macro_rules! skip_until_enter {
($tree:ident, $event_iter:ident, $node:path, $type:ty) => {{
let mut result: Option<$type> = None;
while let Some(event) = $event_iter.next() {
match event {
NodeEvent::Enter(x) => match x {
$node(node) => {
result = Some(node);
break;
}
_ => (),
},
NodeEvent::Leave(_) => (),
}
}
result
}};
}
macro_rules! skip_until_leave {
($tree:ident, $event_iter:ident, $node:path) => {
while let Some(event) = $event_iter.next() {
match event {
NodeEvent::Enter(_) => (),
NodeEvent::Leave(x) => match x {
$node(_) => {
break;
}
_ => (),
},
}
}
};
}
macro_rules! match_until_leave {
($tree:ident, $event_iter:ident, $url:ident, $node:path) => {{
let mut scopes: Vec<Box<dyn Scope>> = Vec::new();
let mut definitions: Vec<Box<dyn Definition>> = Vec::new();
let mut global_scope: GenericScope = GenericScope::new($url);
global_scope.ident = "global".to_string();
while let Some(event) = $event_iter.next() {
match event {
NodeEvent::Enter(node) => {
let mut result = match_definitions($tree, $event_iter, node, $url)?;
definitions.append(&mut result.1);
scopes.append(&mut result.0);
}
NodeEvent::Leave(node) => match node {
$node(_) => {
break;
}
_ => {}
},
}
}
Some((scopes, definitions))
}};
}
pub fn port_dec_ansi(
tree: &SyntaxTree,
node: &AnsiPortDeclaration,
event_iter: &mut EventIter,
url: &Url,
) -> Option<PortDec> {
let mut port = PortDec::new(url);
let mut tokens = String::new();
match node {
AnsiPortDeclaration::Net(x) => {
let ident = get_ident(tree, RefNode::PortIdentifier(&x.nodes.1));
port.ident = ident.0;
port.byte_idx = ident.1;
if let Some(NetPortHeaderOrInterfacePortHeader::InterfacePortHeader(z)) = &x.nodes.0 {
match &**z {
InterfacePortHeader::Identifier(node) => {
port.interface =
Some(get_ident(tree, RefNode::InterfaceIdentifier(&node.nodes.0)).0);
if let Some((_, mod_ident)) = &node.nodes.1 {
port.modport =
Some(get_ident(tree, RefNode::ModportIdentifier(mod_ident)).0);
}
}
InterfacePortHeader::Interface(node) => {
port.interface = Some("interface".to_string());
if let Some((_, mod_ident)) = &node.nodes.1 {
port.modport =
Some(get_ident(tree, RefNode::ModportIdentifier(mod_ident)).0);
}
}
}
}
}
AnsiPortDeclaration::Variable(x) => {
let ident = get_ident(tree, RefNode::PortIdentifier(&x.nodes.1));
port.ident = ident.0;
port.byte_idx = ident.1;
}
AnsiPortDeclaration::Paren(x) => {
let ident = get_ident(tree, RefNode::PortIdentifier(&x.nodes.2));
port.ident = ident.0;
port.byte_idx = ident.1;
}
}
advance_until_leave!(tokens, tree, event_iter, RefNode::AnsiPortDeclaration);
port.type_str = clean_type_str(&tokens, &port.ident);
Some(port)
}
pub fn list_port_idents(
tree: &SyntaxTree,
node: &ListOfPortIdentifiers,
event_iter: &mut EventIter,
url: &Url,
) -> Option<Vec<PortDec>> {
let mut ports: Vec<PortDec> = Vec::new();
for port_def in node.nodes.0.contents() {
let mut port = PortDec::new(url);
let ident = get_ident(tree, RefNode::PortIdentifier(&port_def.0));
port.ident = ident.0;
port.byte_idx = ident.1;
for _ in &port_def.1 {
let tokens = &mut port.type_str;
advance_until_leave!(tokens, tree, event_iter, RefNode::UnpackedDimension);
}
ports.push(port);
}
Some(ports)
}
pub fn list_interface_idents(
tree: &SyntaxTree,
node: &ListOfInterfaceIdentifiers,
event_iter: &mut EventIter,
url: &Url,
) -> Option<Vec<PortDec>> {
let mut ports: Vec<PortDec> = Vec::new();
for port_def in node.nodes.0.contents() {
let mut port = PortDec::new(url);
let ident = get_ident(tree, RefNode::InterfaceIdentifier(&port_def.0));
port.ident = ident.0;
port.byte_idx = ident.1;
for _ in &port_def.1 {
let tokens = &mut port.type_str;
advance_until_leave!(tokens, tree, event_iter, RefNode::UnpackedDimension);
}
ports.push(port);
}
Some(ports)
}
pub fn list_variable_idents(
tree: &SyntaxTree,
node: &ListOfVariableIdentifiers,
event_iter: &mut EventIter,
url: &Url,
) -> Option<Vec<PortDec>> {
let mut ports: Vec<PortDec> = Vec::new();
for port_def in node.nodes.0.contents() {
let mut port = PortDec::new(url);
let ident = get_ident(tree, RefNode::VariableIdentifier(&port_def.0));
port.ident = ident.0;
port.byte_idx = ident.1;
for _ in &port_def.1 {
let tokens = &mut port.type_str;
advance_until_leave!(tokens, tree, event_iter, RefNode::VariableDimension);
}
ports.push(port);
}
Some(ports)
}
pub fn port_dec_non_ansi(
tree: &SyntaxTree,
node: &PortDeclaration,
event_iter: &mut EventIter,
url: &Url,
) -> Option<Vec<PortDec>> {
let mut ports: Vec<PortDec>;
let mut common = String::new();
match node {
PortDeclaration::Inout(_) => {
let port_list = advance_until_enter!(
common,
tree,
event_iter,
RefNode::ListOfPortIdentifiers,
&ListOfPortIdentifiers
)?;
ports = list_port_idents(tree, port_list, event_iter, url)?;
}
PortDeclaration::Input(x) => match &x.nodes.1 {
InputDeclaration::Net(_) => {
let port_list = advance_until_enter!(
common,
tree,
event_iter,
RefNode::ListOfPortIdentifiers,
&ListOfPortIdentifiers
)?;
ports = list_port_idents(tree, port_list, event_iter, url)?;
}
InputDeclaration::Variable(_) => {
let port_list = advance_until_enter!(
common,
tree,
event_iter,
RefNode::ListOfVariableIdentifiers,
&ListOfVariableIdentifiers
)?;
ports = list_variable_idents(tree, port_list, event_iter, url)?;
}
},
PortDeclaration::Output(x) => match &x.nodes.1 {
OutputDeclaration::Net(_) => {
let port_list = advance_until_enter!(
common,
tree,
event_iter,
RefNode::ListOfPortIdentifiers,
&ListOfPortIdentifiers
)?;
ports = list_port_idents(tree, port_list, event_iter, url)?;
}
OutputDeclaration::Variable(_) => {
let port_list = advance_until_enter!(
common,
tree,
event_iter,
RefNode::ListOfVariableIdentifiers,
&ListOfVariableIdentifiers
)?;
ports = list_variable_idents(tree, port_list, event_iter, url)?;
}
},
PortDeclaration::Ref(_) => {
let port_list = advance_until_enter!(
common,
tree,
event_iter,
RefNode::ListOfVariableIdentifiers,
&ListOfVariableIdentifiers
)?;
ports = list_variable_idents(tree, port_list, event_iter, url)?;
}
PortDeclaration::Interface(x) => {
let interface =
Some(get_ident(tree, RefNode::InterfaceIdentifier(&x.nodes.1.nodes.0)).0);
let modport = x
.nodes
.1
.nodes
.1
.as_ref()
.map(|(_, mod_ident)| get_ident(tree, RefNode::ModportIdentifier(mod_ident)).0);
let port_list = advance_until_enter!(
common,
tree,
event_iter,
RefNode::ListOfInterfaceIdentifiers,
&ListOfInterfaceIdentifiers
)?;
ports = list_interface_idents(tree, port_list, event_iter, url)?;
for port in &mut ports {
port.interface = interface.clone();
port.modport = modport.clone();
}
}
}
for port in &mut ports {
port.type_str = format!("{} {}", common, port.type_str);
}
Some(ports)
}
pub fn list_net_decl(
tree: &SyntaxTree,
node: &ListOfNetDeclAssignments,
event_iter: &mut EventIter,
url: &Url,
) -> Option<Vec<GenericDec>> {
let mut nets: Vec<GenericDec> = Vec::new();
for net_def in node.nodes.0.contents() {
let mut net = GenericDec::new(url);
let ident = get_ident(tree, RefNode::NetIdentifier(&net_def.nodes.0));
net.ident = ident.0;
net.byte_idx = ident.1;
for _ in &net_def.nodes.1 {
let tokens = &mut net.type_str;
advance_until_leave!(tokens, tree, event_iter, RefNode::UnpackedDimension);
}
nets.push(net);
}
Some(nets)
}
pub fn net_dec(
tree: &SyntaxTree,
node: &NetDeclaration,
event_iter: &mut EventIter,
url: &Url,
) -> Option<Vec<GenericDec>> {
let mut nets: Vec<GenericDec>;
let mut common = String::new();
match node {
NetDeclaration::NetType(_) => {
let net_list = advance_until_enter!(
common,
tree,
event_iter,
RefNode::ListOfNetDeclAssignments,
&ListOfNetDeclAssignments
)?;
nets = list_net_decl(tree, net_list, event_iter, url)?;
}
NetDeclaration::NetTypeIdentifier(_) => {
let net_list = advance_until_enter!(
common,
tree,
event_iter,
RefNode::ListOfNetDeclAssignments,
&ListOfNetDeclAssignments
)?;
nets = list_net_decl(tree, net_list, event_iter, url)?;
}
NetDeclaration::Interconnect(x) => {
let mut net = GenericDec::new(url);
let ident = get_ident(tree, RefNode::NetIdentifier(&x.nodes.3));
net.ident = ident.0;
net.byte_idx = ident.1;
advance_until_enter!(
common,
tree,
event_iter,
RefNode::NetIdentifier,
&NetIdentifier
);
for _ in &x.nodes.4 {
advance_until_leave!(common, tree, event_iter, RefNode::UnpackedDimension);
}
nets = vec![net];
}
}
for net in &mut nets {
net.completion_kind = CompletionItemKind::VARIABLE;
net.symbol_kind = SymbolKind::VARIABLE;
net.type_str = format!("{} {}", common, net.type_str);
}
Some(nets)
}
pub fn list_var_decl(
tree: &SyntaxTree,
node: &ListOfVariableDeclAssignments,
event_iter: &mut EventIter,
url: &Url,
) -> Option<Vec<GenericDec>> {
let mut vars: Vec<GenericDec> = Vec::new();
for var_def in node.nodes.0.contents() {
let mut var = GenericDec::new(url);
match &var_def {
VariableDeclAssignment::Variable(node) => {
let ident = get_ident(tree, RefNode::VariableIdentifier(&node.nodes.0));
var.ident = ident.0;
var.byte_idx = ident.1;
for _ in &node.nodes.1 {
let tokens = &mut var.type_str;
advance_until_leave!(tokens, tree, event_iter, RefNode::VariableDimension);
}
}
VariableDeclAssignment::DynamicArray(node) => {
let ident = get_ident(tree, RefNode::DynamicArrayVariableIdentifier(&node.nodes.0));
var.ident = ident.0;
var.byte_idx = ident.1;
for _ in &node.nodes.2 {
let tokens = &mut var.type_str;
advance_until_leave!(tokens, tree, event_iter, RefNode::VariableDimension);
}
}
VariableDeclAssignment::Class(node) => {
let ident = get_ident(tree, RefNode::ClassVariableIdentifier(&node.nodes.0));
var.ident = ident.0;
var.byte_idx = ident.1;
}
}
vars.push(var);
}
Some(vars)
}
pub fn package_import(
tree: &SyntaxTree,
node: &PackageImportDeclaration,
_: &mut EventIter,
url: &Url,
) -> Option<Vec<PackageImport>> {
let mut imports = Vec::new();
for import_def in node.nodes.1.contents() {
let mut import = PackageImport::new(url);
match import_def {
PackageImportItem::Identifier(y) => {
let ident = get_ident(tree, RefNode::PackageIdentifier(&y.nodes.0));
import.ident = ident.0;
import.byte_idx = ident.1;
let import_loc = match &y.nodes.2 {
Identifier::SimpleIdentifier(id) => id.nodes.0,
Identifier::EscapedIdentifier(id) => id.nodes.0,
};
import.import_ident = Some(tree.get_str(&import_loc)?.to_string());
}
PackageImportItem::Asterisk(y) => {
let ident = get_ident(tree, RefNode::PackageIdentifier(&y.nodes.0));
import.ident = ident.0;
import.byte_idx = ident.1;
import.asterisk = true;
}
}
imports.push(import);
}
Some(imports)
}
fn struct_union(
tree: &SyntaxTree,
node: &DataTypeStructUnion,
event_iter: &mut EventIter,
url: &Url,
) -> Option<GenericScope> {
let mut scope = GenericScope::new(url);
scope.start = get_loc(tree, RefNode::StructUnion(&node.nodes.0));
scope.end = get_loc(tree, RefNode::Symbol(&node.nodes.2.nodes.2));
scope.completion_kind = CompletionItemKind::STRUCT;
scope.symbol_kind = SymbolKind::STRUCT;
let type_str = &mut scope.type_str;
advance_until_leave!(type_str, tree, event_iter, RefNode::Symbol)?;
let mut members = vec![&(node.nodes.2.nodes.1).0];
for member_def in &(node.nodes.2.nodes.1).1 {
members.push(member_def);
}
for member_def in members {
match member_def.nodes.2 {
DataTypeOrVoid::DataType(_) => {
let mut common = String::new();
let datatype =
advance_until_enter!(common, tree, event_iter, RefNode::DataType, &DataType)?;
let dec = data_type(tree, datatype, event_iter, url)?;
match dec {
Declaration::Dec(x) => {
let var_list = advance_until_enter!(
common,
tree,
event_iter,
RefNode::ListOfVariableDeclAssignments,
&ListOfVariableDeclAssignments
)?;
let mut decs = list_var_decl(tree, var_list, event_iter, url)?;
advance_until_leave!(common, tree, event_iter, RefNode::StructUnionMember);
for var in &mut decs {
var.type_str = format!("{} {} {}", common, x.type_str, var.type_str);
var.completion_kind = CompletionItemKind::VARIABLE;
var.symbol_kind = SymbolKind::VARIABLE;
}
for var in decs {
scope.defs.push(Box::new(var));
}
}
Declaration::Scope(x) => {
let var_list = advance_until_enter!(
common,
tree,
event_iter,
RefNode::ListOfVariableDeclAssignments,
&ListOfVariableDeclAssignments
)?;
let mut decs = list_var_decl(tree, var_list, event_iter, url)?;
advance_until_leave!(common, tree, event_iter, RefNode::StructUnionMember);
for var in &mut decs {
var.type_str = format!("{} {} {}", common, x.type_str, var.type_str);
var.completion_kind = CompletionItemKind::VARIABLE;
var.symbol_kind = SymbolKind::VARIABLE;
}
for var in decs {
let mut member_scope = GenericScope::new(url);
member_scope.start = x.start;
member_scope.end = x.end;
member_scope.defs = copy_defs(&x.defs);
member_scope.scopes = copy_scopes(&x.scopes);
member_scope.ident = var.ident;
member_scope.byte_idx = var.byte_idx;
scope.scopes.push(Box::new(member_scope));
}
}
Declaration::Import(_) => {
// datatype should not return import
unreachable!()
}
}
}
DataTypeOrVoid::Void(_) => {
let mut common = String::new();
let var_list = advance_until_enter!(
common,
tree,
event_iter,
RefNode::ListOfVariableDeclAssignments,
&ListOfVariableDeclAssignments
)?;
let mut decs = list_var_decl(tree, var_list, event_iter, url)?;
advance_until_leave!(common, tree, event_iter, RefNode::StructUnionMember);
for var in &mut decs {
var.type_str = format!("{} {}", common, var.type_str);
var.completion_kind = CompletionItemKind::VARIABLE;
var.symbol_kind = SymbolKind::VARIABLE;
}
for var in decs {
scope.defs.push(Box::new(var));
}
}
}
}
skip_until_leave!(tree, event_iter, RefNode::DataTypeStructUnion);
Some(scope)
}
pub enum Declaration {
Dec(GenericDec),
Scope(GenericScope),
Import(PackageImport),
}
// this isn't enough for a definition
fn data_type(
tree: &SyntaxTree,
node: &DataType,
event_iter: &mut EventIter,
url: &Url,
) -> Option<Declaration> {
let mut common = String::new();
match node {
DataType::Vector(_)
| DataType::Atom(_)
| DataType::NonIntegerType(_)
// TODO: set completion_kind and symbol_kind for string and others
| DataType::String(_)
| DataType::Chandle(_)
// TODO: properly handle the following types
| DataType::Virtual(_)
| DataType::Type(_)
| DataType::ClassType(_)
| DataType::Event(_)
| DataType::PsCovergroupIdentifier(_) => {
advance_until_leave!(common, tree, event_iter, RefNode::DataType)?;
let mut dec = GenericDec::new(url);
dec.type_str = common;
Some(Declaration::Dec(dec))
}
DataType::StructUnion(_) => {
let struct_union_def = advance_until_enter!(
common,
tree,
event_iter,
RefNode::DataTypeStructUnion,
&DataTypeStructUnion
)?;
let def = struct_union(
tree,
struct_union_def,
event_iter,
url,
)?;
advance_until_leave!(common, tree, event_iter, RefNode::DataType)?;
Some(Declaration::Scope(def))
}
DataType::Enum(node) => {
let mut scope = GenericScope::new(url);
scope.start = get_loc(tree, RefNode::Symbol(&node.nodes.2.nodes.0));
scope.end = get_loc(tree, RefNode::Symbol(&node.nodes.2.nodes.2));
scope.completion_kind = CompletionItemKind::ENUM;
scope.symbol_kind = SymbolKind::ENUM;
let mut decs: Vec<GenericDec> = Vec::new();
for emem in node.nodes.2.nodes.1.contents() {
let mut dec = GenericDec::new(url);
let ident = get_ident(tree, RefNode::EnumIdentifier(&emem.nodes.0));
dec.ident = ident.0;
dec.byte_idx = ident.1;
dec.completion_kind = CompletionItemKind::ENUM_MEMBER;
dec.symbol_kind = SymbolKind::ENUM_MEMBER;
let tokens = &mut dec.type_str;
advance_until_leave!(tokens, tree, event_iter, RefNode::EnumNameDeclaration);
decs.push(dec);
}
advance_until_leave!(common, tree, event_iter, RefNode::DataType)?;
Some(Declaration::Scope(scope))
}
DataType::TypeReference(node) => {
match **node{
TypeReference::Expression(_) => {
advance_until_leave!(common, tree, event_iter, RefNode::DataType)?;
let mut dec = GenericDec::new(url);
dec.type_str = common;
Some(Declaration::Dec(dec))
}
TypeReference::DataType(_) => {
let data_type_node = advance_until_enter!(common, tree, event_iter, RefNode::DataType, &DataType)?;
let data_type_def = data_type(tree, data_type_node, event_iter, url);
advance_until_leave!(common, tree, event_iter, RefNode::DataType)?;
data_type_def
}
}
}
}
}
pub fn data_dec(
tree: &SyntaxTree,
node: &DataDeclaration,
event_iter: &mut EventIter,
url: &Url,
) -> Option<Vec<Declaration>> {
let mut common = String::new();
let mut data: Vec<Declaration> = Vec::new();
match node {
DataDeclaration::Variable(x) => match &x.nodes.3 {
DataTypeOrImplicit::DataType(_) => {
let mut common = String::new();
let datatype =
advance_until_enter!(common, tree, event_iter, RefNode::DataType, &DataType)?;
let dec = data_type(tree, datatype, event_iter, url)?;
match dec {
Declaration::Dec(x) => {
let var_list = advance_until_enter!(
common,
tree,
event_iter,
RefNode::ListOfVariableDeclAssignments,
&ListOfVariableDeclAssignments
)?;
let mut decs = list_var_decl(tree, var_list, event_iter, url)?;
for var in &mut decs {
var.type_str = format!("{} {} {}", common, x.type_str, var.type_str);
var.completion_kind = CompletionItemKind::VARIABLE;
var.symbol_kind = SymbolKind::VARIABLE;
}
for var in decs {
data.push(Declaration::Dec(var));
}
}
Declaration::Scope(x) => {
let var_list = advance_until_enter!(
common,
tree,
event_iter,
RefNode::ListOfVariableDeclAssignments,
&ListOfVariableDeclAssignments
)?;
let mut decs = list_var_decl(tree, var_list, event_iter, url)?;
for var in &mut decs {
var.type_str = format!("{} {} {}", common, x.type_str, var.type_str);
var.completion_kind = CompletionItemKind::VARIABLE;
var.symbol_kind = SymbolKind::VARIABLE;
}
for var in decs {
data.push(Declaration::Scope(GenericScope {
ident: var.ident,
byte_idx: var.byte_idx,
start: x.start,
end: x.end,
url: url.clone(),
type_str: var.type_str,
completion_kind: x.completion_kind,
symbol_kind: x.symbol_kind,
def_type: x.def_type,
defs: copy_defs(&x.defs),
scopes: copy_scopes(&x.scopes),
}));
}
}
Declaration::Import(_) => {
// datatype should not return import
unreachable!()
}
}
}
DataTypeOrImplicit::ImplicitDataType(_) => {
let var_list = advance_until_enter!(
common,
tree,
event_iter,
RefNode::ListOfVariableDeclAssignments,
&ListOfVariableDeclAssignments
)?;
let mut decs = list_var_decl(tree, var_list, event_iter, url)?;
data = Vec::new();
for var in &mut decs {
var.type_str = format!("{} {}", common, var.type_str);
var.completion_kind = CompletionItemKind::VARIABLE;
var.symbol_kind = SymbolKind::VARIABLE;
}
for var in decs {
data.push(Declaration::Dec(var));
}
}
},
DataDeclaration::TypeDeclaration(x) => match &**x {
TypeDeclaration::DataType(y) => {
let mut common = String::new();
let datatype =
advance_until_enter!(common, tree, event_iter, RefNode::DataType, &DataType)?;
let dec = data_type(tree, datatype, event_iter, url)?;
match dec {
Declaration::Dec(mut def) => {
let ident = get_ident(tree, RefNode::TypeIdentifier(&y.nodes.2));
def.ident = ident.0;
def.byte_idx = ident.1;
for _ in &y.nodes.3 {
let tokens = &mut def.type_str;
advance_until_leave!(
tokens,
tree,
event_iter,
RefNode::VariableDimension
);
}
def.type_str = format!("{} {}", common, def.type_str);
data = vec![Declaration::Dec(def)];
}
Declaration::Scope(mut def) => {
let ident = get_ident(tree, RefNode::TypeIdentifier(&y.nodes.2));
def.ident = ident.0;
def.byte_idx = ident.1;
for _ in &y.nodes.3 {
let tokens = &mut def.type_str;
advance_until_leave!(
tokens,
tree,
event_iter,
RefNode::VariableDimension
);
}
def.type_str = format!("{} {}", common, def.type_str);
data = vec![Declaration::Scope(def)];
}
Declaration::Import(_) => unreachable!(),
}
}
TypeDeclaration::Interface(y) => {
let mut var = GenericDec::new(url);
let ident = get_ident(tree, RefNode::TypeIdentifier(&y.nodes.5));
var.ident = ident.0;
var.byte_idx = ident.1;
let mut tokens = String::new();
advance_until_enter!(
tokens,
tree,
event_iter,
RefNode::TypeIdentifier,
&TypeIdentifier
);
advance_until_enter!(
tokens,
tree,
event_iter,
RefNode::TypeIdentifier,
&TypeIdentifier
);
var.type_str = tokens;
var.type_str = format!("{} {}", common, var.type_str);
var.completion_kind = CompletionItemKind::INTERFACE;
var.symbol_kind = SymbolKind::INTERFACE;
data = vec![Declaration::Dec(var)];
}
TypeDeclaration::Reserved(y) => {
let mut var = GenericDec::new(url);
let ident = get_ident(tree, RefNode::TypeIdentifier(&y.nodes.2));
var.ident = ident.0;
var.byte_idx = ident.1;
let mut tokens = String::new();
advance_until_enter!(
tokens,
tree,
event_iter,
RefNode::TypeIdentifier,
&TypeIdentifier
);
var.type_str = tokens;
var.type_str = format!("{} {}", common, var.type_str);
var.completion_kind = CompletionItemKind::VARIABLE;
var.symbol_kind = SymbolKind::VARIABLE;
data = vec![Declaration::Dec(var)];
}
},
DataDeclaration::PackageImportDeclaration(x) => {
data = Vec::new();
let imports = package_import(tree, x, event_iter, url)?;
for import in imports {
data.push(Declaration::Import(import));
}
}
DataDeclaration::NetTypeDeclaration(x) => match &**x {
NetTypeDeclaration::DataType(y) => {
let mut common = String::new();
let datatype =
advance_until_enter!(common, tree, event_iter, RefNode::DataType, &DataType)?;
let dec = data_type(tree, datatype, event_iter, url)?;
match dec {
Declaration::Dec(mut def) => {
let ident = get_ident(tree, RefNode::NetTypeIdentifier(&y.nodes.2));
def.ident = ident.0;
def.byte_idx = ident.1;
let mut tokens = String::new();
advance_until_enter!(
tokens,
tree,
event_iter,
RefNode::NetTypeIdentifier,
&NetTypeIdentifier
);
def.type_str = tokens;
def.type_str = format!("{} {}", common, def.type_str);
data = vec![Declaration::Dec(def)];
}
Declaration::Scope(mut def) => {
let ident = get_ident(tree, RefNode::NetTypeIdentifier(&y.nodes.2));
def.ident = ident.0;
def.byte_idx = ident.1;
let mut tokens = String::new();
advance_until_enter!(
tokens,
tree,
event_iter,
RefNode::NetTypeIdentifier,
&NetTypeIdentifier
);
def.type_str = tokens;
def.type_str = format!("{} {}", common, def.type_str);
data = vec![Declaration::Scope(def)];
}
Declaration::Import(_) => unreachable!(),
}
}
NetTypeDeclaration::NetType(y) => {
let mut var = GenericDec::new(url);
let ident = get_ident(tree, RefNode::NetTypeIdentifier(&y.nodes.2));
var.ident = ident.0;
var.byte_idx = ident.1;
let mut tokens = String::new();
advance_until_leave!(tokens, tree, event_iter, RefNode::NetTypeIdentifier);
var.type_str = tokens;
var.type_str = format!("{} {}", common, var.type_str);
var.completion_kind = CompletionItemKind::VARIABLE;
var.symbol_kind = SymbolKind::VARIABLE;
data = vec![Declaration::Dec(var)];
}
},
}
Some(data)
}
pub fn tfport_list(
tree: &SyntaxTree,
node: &TfPortList,
event_iter: &mut EventIter,
url: &Url,
) -> Option<Vec<PortDec>> {
let mut tfports: Vec<PortDec> = Vec::new();
for tfports_def in node.nodes.0.contents() {
if let Some(def) = &tfports_def.nodes.4 {
let mut tfport = PortDec::new(url);
let ident = get_ident(tree, RefNode::PortIdentifier(&def.0));
tfport.ident = ident.0;
tfport.byte_idx = ident.1;
for _ in &def.1 {
let tokens = &mut tfport.type_str;
advance_until_leave!(tokens, tree, event_iter, RefNode::UnpackedDimension);
}
tfports.push(tfport);
}
}
Some(tfports)
}
pub fn function_dec(
tree: &SyntaxTree,
node: &FunctionDeclaration,
event_iter: &mut EventIter,
url: &Url,
) -> Option<SubDec> {
let mut func: SubDec = SubDec::new(url);
func.start = get_loc(tree, RefNode::Keyword(&node.nodes.0));
match &node.nodes.2 {
FunctionBodyDeclaration::WithoutPort(x) => {
func.end = get_loc(tree, RefNode::Keyword(&x.nodes.6));
let ident = get_ident(tree, RefNode::FunctionIdentifier(&x.nodes.2));
func.ident = ident.0;
func.byte_idx = ident.1;
let mut tokens = String::new();
advance_until_enter!(
tokens,
tree,
event_iter,
RefNode::FunctionIdentifier,
&FunctionIdentifier
);
func.type_str = tokens;
}
FunctionBodyDeclaration::WithPort(x) => {
func.end = get_loc(tree, RefNode::Keyword(&x.nodes.7));
let ident = get_ident(tree, RefNode::FunctionIdentifier(&x.nodes.2));
func.ident = ident.0;
func.byte_idx = ident.1;
let mut tokens = String::new();
advance_until_enter!(
tokens,
tree,
event_iter,
RefNode::FunctionIdentifier,
&FunctionIdentifier
);
func.type_str = tokens;
if let Some(tfports) = &x.nodes.3.nodes.1 {
skip_until_enter!(tree, event_iter, RefNode::TfPortList, &TfPortList);
let ports = tfport_list(tree, tfports, event_iter, url)?;
for port in ports {
func.defs.push(Box::new(port));
}
}
}
}
let (scopes, mut defs) =
match_until_leave!(tree, event_iter, url, RefNode::FunctionDeclaration)?;
func.scopes = scopes;
func.defs.append(&mut defs);
Some(func)
}
pub fn task_dec(
tree: &SyntaxTree,
node: &TaskDeclaration,
event_iter: &mut EventIter,
url: &Url,
) -> Option<SubDec> {
let mut task = SubDec::new(url);
task.start = get_loc(tree, RefNode::Keyword(&node.nodes.0));
match &node.nodes.2 {
TaskBodyDeclaration::WithoutPort(x) => {
task.end = get_loc(tree, RefNode::Keyword(&x.nodes.5));
let ident = get_ident(tree, RefNode::TaskIdentifier(&x.nodes.1));
task.ident = ident.0;
task.byte_idx = ident.1;
let mut tokens = String::new();
advance_until_enter!(
tokens,
tree,
event_iter,
RefNode::TaskIdentifier,
&TaskIdentifier
);
task.type_str = tokens;
}
TaskBodyDeclaration::WithPort(x) => {
task.end = get_loc(tree, RefNode::Keyword(&x.nodes.6));
let mut task = SubDec::new(url);
let ident = get_ident(tree, RefNode::TaskIdentifier(&x.nodes.1));
task.ident = ident.0;
task.byte_idx = ident.1;
let mut tokens = String::new();
advance_until_enter!(
tokens,
tree,
event_iter,
RefNode::TaskIdentifier,
&TaskIdentifier
);
task.type_str = tokens;
if let Some(tfports) = &x.nodes.2.nodes.1 {
skip_until_enter!(tree, event_iter, RefNode::TfPortList, &TfPortList);
let ports = tfport_list(tree, tfports, event_iter, url)?;
for port in ports {
task.defs.push(Box::new(port));
}
}
}
}
let (scopes, mut defs) = match_until_leave!(tree, event_iter, url, RefNode::TaskDeclaration)?;
task.scopes = scopes;
task.defs.append(&mut defs);
Some(task)
}
pub fn modport_dec(
tree: &SyntaxTree,
node: &ModportDeclaration,
event_iter: &mut EventIter,
url: &Url,
) -> Option<Vec<ModportDec>> {
let mut modports: Vec<ModportDec> = Vec::new();
let mut common = String::new();
advance_until_enter!(common, tree, event_iter, RefNode::ModportItem, &ModportItem);
for modport_def in node.nodes.1.contents() {
let mut modport = ModportDec::new(url);
let ident = get_ident(tree, RefNode::ModportIdentifier(&modport_def.nodes.0));
modport.ident = ident.0;
modport.byte_idx = ident.1;
modport.type_str = common.clone();
for mp_port_dec in modport_def.nodes.1.nodes.1.contents() {
match mp_port_dec {
ModportPortsDeclaration::Simple(x) => {
skip_until_enter!(
tree,
event_iter,
RefNode::ModportPortsDeclarationSimple,
&ModportPortsDeclarationSimple
);
let mut prepend = String::new();
advance_until_enter!(
prepend,
tree,
event_iter,
RefNode::ModportSimplePort,
&ModportSimplePort
);
for mp_simple_def in x.nodes.1.nodes.1.contents() {
match mp_simple_def {
ModportSimplePort::Ordered(y) => {
let mut port = PortDec::new(url);
let ident = get_ident(tree, RefNode::PortIdentifier(&y.nodes.0));
port.ident = ident.0;
port.byte_idx = ident.1;
port.type_str = prepend.clone();
modport.ports.push(Box::new(port));
}
ModportSimplePort::Named(_) => {
let port_ident = skip_until_enter!(
tree,
event_iter,
RefNode::PortIdentifier,
&PortIdentifier
)?;
let mut port = PortDec::new(url);
let ident = get_ident(tree, RefNode::PortIdentifier(port_ident));
port.ident = ident.0;
port.byte_idx = ident.1;
let mut append = String::new();
advance_until_leave!(
append,
tree,
event_iter,
RefNode::ModportSimplePortNamed
);
port.type_str = format!("{} {}", prepend, append);
modport.ports.push(Box::new(port));
}
}
}
}
ModportPortsDeclaration::Tf(_) => {
skip_until_enter!(
tree,
event_iter,
RefNode::ModportPortsDeclarationTf,
&ModportPortsDeclarationTf
);
let mut prepend = String::new();
let mp_tf_ports_dec = advance_until_enter!(
prepend,
tree,
event_iter,
RefNode::ModportTfPortsDeclaration,
&ModportTfPortsDeclaration
)?;
for mp_tf_port in mp_tf_ports_dec.nodes.1.contents() {
match mp_tf_port {
ModportTfPort::MethodPrototype(y) => match &**y {
MethodPrototype::TaskPrototype(z) => {
let mut port = SubDec::new(url);
let ident =
get_ident(tree, RefNode::TaskIdentifier(&z.nodes.1));
port.ident = ident.0;
port.byte_idx = ident.1;
skip_until_enter!(
tree,
event_iter,
RefNode::TaskPrototype,
&TaskPrototype
);
let tokens = &mut port.type_str;
advance_until_leave!(
tokens,
tree,
event_iter,
RefNode::TaskPrototype
);
modport.ports.push(Box::new(port));
}
MethodPrototype::FunctionPrototype(z) => {
let mut port = SubDec::new(url);
let ident =
get_ident(tree, RefNode::FunctionIdentifier(&z.nodes.2));
port.ident = ident.0;
port.byte_idx = ident.1;
skip_until_enter!(
tree,
event_iter,
RefNode::FunctionPrototype,
&FunctionPrototype
);
let tokens = &mut port.type_str;
advance_until_leave!(
tokens,
tree,
event_iter,
RefNode::FunctionIdentifier
);
modport.ports.push(Box::new(port));
}
},
ModportTfPort::TfIdentifier(y) => {
let mut port = SubDec::new(url);
let ident = get_ident(tree, RefNode::TfIdentifier(y));
port.ident = ident.0;
port.byte_idx = ident.1;
port.type_str = prepend.clone();
modport.ports.push(Box::new(port));
}
}
}
}
ModportPortsDeclaration::Clocking(_) => {
skip_until_enter!(
tree,
event_iter,
RefNode::ModportPortsDeclarationClocking,
&ModportPortsDeclarationClocking
);
let mut tokens = String::new();
let clock_ident = advance_until_enter!(
tokens,
tree,
event_iter,
RefNode::ClockingIdentifier,
&ClockingIdentifier
)?;
let ident = get_ident(tree, RefNode::ClockingIdentifier(clock_ident));
let mut port = PortDec::new(url);
port.ident = ident.0;
port.byte_idx = ident.1;
port.type_str = tokens;
modport.ports.push(Box::new(port));
}
}
}
modports.push(modport);
}
Some(modports)
}
pub fn module_inst(
tree: &SyntaxTree,
node: &ModuleInstantiation,
event_iter: &mut EventIter,
url: &Url,
) -> Option<Vec<ModInst>> {
let mut defs: Vec<ModInst> = Vec::new();
let mod_ident = get_ident(tree, RefNode::ModuleIdentifier(&node.nodes.0)).0;
for _ in node.nodes.2.contents() {
let hinst = skip_until_enter!(
tree,
event_iter,
RefNode::HierarchicalInstance,
&HierarchicalInstance
)?;
let mut instance = ModInst::new(url);
let ident = get_ident(tree, RefNode::InstanceIdentifier(&hinst.nodes.0.nodes.0));
instance.ident = ident.0;
instance.byte_idx = ident.1;
instance.type_str = mod_ident.clone();
instance.mod_ident = mod_ident.clone();
let type_str = &mut instance.type_str;
for _ in &hinst.nodes.0.nodes.1 {
advance_until_leave!(type_str, tree, event_iter, RefNode::UnpackedDimension);
}
defs.push(instance);
}
Some(defs)
}
fn param_assignment(
tree: &SyntaxTree,
_: &ParamAssignment,
event_iter: &mut EventIter,
url: &Url,
) -> Option<GenericDec> {
let param_assign =
skip_until_enter!(tree, event_iter, RefNode::ParamAssignment, &ParamAssignment)?;
let mut def = GenericDec::new(url);
let ident = get_ident(tree, RefNode::ParameterIdentifier(¶m_assign.nodes.0));
def.ident = ident.0;
def.byte_idx = ident.1;
let type_str = &mut def.type_str;
def.completion_kind = CompletionItemKind::TYPE_PARAMETER;
def.symbol_kind = SymbolKind::TYPE_PARAMETER;
advance_until_leave!(type_str, tree, event_iter, RefNode::ParamAssignment);
Some(def)
}
fn list_param_assignment(
tree: &SyntaxTree,
_: &ListOfParamAssignments,
event_iter: &mut EventIter,
url: &Url,
) -> Option<Vec<GenericDec>> {
let mut defs: Vec<GenericDec> = Vec::new();
let p_a_list = skip_until_enter!(
tree,
event_iter,
RefNode::ListOfParamAssignments,
&ListOfParamAssignments
)?;
for param_assign in p_a_list.nodes.0.contents() {
defs.push(param_assignment(tree, param_assign, event_iter, url)?);
}
Some(defs)
}
fn type_assignment(
tree: &SyntaxTree,
_: &TypeAssignment,
event_iter: &mut EventIter,
url: &Url,
) -> Option<GenericDec> {
let type_assign =
skip_until_enter!(tree, event_iter, RefNode::TypeAssignment, &TypeAssignment)?;
let mut def = GenericDec::new(url);
let ident = get_ident(tree, RefNode::TypeIdentifier(&type_assign.nodes.0));
def.ident = ident.0;
def.byte_idx = ident.1;
def.completion_kind = CompletionItemKind::TYPE_PARAMETER;
def.symbol_kind = SymbolKind::TYPE_PARAMETER;
let type_str = &mut def.type_str;
advance_until_leave!(type_str, tree, event_iter, RefNode::TypeAssignment);
Some(def)
}
fn list_type_assignment(
tree: &SyntaxTree,
_: &ListOfTypeAssignments,
event_iter: &mut EventIter,
url: &Url,
) -> Option<Vec<GenericDec>> {
let mut defs: Vec<GenericDec> = Vec::new();
let p_a_list = skip_until_enter!(
tree,
event_iter,
RefNode::ListOfTypeAssignments,
&ListOfTypeAssignments
)?;
for type_assign in p_a_list.nodes.0.contents() {
defs.push(type_assignment(tree, type_assign, event_iter, url)?);
}
Some(defs)
}
pub fn param_dec(
tree: &SyntaxTree,
param_dec: &ParameterDeclaration,
event_iter: &mut EventIter,
url: &Url,
) -> Option<Vec<GenericDec>> {
match param_dec {
ParameterDeclaration::Param(x) => {
let mut prepend = String::new();
advance_until_leave!(prepend, tree, event_iter, RefNode::DataTypeOrImplicit);
let mut defs = list_param_assignment(tree, &x.nodes.2, event_iter, url)?;
for def in &mut defs {
def.type_str = format!("{} {}", prepend, def.type_str);
def.completion_kind = CompletionItemKind::TYPE_PARAMETER;
def.symbol_kind = SymbolKind::TYPE_PARAMETER;
}
Some(defs)
}
ParameterDeclaration::Type(x) => {
let mut prepend = String::new();
advance_until_leave!(prepend, tree, event_iter, RefNode::Keyword);
advance_until_leave!(prepend, tree, event_iter, RefNode::Keyword);
let mut defs = list_type_assignment(tree, &x.nodes.2, event_iter, url)?;
for def in &mut defs {
def.type_str = format!("{} {}", prepend, def.type_str);
def.completion_kind = CompletionItemKind::TYPE_PARAMETER;
def.symbol_kind = SymbolKind::TYPE_PARAMETER;
}
Some(defs)
}
}
}
pub fn localparam_dec(
tree: &SyntaxTree,
localparam_dec: &LocalParameterDeclaration,
event_iter: &mut EventIter,
url: &Url,
) -> Option<Vec<GenericDec>> {
match localparam_dec {
LocalParameterDeclaration::Param(x) => {
let mut prepend = String::new();
advance_until_leave!(prepend, tree, event_iter, RefNode::DataTypeOrImplicit);
let mut defs = list_param_assignment(tree, &x.nodes.2, event_iter, url)?;
for def in &mut defs {
def.type_str = format!("{} {}", prepend, def.type_str);
def.completion_kind = CompletionItemKind::TYPE_PARAMETER;
def.symbol_kind = SymbolKind::TYPE_PARAMETER;
}
Some(defs)
}
LocalParameterDeclaration::Type(x) => {
let mut prepend = String::new();
advance_until_leave!(prepend, tree, event_iter, RefNode::Keyword);
advance_until_leave!(prepend, tree, event_iter, RefNode::Keyword);
let mut defs = list_type_assignment(tree, &x.nodes.2, event_iter, url)?;
for def in &mut defs {
def.type_str = format!("{} {}", prepend, def.type_str);
def.completion_kind = CompletionItemKind::TYPE_PARAMETER;
def.symbol_kind = SymbolKind::TYPE_PARAMETER;
}
Some(defs)
}
}
}
fn param_port_dec(
tree: &SyntaxTree,
node: &ParameterPortDeclaration,
event_iter: &mut EventIter,
url: &Url,
) -> Option<Vec<GenericDec>> {
match node {
ParameterPortDeclaration::ParameterDeclaration(_) => {
let param = skip_until_enter!(
tree,
event_iter,
RefNode::ParameterDeclaration,
&ParameterDeclaration
)?;
param_dec(tree, param, event_iter, url)
}
ParameterPortDeclaration::LocalParameterDeclaration(_) => {
let localparam = skip_until_enter!(
tree,
event_iter,
RefNode::LocalParameterDeclaration,
&LocalParameterDeclaration
)?;
localparam_dec(tree, localparam, event_iter, url)
}
ParameterPortDeclaration::ParamList(x) => {
let mut prepend = String::new();
advance_until_leave!(prepend, tree, event_iter, RefNode::DataType);
let mut defs = list_param_assignment(tree, &x.nodes.1, event_iter, url)?;
for def in &mut defs {
def.type_str = format!("{} {}", prepend, def.type_str);
def.completion_kind = CompletionItemKind::TYPE_PARAMETER;
def.symbol_kind = SymbolKind::TYPE_PARAMETER;
}
Some(defs)
}
ParameterPortDeclaration::TypeList(x) => {
let mut prepend = String::new();
advance_until_leave!(prepend, tree, event_iter, RefNode::Keyword);
let mut defs = list_type_assignment(tree, &x.nodes.1, event_iter, url)?;
for def in &mut defs {
def.type_str = format!("{} {}", prepend, def.type_str);
def.completion_kind = CompletionItemKind::TYPE_PARAMETER;
def.symbol_kind = SymbolKind::TYPE_PARAMETER;
}
Some(defs)
}
}
}
pub fn param_port_list(
tree: &SyntaxTree,
node: &ParameterPortList,
event_iter: &mut EventIter,
url: &Url,
) -> Option<Vec<GenericDec>> {
let mut defs: Vec<GenericDec> = Vec::new();
match node {
ParameterPortList::Assignment(x) => {
defs.append(&mut list_param_assignment(
tree,
&(x.nodes.1.nodes.1).0,
event_iter,
url,
)?);
for port_dec in &(x.nodes.1.nodes.1).1 {
defs.append(&mut param_port_dec(tree, &port_dec.1, event_iter, url)?);
}
}
ParameterPortList::Declaration(x) => {
let mut param_port_decs = vec![&x.nodes.1.nodes.1.nodes.0];
for param_port_dec in &x.nodes.1.nodes.1.nodes.1 {
param_port_decs.push(¶m_port_dec.1);
}
for port_dec in param_port_decs {
defs.append(&mut param_port_dec(tree, port_dec, event_iter, url)?);
}
}
ParameterPortList::Empty(_) => {}
}
Some(defs)
}
pub fn module_dec(
tree: &SyntaxTree,
node: &ModuleDeclaration,
event_iter: &mut EventIter,
url: &Url,
) -> Option<GenericScope> {
let mut scope: GenericScope = GenericScope::new(url);
match node {
ModuleDeclaration::Nonansi(x) => {
scope.start = get_loc(tree, RefNode::ModuleKeyword(&x.nodes.0.nodes.1));
scope.end = get_loc(tree, RefNode::Keyword(&x.nodes.3));
let ident = get_ident(tree, RefNode::ModuleIdentifier(&x.nodes.0.nodes.3));
scope.ident = ident.0;
scope.byte_idx = ident.1;
let type_str = &mut scope.type_str;
advance_until_leave!(type_str, tree, event_iter, RefNode::ModuleIdentifier);
for import_dec in &x.nodes.0.nodes.4 {
let imports = package_import(tree, import_dec, event_iter, url)?;
for import in imports {
scope.defs.push(Box::new(import));
}
}
if let Some(pport_list) = &x.nodes.0.nodes.5 {
let pports = param_port_list(tree, pport_list, event_iter, url)?;
for pport in pports {
scope.defs.push(Box::new(pport));
}
}
}
ModuleDeclaration::Ansi(x) => {
scope.start = get_loc(tree, RefNode::ModuleKeyword(&x.nodes.0.nodes.1));
scope.end = get_loc(tree, RefNode::Keyword(&x.nodes.3));
let ident = get_ident(tree, RefNode::ModuleIdentifier(&x.nodes.0.nodes.3));
scope.ident = ident.0;
scope.byte_idx = ident.1;
let type_str = &mut scope.type_str;
advance_until_leave!(type_str, tree, event_iter, RefNode::ModuleIdentifier);
for import_dec in &x.nodes.0.nodes.4 {
let imports = package_import(tree, import_dec, event_iter, url)?;
for import in imports {
scope.defs.push(Box::new(import));
}
}
if let Some(pport_list) = &x.nodes.0.nodes.5 {
let pports = param_port_list(tree, pport_list, event_iter, url)?;
for pport in pports {
scope.defs.push(Box::new(pport));
}
}
if let Some(list_port_decs) = &x.nodes.0.nodes.6 {
if let Some(port_decs) = &list_port_decs.nodes.0.nodes.1 {
let mut prev_type_str = String::new();
for _ in port_decs.contents() {
let ansi_dec = skip_until_enter!(
tree,
event_iter,
RefNode::AnsiPortDeclaration,
&AnsiPortDeclaration
)?;
// propogate type str for multi-port declaration
let mut port_dec = port_dec_ansi(tree, ansi_dec, event_iter, url)?;
if port_dec.type_str.is_empty() && !prev_type_str.is_empty() {
port_dec.type_str = prev_type_str.clone();
} else {
prev_type_str = port_dec.type_str.clone();
}
scope.defs.push(Box::new(port_dec))
}
}
}
}
ModuleDeclaration::Wildcard(x) => {
scope.start = get_loc(tree, RefNode::ModuleKeyword(&x.nodes.1));
scope.end = get_loc(tree, RefNode::Keyword(&x.nodes.8));
let ident = get_ident(tree, RefNode::ModuleIdentifier(&x.nodes.3));
scope.ident = ident.0;
scope.byte_idx = ident.1;
let type_str = &mut scope.type_str;
advance_until_leave!(type_str, tree, event_iter, RefNode::ModuleIdentifier);
}
ModuleDeclaration::ExternNonansi(x) => {
scope.start = get_loc(tree, RefNode::Keyword(&x.nodes.0));
scope.end = get_loc(tree, RefNode::Symbol(&x.nodes.1.nodes.7));
let ident = get_ident(tree, RefNode::ModuleIdentifier(&x.nodes.1.nodes.3));
scope.ident = ident.0;
scope.byte_idx = ident.1;
let type_str = &mut scope.type_str;
advance_until_leave!(type_str, tree, event_iter, RefNode::ModuleIdentifier);
for import_dec in &x.nodes.1.nodes.4 {
let imports = package_import(tree, import_dec, event_iter, url)?;
for import in imports {
scope.defs.push(Box::new(import));
}
}
if let Some(pport_list) = &x.nodes.1.nodes.5 {
let pports = param_port_list(tree, pport_list, event_iter, url)?;
for pport in pports {
scope.defs.push(Box::new(pport));
}
}
}
ModuleDeclaration::ExternAnsi(x) => {
scope.start = get_loc(tree, RefNode::Keyword(&x.nodes.0));
scope.end = get_loc(tree, RefNode::Symbol(&x.nodes.1.nodes.7));
let ident = get_ident(tree, RefNode::ModuleIdentifier(&x.nodes.1.nodes.3));
scope.ident = ident.0;
scope.byte_idx = ident.1;
let type_str = &mut scope.type_str;
advance_until_leave!(type_str, tree, event_iter, RefNode::ModuleIdentifier);
for import_dec in &x.nodes.1.nodes.4 {
let imports = package_import(tree, import_dec, event_iter, url)?;
for import in imports {
scope.defs.push(Box::new(import));
}
}
if let Some(pport_list) = &x.nodes.1.nodes.5 {
let pports = param_port_list(tree, pport_list, event_iter, url)?;
for pport in pports {
scope.defs.push(Box::new(pport));
}
}
if let Some(list_port_decs) = &x.nodes.1.nodes.6 {
if let Some(port_decs) = &list_port_decs.nodes.0.nodes.1 {
for _ in port_decs.contents() {
let ansi_dec = skip_until_enter!(
tree,
event_iter,
RefNode::AnsiPortDeclaration,
&AnsiPortDeclaration
)?;
scope
.defs
.push(Box::new(port_dec_ansi(tree, ansi_dec, event_iter, url)?))
}
}
}
}
}
let (scopes, mut defs) = match_until_leave!(tree, event_iter, url, RefNode::ModuleDeclaration)?;
scope.scopes = scopes;
scope.defs.append(&mut defs);
scope.completion_kind = CompletionItemKind::MODULE;
scope.symbol_kind = SymbolKind::MODULE;
Some(scope)
}
pub fn interface_dec(
tree: &SyntaxTree,
node: &InterfaceDeclaration,
event_iter: &mut EventIter,
url: &Url,
) -> Option<GenericScope> {
let mut scope: GenericScope = GenericScope::new(url);
match node {
InterfaceDeclaration::Nonansi(x) => {
scope.start = get_loc(tree, RefNode::Keyword(&x.nodes.0.nodes.1));
scope.end = get_loc(tree, RefNode::Keyword(&x.nodes.3));
let ident = get_ident(tree, RefNode::InterfaceIdentifier(&x.nodes.0.nodes.3));
scope.ident = ident.0;
scope.byte_idx = ident.1;
let type_str = &mut scope.type_str;
advance_until_leave!(type_str, tree, event_iter, RefNode::InterfaceIdentifier);
for import_dec in &x.nodes.0.nodes.4 {
let imports = package_import(tree, import_dec, event_iter, url)?;
for import in imports {
scope.defs.push(Box::new(import));
}
}
if let Some(pport_list) = &x.nodes.0.nodes.5 {
let pports = param_port_list(tree, pport_list, event_iter, url)?;
for pport in pports {
scope.defs.push(Box::new(pport));
}
}
}
InterfaceDeclaration::Ansi(x) => {
scope.start = get_loc(tree, RefNode::Keyword(&x.nodes.0.nodes.1));
scope.end = get_loc(tree, RefNode::Keyword(&x.nodes.3));
let ident = get_ident(tree, RefNode::InterfaceIdentifier(&x.nodes.0.nodes.3));
scope.ident = ident.0;
scope.byte_idx = ident.1;
let type_str = &mut scope.type_str;
advance_until_leave!(type_str, tree, event_iter, RefNode::InterfaceIdentifier);
for import_dec in &x.nodes.0.nodes.4 {
let imports = package_import(tree, import_dec, event_iter, url)?;
for import in imports {
scope.defs.push(Box::new(import));
}
}
if let Some(pport_list) = &x.nodes.0.nodes.5 {
let pports = param_port_list(tree, pport_list, event_iter, url)?;
for pport in pports {
scope.defs.push(Box::new(pport));
}
}
if let Some(list_port_decs) = &x.nodes.0.nodes.6 {
if let Some(port_decs) = &list_port_decs.nodes.0.nodes.1 {
for _ in port_decs.contents() {
let ansi_dec = skip_until_enter!(
tree,
event_iter,
RefNode::AnsiPortDeclaration,
&AnsiPortDeclaration
)?;
scope
.defs
.push(Box::new(port_dec_ansi(tree, ansi_dec, event_iter, url)?))
}
}
}
}
InterfaceDeclaration::Wildcard(x) => {
scope.start = get_loc(tree, RefNode::Keyword(&x.nodes.1));
scope.end = get_loc(tree, RefNode::Keyword(&x.nodes.8));
let ident = get_ident(tree, RefNode::InterfaceIdentifier(&x.nodes.3));
scope.ident = ident.0;
scope.byte_idx = ident.1;
let type_str = &mut scope.type_str;
advance_until_leave!(type_str, tree, event_iter, RefNode::InterfaceIdentifier);
}
InterfaceDeclaration::ExternNonansi(x) => {
scope.start = get_loc(tree, RefNode::Keyword(&x.nodes.0));
scope.end = get_loc(tree, RefNode::Symbol(&x.nodes.1.nodes.7));
let ident = get_ident(tree, RefNode::InterfaceIdentifier(&x.nodes.1.nodes.3));
scope.ident = ident.0;
scope.byte_idx = ident.1;
let type_str = &mut scope.type_str;
advance_until_leave!(type_str, tree, event_iter, RefNode::InterfaceIdentifier);
for import_dec in &x.nodes.1.nodes.4 {
let imports = package_import(tree, import_dec, event_iter, url)?;
for import in imports {
scope.defs.push(Box::new(import));
}
}
if let Some(pport_list) = &x.nodes.1.nodes.5 {
let pports = param_port_list(tree, pport_list, event_iter, url)?;
for pport in pports {
scope.defs.push(Box::new(pport));
}
}
}
InterfaceDeclaration::ExternAnsi(x) => {
scope.start = get_loc(tree, RefNode::Keyword(&x.nodes.0));
scope.end = get_loc(tree, RefNode::Symbol(&x.nodes.1.nodes.7));
let ident = get_ident(tree, RefNode::InterfaceIdentifier(&x.nodes.1.nodes.3));
scope.ident = ident.0;
scope.byte_idx = ident.1;
let type_str = &mut scope.type_str;
advance_until_leave!(type_str, tree, event_iter, RefNode::InterfaceIdentifier);
for import_dec in &x.nodes.1.nodes.4 {
let imports = package_import(tree, import_dec, event_iter, url)?;
for import in imports {
scope.defs.push(Box::new(import));
}
}
if let Some(pport_list) = &x.nodes.1.nodes.5 {
let pports = param_port_list(tree, pport_list, event_iter, url)?;
for pport in pports {
scope.defs.push(Box::new(pport));
}
}
if let Some(list_port_decs) = &x.nodes.1.nodes.6 {
if let Some(port_decs) = &list_port_decs.nodes.0.nodes.1 {
for _ in port_decs.contents() {
let ansi_dec = skip_until_enter!(
tree,
event_iter,
RefNode::AnsiPortDeclaration,
&AnsiPortDeclaration
)?;
scope
.defs
.push(Box::new(port_dec_ansi(tree, ansi_dec, event_iter, url)?))
}
}
}
}
}
let (scopes, mut defs) =
match_until_leave!(tree, event_iter, url, RefNode::InterfaceDeclaration)?;
scope.scopes = scopes;
scope.defs.append(&mut defs);
scope.completion_kind = CompletionItemKind::INTERFACE;
scope.symbol_kind = SymbolKind::INTERFACE;
Some(scope)
}
fn list_udp_port_idents(
tree: &SyntaxTree,
node: &ListOfUdpPortIdentifiers,
_: &mut EventIter,
url: &Url,
) -> Vec<PortDec> {
let mut ports: Vec<PortDec> = Vec::new();
for port_def in node.nodes.0.contents() {
let mut port = PortDec::new(url);
let ident = get_ident(tree, RefNode::PortIdentifier(port_def));
port.ident = ident.0;
port.byte_idx = ident.1;
ports.push(port);
}
ports
}
//non-ansi udp ports
fn udp_port_dec(
tree: &SyntaxTree,
node: &UdpPortDeclaration,
event_iter: &mut EventIter,
url: &Url,
) -> Option<Vec<PortDec>> {
match node {
UdpPortDeclaration::UdpOutputDeclaration(x) => match &x.0 {
UdpOutputDeclaration::Nonreg(x) => {
let mut port = PortDec::new(url);
let ident = get_ident(tree, RefNode::PortIdentifier(&x.nodes.2));
port.ident = ident.0;
port.byte_idx = ident.1;
skip_until_enter!(
tree,
event_iter,
RefNode::UdpOutputDeclarationNonreg,
&UdpOutputDeclarationNonreg
);
let type_str = &mut port.type_str;
advance_until_leave!(
type_str,
tree,
event_iter,
RefNode::UdpOutputDeclarationNonreg
);
Some(vec![port])
}
UdpOutputDeclaration::Reg(x) => {
let mut port = PortDec::new(url);
let ident = get_ident(tree, RefNode::PortIdentifier(&x.nodes.3));
port.ident = ident.0;
port.byte_idx = ident.1;
skip_until_enter!(
tree,
event_iter,
RefNode::UdpOutputDeclarationReg,
&UdpOutputDeclarationReg
);
let type_str = &mut port.type_str;
advance_until_leave!(type_str, tree, event_iter, RefNode::UdpOutputDeclarationReg);
Some(vec![port])
}
},
UdpPortDeclaration::UdpInputDeclaration(_) => {
skip_until_enter!(
tree,
event_iter,
RefNode::UdpInputDeclaration,
&UdpInputDeclaration
);
let mut type_str = String::new();
let list_udp_ports = advance_until_enter!(
type_str,
tree,
event_iter,
RefNode::ListOfUdpPortIdentifiers,
&ListOfUdpPortIdentifiers
)?;
let mut ports = list_udp_port_idents(tree, list_udp_ports, event_iter, url);
for port in &mut ports {
port.type_str = type_str.clone();
}
Some(ports)
}
UdpPortDeclaration::UdpRegDeclaration(_) => {
let udp_reg_dec = skip_until_enter!(
tree,
event_iter,
RefNode::UdpRegDeclaration,
&UdpRegDeclaration
)?;
let mut port = PortDec::new(url);
let type_str = &mut port.type_str;
advance_until_leave!(type_str, tree, event_iter, RefNode::Keyword);
let ident = get_ident(tree, RefNode::VariableIdentifier(&udp_reg_dec.nodes.2));
port.ident = ident.0;
port.byte_idx = ident.1;
Some(vec![port])
}
}
}
//ansi udp ports
fn udp_port_list(
tree: &SyntaxTree,
node: &UdpDeclarationPortList,
event_iter: &mut EventIter,
url: &Url,
) -> Option<Vec<PortDec>> {
let mut ports: Vec<PortDec> = Vec::new();
match &node.nodes.0 {
UdpOutputDeclaration::Nonreg(x) => {
let mut port = PortDec::new(url);
let ident = get_ident(tree, RefNode::PortIdentifier(&x.nodes.2));
port.ident = ident.0;
port.byte_idx = ident.1;
skip_until_enter!(
tree,
event_iter,
RefNode::UdpOutputDeclarationNonreg,
&UdpOutputDeclarationNonreg
);
let type_str = &mut port.type_str;
advance_until_leave!(
type_str,
tree,
event_iter,
RefNode::UdpOutputDeclarationNonreg
);
ports.push(port);
}
UdpOutputDeclaration::Reg(x) => {
let mut port = PortDec::new(url);
let ident = get_ident(tree, RefNode::PortIdentifier(&x.nodes.3));
port.ident = ident.0;
port.byte_idx = ident.1;
skip_until_enter!(
tree,
event_iter,
RefNode::UdpOutputDeclarationReg,
&UdpOutputDeclarationReg
);
let type_str = &mut port.type_str;
advance_until_leave!(type_str, tree, event_iter, RefNode::UdpOutputDeclarationReg);
ports.push(port);
}
}
for _port_def in node.nodes.2.contents() {
skip_until_enter!(
tree,
event_iter,
RefNode::UdpInputDeclaration,
&UdpInputDeclaration
);
let mut type_str = String::new();
let list_udp_ports = advance_until_enter!(
type_str,
tree,
event_iter,
RefNode::ListOfUdpPortIdentifiers,
&ListOfUdpPortIdentifiers
)?;
let mut port_decs = list_udp_port_idents(tree, list_udp_ports, event_iter, url);
for port in &mut port_decs {
port.type_str = type_str.clone();
}
ports.append(&mut port_decs);
}
Some(ports)
}
pub fn udp_dec(
tree: &SyntaxTree,
node: &UdpDeclaration,
event_iter: &mut EventIter,
url: &Url,
) -> Option<GenericScope> {
let mut scope: GenericScope = GenericScope::new(url);
match node {
UdpDeclaration::Nonansi(x) => {
scope.start = get_loc(tree, RefNode::Keyword(&x.nodes.0.nodes.1));
scope.end = get_loc(tree, RefNode::Keyword(&x.nodes.4));
let ident = get_ident(tree, RefNode::UdpIdentifier(&x.nodes.0.nodes.2));
scope.ident = ident.0;
scope.byte_idx = ident.1;
let type_str = &mut scope.type_str;
advance_until_leave!(type_str, tree, event_iter, RefNode::UdpIdentifier);
let mut port_decs = vec![&x.nodes.1];
for port_dec in &x.nodes.2 {
port_decs.push(port_dec);
}
for port in port_decs {
let ports = udp_port_dec(tree, port, event_iter, url)?;
for port_dec in ports {
scope.defs.push(Box::new(port_dec));
}
}
}
UdpDeclaration::Ansi(x) => {
scope.start = get_loc(tree, RefNode::Keyword(&x.nodes.0.nodes.1));
scope.end = get_loc(tree, RefNode::Keyword(&x.nodes.2));
let ident = get_ident(tree, RefNode::UdpIdentifier(&x.nodes.0.nodes.2));
scope.ident = ident.0;
scope.byte_idx = ident.1;
let type_str = &mut scope.type_str;
advance_until_leave!(type_str, tree, event_iter, RefNode::UdpIdentifier);
let ports = udp_port_list(tree, &x.nodes.0.nodes.3.nodes.1, event_iter, url)?;
for port_dec in ports {
scope.defs.push(Box::new(port_dec));
}
}
UdpDeclaration::ExternNonansi(x) => {
scope.start = get_loc(tree, RefNode::Keyword(&x.nodes.0));
scope.end = get_loc(tree, RefNode::Symbol(&x.nodes.1.nodes.4));
let ident = get_ident(tree, RefNode::UdpIdentifier(&x.nodes.1.nodes.2));
scope.ident = ident.0;
scope.byte_idx = ident.1;
let type_str = &mut scope.type_str;
advance_until_leave!(type_str, tree, event_iter, RefNode::UdpIdentifier);
}
UdpDeclaration::ExternAnsi(x) => {
scope.start = get_loc(tree, RefNode::Keyword(&x.nodes.0));
scope.end = get_loc(tree, RefNode::Symbol(&x.nodes.1.nodes.4));
let ident = get_ident(tree, RefNode::UdpIdentifier(&x.nodes.1.nodes.2));
scope.ident = ident.0;
scope.byte_idx = ident.1;
let type_str = &mut scope.type_str;
advance_until_leave!(type_str, tree, event_iter, RefNode::UdpIdentifier);
let ports = udp_port_list(tree, &x.nodes.1.nodes.3.nodes.1, event_iter, url)?;
for port_dec in ports {
scope.defs.push(Box::new(port_dec));
}
}
UdpDeclaration::Wildcard(x) => {
scope.start = get_loc(tree, RefNode::Keyword(&x.nodes.1));
scope.end = get_loc(tree, RefNode::Keyword(&x.nodes.7));
let ident = get_ident(tree, RefNode::UdpIdentifier(&x.nodes.2));
scope.ident = ident.0;
scope.byte_idx = ident.1;
let type_str = &mut scope.type_str;
advance_until_leave!(type_str, tree, event_iter, RefNode::UdpIdentifier);
for port_dec in &x.nodes.5 {
let ports = udp_port_dec(tree, port_dec, event_iter, url)?;
for port in ports {
scope.defs.push(Box::new(port));
}
}
}
}
let (scopes, mut defs) = match_until_leave!(tree, event_iter, url, RefNode::UdpDeclaration)?;
scope.scopes = scopes;
scope.defs.append(&mut defs);
scope.completion_kind = CompletionItemKind::MODULE;
scope.symbol_kind = SymbolKind::MODULE;
Some(scope)
}
pub fn program_dec(
tree: &SyntaxTree,
node: &ProgramDeclaration,
event_iter: &mut EventIter,
url: &Url,
) -> Option<GenericScope> {
let mut scope: GenericScope = GenericScope::new(url);
match node {
ProgramDeclaration::Nonansi(x) => {
scope.start = get_loc(tree, RefNode::Keyword(&x.nodes.0.nodes.1));
scope.end = get_loc(tree, RefNode::Keyword(&x.nodes.3));
let ident = get_ident(tree, RefNode::ProgramIdentifier(&x.nodes.0.nodes.3));
scope.ident = ident.0;
scope.byte_idx = ident.1;
let type_str = &mut scope.type_str;
advance_until_leave!(type_str, tree, event_iter, RefNode::InterfaceIdentifier);
for import_dec in &x.nodes.0.nodes.4 {
let imports = package_import(tree, import_dec, event_iter, url)?;
for import in imports {
scope.defs.push(Box::new(import));
}
gitextract_lil_lsx1/
├── .github/
│ └── workflows/
│ └── ci.yml
├── .gitignore
├── Cargo.toml
├── LICENSE
├── README.md
├── extensions/
│ └── vscode/
│ ├── .eslintignore
│ ├── .eslintrc.js
│ ├── .eslintrc.json
│ ├── .gitignore
│ ├── .vscodeignore
│ ├── LICENSE
│ ├── README.md
│ ├── package.json
│ ├── src/
│ │ └── extension.ts
│ ├── syntaxes/
│ │ └── systemverilog.tmLanguage.json
│ ├── tsconfig.json
│ └── tsconfig.tsbuildinfo
├── rustfmt.toml
├── src/
│ ├── completion/
│ │ └── keyword.rs
│ ├── completion.rs
│ ├── definition/
│ │ ├── def_types.rs
│ │ └── extract_defs.rs
│ ├── definition.rs
│ ├── diagnostics.rs
│ ├── format.rs
│ ├── lib.rs
│ ├── main.rs
│ ├── server.rs
│ ├── sources.rs
│ └── support.rs
├── test_data/
│ ├── complete.sv
│ ├── definition_test.sv
│ ├── diag/
│ │ └── diag_test.sv
│ ├── ind.sv
│ ├── interface_obj.sv
│ ├── simple_bus.svh
│ ├── test_inter.sv
│ ├── top.sv
│ ├── top_inc.sv
│ └── verilator_errors.txt
└── veridian-slang/
├── Cargo.toml
├── build.rs
├── slang_wrapper/
│ ├── CMakeLists.txt
│ └── src/
│ ├── BasicClient.h
│ ├── FormatBuffer.h
│ ├── basic_client.cpp
│ ├── slang_lib.cpp
│ └── slang_wrapper.h
└── src/
├── lib.rs
└── wrapper.rs
SYMBOL INDEX (317 symbols across 19 files)
FILE: extensions/vscode/src/extension.ts
function activate (line 20) | function activate(context: ExtensionContext) {
function deactivate (line 51) | function deactivate(): Thenable<void> | undefined {
FILE: src/completion.rs
method completion (line 11) | pub fn completion(&self, params: CompletionParams) -> Option<CompletionR...
function prev_char (line 111) | fn prev_char(text: &Rope, pos: &Position) -> char {
function get_completion_token (line 128) | fn get_completion_token(text: &Rope, line: RopeSlice, pos: Position) -> ...
function test_get_completion_token (line 189) | fn test_get_completion_token() {
function test_completion (line 231) | fn test_completion() {
function test_nested_completion (line 343) | fn test_nested_completion() {
function test_dot_completion (line 465) | fn test_dot_completion() {
function test_trigger_dot_nocontext (line 554) | fn test_trigger_dot_nocontext() {
function test_dot_completion_instantiation (line 640) | fn test_dot_completion_instantiation() {
function test_inter_file_completion (line 720) | fn test_inter_file_completion() {
FILE: src/completion/keyword.rs
function keyword_completions (line 3) | pub fn keyword_completions(keywords: &[(&str, &str)]) -> Vec<CompletionI...
function other_completions (line 25) | pub fn other_completions(tasks: &[&str]) -> Vec<CompletionItem> {
constant KEYWORDS (line 36) | pub const KEYWORDS: &[(&str, &str)] = &[
constant SYS_TASKS (line 287) | pub const SYS_TASKS: &[&str] = &[
constant DIRECTIVES (line 437) | pub const DIRECTIVES: &[&str] = &[
FILE: src/definition.rs
method goto_definition (line 16) | pub fn goto_definition(&self, params: GotoDefinitionParams) -> Option<Go...
method hover (line 38) | pub fn hover(&self, params: HoverParams) -> Option<Hover> {
method document_symbol (line 61) | pub fn document_symbol(&self, params: DocumentSymbolParams) -> Option<Do...
method document_highlight (line 73) | pub fn document_highlight(
function all_identifiers (line 105) | fn all_identifiers(syntax_tree: &SyntaxTree, token: &str) -> Vec<(String...
function get_definition_token (line 119) | fn get_definition_token(line: RopeSlice, pos: Position) -> String {
type ScopesAndDefs (line 143) | type ScopesAndDefs = Option<(Vec<Box<dyn Scope>>, Vec<Box<dyn Definition...
function match_definitions (line 147) | pub fn match_definitions(
function get_scopes (line 283) | pub fn get_scopes(syntax_tree: &SyntaxTree, url: &Url) -> Option<Generic...
function get_hover (line 306) | fn get_hover(doc: &Rope, line: usize) -> String {
function test_definition_token (line 361) | fn test_definition_token() {
function test_get_definition (line 369) | fn test_get_definition() {
function test_hover (line 392) | fn test_hover() {
function test_symbols (line 425) | fn test_symbols() {
function test_highlight (line 451) | fn test_highlight() {
FILE: src/definition/def_types.rs
function clean_type_str (line 7) | pub fn clean_type_str(type_str: &str, ident: &str) -> String {
function copy_defs (line 26) | pub fn copy_defs(defs: &[Box<dyn Definition>]) -> Vec<Box<dyn Definition...
function copy_scopes (line 42) | pub fn copy_scopes(scopes: &[Box<dyn Scope>]) -> Vec<Box<dyn Scope>> {
type Definition (line 66) | pub trait Definition: std::fmt::Debug + Sync + Send {
method ident (line 68) | fn ident(&self) -> String;
method byte_idx (line 70) | fn byte_idx(&self) -> usize;
method url (line 72) | fn url(&self) -> Url;
method type_str (line 74) | fn type_str(&self) -> String;
method completion_kind (line 76) | fn completion_kind(&self) -> CompletionItemKind;
method symbol_kind (line 79) | fn symbol_kind(&self) -> SymbolKind;
method def_type (line 81) | fn def_type(&self) -> DefinitionType;
method starts_with (line 83) | fn starts_with(&self, token: &str) -> bool;
method completion (line 85) | fn completion(&self) -> CompletionItem;
method dot_completion (line 86) | fn dot_completion(&self, scope_tree: &GenericScope) -> Vec<CompletionI...
method ident (line 333) | fn ident(&self) -> String {
method byte_idx (line 336) | fn byte_idx(&self) -> usize {
method url (line 339) | fn url(&self) -> Url {
method type_str (line 342) | fn type_str(&self) -> String {
method completion_kind (line 345) | fn completion_kind(&self) -> CompletionItemKind {
method symbol_kind (line 348) | fn symbol_kind(&self) -> SymbolKind {
method def_type (line 351) | fn def_type(&self) -> DefinitionType {
method starts_with (line 354) | fn starts_with(&self, token: &str) -> bool {
method completion (line 357) | fn completion(&self) -> CompletionItem {
method dot_completion (line 365) | fn dot_completion(&self, scope_tree: &GenericScope) -> Vec<CompletionI...
method ident (line 419) | fn ident(&self) -> String {
method byte_idx (line 422) | fn byte_idx(&self) -> usize {
method url (line 425) | fn url(&self) -> Url {
method type_str (line 428) | fn type_str(&self) -> String {
method completion_kind (line 431) | fn completion_kind(&self) -> CompletionItemKind {
method symbol_kind (line 434) | fn symbol_kind(&self) -> SymbolKind {
method def_type (line 437) | fn def_type(&self) -> DefinitionType {
method starts_with (line 440) | fn starts_with(&self, token: &str) -> bool {
method completion (line 443) | fn completion(&self) -> CompletionItem {
method dot_completion (line 451) | fn dot_completion(&self, _: &GenericScope) -> Vec<CompletionItem> {
method ident (line 486) | fn ident(&self) -> String {
method byte_idx (line 489) | fn byte_idx(&self) -> usize {
method url (line 492) | fn url(&self) -> Url {
method type_str (line 495) | fn type_str(&self) -> String {
method completion_kind (line 498) | fn completion_kind(&self) -> CompletionItemKind {
method symbol_kind (line 501) | fn symbol_kind(&self) -> SymbolKind {
method def_type (line 504) | fn def_type(&self) -> DefinitionType {
method starts_with (line 507) | fn starts_with(&self, token: &str) -> bool {
method completion (line 510) | fn completion(&self) -> CompletionItem {
method dot_completion (line 518) | fn dot_completion(&self, _: &GenericScope) -> Vec<CompletionItem> {
method ident (line 557) | fn ident(&self) -> String {
method byte_idx (line 560) | fn byte_idx(&self) -> usize {
method url (line 563) | fn url(&self) -> Url {
method type_str (line 566) | fn type_str(&self) -> String {
method completion_kind (line 569) | fn completion_kind(&self) -> CompletionItemKind {
method symbol_kind (line 572) | fn symbol_kind(&self) -> SymbolKind {
method def_type (line 575) | fn def_type(&self) -> DefinitionType {
method starts_with (line 578) | fn starts_with(&self, token: &str) -> bool {
method completion (line 581) | fn completion(&self) -> CompletionItem {
method dot_completion (line 589) | fn dot_completion(&self, _: &GenericScope) -> Vec<CompletionItem> {
method ident (line 639) | fn ident(&self) -> String {
method byte_idx (line 642) | fn byte_idx(&self) -> usize {
method url (line 645) | fn url(&self) -> Url {
method type_str (line 648) | fn type_str(&self) -> String {
method completion_kind (line 651) | fn completion_kind(&self) -> CompletionItemKind {
method symbol_kind (line 654) | fn symbol_kind(&self) -> SymbolKind {
method def_type (line 657) | fn def_type(&self) -> DefinitionType {
method starts_with (line 660) | fn starts_with(&self, token: &str) -> bool {
method completion (line 663) | fn completion(&self) -> CompletionItem {
method dot_completion (line 671) | fn dot_completion(&self, _: &GenericScope) -> Vec<CompletionItem> {
method ident (line 704) | fn ident(&self) -> String {
method byte_idx (line 707) | fn byte_idx(&self) -> usize {
method url (line 710) | fn url(&self) -> Url {
method type_str (line 713) | fn type_str(&self) -> String {
method completion_kind (line 716) | fn completion_kind(&self) -> CompletionItemKind {
method symbol_kind (line 719) | fn symbol_kind(&self) -> SymbolKind {
method def_type (line 722) | fn def_type(&self) -> DefinitionType {
method starts_with (line 725) | fn starts_with(&self, token: &str) -> bool {
method completion (line 728) | fn completion(&self) -> CompletionItem {
method dot_completion (line 736) | fn dot_completion(&self, scope_tree: &GenericScope) -> Vec<CompletionI...
method ident (line 795) | fn ident(&self) -> String {
method byte_idx (line 798) | fn byte_idx(&self) -> usize {
method url (line 801) | fn url(&self) -> Url {
method type_str (line 804) | fn type_str(&self) -> String {
method completion_kind (line 807) | fn completion_kind(&self) -> CompletionItemKind {
method symbol_kind (line 810) | fn symbol_kind(&self) -> SymbolKind {
method def_type (line 813) | fn def_type(&self) -> DefinitionType {
method starts_with (line 816) | fn starts_with(&self, token: &str) -> bool {
method completion (line 819) | fn completion(&self) -> CompletionItem {
method dot_completion (line 827) | fn dot_completion(&self, scope_tree: &GenericScope) -> Vec<CompletionI...
method ident (line 900) | fn ident(&self) -> String {
method byte_idx (line 903) | fn byte_idx(&self) -> usize {
method url (line 906) | fn url(&self) -> Url {
method type_str (line 909) | fn type_str(&self) -> String {
method completion_kind (line 912) | fn completion_kind(&self) -> CompletionItemKind {
method symbol_kind (line 915) | fn symbol_kind(&self) -> SymbolKind {
method def_type (line 918) | fn def_type(&self) -> DefinitionType {
method starts_with (line 921) | fn starts_with(&self, token: &str) -> bool {
method completion (line 924) | fn completion(&self) -> CompletionItem {
method dot_completion (line 932) | fn dot_completion(&self, scope_tree: &GenericScope) -> Vec<CompletionI...
type Scope (line 89) | pub trait Scope: std::fmt::Debug + Definition + Sync + Send {
method start (line 91) | fn start(&self) -> usize;
method end (line 93) | fn end(&self) -> usize;
method defs (line 95) | fn defs(&self) -> &Vec<Box<dyn Definition>>;
method scopes (line 97) | fn scopes(&self) -> &Vec<Box<dyn Scope>>;
method definition (line 99) | fn definition(&self) -> GenericDec {
method get_completion (line 111) | fn get_completion(&self, token: &str, byte_idx: usize, url: &Url) -> V...
method get_dot_completion (line 140) | fn get_dot_completion(
method get_definition (line 188) | fn get_definition(&self, token: &str, byte_idx: usize, url: &Url) -> O...
method document_symbols (line 219) | fn document_symbols(&self, uri: &Url, doc: &Rope) -> Vec<DocumentSymbo...
method document_highlights (line 262) | fn document_highlights(
method start (line 595) | fn start(&self) -> usize {
method end (line 599) | fn end(&self) -> usize {
method defs (line 602) | fn defs(&self) -> &Vec<Box<dyn Definition>> {
method scopes (line 606) | fn scopes(&self) -> &Vec<Box<dyn Scope>> {
method start (line 843) | fn start(&self) -> usize {
method end (line 847) | fn end(&self) -> usize {
method defs (line 851) | fn defs(&self) -> &Vec<Box<dyn Definition>> {
method scopes (line 855) | fn scopes(&self) -> &Vec<Box<dyn Scope>> {
method start (line 948) | fn start(&self) -> usize {
method end (line 952) | fn end(&self) -> usize {
method defs (line 956) | fn defs(&self) -> &Vec<Box<dyn Definition>> {
method scopes (line 960) | fn scopes(&self) -> &Vec<Box<dyn Scope>> {
type DefinitionType (line 292) | pub enum DefinitionType {
type PortDec (line 304) | pub struct PortDec {
method new (line 317) | pub fn new(url: &Url) -> Self {
type GenericDec (line 393) | pub struct GenericDec {
method new (line 404) | pub fn new(url: &Url) -> Self {
type PackageImport (line 457) | pub struct PackageImport {
method new (line 470) | pub fn new(url: &Url) -> Self {
type SubDec (line 524) | pub struct SubDec {
method new (line 539) | pub fn new(url: &Url) -> Self {
type ModportDec (line 612) | pub struct ModportDec {
method new (line 624) | pub fn new(url: &Url) -> Self {
type ModInst (line 677) | pub struct ModInst {
method new (line 689) | pub fn new(url: &Url) -> Self {
type GenericScope (line 752) | pub struct GenericScope {
method new (line 767) | pub fn new(url: &Url) -> Self {
method contains_scope (line 784) | pub fn contains_scope(&self, scope_ident: &str) -> bool {
type ClassDec (line 861) | pub struct ClassDec {
method new (line 880) | pub fn new(url: &Url) -> Self {
FILE: src/definition/extract_defs.rs
function get_ident (line 6) | pub fn get_ident(tree: &SyntaxTree, node: RefNode) -> (String, usize) {
function get_loc (line 13) | fn get_loc(tree: &SyntaxTree, node: RefNode) -> usize {
function port_dec_ansi (line 124) | pub fn port_dec_ansi(
function list_port_idents (line 173) | pub fn list_port_idents(
function list_interface_idents (line 194) | pub fn list_interface_idents(
function list_variable_idents (line 215) | pub fn list_variable_idents(
function port_dec_non_ansi (line 236) | pub fn port_dec_non_ansi(
function list_net_decl (line 339) | pub fn list_net_decl(
function net_dec (line 360) | pub fn net_dec(
function list_var_decl (line 415) | pub fn list_var_decl(
function package_import (line 454) | pub fn package_import(
function struct_union (line 486) | fn struct_union(
type Declaration (line 588) | pub enum Declaration {
function data_type (line 595) | fn data_type(
function data_dec (line 677) | pub fn data_dec(
function tfport_list (line 922) | pub fn tfport_list(
function function_dec (line 945) | pub fn function_dec(
function task_dec (line 999) | pub fn task_dec(
function modport_dec (line 1053) | pub fn modport_dec(
function module_inst (line 1222) | pub fn module_inst(
function param_assignment (line 1252) | fn param_assignment(
function list_param_assignment (line 1271) | fn list_param_assignment(
function type_assignment (line 1290) | fn type_assignment(
function list_type_assignment (line 1309) | fn list_type_assignment(
function param_dec (line 1328) | pub fn param_dec(
function localparam_dec (line 1361) | pub fn localparam_dec(
function param_port_dec (line 1394) | fn param_port_dec(
function param_port_list (line 1444) | pub fn param_port_list(
function module_dec (line 1477) | pub fn module_dec(
function interface_dec (line 1623) | pub fn interface_dec(
function list_udp_port_idents (line 1764) | fn list_udp_port_idents(
function udp_port_dec (line 1782) | fn udp_port_dec(
function udp_port_list (line 1866) | fn udp_port_list(
function udp_dec (line 1934) | pub fn udp_dec(
function program_dec (line 2021) | pub fn program_dec(
function package_dec (line 2164) | pub fn package_dec(
function config_dec (line 2188) | pub fn config_dec(
function class_dec (line 2217) | pub fn class_dec(
function text_macro_def (line 2278) | pub fn text_macro_def(
FILE: src/diagnostics.rs
function get_diagnostics (line 20) | pub fn get_diagnostics(
function get_diagnostics (line 67) | pub fn get_diagnostics(
function get_paths (line 111) | fn get_paths(files: Vec<Url>, search_workdir: bool) -> Vec<PathBuf> {
function is_hidden (line 156) | pub fn is_hidden(entry: &DirEntry) -> bool {
function parse_report (line 166) | fn parse_report(uri: Url, report: String) -> Vec<Diagnostic> {
function slang_severity (line 190) | fn slang_severity(severity: &str) -> Option<DiagnosticSeverity> {
function absolute_path (line 201) | fn absolute_path(path_str: &str) -> PathBuf {
function verilator_severity (line 207) | fn verilator_severity(severity: &str) -> Option<DiagnosticSeverity> {
function verilator_syntax (line 217) | fn verilator_syntax(
function verible_syntax (line 290) | fn verible_syntax(
function test_diagnostics (line 354) | fn test_diagnostics() {
function test_unsaved_file (line 382) | fn test_unsaved_file() {
function test_verible_syntax (line 394) | fn test_verible_syntax() {
function test_verilator_syntax (line 429) | fn test_verilator_syntax() {
FILE: src/format.rs
method formatting (line 9) | pub fn formatting(&self, params: DocumentFormattingParams) -> Option<Vec...
method range_formatting (line 36) | pub fn range_formatting(&self, params: DocumentRangeFormattingParams) ->...
function format_document (line 62) | pub fn format_document(
function test_formatting (line 102) | fn test_formatting() {
function test_range_formatting (line 131) | fn test_range_formatting() {
FILE: src/main.rs
type Opt (line 20) | struct Opt {}
function main (line 23) | async fn main() {
FILE: src/server.rs
type LSPServer (line 19) | pub struct LSPServer {
method new (line 29) | pub fn new(log_handle: Option<LoggerHandle>) -> LSPServer {
type Backend (line 41) | pub struct Backend {
method new (line 47) | pub fn new(client: Client, log_handle: LoggerHandle) -> Backend {
type LogLevel (line 56) | pub enum LogLevel {
type ProjectConfig (line 71) | pub struct ProjectConfig {
method default (line 87) | fn default() -> Self {
type Verible (line 101) | pub struct Verible {
type VeribleSyntax (line 108) | pub struct VeribleSyntax {
method default (line 115) | fn default() -> Self {
type Verilator (line 126) | pub struct Verilator {
type VerilatorSyntax (line 132) | pub struct VerilatorSyntax {
method default (line 139) | fn default() -> Self {
type VeribleFormat (line 154) | pub struct VeribleFormat {
method default (line 161) | fn default() -> Self {
function read_config (line 170) | fn read_config(root_uri: Option<Url>) -> anyhow::Result<ProjectConfig> {
function absolute_path (line 198) | fn absolute_path(path_str: &str) -> Option<PathBuf> {
method initialize (line 212) | async fn initialize(&self, params: InitializeParams) -> Result<Initializ...
method initialized (line 297) | async fn initialized(&self, _: InitializedParams) {
method shutdown (line 302) | async fn shutdown(&self) -> Result<()> {
method did_open (line 305) | async fn did_open(&self, params: DidOpenTextDocumentParams) {
method did_change (line 315) | async fn did_change(&self, params: DidChangeTextDocumentParams) {
method did_save (line 318) | async fn did_save(&self, params: DidSaveTextDocumentParams) {
method completion (line 328) | async fn completion(&self, params: CompletionParams) -> Result<Option<Co...
method goto_definition (line 331) | async fn goto_definition(
method hover (line 337) | async fn hover(&self, params: HoverParams) -> Result<Option<Hover>> {
method document_symbol (line 340) | async fn document_symbol(
method formatting (line 346) | async fn formatting(&self, params: DocumentFormattingParams) -> Result<O...
method range_formatting (line 349) | async fn range_formatting(
method document_highlight (line 355) | async fn document_highlight(
function test_config (line 368) | fn test_config() {
FILE: src/sources.rs
method did_open (line 22) | pub fn did_open(&self, params: DidOpenTextDocumentParams) -> PublishDiag...
method did_change (line 48) | pub fn did_change(&self, params: DidChangeTextDocumentParams) {
method did_save (line 73) | pub fn did_save(&self, params: DidSaveTextDocumentParams) -> PublishDiag...
type Source (line 88) | pub struct Source {
type SourceMeta (line 99) | pub struct SourceMeta {
function find_src_paths (line 105) | fn find_src_paths(dirs: &[PathBuf]) -> Vec<PathBuf> {
type Sources (line 129) | pub struct Sources {
method default (line 146) | fn default() -> Self {
method new (line 152) | pub fn new() -> Self {
method init (line 162) | pub fn init(&self) {
method add (line 187) | pub fn add(&self, doc: TextDocumentItem) {
method get_file (line 275) | pub fn get_file(&self, id: usize) -> Option<Arc<RwLock<Source>>> {
method get_meta_data (line 287) | pub fn get_meta_data(&self, id: usize) -> Option<Arc<RwLock<SourceMeta...
method wait_parse_ready (line 299) | pub fn wait_parse_ready(&self, id: usize, wait_valid: bool) {
method get_id (line 314) | pub fn get_id(&self, uri: &Url) -> usize {
method get_completions (line 319) | pub fn get_completions(
method get_dot_completions (line 338) | pub fn get_dot_completions(
function parse (line 357) | pub fn parse(
type LSPSupport (line 441) | pub trait LSPSupport {
method pos_to_byte (line 442) | fn pos_to_byte(&self, pos: &Position) -> usize;
method pos_to_char (line 443) | fn pos_to_char(&self, pos: &Position) -> usize;
method byte_to_pos (line 444) | fn byte_to_pos(&self, byte_idx: usize) -> Position;
method char_to_pos (line 445) | fn char_to_pos(&self, char_idx: usize) -> Position;
method range_to_char_range (line 446) | fn range_to_char_range(&self, range: &Range) -> StdRange<usize>;
method char_range_to_range (line 447) | fn char_range_to_range(&self, range: StdRange<usize>) -> Range;
method apply_change (line 448) | fn apply_change(&mut self, change: &TextDocumentContentChangeEvent);
method pos_to_byte (line 453) | fn pos_to_byte(&self, pos: &Position) -> usize {
method pos_to_char (line 456) | fn pos_to_char(&self, pos: &Position) -> usize {
method byte_to_pos (line 460) | fn byte_to_pos(&self, byte_idx: usize) -> Position {
method char_to_pos (line 463) | fn char_to_pos(&self, char_idx: usize) -> Position {
method range_to_char_range (line 471) | fn range_to_char_range(&self, range: &Range) -> StdRange<usize> {
method char_range_to_range (line 474) | fn char_range_to_range(&self, range: StdRange<usize>) -> Range {
method apply_change (line 480) | fn apply_change(&mut self, change: &TextDocumentContentChangeEvent) {
method pos_to_byte (line 492) | fn pos_to_byte(&self, pos: &Position) -> usize {
method pos_to_char (line 495) | fn pos_to_char(&self, pos: &Position) -> usize {
method byte_to_pos (line 499) | fn byte_to_pos(&self, byte_idx: usize) -> Position {
method char_to_pos (line 502) | fn char_to_pos(&self, char_idx: usize) -> Position {
method range_to_char_range (line 510) | fn range_to_char_range(&self, range: &Range) -> StdRange<usize> {
method char_range_to_range (line 513) | fn char_range_to_range(&self, range: StdRange<usize>) -> Range {
method apply_change (line 519) | fn apply_change(&mut self, _: &TextDocumentContentChangeEvent) {
function test_open_and_change (line 531) | fn test_open_and_change() {
function test_fault_tolerance (line 585) | fn test_fault_tolerance() {
function test_header (line 616) | fn test_header() {
FILE: src/support.rs
function test_init (line 1) | pub fn test_init() {
FILE: veridian-slang/build.rs
type Result (line 7) | type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
function download_slang (line 9) | fn download_slang(download_to: &Path) -> Result<PathBuf> {
function build_slang (line 35) | fn build_slang(slang_src: &Path, slang_install: &Path) {
function build_slang_wrapper (line 43) | fn build_slang_wrapper(slang: &Path, wrapper_install: &Path) {
function main (line 51) | fn main() -> Result<()> {
FILE: veridian-slang/slang_wrapper/src/BasicClient.h
function namespace (line 14) | namespace slang {
FILE: veridian-slang/slang_wrapper/src/FormatBuffer.h
function namespace (line 13) | namespace slang {
FILE: veridian-slang/slang_wrapper/src/basic_client.cpp
type slang (line 13) | namespace slang {
function getSeverityColor (line 23) | static fmt::terminal_color getSeverityColor(DiagnosticSeverity severit...
FILE: veridian-slang/slang_wrapper/src/slang_lib.cpp
function delete_report (line 128) | void delete_report(char* report) {
FILE: veridian-slang/src/lib.rs
function slang_compile (line 9) | pub fn slang_compile(paths: Vec<PathBuf>) -> Result<String, Box<dyn erro...
function test_paths_wrapper (line 47) | fn test_paths_wrapper() {
FILE: veridian-slang/src/wrapper.rs
function test_path (line 14) | fn test_path() {
function test_paths (line 38) | fn test_paths() {
function test_compilation_multi (line 88) | fn test_compilation_multi() {
Condensed preview — 50 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (326K chars).
[
{
"path": ".github/workflows/ci.yml",
"chars": 5893,
"preview": "on:\n push:\n pull_request:\n workflow_dispatch:\n schedule:\n - cron: '0 0 * * 0'\n\nname: CI\n\njobs:\n t"
},
{
"path": ".gitignore",
"chars": 213,
"preview": "# Generated by Cargo\n# will have compiled files and executables\ndebug/\ntarget/\n\n# These are backup files generated by ru"
},
{
"path": "Cargo.toml",
"chars": 671,
"preview": "[package]\nname = \"veridian\"\nversion = \"0.1.0\"\nauthors = [\"Vivek Malneedi <vivekmalneedi@gmail.com>\"]\nedition = \"2018\"\n\n["
},
{
"path": "LICENSE",
"chars": 1071,
"preview": "MIT License\n\nCopyright (c) 2021 Vivek Malneedi\n\nPermission is hereby granted, free of charge, to any person obtaining a "
},
{
"path": "README.md",
"chars": 5035,
"preview": "# veridian\n\n\n.Linter.Config} */\n// eslint-disable-next-line no-undef\nmodule.exports = {\n\troot: true,\n\tparse"
},
{
"path": "extensions/vscode/.eslintrc.json",
"chars": 378,
"preview": "{\r\n\t\"parser\": \"@typescript-eslint/parser\",\r\n\t\"parserOptions\": {\r\n\t\t\"ecmaVersion\": 6,\r\n\t\t\"sourceType\": \"module\"\r\n\t},\r\n\t\"e"
},
{
"path": "extensions/vscode/.gitignore",
"chars": 37,
"preview": "out\nnode_modules\n.vscode-test\n*.vsix\n"
},
{
"path": "extensions/vscode/.vscodeignore",
"chars": 114,
"preview": ".vscode/**\r\n**/*.ts\r\n**/*.map\r\n.gitignore\r\n**/tsconfig.json\r\n**/tsconfig.base.json\r\ncontributing.md\r\n.travis.yml\r\n"
},
{
"path": "extensions/vscode/LICENSE",
"chars": 1071,
"preview": "MIT License\n\nCopyright (c) 2021 Vivek Malneedi\n\nPermission is hereby granted, free of charge, to any person obtaining a "
},
{
"path": "extensions/vscode/README.md",
"chars": 321,
"preview": "# veridian\n\na vscode client extension for the veridian language server.\n\n- veridian must be installed seperately, see ht"
},
{
"path": "extensions/vscode/package.json",
"chars": 2690,
"preview": "{\n \"name\": \"veridian\",\n \"description\": \"A client for the Veridian Language Server for SystemVerilog/Verilog\",\n "
},
{
"path": "extensions/vscode/src/extension.ts",
"chars": 1663,
"preview": "/* --------------------------------------------------------------------------------------------\n * Copyright (c) Microso"
},
{
"path": "extensions/vscode/syntaxes/systemverilog.tmLanguage.json",
"chars": 29169,
"preview": "{\n \"$schema\": \"https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json\",\n \"fileTypes\": [\n \"s"
},
{
"path": "extensions/vscode/tsconfig.json",
"chars": 234,
"preview": "{\r\n\t\"compilerOptions\": {\r\n\t\t\"module\": \"commonjs\",\r\n\t\t\"target\": \"es2019\",\r\n\t\t\"lib\": [\"ES2019\"],\r\n\t\t\"outDir\": \"out\",\r\n\t\t\"r"
},
{
"path": "extensions/vscode/tsconfig.tsbuildinfo",
"chars": 49,
"preview": "{\"root\":[\"./src/extension.ts\"],\"version\":\"5.9.3\"}"
},
{
"path": "rustfmt.toml",
"chars": 33,
"preview": "edition = \"2018\"\nmax_width = 100\n"
},
{
"path": "src/completion/keyword.rs",
"chars": 9856,
"preview": "use tower_lsp::lsp_types::*;\n\npub fn keyword_completions(keywords: &[(&str, &str)]) -> Vec<CompletionItem> {\n let mut"
},
{
"path": "src/completion.rs",
"chars": 27061,
"preview": "use crate::server::LSPServer;\nuse crate::sources::LSPSupport;\nuse log::{debug, trace};\nuse ropey::{Rope, RopeSlice};\nuse"
},
{
"path": "src/definition/def_types.rs",
"chars": 28733,
"preview": "use crate::sources::LSPSupport;\nuse log::trace;\nuse ropey::Rope;\nuse tower_lsp::lsp_types::*;\n\n/// cleanup the text of a"
},
{
"path": "src/definition/extract_defs.rs",
"chars": 92819,
"preview": "use crate::definition::def_types::*;\nuse crate::definition::match_definitions;\nuse sv_parser::*;\nuse tower_lsp::lsp_type"
},
{
"path": "src/definition.rs",
"chars": 17212,
"preview": "use crate::definition::extract_defs::get_ident;\nuse crate::server::LSPServer;\nuse crate::sources::LSPSupport;\nuse log::{"
},
{
"path": "src/diagnostics.rs",
"chars": 15929,
"preview": "use crate::server::ProjectConfig;\n#[cfg(feature = \"slang\")]\nuse path_clean::PathClean;\nuse regex::Regex;\nuse ropey::Rope"
},
{
"path": "src/format.rs",
"chars": 4534,
"preview": "use crate::server::LSPServer;\nuse crate::sources::LSPSupport;\nuse log::info;\nuse ropey::Rope;\nuse std::process::{Command"
},
{
"path": "src/lib.rs",
"chars": 156,
"preview": "#![recursion_limit = \"256\"]\n\npub mod completion;\npub mod definition;\npub mod diagnostics;\npub mod format;\npub mod server"
},
{
"path": "src/main.rs",
"chars": 851,
"preview": "#![recursion_limit = \"256\"]\n\nuse log::info;\nuse std::sync::Arc;\nuse structopt::StructOpt;\nuse tower_lsp::{LspService, Se"
},
{
"path": "src/server.rs",
"chars": 12219,
"preview": "use crate::sources::*;\n\nuse crate::completion::keyword::*;\nuse flexi_logger::LoggerHandle;\nuse log::{debug, info, warn};"
},
{
"path": "src/sources.rs",
"chars": 22959,
"preview": "use crate::definition::def_types::*;\nuse crate::definition::get_scopes;\nuse crate::diagnostics::{get_diagnostics, is_hid"
},
{
"path": "src/support.rs",
"chars": 111,
"preview": "pub fn test_init() {\n let _ = flexi_logger::Logger::with(flexi_logger::LogSpecification::info()).start();\n}\n"
},
{
"path": "test_data/complete.sv",
"chars": 201,
"preview": "interface test(logic clk);\n logic a;\n logic b;\n modport in (input clk, a , b);\n modport out (output clk, a, "
},
{
"path": "test_data/definition_test.sv",
"chars": 642,
"preview": "interface simple_bus (input logic clk); // Define the interface\n logic req, gnt;\n logic [7:0] addr, data;\n logi"
},
{
"path": "test_data/diag/diag_test.sv",
"chars": 67,
"preview": "module test;\n logic [1:0] abc;\n\n assign abc[2] = 1'b0;\nendmodule\n"
},
{
"path": "test_data/ind.sv",
"chars": 60,
"preview": "module test;\n logic abc;\n logic abcd;\n\n a\nendmodule\n\n"
},
{
"path": "test_data/interface_obj.sv",
"chars": 427,
"preview": "interface ebus_i;\n integer I;\n // reference to I not allowed through modport mp\n typedef enum {Y,N} choice;\n "
},
{
"path": "test_data/simple_bus.svh",
"chars": 578,
"preview": "interface simple_bus (input logic clk); // Define the interface\n logic req, gnt;\n logic [7:0] addr, data;\n logi"
},
{
"path": "test_data/test_inter.sv",
"chars": 96,
"preview": "interface simple_bus;\n logic clk;\nendinterface\n\nmodule test2;\n simple_bus b ();\nendmodule\n"
},
{
"path": "test_data/top.sv",
"chars": 46,
"preview": "module test;\n simple_bus bus ();\nendmodule\n"
},
{
"path": "test_data/top_inc.sv",
"chars": 92,
"preview": "`timescale 1ns/1ps\n`include \"simple_bus.svh\"\n\nmodule test;\n simple_bus bus ();\nendmodule\n"
},
{
"path": "test_data/verilator_errors.txt",
"chars": 446,
"preview": "%Error: test.sv:6: syntax error, unexpected endmodule, expecting IDENTIFIER endmodule\n%Error: test.sv:6:1: syntax error,"
},
{
"path": "veridian-slang/Cargo.toml",
"chars": 447,
"preview": "[package]\nname = \"veridian_slang\"\nversion = \"0.1.0\"\nauthors = [\"Vivek Malneedi <vivekmalneedi@gmail.com>\"]\nedition = \"20"
},
{
"path": "veridian-slang/build.rs",
"chars": 3686,
"preview": "use flate2::read::GzDecoder;\nuse std::env;\nuse std::fs::{self, File};\nuse std::path::{Path, PathBuf};\nuse tar::Archive;\n"
},
{
"path": "veridian-slang/slang_wrapper/CMakeLists.txt",
"chars": 555,
"preview": "cmake_minimum_required(VERSION 3.20)\n\nproject(\n slang_wrapper\n LANGUAGES CXX\n)\n\n# Keep the version the same as the"
},
{
"path": "veridian-slang/slang_wrapper/src/BasicClient.h",
"chars": 1382,
"preview": "//------------------------------------------------------------------------------\n//! @file BasicClient.h\n//! @brief Diag"
},
{
"path": "veridian-slang/slang_wrapper/src/FormatBuffer.h",
"chars": 2009,
"preview": "//------------------------------------------------------------------------------\n// FormatBuffer.h\n// Internal string fo"
},
{
"path": "veridian-slang/slang_wrapper/src/basic_client.cpp",
"chars": 4710,
"preview": "//------------------------------------------------------------------------------\n// BasicClient.cpp\n// Diagnostic client"
},
{
"path": "veridian-slang/slang_wrapper/src/slang_lib.cpp",
"chars": 3988,
"preview": "#include \"BasicClient.h\"\n#include \"slang_wrapper.h\"\n#include <array>\n#include <iostream>\n#include <filesystem>\n#include "
},
{
"path": "veridian-slang/slang_wrapper/src/slang_wrapper.h",
"chars": 333,
"preview": "#pragma once\n\nextern \"C\" {\nvoid delete_report(char* report);\nchar* compile_source(const char* name, const char* text);\nc"
},
{
"path": "veridian-slang/src/lib.rs",
"chars": 2897,
"preview": "#![allow(dead_code)]\nuse std::error;\nuse std::ffi::{CStr, CString};\nuse std::path::PathBuf;\n\nmod wrapper;\nuse wrapper::*"
},
{
"path": "veridian-slang/src/wrapper.rs",
"chars": 4846,
"preview": "include!(concat!(env!(\"OUT_DIR\"), \"/bindings.rs\"));\n\n#[cfg(test)]\nmod tests {\n use super::*;\n use serial_test::ser"
}
]
About this extraction
This page contains the full source code of the vivekmalneedi/veridian GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 50 files (301.9 KB), approximately 71.6k tokens, and a symbol index with 317 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.