Skip to content

Commit 0fd0537

Browse files
committed
Use syntax AST for resource field checks
1 parent b3999b3 commit 0fd0537

2 files changed

Lines changed: 12 additions & 62 deletions

File tree

src/analyzer.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::checks;
33
use crate::diagnostic::Diagnostic;
44
use crate::hir::{FunctionSig, Hir, HirTypeKind};
55
use crate::lexer::{Token, lex};
6-
use crate::syntax::ast::Callee;
6+
use crate::syntax::ast::{Callee, Item};
77
use crate::syntax::parse_source;
88

99
pub fn analyze_source(file: &str, source: &str) -> Vec<Diagnostic> {
@@ -137,16 +137,19 @@ impl Analyzer<'_> {
137137
}
138138

139139
fn check_resource_fields(&mut self) {
140-
for decl in self.program.types.values() {
140+
for item in &self.syntax_program.items {
141+
let Item::Type(decl) = item else {
142+
continue;
143+
};
141144
if self.hir.type_kind(&decl.name) == Some(HirTypeKind::Resource) {
142145
continue;
143146
}
144147
for field in &decl.fields {
145-
if self.hir.type_kind(&field.type_name) == Some(HirTypeKind::Resource) {
148+
if self.hir.type_kind(&field.ty.name) == Some(HirTypeKind::Resource) {
146149
self.diagnostics.push(
147150
Diagnostic::error(
148151
"RS0701",
149-
format!("resource `{}` cannot be stored in `{}`.", field.type_name, decl.name),
152+
format!("resource `{}` cannot be stored in `{}`.", field.ty.name, decl.name),
150153
field.span.clone(),
151154
"resource field",
152155
)

src/ast.rs

Lines changed: 5 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,6 @@ pub enum FileMode {
99
UsesLocal,
1010
}
1111

12-
#[derive(Debug, Clone)]
13-
pub struct FieldDecl {
14-
pub type_name: String,
15-
pub span: Span,
16-
}
17-
18-
#[derive(Debug, Clone)]
19-
pub struct TypeDecl {
20-
pub name: String,
21-
pub fields: Vec<FieldDecl>,
22-
}
23-
2412
#[derive(Debug, Clone)]
2513
pub struct Param {
2614
pub name: String,
@@ -39,7 +27,6 @@ pub struct FunctionDecl {
3927
#[derive(Debug, Default)]
4028
pub struct Program {
4129
pub mode: Option<(FileMode, Span)>,
42-
pub types: HashMap<String, TypeDecl>,
4330
pub functions: HashMap<String, FunctionDecl>,
4431
}
4532

@@ -66,7 +53,7 @@ impl Parser<'_> {
6653
self.parse_mode();
6754
} else if self.at_ident("class") || self.at_ident("struct") || self.at_ident("resource")
6855
{
69-
self.parse_type_decl();
56+
self.skip_type_decl();
7057
} else if self.at_ident("pub") || self.at_ident("async") || self.at_ident("fn") {
7158
self.parse_function_decl();
7259
} else {
@@ -94,52 +81,17 @@ impl Parser<'_> {
9481
self.index += 1;
9582
}
9683

97-
fn parse_type_decl(&mut self) {
84+
fn skip_type_decl(&mut self) {
9885
self.index += 1;
99-
let Some(name) = self.take_ident_name() else {
86+
if self.take_ident_name().is_none() {
10087
return;
101-
};
102-
let mut fields = Vec::new();
88+
}
10389
if !self.at_symbol("{") {
10490
return;
10591
}
106-
self.index += 1;
10792
let body_end = self
108-
.find_matching(self.index - 1, "{", "}")
93+
.find_matching(self.index, "{", "}")
10994
.unwrap_or(self.tokens.len() - 1);
110-
let mut i = self.index;
111-
while i < body_end {
112-
if self.tokens[i].is_ident_text("drop") {
113-
i = skip_block(self.tokens, i).unwrap_or(body_end);
114-
continue;
115-
}
116-
let field_name_index = i;
117-
if ident_name(&self.tokens[field_name_index]).is_some()
118-
&& self
119-
.tokens
120-
.get(field_name_index + 1)
121-
.is_some_and(|token| token.symbol(":"))
122-
{
123-
let mut type_start = field_name_index + 2;
124-
let is_handle = self
125-
.tokens
126-
.get(type_start)
127-
.is_some_and(|token| token.is_ident_text("handle"));
128-
if is_handle {
129-
type_start += 1;
130-
}
131-
if let Some(type_name) = first_type_name(self.tokens, type_start, body_end) {
132-
fields.push(FieldDecl {
133-
type_name,
134-
span: self.tokens[field_name_index].span.clone(),
135-
});
136-
}
137-
}
138-
i += 1;
139-
}
140-
self.program
141-
.types
142-
.insert(name.clone(), TypeDecl { name, fields });
14395
self.index = body_end + 1;
14496
}
14597

@@ -292,11 +244,6 @@ pub fn find_matching(
292244
None
293245
}
294246

295-
fn skip_block(tokens: &[Token], start: usize) -> Option<usize> {
296-
let open = (start..tokens.len()).find(|index| tokens[*index].symbol("{"))?;
297-
find_matching(tokens, open, "{", "}").map(|index| index + 1)
298-
}
299-
300247
fn first_type_name(tokens: &[Token], start: usize, end: usize) -> Option<String> {
301248
(start..end).find_map(|index| match &tokens[index].kind {
302249
TokenKind::Ident(value) => Some(value.clone()),

0 commit comments

Comments
 (0)