Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 73 additions & 5 deletions crates/hir/src/hir_def/declaration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,30 @@ pub enum NetStrength {
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct ParamDecl {
pub ty: DataTy,
pub kind: ParamDeclKind,
pub is_port: bool,
pub decls: DeclsRange,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum ParamDeclKind {
Parameter,
LocalParam,
}

impl ParamDeclKind {
pub fn is_overridable(self) -> bool {
matches!(self, Self::Parameter)
}

pub fn keyword(self) -> &'static str {
match self {
Self::Parameter => "parameter",
Self::LocalParam => "localparam",
}
}
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub struct GenvarDecl {
pub ty: DataTy,
Expand Down Expand Up @@ -246,40 +267,71 @@ impl LowerDeclarationCtx<'_> {
pub(crate) fn lower_param_decl_base(
&mut self,
param_decl: ast::ParameterDeclarationBase,
) -> DeclarationId {
self.lower_param_decl_base_with_context(param_decl, None, false, false)
}

pub(crate) fn lower_param_decl_base_with_context(
&mut self,
param_decl: ast::ParameterDeclarationBase,
inherited_kind: Option<ParamDeclKind>,
force_local: bool,
is_port: bool,
) -> DeclarationId {
use ast::ParameterDeclarationBase::*;
match param_decl {
ParameterDeclaration(param_decl) => self.lower_param_decl(param_decl),
ParameterDeclaration(param_decl) => {
self.lower_param_decl(param_decl, inherited_kind, force_local, is_port)
}
TypeParameterDeclaration(type_param_decl) => {
self.lower_type_param_decl(type_param_decl)
self.lower_type_param_decl(type_param_decl, inherited_kind, force_local, is_port)
}
}
}

fn lower_type_param_decl(
&mut self,
type_param_decl: ast::TypeParameterDeclaration,
inherited_kind: Option<ParamDeclKind>,
force_local: bool,
is_port: bool,
) -> DeclarationId {
let kind = lower_param_decl_kind(
type_param_decl.keyword().map(|keyword| keyword.kind()),
inherited_kind,
force_local,
);
let start = self.decls.nxt_idx();
let ty = DataTy::Builtin(
self.db.intern_ty(crate::hir_def::expr::data_ty::BuiltinDataTy::default()),
);
let decls = DeclsRange::new(start..self.decls.nxt_idx());

alloc_idx_and_src! {
ParamDecl { ty, decls } => self.declarations,
ParamDecl { ty, kind, is_port, decls } => self.declarations,
type_param_decl => self.declaration_srcs,
}
}

fn lower_param_decl(&mut self, param_decl: ast::ParameterDeclaration) -> DeclarationId {
fn lower_param_decl(
&mut self,
param_decl: ast::ParameterDeclaration,
inherited_kind: Option<ParamDeclKind>,
force_local: bool,
is_port: bool,
) -> DeclarationId {
let kind = lower_param_decl_kind(
param_decl.keyword().map(|keyword| keyword.kind()),
inherited_kind,
force_local,
);
let ty = self.expr_ctx().lower_data_ty(param_decl.type_());

let parent = self.declarations.nxt_idx().into();
let decls = self.decl_ctx().lower_declarators(param_decl.declarators(), parent);

alloc_idx_and_src! {
ParamDecl { ty, decls } => self.declarations,
ParamDecl { ty, kind, is_port, decls } => self.declarations,
param_decl => self.declaration_srcs,
}
}
Expand Down Expand Up @@ -315,3 +367,19 @@ impl LowerDeclarationCtx<'_> {
}
}
}

fn lower_param_decl_kind(
keyword: Option<TokenKind>,
inherited_kind: Option<ParamDeclKind>,
force_local: bool,
) -> ParamDeclKind {
if force_local {
return ParamDeclKind::LocalParam;
}

match keyword {
Some(TokenKind::LOCAL_PARAM_KEYWORD) => ParamDeclKind::LocalParam,
Some(TokenKind::PARAMETER_KEYWORD) => ParamDeclKind::Parameter,
_ => inherited_kind.unwrap_or(ParamDeclKind::Parameter),
}
}
40 changes: 35 additions & 5 deletions crates/hir/src/hir_def/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ use super::{
alloc_idx_and_src,
block::{BlockInfo, BlockSrc, LocalBlockId},
declaration::{
Declaration, DeclarationId, DeclarationSrc, LowerDeclaration, impl_lower_declaration,
Declaration, DeclarationId, DeclarationSrc, LowerDeclaration, ParamDeclKind,
impl_lower_declaration,
},
expr::{
Expr, ExprSrc, LowerExpr,
Expand Down Expand Up @@ -151,6 +152,19 @@ impl Module {
self.param_ports.clone()?.nth(idx)
}

pub fn overridable_param_id_by_idx(&self, idx: usize) -> Option<DeclId> {
self.declarations
.values()
.filter_map(|declaration| match declaration {
Declaration::ParamDecl(param_decl) if param_decl.kind.is_overridable() => {
Some(param_decl.decls.clone())
}
_ => None,
})
.flatten()
.nth(idx)
}

pub fn non_ansi_port_id_by_idx(&self, idx: usize) -> Option<NonAnsiPortId> {
let Ports::NonAnsi { ports, .. } = &self.ports else {
return None;
Expand Down Expand Up @@ -331,9 +345,19 @@ impl LowerModuleCtx<'_> {

pub(crate) fn lower_module_decl(&mut self, decl: ast::ModuleDeclaration) {
let header = decl.header();
let has_param_ports = header.parameters().is_some();
if let Some(param_ports) = header.parameters() {
let mut inherited_kind = ParamDeclKind::Parameter;
for decls in param_ports.declarations().children() {
self.declaration_ctx().lower_param_decl_base(decls);
let decl_id = self.declaration_ctx().lower_param_decl_base_with_context(
decls,
Some(inherited_kind),
false,
true,
);
if let Declaration::ParamDecl(param_decl) = self.module.get(decl_id) {
inherited_kind = param_decl.kind;
}
self.region_tree.handle_node(decls.syntax());
}

Expand Down Expand Up @@ -367,9 +391,15 @@ impl LowerModuleCtx<'_> {
}
NetDeclaration(net_decl) => self.declaration_ctx().lower_net_decl(net_decl).into(),
LocalVariableDeclaration(_) => continue,
ParameterDeclarationStatement(param_decl) => {
self.declaration_ctx().lower_param_decl_base(param_decl.parameter()).into()
}
ParameterDeclarationStatement(param_decl) => self
.declaration_ctx()
.lower_param_decl_base_with_context(
param_decl.parameter(),
None,
has_param_ports,
false,
)
.into(),
TypedefDeclaration(typedef_decl) => self.lower_typedef(typedef_decl).into(),
GenvarDeclaration(genvar_decl) => {
self.declaration_ctx().lower_genvar_decl(genvar_decl).into()
Expand Down
4 changes: 2 additions & 2 deletions crates/ide/src/code_action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ pub use diagnostics::{
pub(crate) use edits::{apply_missing_list_edit, line_indent};
pub(crate) use engine::code_action;
pub(crate) use module_members::{
all_parameter_names, leading_parameter_names, missing_member_entry_text, port_names,
remaining_ordered_port_names,
all_overridable_parameter_names, leading_overridable_parameter_names,
missing_member_entry_text, port_names, remaining_ordered_port_names,
};

#[cfg(test)]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
//- repair: MissingParameter
module child #(localparam int L = 1, int H = 2, parameter int A = 3, int B = 4) (); endmodule
module top; child #(/*caret*/.A(1)) u(); endmodule
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
//- repair: MissingParameter
module child #(parameter A = 1, parameter B = 2) (); localparam L = 3; endmodule
module top; localparam L = 4; child #(/*caret*/.A(1)) u(); endmodule
8 changes: 4 additions & 4 deletions crates/ide/src/code_action/handlers/add_missing_parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ use utils::get::{Get, GetRef};
use crate::{
code_action::{
CodeActionCollector, CodeActionCtx, CodeActionId, CodeActionKind, RepairKind,
all_parameter_names, apply_missing_list_edit, leading_parameter_names,
missing_member_entry_text,
all_overridable_parameter_names, apply_missing_list_edit,
leading_overridable_parameter_names, missing_member_entry_text,
},
module_resolution::resolve_hir_instantiation_target,
};
Expand Down Expand Up @@ -65,7 +65,7 @@ pub(super) fn add_missing_parameters(
.unwrap_or_default();

let names: Vec<_> = if is_ordered {
leading_parameter_names(&target_module)
leading_overridable_parameter_names(&target_module)
.into_iter()
.skip(instantiation.param_assigns.len())
.collect()
Expand All @@ -81,7 +81,7 @@ pub(super) fn add_missing_parameters(
}
}

all_parameter_names(&target_module)
all_overridable_parameter_names(&target_module)
.into_iter()
.filter(|name| !assigned_names.contains(name))
.collect()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use utils::get::{Get, GetRef};
use crate::{
code_action::{
CodeActionCollector, CodeActionCtx, CodeActionId, CodeActionKind, RepairKind,
leading_parameter_names, port_names,
leading_overridable_parameter_names, port_names,
},
module_resolution::resolve_hir_instantiation_target,
};
Expand Down Expand Up @@ -115,7 +115,7 @@ pub(super) fn convert_ordered_params(
let instantiation = module.get(instantiation_id);
let target_module_id = resolve_hir_instantiation_target(db, ctx.file_id(), instantiation)?;
let target_module = db.module(target_module_id);
let param_names = leading_parameter_names(&target_module);
let param_names = leading_overridable_parameter_names(&target_module);

let replacements = instantiation
.param_assigns
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ use utils::{

use crate::{
code_action::{
CodeActionCollector, CodeActionCtx, CodeActionId, CodeActionKind, all_parameter_names,
line_indent, port_names,
CodeActionCollector, CodeActionCtx, CodeActionId, CodeActionKind,
all_overridable_parameter_names, line_indent, port_names,
},
module_resolution::resolve_hir_instantiation_target,
};
Expand Down Expand Up @@ -61,7 +61,7 @@ pub(super) fn sort_named_parameter_assignments(
let (module, module_src_map) = db.module_with_source_map(module_id);
let instantiation = module.get(instantiation_id);
let target_module_id = resolve_hir_instantiation_target(db, ctx.file_id(), instantiation)?;
let parameter_order = all_parameter_names(&db.module(target_module_id));
let parameter_order = all_overridable_parameter_names(&db.module(target_module_id));
let parameter_order_map: FxHashMap<_, _> =
parameter_order.iter().enumerate().map(|(index, name)| (name.as_ref(), index)).collect();

Expand Down
11 changes: 8 additions & 3 deletions crates/ide/src/code_action/module_members.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,21 +38,26 @@ pub(crate) fn remaining_ordered_port_names(module: &Module, connected: usize) ->
}
}

pub(crate) fn leading_parameter_names(module: &Module) -> Vec<SmolStr> {
pub(crate) fn leading_overridable_parameter_names(module: &Module) -> Vec<SmolStr> {
module
.declarations
.values()
.take_while(|declaration| matches!(declaration, Declaration::ParamDecl(_)))
.filter(|declaration| {
matches!(declaration, Declaration::ParamDecl(param_decl) if param_decl.kind.is_overridable())
})
.flat_map(|declaration| declaration.decls())
.filter_map(|decl| module.get(decl).name.clone())
.collect()
}

pub(crate) fn all_parameter_names(module: &Module) -> Vec<SmolStr> {
pub(crate) fn all_overridable_parameter_names(module: &Module) -> Vec<SmolStr> {
module
.declarations
.values()
.filter(|declaration| matches!(declaration, Declaration::ParamDecl(_)))
.filter(|declaration| {
matches!(declaration, Declaration::ParamDecl(param_decl) if param_decl.kind.is_overridable())
})
.flat_map(|declaration| declaration.decls())
.filter_map(|decl| module.get(decl).name.clone())
.collect()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ reformat_number_literal_requires_enough_digits:
- Convert literal to hexadecimal
missing_parameter_repair_is_not_offered_when_nothing_is_missing:
<none>
missing_parameter_repair_skips_body_params_when_header_has_parameter_ports:
<none>
named_port_shorthand_collapse_requires_same_name:
<none>
named_port_shorthand_requires_all_connections_named:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
source: crates/ide/src/code_action/tests.rs
expression: fixed
input_file: crates/ide/src/code_action/fixtures/code_actions/missing_parameter_honors_parameter_port_keyword_inheritance.sv
---
module child #(localparam int L = 1, int H = 2, parameter int A = 3, int B = 4) (); endmodule
module top; child #(.A(1), .B()) u(); endmodule
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
source: crates/ide/src/code_action/tests.rs
expression: fixed
input_file: crates/ide/src/code_action/fixtures/code_actions/missing_parameter_skips_localparams.sv
---
module child #(parameter A = 1, parameter B = 2) (); localparam L = 3; endmodule
module top; localparam L = 4; child #(.A(1), .B()) u(); endmodule
5 changes: 5 additions & 0 deletions crates/ide/src/code_action/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,11 @@ fn code_action_availability_matrix() {
kind: LabelCaseKind::Repair(RepairKind::MissingParameter),
text: "module child #(parameter A = 1) (); endmodule\nmodule top; child #(/*caret*/.A(1)) u(); endmodule\n",
},
LabelCase {
name: "missing_parameter_repair_skips_body_params_when_header_has_parameter_ports",
kind: LabelCaseKind::Repair(RepairKind::MissingParameter),
text: "module child #(parameter A = 1) (); parameter B = 2; endmodule\nmodule top; child #(/*caret*/.A(1)) u(); endmodule\n",
},
LabelCase {
name: "named_port_shorthand_collapse_requires_same_name",
kind: LabelCaseKind::NoDiagnostics,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
module child #(parameter A = 1) (); parameter B = 2; endmodule
module top; child #(./*caret*/) u(); endmodule
Loading
Loading