Skip to content

Commit d3bd6d3

Browse files
GearsDatapackslpil
authored andcommitted
Store information in TypedExpr::Invalid
1 parent 47f0abd commit d3bd6d3

File tree

7 files changed

+95
-73
lines changed

7 files changed

+95
-73
lines changed

compiler-core/src/analyse.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,7 @@ impl<'a, A> ModuleAnalyzer<'a, A> {
628628
start: body_location.end,
629629
end: body_location.end,
630630
},
631+
extra_information: None,
631632
}));
632633
let implementations = Implementations::supporting_all();
633634
(

compiler-core/src/ast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ mod untyped;
66
mod tests;
77
pub mod visit;
88

9-
pub use self::typed::TypedExpr;
9+
pub use self::typed::{InvalidExpression, TypedExpr};
1010
pub use self::untyped::{FunctionLiteralKind, UntypedExpr};
1111

1212
pub use self::constant::{Constant, TypedConstant, UntypedConstant};

compiler-core/src/ast/typed.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,10 @@ pub enum TypedExpr {
188188
Invalid {
189189
location: SrcSpan,
190190
type_: Arc<Type>,
191+
/// Extra information about the invalid expression, useful for providing
192+
/// addition help or information, such as code actions to fix invalid
193+
/// states.
194+
extra_information: Option<InvalidExpression>,
191195
},
192196
}
193197

@@ -1162,3 +1166,11 @@ impl bit_array::GetLiteralValue for TypedExpr {
11621166
}
11631167
}
11641168
}
1169+
1170+
#[derive(Debug, Clone, PartialEq, Eq)]
1171+
pub enum InvalidExpression {
1172+
ModuleSelect {
1173+
module_name: EcoString,
1174+
label: EcoString,
1175+
},
1176+
}

compiler-core/src/ast/visit.rs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
4141
use crate::{
4242
analyse::Inferred,
43-
ast::{BitArraySize, TypedBitArraySize},
43+
ast::{BitArraySize, TypedBitArraySize, typed::InvalidExpression},
4444
exhaustiveness::CompiledCase,
4545
type_::{
4646
ModuleValueConstructor, PatternConstructor, TypedCallArg, ValueConstructor,
@@ -335,8 +335,13 @@ pub trait Visit<'ast> {
335335
visit_typed_expr_negate_int(self, location, value)
336336
}
337337

338-
fn visit_typed_expr_invalid(&mut self, location: &'ast SrcSpan, type_: &'ast Arc<Type>) {
339-
visit_typed_expr_invalid(self, location, type_);
338+
fn visit_typed_expr_invalid(
339+
&mut self,
340+
location: &'ast SrcSpan,
341+
type_: &'ast Arc<Type>,
342+
extra_information: &'ast Option<InvalidExpression>,
343+
) {
344+
visit_typed_expr_invalid(self, location, type_, extra_information);
340345
}
341346

342347
fn visit_typed_statement(&mut self, stmt: &'ast TypedStatement) {
@@ -903,7 +908,11 @@ where
903908
v.visit_typed_expr_negate_bool(location, value)
904909
}
905910
TypedExpr::NegateInt { location, value } => v.visit_typed_expr_negate_int(location, value),
906-
TypedExpr::Invalid { location, type_ } => v.visit_typed_expr_invalid(location, type_),
911+
TypedExpr::Invalid {
912+
location,
913+
type_,
914+
extra_information,
915+
} => v.visit_typed_expr_invalid(location, type_, extra_information),
907916
TypedExpr::Echo {
908917
location,
909918
expression,
@@ -1843,8 +1852,12 @@ where
18431852
{
18441853
}
18451854

1846-
pub fn visit_typed_expr_invalid<'a, V>(_v: &mut V, _location: &'a SrcSpan, _type_: &'a Arc<Type>)
1847-
where
1855+
pub fn visit_typed_expr_invalid<'a, V>(
1856+
_v: &mut V,
1857+
_location: &'a SrcSpan,
1858+
_type_: &'a Arc<Type>,
1859+
_extra_information: &'a Option<InvalidExpression>,
1860+
) where
18481861
V: Visit<'a> + ?Sized,
18491862
{
18501863
}

compiler-core/src/language_server/code_action.rs

Lines changed: 41 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ use crate::{
44
Error, STDLIB_PACKAGE_NAME, analyse,
55
ast::{
66
self, ArgNames, AssignName, AssignmentKind, BitArraySegmentTruncation, BoundVariable,
7-
CallArg, CustomType, FunctionLiteralKind, ImplicitCallArgOrigin, Import, PIPE_PRECEDENCE,
8-
Pattern, PatternUnusedArguments, PipelineAssignmentKind, Publicity, RecordConstructor,
9-
SrcSpan, TodoKind, TypedArg, TypedAssignment, TypedClauseGuard, TypedExpr,
10-
TypedModuleConstant, TypedPattern, TypedPipelineAssignment, TypedRecordConstructor,
11-
TypedStatement, TypedUse, visit::Visit as _,
7+
CallArg, CustomType, FunctionLiteralKind, ImplicitCallArgOrigin, Import, InvalidExpression,
8+
PIPE_PRECEDENCE, Pattern, PatternUnusedArguments, PipelineAssignmentKind, Publicity,
9+
RecordConstructor, SrcSpan, TodoKind, TypedArg, TypedAssignment, TypedClauseGuard,
10+
TypedExpr, TypedModuleConstant, TypedPattern, TypedPipelineAssignment,
11+
TypedRecordConstructor, TypedStatement, TypedUse, visit::Visit as _,
1212
},
1313
build::{Located, Module},
1414
config::PackageConfig,
@@ -3006,7 +3006,12 @@ impl<'ast> ast::visit::Visit<'ast> for ExtractVariable<'ast> {
30063006

30073007
// We don't want to offer the action if the cursor is over some invalid
30083008
// piece of code.
3009-
fn visit_typed_expr_invalid(&mut self, location: &'ast SrcSpan, _type_: &'ast Arc<Type>) {
3009+
fn visit_typed_expr_invalid(
3010+
&mut self,
3011+
location: &'ast SrcSpan,
3012+
_type_: &'ast Arc<Type>,
3013+
_extra_information: &'ast Option<InvalidExpression>,
3014+
) {
30103015
let invalid_range = self.edits.src_span_to_lsp_range(*location);
30113016
if within(self.params.range, invalid_range) {
30123017
self.selected_expression = None;
@@ -5121,34 +5126,23 @@ impl<'ast> ast::visit::Visit<'ast> for GenerateFunction<'ast> {
51215126
ast::visit::visit_typed_function(self, fun);
51225127
}
51235128

5124-
fn visit_typed_expr_invalid(&mut self, location: &'ast SrcSpan, type_: &'ast Arc<Type>) {
5125-
let invalid_range = self.edits.src_span_to_lsp_range(*location);
5126-
if within(self.params.range, invalid_range) {
5127-
self.try_save_function_to_generate(*location, type_, None);
5128-
}
5129-
5130-
ast::visit::visit_typed_expr_invalid(self, location, type_);
5131-
}
5132-
5133-
fn visit_typed_expr_module_select(
5129+
fn visit_typed_expr_invalid(
51345130
&mut self,
5135-
_location: &'ast SrcSpan,
5136-
_field_start: &'ast u32,
5131+
location: &'ast SrcSpan,
51375132
type_: &'ast Arc<Type>,
5138-
label: &'ast EcoString,
5139-
module_name: &'ast EcoString,
5140-
_module_alias: &'ast EcoString,
5141-
constructor: &'ast ModuleValueConstructor,
5133+
extra_information: &'ast Option<InvalidExpression>,
51425134
) {
5143-
match constructor {
5144-
// Invalid module selects leave the `name` field blank
5145-
ModuleValueConstructor::Fn { name, .. } if name.is_empty() => {
5146-
self.try_save_function_from_other_module(module_name, label, type_, None);
5135+
let invalid_range = self.edits.src_span_to_lsp_range(*location);
5136+
if within(self.params.range, invalid_range) {
5137+
match extra_information {
5138+
Some(InvalidExpression::ModuleSelect { module_name, label }) => {
5139+
self.try_save_function_from_other_module(module_name, label, type_, None)
5140+
}
5141+
None => self.try_save_function_to_generate(*location, type_, None),
51475142
}
5148-
ModuleValueConstructor::Fn { .. }
5149-
| ModuleValueConstructor::Record { .. }
5150-
| ModuleValueConstructor::Constant { .. } => {}
51515143
}
5144+
5145+
ast::visit::visit_typed_expr_invalid(self, location, type_, extra_information);
51525146
}
51535147

51545148
fn visit_typed_expr_call(
@@ -5168,23 +5162,25 @@ impl<'ast> ast::visit::Visit<'ast> for GenerateFunction<'ast> {
51685162
}
51695163

51705164
match fun {
5171-
TypedExpr::Invalid { type_, location } => {
5172-
return self.try_save_function_to_generate(*location, type_, Some(arguments));
5173-
}
5174-
TypedExpr::ModuleSelect {
5175-
module_name,
5176-
label,
5165+
TypedExpr::Invalid {
51775166
type_,
5178-
constructor: ModuleValueConstructor::Fn { name, .. },
5179-
..
5180-
} if name.is_empty() => {
5167+
extra_information: Some(InvalidExpression::ModuleSelect { module_name, label }),
5168+
location: _,
5169+
} => {
51815170
return self.try_save_function_from_other_module(
51825171
module_name,
51835172
label,
51845173
type_,
51855174
Some(arguments),
51865175
);
51875176
}
5177+
TypedExpr::Invalid {
5178+
type_,
5179+
location,
5180+
extra_information: _,
5181+
} => {
5182+
return self.try_save_function_to_generate(*location, type_, Some(arguments));
5183+
}
51885184
_ => {}
51895185
}
51905186
}
@@ -5494,12 +5490,17 @@ impl<'ast, IO> ast::visit::Visit<'ast> for GenerateVariant<'ast, IO>
54945490
where
54955491
IO: FileSystemReader + FileSystemWriter + BeamCompiler + CommandExecutor + Clone,
54965492
{
5497-
fn visit_typed_expr_invalid(&mut self, location: &'ast SrcSpan, type_: &'ast Arc<Type>) {
5493+
fn visit_typed_expr_invalid(
5494+
&mut self,
5495+
location: &'ast SrcSpan,
5496+
type_: &'ast Arc<Type>,
5497+
extra_information: &'ast Option<InvalidExpression>,
5498+
) {
54985499
let invalid_range = src_span_to_lsp_range(*location, self.line_numbers);
54995500
if within(self.params.range, invalid_range) {
55005501
self.try_save_variant_to_generate(*location, type_, None);
55015502
}
5502-
ast::visit::visit_typed_expr_invalid(self, location, type_);
5503+
ast::visit::visit_typed_expr_invalid(self, location, type_, extra_information);
55035504
}
55045505

55055506
fn visit_typed_expr_call(

compiler-core/src/type_/expression.rs

Lines changed: 18 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@ use crate::{
55
ast::{
66
Arg, Assert, Assignment, AssignmentKind, BinOp, BitArrayOption, BitArraySegment,
77
CAPTURE_VARIABLE, CallArg, Clause, ClauseGuard, Constant, FunctionLiteralKind, HasLocation,
8-
ImplicitCallArgOrigin, Layer, RECORD_UPDATE_VARIABLE, RecordBeingUpdated, SrcSpan,
9-
Statement, TodoKind, TypeAst, TypedArg, TypedAssert, TypedAssignment, TypedClause,
10-
TypedClauseGuard, TypedConstant, TypedExpr, TypedMultiPattern, TypedStatement,
11-
USE_ASSIGNMENT_VARIABLE, UntypedArg, UntypedAssert, UntypedAssignment, UntypedClause,
12-
UntypedClauseGuard, UntypedConstant, UntypedConstantBitArraySegment, UntypedExpr,
13-
UntypedExprBitArraySegment, UntypedMultiPattern, UntypedStatement, UntypedUse,
14-
UntypedUseAssignment, Use, UseAssignment,
8+
ImplicitCallArgOrigin, InvalidExpression, Layer, RECORD_UPDATE_VARIABLE,
9+
RecordBeingUpdated, SrcSpan, Statement, TodoKind, TypeAst, TypedArg, TypedAssert,
10+
TypedAssignment, TypedClause, TypedClauseGuard, TypedConstant, TypedExpr,
11+
TypedMultiPattern, TypedStatement, USE_ASSIGNMENT_VARIABLE, UntypedArg, UntypedAssert,
12+
UntypedAssignment, UntypedClause, UntypedClauseGuard, UntypedConstant,
13+
UntypedConstantBitArraySegment, UntypedExpr, UntypedExprBitArraySegment,
14+
UntypedMultiPattern, UntypedStatement, UntypedUse, UntypedUseAssignment, Use,
15+
UseAssignment,
1516
},
1617
build::Target,
1718
exhaustiveness::{self, CompileCaseResult, CompiledCase, Reachability},
@@ -728,6 +729,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
728729
TypedExpr::Invalid {
729730
location,
730731
type_: self.new_unbound_var(),
732+
extra_information: None,
731733
}
732734
}
733735

@@ -1420,10 +1422,9 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
14201422
}
14211423
}
14221424
// If module access failed because the module exists but that module does not export
1423-
// the referenced value, we return a `TypedExpr::ModuleSelect` instead of
1424-
// `TypedExpr::Invalid`, so that we have information about the attempted module select
1425-
// and can use it, for example, in the "Generate function" code action to support other
1426-
// modules.
1425+
// the referenced value, we return extra information about the invalid module select,
1426+
// so that we have information about the attempted module select and can use it, for
1427+
// example, in the "Generate function" code action to support other modules.
14271428
(
14281429
_,
14291430
Some((
@@ -1446,23 +1447,10 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
14461447
type_with_same_name,
14471448
context,
14481449
});
1449-
TypedExpr::ModuleSelect {
1450+
TypedExpr::Invalid {
14501451
location,
1451-
field_start: label_location.start,
14521452
type_: self.new_unbound_var(),
1453-
label,
1454-
module_alias: module_name.clone(),
1455-
module_name,
1456-
constructor: ModuleValueConstructor::Fn {
1457-
location,
1458-
module: "".into(),
1459-
name: "".into(),
1460-
external_erlang: None,
1461-
external_javascript: None,
1462-
field_map: None,
1463-
documentation: None,
1464-
purity: Purity::Unknown,
1465-
},
1453+
extra_information: Some(InvalidExpression::ModuleSelect { module_name, label }),
14661454
}
14671455
}
14681456
// If module access failed for some other reason, and no local variable shadows the
@@ -1472,6 +1460,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
14721460
TypedExpr::Invalid {
14731461
location,
14741462
type_: self.new_unbound_var(),
1463+
extra_information: None,
14751464
}
14761465
}
14771466
// In any other case use the record access for the error
@@ -1493,6 +1482,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
14931482
Err(_) => TypedExpr::Invalid {
14941483
location,
14951484
type_: self.new_unbound_var(),
1485+
extra_information: None,
14961486
},
14971487
}
14981488
}
@@ -4410,6 +4400,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
44104400
value: TypedExpr::Invalid {
44114401
location,
44124402
type_: self.new_unbound_var(),
4403+
extra_information: None,
44134404
},
44144405
implicit,
44154406
location,
@@ -4590,6 +4581,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
45904581
end: body.last().location().end,
45914582
},
45924583
type_: body_typer.new_unbound_var(),
4584+
extra_information: None,
45934585
}))
45944586
};
45954587

compiler-core/src/type_/pipe.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ impl<'a, 'b, 'c> PipeTyper<'a, 'b, 'c> {
6363
TypedExpr::Invalid {
6464
location: first_location,
6565
type_: expr_typer.new_unbound_var(),
66+
extra_information: None,
6667
}
6768
}
6869
};
@@ -149,6 +150,7 @@ impl<'a, 'b, 'c> PipeTyper<'a, 'b, 'c> {
149150
TypedExpr::Invalid {
150151
location,
151152
type_: self.expr_typer.new_unbound_var(),
153+
extra_information: None,
152154
}
153155
}
154156
};
@@ -359,6 +361,7 @@ impl<'a, 'b, 'c> PipeTyper<'a, 'b, 'c> {
359361
TypedExpr::Invalid {
360362
location: function_location,
361363
type_: self.expr_typer.new_unbound_var(),
364+
extra_information: None,
362365
}
363366
}
364367
});

0 commit comments

Comments
 (0)