Skip to content

Commit f14abbc

Browse files
committed
feat: better fault tolerant on struct field defination
1 parent 845ddc6 commit f14abbc

File tree

8 files changed

+267
-74
lines changed

8 files changed

+267
-74
lines changed

planglib/std/slice.pi

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,21 @@ pub struct SliceOutOfIdxErr {
1313

1414
fn arr_next<T:Eq<T>>(arr:[T]) [i64] {
1515
let len = arr.len();
16-
let next = [0* len];
16+
let next = [i64*len;];
1717
next[0] = -1;
1818
let i = 0;
1919
let j = -1;
2020
while i < len - 1 {
21-
if j == -1 || arr[i].eq(&arr[j]) {
21+
if j == -1 || (j >= 0 && arr[i].eq(&arr[j])) {
2222
i = i + 1;
2323
j = j + 1;
2424
next[i] = j;
2525
} else {
26-
j = next[j];
26+
if j < 0 || j >= len {
27+
j = -1;
28+
} else {
29+
j = next[j];
30+
}
2731
}
2832
}
2933
return next;
@@ -74,17 +78,22 @@ impl<T:Eq<T>> SliceExt<T> for [T] {
7478
fn index_of_kmp(sub_arr:[T]) Option<i64> {
7579
let len = self.len();
7680
let sub_len = sub_arr.len();
81+
7782
if sub_len > len || sub_len == 0{
7883
return None{};
7984
}
8085
let next = arr_next(sub_arr);
8186
let i = 0;
8287
let j = 0;
8388
while i < len {
84-
if j == -1 || (*self)[i].eq(&sub_arr[j]) {
89+
if j == -1 || (j >= 0 && j < sub_len && i < len && (*self)[i].eq(&sub_arr[j])) {
8590
i = i + 1;
8691
j = j + 1;
8792
} else {
93+
if j < 0 || j >= next.len() {
94+
// 超出有效范围,无法继续匹配
95+
return None{};
96+
}
8897
j = next[j];
8998
}
9099
if j == sub_len {

src/ast/diag.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ define_diag!(
7777
ASSIGN_CONST = "try assigning to a const value",
7878
REF_CONST = "try referencing to a const value",
7979
INVALID_STRUCT_DEF = "invalid struct definition",
80+
INVALID_STRUCT_FIELD = "invalid struct field definition",
8081
UNDEFINED_TYPE = "undefined type",
8182
UNKNOWN_TYPE = "unknown type",
8283
TYPE_CANNOT_BE_FULLY_INFERRED = "type cannot be fully inferred",

src/ast/expects/test_diag.pi.expect

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,28 @@
109109
},
110110
},
111111
},
112+
PLDiag {
113+
raw: PLDiagRaw {
114+
code: Err(
115+
INVALID_STRUCT_FIELD,
116+
),
117+
help: None,
118+
labels: [],
119+
source: None,
120+
range: Range {
121+
start: Pos {
122+
line: 186,
123+
column: 5,
124+
offset: 2083,
125+
},
126+
end: Pos {
127+
line: 187,
128+
column: 1,
129+
offset: 2085,
130+
},
131+
},
132+
},
133+
},
112134
PLDiag {
113135
raw: PLDiagRaw {
114136
code: Err(

src/ast/fmt.rs

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ use super::{
2626
tuple::{TupleInitNode, TupleTypeNode},
2727
types::{
2828
ArrayInitNode, ArrayTypeNameNode, ClosureTypeNode, GenericDefNode, GenericParamNode,
29-
PointerTypeNode, StructDefNode, StructInitFieldNode, StructInitNode, TypeNameNode,
30-
TypedIdentifierNode,
29+
ParsedField, PointerTypeNode, StructDefNode, StructInitFieldNode, StructInitNode,
30+
TypeNameNode, TypedIdentifierNode,
3131
},
3232
union::UnionDefNode,
3333
FmtTrait, NodeEnum, TypeNodeEnum,
@@ -213,17 +213,27 @@ impl FmtBuilder {
213213
for field in &node.fields {
214214
self.enter();
215215
self.prefix();
216-
if let Some((modi, _)) = field.modifier {
217-
self.token(modi.get_str());
218-
self.space();
219-
}
220-
self.token(field.id.id.name.as_str());
221-
self.colon();
222-
self.space();
223-
field.id.typenode.format(self);
224-
self.semicolon();
225-
if let Some(doc) = &field.id.doc {
226-
doc.format(self);
216+
match field {
217+
ParsedField::Normal(field) => {
218+
if let Some((modi, _)) = field.modifier {
219+
self.token(modi.get_str());
220+
self.space();
221+
}
222+
self.token(field.id.id.name.as_str());
223+
self.colon();
224+
self.space();
225+
field.id.typenode.format(self);
226+
self.semicolon();
227+
if let Some(doc) = &field.id.doc {
228+
doc.format(self);
229+
}
230+
}
231+
ParsedField::Err(err_node) => {
232+
if let NodeEnum::Err(err) = &**err_node {
233+
self.token(&err.src);
234+
}
235+
self.semicolon();
236+
}
227237
}
228238
}
229239
self.enter();

src/ast/node/types.rs

Lines changed: 79 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -443,14 +443,21 @@ pub struct StructDefNode {
443443
pub id: Box<VarNode>,
444444

445445
/// fields is all fields of a structure, the order follows the code order from top to bottom
446-
pub fields: Vec<StructField>,
446+
pub fields: Vec<ParsedField>,
447447

448448
/// generics stands for the generics arguments in the structure
449449
pub generics: Option<Box<GenericDefNode>>,
450450

451451
/// modifier indicates whether the trait is decorated by a keyword `pub`
452452
pub modifier: Option<(TokenType, Range)>,
453453
}
454+
455+
#[derive(Clone, PartialEq, Eq, Debug)]
456+
pub enum ParsedField {
457+
Normal(StructField),
458+
Err(Box<NodeEnum>),
459+
}
460+
454461
#[derive(Clone, PartialEq, Eq, Debug)]
455462
pub struct StructField {
456463
pub id: Box<TypedIdentifierNode>,
@@ -471,7 +478,14 @@ impl PrintTrait for StructDefNode {
471478
let mut i = self.fields.len();
472479
for field in &self.fields {
473480
i -= 1;
474-
field.id.print(tabs + 1, i == 0, line.clone());
481+
match field {
482+
ParsedField::Normal(field) => {
483+
field.id.print(tabs + 1, i == 0, line.clone());
484+
}
485+
ParsedField::Err(err_node) => {
486+
err_node.print(tabs + 1, i == 0, line.clone());
487+
}
488+
}
475489
}
476490
}
477491
}
@@ -488,13 +502,20 @@ impl Node for StructDefNode {
488502
generics.emit_highlight(ctx);
489503
}
490504
for field in self.fields.iter() {
491-
ctx.push_semantic_token(field.id.id.range, SemanticTokenType::PROPERTY, 0);
492-
field.id.typenode.emit_highlight(ctx);
493-
if !field.has_semi {
494-
ctx.add_diag(field.id.range.new_err(ErrorCode::COMPLETION));
495-
}
496-
if let Some(doc) = &field.id.doc {
497-
ctx.push_semantic_token(doc.range, SemanticTokenType::COMMENT, 0);
505+
match field {
506+
ParsedField::Normal(field) => {
507+
ctx.push_semantic_token(field.id.id.range, SemanticTokenType::PROPERTY, 0);
508+
field.id.typenode.emit_highlight(ctx);
509+
if !field.has_semi {
510+
ctx.add_diag(field.id.range.new_err(ErrorCode::COMPLETION));
511+
}
512+
if let Some(doc) = &field.id.doc {
513+
ctx.push_semantic_token(doc.range, SemanticTokenType::COMMENT, 0);
514+
}
515+
}
516+
ParsedField::Err(_) => {
517+
// 对于错误节点,不需要进行高亮处理
518+
}
498519
}
499520
}
500521
Ok(Default::default())
@@ -542,17 +563,24 @@ impl StructDefNode {
542563
) -> Result<(), PLDiag> {
543564
let pltype = ctx.get_type(&self.id.name, self.id.range)?;
544565
for f in self.fields.iter() {
545-
let id = &f.id;
546-
// 自引用检查
547-
if let TypeNodeEnum::Basic(b) = &*id.typenode {
548-
if let Some(id) = &b.id {
549-
if id.namespace.is_empty() {
550-
// 只有本包内类型可能自引用
551-
let v = ctx.self_ref_map.entry(id.id.name).or_default();
552-
v.insert((self.id.name, self.id.range()));
553-
ctx.check_self_ref(&id.id.name, id.range)?;
566+
match f {
567+
ParsedField::Normal(field) => {
568+
let id = &field.id;
569+
// 自引用检查
570+
if let TypeNodeEnum::Basic(b) = &*id.typenode {
571+
if let Some(id) = &b.id {
572+
if id.namespace.is_empty() {
573+
// 只有本包内类型可能自引用
574+
let v = ctx.self_ref_map.entry(id.id.name).or_default();
575+
v.insert((self.id.name, self.id.range()));
576+
ctx.check_self_ref(&id.id.name, id.range)?;
577+
}
578+
}
554579
}
555580
}
581+
ParsedField::Err(e) => {
582+
_ = e.clone().emit(ctx, builder);
583+
}
556584
}
557585
}
558586
let generic_map = if let PLType::Struct(st) = &mut *pltype.borrow_mut() {
@@ -566,32 +594,40 @@ impl StructDefNode {
566594
let clone_map = ctx.plmod.types.clone();
567595
let mut is_atomic = true;
568596
for (i, field) in self.fields.iter().enumerate() {
569-
if !field.has_semi {
570-
ctx.add_diag(field.id.range.new_err(ErrorCode::COMPLETION));
571-
}
572-
let id = field.id.id.clone();
573-
let f = Field {
574-
index: i as u32 + 1,
575-
typenode: field.id.typenode.clone(),
576-
name: id.name,
577-
range: field.id.id.range,
578-
modifier: field.modifier,
579-
};
580-
let tpre = field
581-
.id
582-
.typenode
583-
.get_type(ctx, builder, self.generics.is_none());
584-
if tpre.is_err() {
585-
continue;
586-
}
587-
let tp = tpre.unwrap();
588-
if !tp.borrow().is_atomic() {
589-
is_atomic = false;
597+
match field {
598+
ParsedField::Normal(field) => {
599+
if !field.has_semi {
600+
ctx.add_diag(field.id.range.new_err(ErrorCode::COMPLETION));
601+
}
602+
let id = field.id.id.clone();
603+
let f = Field {
604+
index: i as u32 + 1,
605+
typenode: field.id.typenode.clone(),
606+
name: id.name,
607+
range: field.id.id.range,
608+
modifier: field.modifier,
609+
};
610+
let tpre =
611+
field
612+
.id
613+
.typenode
614+
.get_type(ctx, builder, self.generics.is_none());
615+
if tpre.is_err() {
616+
continue;
617+
}
618+
let tp = tpre.unwrap();
619+
if !tp.borrow().is_atomic() {
620+
is_atomic = false;
621+
}
622+
field_pltps.push(tp.clone());
623+
ctx.set_field_refs(pltype.typ.clone(), &f, f.range);
624+
ctx.send_if_go_to_def(f.range, f.range, ctx.plmod.path);
625+
fields.insert(id.name.to_string().into(), f.clone());
626+
}
627+
ParsedField::Err(_) => {
628+
// 对于错误节点,跳过字段处理
629+
}
590630
}
591-
field_pltps.push(tp.clone());
592-
ctx.set_field_refs(pltype.typ.clone(), &f, f.range);
593-
ctx.send_if_go_to_def(f.range, f.range, ctx.plmod.path);
594-
fields.insert(id.name.to_string().into(), f.clone());
595631
}
596632
ctx.plmod.types = clone_map;
597633
if let PLType::Struct(st) = &mut *pltype.borrow_mut() {

0 commit comments

Comments
 (0)