mirror of
https://github.com/g-plane/wasm-language-tools.git
synced 2025-12-23 11:12:52 +00:00
feat(service): add "import-with-def" check
This commit is contained in:
parent
9446f048bd
commit
4647b1937f
8 changed files with 359 additions and 1 deletions
45
crates/service/src/checker/import_with_def.rs
Normal file
45
crates/service/src/checker/import_with_def.rs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
use crate::{LanguageService, helpers, uri::InternUri};
|
||||
use line_index::LineIndex;
|
||||
use lspt::{Diagnostic, DiagnosticRelatedInformation, DiagnosticSeverity, Location, Union2};
|
||||
use wat_syntax::{SyntaxKind, SyntaxNode};
|
||||
|
||||
const DIAGNOSTIC_CODE: &str = "import-with-def";
|
||||
|
||||
pub fn check(
|
||||
service: &LanguageService,
|
||||
uri: InternUri,
|
||||
line_index: &LineIndex,
|
||||
node: &SyntaxNode,
|
||||
) -> Option<Diagnostic> {
|
||||
let import = node.first_child_by_kind(&|kind| kind == SyntaxKind::IMPORT)?;
|
||||
let first = node.first_child_by_kind(&|kind| {
|
||||
!matches!(
|
||||
kind,
|
||||
SyntaxKind::EXPORT
|
||||
| SyntaxKind::IMPORT
|
||||
| SyntaxKind::TYPE_USE
|
||||
| SyntaxKind::GLOBAL_TYPE
|
||||
| SyntaxKind::MEMORY_TYPE
|
||||
| SyntaxKind::TABLE_TYPE
|
||||
)
|
||||
})?;
|
||||
let last = node.last_child()?;
|
||||
Some(Diagnostic {
|
||||
range: helpers::rowan_range_to_lsp_range(
|
||||
line_index,
|
||||
first.text_range().cover(last.text_range()),
|
||||
),
|
||||
severity: Some(DiagnosticSeverity::Error),
|
||||
source: Some("wat".into()),
|
||||
code: Some(Union2::B(DIAGNOSTIC_CODE.into())),
|
||||
message: "imported item can't contain definition".into(),
|
||||
related_information: Some(vec![DiagnosticRelatedInformation {
|
||||
location: Location {
|
||||
uri: uri.raw(service),
|
||||
range: helpers::rowan_range_to_lsp_range(line_index, import.text_range()),
|
||||
},
|
||||
message: "import declared here".into(),
|
||||
}]),
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ mod elem_type;
|
|||
mod immediates;
|
||||
mod implicit_module;
|
||||
mod import_occur;
|
||||
mod import_with_def;
|
||||
mod mem_type;
|
||||
mod multi_modules;
|
||||
mod mutated_immutable;
|
||||
|
|
@ -105,6 +106,9 @@ pub fn check(service: &LanguageService, document: Document) -> Vec<Diagnostic> {
|
|||
symbol_table,
|
||||
&node,
|
||||
);
|
||||
if let Some(diagnostic) = import_with_def::check(service, uri, line_index, &node) {
|
||||
diagnostics.push(diagnostic);
|
||||
}
|
||||
}
|
||||
SyntaxKind::MODULE_FIELD_GLOBAL => {
|
||||
typeck::check_global(
|
||||
|
|
@ -128,6 +132,9 @@ pub fn check(service: &LanguageService, document: Document) -> Vec<Diagnostic> {
|
|||
if let Some(diagnostic) = const_expr::check(line_index, &node) {
|
||||
diagnostics.push(diagnostic);
|
||||
}
|
||||
if let Some(diagnostic) = import_with_def::check(service, uri, line_index, &node) {
|
||||
diagnostics.push(diagnostic);
|
||||
}
|
||||
}
|
||||
SyntaxKind::MODULE_FIELD_IMPORT => {
|
||||
if let Some(diagnostic) = import_occur::check(line_index, &node) {
|
||||
|
|
@ -194,6 +201,9 @@ pub fn check(service: &LanguageService, document: Document) -> Vec<Diagnostic> {
|
|||
if let Some(diagnostic) = const_expr::check(line_index, &node) {
|
||||
diagnostics.push(diagnostic);
|
||||
}
|
||||
if let Some(diagnostic) = import_with_def::check(service, uri, line_index, &node) {
|
||||
diagnostics.push(diagnostic);
|
||||
}
|
||||
}
|
||||
SyntaxKind::MODULE_FIELD_ELEM => {
|
||||
if let Some(diagnostic) = elem_type::check(
|
||||
|
|
@ -208,6 +218,11 @@ pub fn check(service: &LanguageService, document: Document) -> Vec<Diagnostic> {
|
|||
diagnostics.push(diagnostic);
|
||||
}
|
||||
}
|
||||
SyntaxKind::MODULE_FIELD_MEMORY => {
|
||||
if let Some(diagnostic) = import_with_def::check(service, uri, line_index, &node) {
|
||||
diagnostics.push(diagnostic);
|
||||
}
|
||||
}
|
||||
SyntaxKind::MEMORY_TYPE => {
|
||||
mem_type::check(&mut diagnostics, line_index, &node);
|
||||
}
|
||||
|
|
@ -241,7 +256,20 @@ pub fn check(service: &LanguageService, document: Document) -> Vec<Diagnostic> {
|
|||
diagnostics.push(diagnostic);
|
||||
}
|
||||
}
|
||||
SyntaxKind::MODULE_FIELD_TAG | SyntaxKind::EXTERN_TYPE_TAG => {
|
||||
SyntaxKind::MODULE_FIELD_TAG => {
|
||||
tag_type::check(
|
||||
&mut diagnostics,
|
||||
service,
|
||||
document,
|
||||
line_index,
|
||||
symbol_table,
|
||||
&node,
|
||||
);
|
||||
if let Some(diagnostic) = import_with_def::check(service, uri, line_index, &node) {
|
||||
diagnostics.push(diagnostic);
|
||||
}
|
||||
}
|
||||
SyntaxKind::EXTERN_TYPE_TAG => {
|
||||
tag_type::check(
|
||||
&mut diagnostics,
|
||||
service,
|
||||
|
|
|
|||
80
crates/service/tests/diagnostics/import_with_def.rs
Normal file
80
crates/service/tests/diagnostics/import_with_def.rs
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
use super::*;
|
||||
use insta::assert_json_snapshot;
|
||||
use wat_service::LanguageService;
|
||||
|
||||
#[test]
|
||||
fn func() {
|
||||
let uri = "untitled:test".to_string();
|
||||
let source = r#"
|
||||
(module
|
||||
(func (import "" "a") (param i32) (result i32))
|
||||
(func (import "" "b") (param i32) (result i32) (local i32) (local)))
|
||||
"#;
|
||||
let mut service = LanguageService::default();
|
||||
service.commit(&uri, source.into());
|
||||
calm(&mut service, &uri);
|
||||
let response = service.pull_diagnostics(create_params(uri));
|
||||
assert_json_snapshot!(response);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn global() {
|
||||
let uri = "untitled:test".to_string();
|
||||
let source = r#"
|
||||
(module
|
||||
(global (import "" "a") i32)
|
||||
(global (import "" "b") i32
|
||||
i32.const 0))
|
||||
"#;
|
||||
let mut service = LanguageService::default();
|
||||
service.commit(&uri, source.into());
|
||||
calm(&mut service, &uri);
|
||||
let response = service.pull_diagnostics(create_params(uri));
|
||||
assert_json_snapshot!(response);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn memory() {
|
||||
let uri = "untitled:test".to_string();
|
||||
let source = r#"
|
||||
(module
|
||||
(memory (import "" "a") 1)
|
||||
(memory (import "" "b") (data)))
|
||||
"#;
|
||||
let mut service = LanguageService::default();
|
||||
service.commit(&uri, source.into());
|
||||
calm(&mut service, &uri);
|
||||
let response = service.pull_diagnostics(create_params(uri));
|
||||
assert_json_snapshot!(response);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn table() {
|
||||
let uri = "untitled:test".to_string();
|
||||
let source = r#"
|
||||
(module
|
||||
(table (import "" "a") 0 funcref)
|
||||
(table (import "" "b") 0 funcref
|
||||
ref.func 0)
|
||||
(func))
|
||||
"#;
|
||||
let mut service = LanguageService::default();
|
||||
service.commit(&uri, source.into());
|
||||
calm(&mut service, &uri);
|
||||
let response = service.pull_diagnostics(create_params(uri));
|
||||
assert_json_snapshot!(response);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tag() {
|
||||
let uri = "untitled:test".to_string();
|
||||
let source = r#"
|
||||
(module
|
||||
(tag (import "" "") (param i32)))
|
||||
"#;
|
||||
let mut service = LanguageService::default();
|
||||
service.commit(&uri, source.into());
|
||||
calm(&mut service, &uri);
|
||||
let response = service.pull_diagnostics(create_params(uri));
|
||||
assert!(response.items.is_empty());
|
||||
}
|
||||
|
|
@ -14,6 +14,7 @@ mod elem_type;
|
|||
mod immediates;
|
||||
mod implicit_module;
|
||||
mod import_occur;
|
||||
mod import_with_def;
|
||||
mod mem_type;
|
||||
mod multi_modules;
|
||||
mod mutated_immutable;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
---
|
||||
source: crates/service/tests/diagnostics/import_with_def.rs
|
||||
expression: response
|
||||
---
|
||||
{
|
||||
"kind": "full",
|
||||
"items": [
|
||||
{
|
||||
"range": {
|
||||
"start": {
|
||||
"line": 3,
|
||||
"character": 49
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"character": 68
|
||||
}
|
||||
},
|
||||
"severity": 1,
|
||||
"code": "import-with-def",
|
||||
"source": "wat",
|
||||
"message": "imported item can't contain definition",
|
||||
"relatedInformation": [
|
||||
{
|
||||
"location": {
|
||||
"uri": "untitled:test",
|
||||
"range": {
|
||||
"start": {
|
||||
"line": 3,
|
||||
"character": 8
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"character": 23
|
||||
}
|
||||
}
|
||||
},
|
||||
"message": "import declared here"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
---
|
||||
source: crates/service/tests/diagnostics/import_with_def.rs
|
||||
expression: response
|
||||
---
|
||||
{
|
||||
"kind": "full",
|
||||
"items": [
|
||||
{
|
||||
"range": {
|
||||
"start": {
|
||||
"line": 4,
|
||||
"character": 15
|
||||
},
|
||||
"end": {
|
||||
"line": 4,
|
||||
"character": 16
|
||||
}
|
||||
},
|
||||
"severity": 1,
|
||||
"code": "type-check",
|
||||
"source": "wat",
|
||||
"message": "expected types [i32], found [i32, i32] at the end"
|
||||
},
|
||||
{
|
||||
"range": {
|
||||
"start": {
|
||||
"line": 4,
|
||||
"character": 4
|
||||
},
|
||||
"end": {
|
||||
"line": 4,
|
||||
"character": 15
|
||||
}
|
||||
},
|
||||
"severity": 1,
|
||||
"code": "import-with-def",
|
||||
"source": "wat",
|
||||
"message": "imported item can't contain definition",
|
||||
"relatedInformation": [
|
||||
{
|
||||
"location": {
|
||||
"uri": "untitled:test",
|
||||
"range": {
|
||||
"start": {
|
||||
"line": 3,
|
||||
"character": 10
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"character": 25
|
||||
}
|
||||
}
|
||||
},
|
||||
"message": "import declared here"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
---
|
||||
source: crates/service/tests/diagnostics/import_with_def.rs
|
||||
expression: response
|
||||
---
|
||||
{
|
||||
"kind": "full",
|
||||
"items": [
|
||||
{
|
||||
"range": {
|
||||
"start": {
|
||||
"line": 3,
|
||||
"character": 26
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"character": 32
|
||||
}
|
||||
},
|
||||
"severity": 1,
|
||||
"code": "import-with-def",
|
||||
"source": "wat",
|
||||
"message": "imported item can't contain definition",
|
||||
"relatedInformation": [
|
||||
{
|
||||
"location": {
|
||||
"uri": "untitled:test",
|
||||
"range": {
|
||||
"start": {
|
||||
"line": 3,
|
||||
"character": 10
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"character": 25
|
||||
}
|
||||
}
|
||||
},
|
||||
"message": "import declared here"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
---
|
||||
source: crates/service/tests/diagnostics/import_with_def.rs
|
||||
expression: response
|
||||
---
|
||||
{
|
||||
"kind": "full",
|
||||
"items": [
|
||||
{
|
||||
"range": {
|
||||
"start": {
|
||||
"line": 4,
|
||||
"character": 14
|
||||
},
|
||||
"end": {
|
||||
"line": 4,
|
||||
"character": 15
|
||||
}
|
||||
},
|
||||
"severity": 1,
|
||||
"code": "type-check",
|
||||
"source": "wat",
|
||||
"message": "expected types [(ref null func)], found [(ref null func), (func 0)] at the end"
|
||||
},
|
||||
{
|
||||
"range": {
|
||||
"start": {
|
||||
"line": 4,
|
||||
"character": 4
|
||||
},
|
||||
"end": {
|
||||
"line": 4,
|
||||
"character": 14
|
||||
}
|
||||
},
|
||||
"severity": 1,
|
||||
"code": "import-with-def",
|
||||
"source": "wat",
|
||||
"message": "imported item can't contain definition",
|
||||
"relatedInformation": [
|
||||
{
|
||||
"location": {
|
||||
"uri": "untitled:test",
|
||||
"range": {
|
||||
"start": {
|
||||
"line": 3,
|
||||
"character": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"character": 24
|
||||
}
|
||||
}
|
||||
},
|
||||
"message": "import declared here"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue