Add quickfix for unknown constructors.

This commit is contained in:
KtorZ 2023-10-21 14:24:47 +02:00
parent f6eff7ec58
commit c0513da032
No known key found for this signature in database
GPG Key ID: 33173CB6F77F4277
3 changed files with 48 additions and 13 deletions

View File

@ -90,6 +90,22 @@ impl TypedModule {
}) })
} }
pub fn has_constructor(&self, name: &str) -> bool {
self.definitions.iter().any(|def| match def {
Definition::DataType(t) if t.public && !t.opaque => t
.constructors
.iter()
.any(|constructor| constructor.name == name),
Definition::DataType(_) => false,
Definition::Fn(_) => false,
Definition::TypeAlias(_) => false,
Definition::ModuleConstant(_) => false,
Definition::Use(_) => false,
Definition::Test(_) => false,
Definition::Validator(_) => false,
})
}
pub fn validate_module_name(&self) -> Result<(), Error> { pub fn validate_module_name(&self) -> Result<(), Error> {
if self.name == "aiken" || self.name == "aiken/builtin" { if self.name == "aiken" || self.name == "aiken/builtin" {
return Err(Error::ReservedModuleName { return Err(Error::ReservedModuleName {

View File

@ -131,10 +131,7 @@ impl ParsedDocument {
unqualified: &str, unqualified: &str,
location: Span, location: Span,
) -> AnnotatedEdit { ) -> AnnotatedEdit {
let title = format!( let title = format!("Use '{}' from {}", unqualified, import.name);
"Insert new unqualified import '{}' to {}",
unqualified, import.name
);
( (
title, title,
insert_text( insert_text(
@ -151,10 +148,7 @@ impl ParsedDocument {
unqualified: &str, unqualified: &str,
location: Span, location: Span,
) -> AnnotatedEdit { ) -> AnnotatedEdit {
let title = format!( let title = format!("Use '{}' from {}", unqualified, import.name);
"Insert new unqualified import '{}' to {}",
unqualified, import.name
);
( (
title, title,
insert_text( insert_text(
@ -171,10 +165,7 @@ impl ParsedDocument {
unqualified: &str, unqualified: &str,
location: Span, location: Span,
) -> AnnotatedEdit { ) -> AnnotatedEdit {
let title = format!( let title = format!("Use '{}' from {}", unqualified, import.name);
"Add new unqualified import '{}' to {}",
unqualified, import.name
);
( (
title, title,
insert_text( insert_text(

View File

@ -5,13 +5,16 @@ use crate::{
use std::collections::HashMap; use std::collections::HashMap;
const UNKNOWN_VARIABLE: &str = "aiken::check::unknown::variable"; const UNKNOWN_VARIABLE: &str = "aiken::check::unknown::variable";
const UNKNOWN_MODULE: &str = "aiken::check::unknown::module";
const UNKNOWN_TYPE: &str = "aiken::check::unknown::type"; const UNKNOWN_TYPE: &str = "aiken::check::unknown::type";
const UNKNOWN_CONSTRUCTOR: &str = "aiken::check::unknown::type_constructor";
const UNKNOWN_MODULE: &str = "aiken::check::unknown::module";
/// Errors for which we can provide quickfixes /// Errors for which we can provide quickfixes
#[allow(clippy::enum_variant_names)]
pub enum Quickfix { pub enum Quickfix {
UnknownIdentifier, UnknownIdentifier,
UnknownModule, UnknownModule,
UnknownConstructor,
} }
fn match_code(diagnostic: &lsp_types::Diagnostic, expected: &str) -> bool { fn match_code(diagnostic: &lsp_types::Diagnostic, expected: &str) -> bool {
@ -35,6 +38,10 @@ pub fn assert(diagnostic: &lsp_types::Diagnostic) -> Option<Quickfix> {
return Some(Quickfix::UnknownIdentifier); return Some(Quickfix::UnknownIdentifier);
} }
if match_code(diagnostic, UNKNOWN_CONSTRUCTOR) {
return Some(Quickfix::UnknownConstructor);
}
if match_code(diagnostic, UNKNOWN_MODULE) { if match_code(diagnostic, UNKNOWN_MODULE) {
return Some(Quickfix::UnknownModule); return Some(Quickfix::UnknownModule);
} }
@ -55,6 +62,9 @@ pub fn quickfix(
let edits = match quickfix { let edits = match quickfix {
Quickfix::UnknownIdentifier => unknown_identifier(compiler, parsed_document, data), Quickfix::UnknownIdentifier => unknown_identifier(compiler, parsed_document, data),
Quickfix::UnknownModule => unknown_module(compiler, parsed_document, data), Quickfix::UnknownModule => unknown_module(compiler, parsed_document, data),
Quickfix::UnknownConstructor => {
unknown_constructor(compiler, parsed_document, data)
}
}; };
for (title, edit) in edits.into_iter() { for (title, edit) in edits.into_iter() {
@ -99,6 +109,24 @@ fn unknown_identifier(
edits edits
} }
fn unknown_constructor(
compiler: &LspProject,
parsed_document: &ParsedDocument,
constructor_name: &str,
) -> Vec<AnnotatedEdit> {
let mut edits = Vec::new();
for module in compiler.project.modules() {
if module.ast.has_constructor(constructor_name) {
if let Some(edit) = parsed_document.import(&module, Some(constructor_name)) {
edits.push(edit)
}
}
}
edits
}
fn unknown_module( fn unknown_module(
compiler: &LspProject, compiler: &LspProject,
parsed_document: &ParsedDocument, parsed_document: &ParsedDocument,