+1015
-18
compiler-core/src/error.rs
+1015
-18
compiler-core/src/error.rs
···
2
2
use crate::build::{Origin, Outcome, Runtime, Target};
3
3
use crate::dependency::{PackageFetcher, ResolutionError};
4
4
use crate::diagnostic::{Diagnostic, ExtraLabel, Label, Location};
5
+
use crate::parse::Token;
5
6
use crate::strings::{to_snake_case, to_upper_camel_case};
6
7
use crate::type_::collapse_links;
7
8
use crate::type_::error::{
···
3757
3758
3758
3759
3759
3760
Error::Parse { path, src, error } => {
3760
-
let (label, extra) = error.details();
3761
-
let text = extra.join("\n");
3762
-
3763
-
let adjusted_location = if error.error == ParseErrorType::UnexpectedEof {
3761
+
let location = if error.error == ParseErrorType::UnexpectedEof {
3764
3762
crate::ast::SrcSpan {
3765
3763
start: (src.len() - 1) as u32,
3766
3764
end: (src.len() - 1) as u32,
···
3769
3767
error.location
3770
3768
};
3771
3769
3772
-
vec![Diagnostic {
3773
-
title: "Syntax error".into(),
3774
-
text,
3775
-
hint: None,
3776
-
level: Level::Error,
3777
-
location: Some(Location {
3778
-
label: Label {
3779
-
text: Some(label.to_string()),
3780
-
span: adjusted_location,
3770
+
let title = String::from("Syntax error");
3771
+
let diagnostic =
3772
+
match &error.error {
3773
+
ParseErrorType::ExpectedEqual =>
3774
+
Diagnostic {
3775
+
title,
3776
+
text: "".into(),
3777
+
hint: None,
3778
+
level: Level::Error,
3779
+
location: Some(Location {
3780
+
label: Label {
3781
+
text: Some("I was expecting a '=' after this".into()),
3782
+
span: location
3783
+
},
3784
+
path: path.clone(),
3785
+
src: src.clone(),
3786
+
extra_labels: vec![],
3787
+
}),
3788
+
},
3789
+
3790
+
ParseErrorType::ExpectedExpr =>
3791
+
Diagnostic {
3792
+
title,
3793
+
text: "".into(),
3794
+
hint: None,
3795
+
level: Level::Error,
3796
+
location: Some(Location {
3797
+
label: Label {
3798
+
text: Some("I was expecting an expression after this".into()),
3799
+
span: location
3800
+
},
3801
+
path: path.clone(),
3802
+
src: src.clone(),
3803
+
extra_labels: vec![],
3804
+
}),
3805
+
},
3806
+
3807
+
ParseErrorType::ExpectedName =>
3808
+
Diagnostic {
3809
+
title,
3810
+
text: "".into(),
3811
+
hint: None,
3812
+
level: Level::Error,
3813
+
location: Some(Location {
3814
+
label: Label {
3815
+
text: Some("I was expecting a name here".into()),
3816
+
span: location
3817
+
},
3818
+
path: path.clone(),
3819
+
src: src.clone(),
3820
+
extra_labels: vec![],
3821
+
}),
3822
+
},
3823
+
3824
+
ParseErrorType::ExpectedPattern =>
3825
+
Diagnostic {
3826
+
title,
3827
+
text: "".into(),
3828
+
hint: None,
3829
+
level: Level::Error,
3830
+
location: Some(Location {
3831
+
label: Label {
3832
+
text: Some("I was expecting a pattern after this".into()),
3833
+
span: location
3834
+
},
3835
+
path: path.clone(),
3836
+
src: src.clone(),
3837
+
extra_labels: vec![],
3838
+
}),
3839
+
},
3840
+
3841
+
ParseErrorType::ExpectedType =>
3842
+
Diagnostic {
3843
+
title,
3844
+
text: "See: https://tour.gleam.run/basics/assignments/".into(),
3845
+
hint: None,
3846
+
level: Level::Error,
3847
+
location: Some(Location {
3848
+
label: Label {
3849
+
text: Some("I was expecting a type after this".into()),
3850
+
span: location
3851
+
},
3852
+
path: path.clone(),
3853
+
src: src.clone(),
3854
+
extra_labels: vec![],
3855
+
}),
3856
+
},
3857
+
3858
+
ParseErrorType::ExpectedUpName =>
3859
+
Diagnostic {
3860
+
title,
3861
+
text: "".into(),
3862
+
hint: None,
3863
+
level: Level::Error,
3864
+
location: Some(Location {
3865
+
label: Label {
3866
+
text: Some("I was expecting a type name here".into()),
3867
+
span: location
3868
+
},
3869
+
path: path.clone(),
3870
+
src: src.clone(),
3871
+
extra_labels: vec![],
3872
+
}),
3873
+
},
3874
+
3875
+
ParseErrorType::ExpectedValue =>
3876
+
Diagnostic {
3877
+
title,
3878
+
text: "".into(),
3879
+
hint: None,
3880
+
level: Level::Error,
3881
+
location: Some(Location {
3882
+
label: Label {
3883
+
text: Some("I was expecting a value after this".into()),
3884
+
span: location
3885
+
},
3886
+
path: path.clone(),
3887
+
src: src.clone(),
3888
+
extra_labels: vec![],
3889
+
}),
3890
+
},
3891
+
3892
+
ParseErrorType::ExpectedDefinition =>
3893
+
Diagnostic {
3894
+
title,
3895
+
text: "".into(),
3896
+
hint: None,
3897
+
level: Level::Error,
3898
+
location: Some(Location {
3899
+
label: Label {
3900
+
text: Some("I was expecting a definition after this".into()),
3901
+
span: location
3902
+
},
3903
+
path: path.clone(),
3904
+
src: src.clone(),
3905
+
extra_labels: vec![],
3906
+
}),
3907
+
},
3908
+
3909
+
ParseErrorType::ExpectedDeprecationMessage =>
3910
+
Diagnostic {
3911
+
title,
3912
+
text: "".into(),
3913
+
hint: None,
3914
+
level: Level::Error,
3915
+
location: Some(Location {
3916
+
label: Label {
3917
+
text: Some("A deprecation attribute must have a string message.".into()),
3918
+
span: location
3919
+
},
3920
+
path: path.clone(),
3921
+
src: src.clone(),
3922
+
extra_labels: vec![],
3923
+
}),
3924
+
},
3925
+
3926
+
ParseErrorType::ExpectedFunctionDefinition =>
3927
+
Diagnostic {
3928
+
title,
3929
+
text: "".into(),
3930
+
hint: None,
3931
+
level: Level::Error,
3932
+
location: Some(Location {
3933
+
label: Label {
3934
+
text: Some("I was expecting a function definition after this".into()),
3935
+
span: location
3936
+
},
3937
+
path: path.clone(),
3938
+
src: src.clone(),
3939
+
extra_labels: vec![],
3940
+
}),
3941
+
},
3942
+
3943
+
ParseErrorType::ExpectedTargetName =>
3944
+
Diagnostic {
3945
+
title,
3946
+
text: "Try `erlang`, `javascript`.".into(),
3947
+
hint: None,
3948
+
level: Level::Error,
3949
+
location: Some(Location {
3950
+
label: Label {
3951
+
text: Some("I was expecting a target name after this".into()),
3952
+
span: location
3953
+
},
3954
+
path: path.clone(),
3955
+
src: src.clone(),
3956
+
extra_labels: vec![],
3957
+
}),
3958
+
},
3959
+
3960
+
ParseErrorType::ExtraSeparator =>
3961
+
Diagnostic {
3962
+
title,
3963
+
text: "".into(),
3964
+
hint: Some("Try removing it?".into()),
3965
+
level: Level::Error,
3966
+
location: Some(Location {
3967
+
label: Label {
3968
+
text: Some("This is an extra delimiter".into()),
3969
+
span: location
3970
+
},
3971
+
path: path.clone(),
3972
+
src: src.clone(),
3973
+
extra_labels: vec![],
3974
+
}),
3975
+
},
3976
+
3977
+
ParseErrorType::ExprLparStart =>
3978
+
Diagnostic {
3979
+
title,
3980
+
text: "".into(),
3981
+
hint: Some("To group expressions in Gleam, use \"{\" and \"}\"; tuples are created with `#(` and `)`.".into()),
3982
+
level: Level::Error,
3983
+
location: Some(Location {
3984
+
label: Label {
3985
+
text: Some("This parenthesis cannot be understood here".into()),
3986
+
span: location
3987
+
},
3988
+
path: path.clone(),
3989
+
src: src.clone(),
3990
+
extra_labels: vec![],
3991
+
}),
3992
+
},
3993
+
3994
+
ParseErrorType::IncorrectName =>
3995
+
Diagnostic {
3996
+
title,
3997
+
text: "".into(),
3998
+
hint: Some(wrap("Variable and module names start with a lowercase letter, \
3999
+
and can contain a-z, 0-9, or _.")),
4000
+
level: Level::Error,
4001
+
location: Some(Location {
4002
+
label: Label {
4003
+
text: Some("I'm expecting a lowercase name here".into()),
4004
+
span: location
4005
+
},
4006
+
path: path.clone(),
4007
+
src: src.clone(),
4008
+
extra_labels: vec![],
4009
+
}),
4010
+
},
4011
+
4012
+
ParseErrorType::IncorrectUpName =>
4013
+
Diagnostic {
4014
+
title,
4015
+
text: "".into(),
4016
+
hint: Some(wrap("Type names start with a uppercase letter, and can \
4017
+
contain a-z, A-Z, or 0-9.")),
4018
+
level: Level::Error,
4019
+
location: Some(Location {
4020
+
label: Label {
4021
+
text: Some("I'm expecting a type name here".into()),
4022
+
span: location
4023
+
},
4024
+
path: path.clone(),
4025
+
src: src.clone(),
4026
+
extra_labels: vec![],
4027
+
}),
4028
+
},
4029
+
4030
+
ParseErrorType::InvalidBitArraySegment =>
4031
+
Diagnostic {
4032
+
title,
4033
+
text: "See: https://tour.gleam.run/data-types/bit-arrays/".into(),
4034
+
hint: Some(format!("Valid BitArray segment options are:\n{}", wrap(
4035
+
"bits, bytes, int, float, utf8, utf16, utf32, utf8_codepoint, \
4036
+
utf16_codepoint, utf32_codepoint, signed, unsigned, big, little, native, size, unit.",
4037
+
))),
4038
+
level: Level::Error,
4039
+
location: Some(Location {
4040
+
label: Label {
4041
+
text: Some("This is not a valid BitArray segment option".into()),
4042
+
span: location
4043
+
},
4044
+
path: path.clone(),
4045
+
src: src.clone(),
4046
+
extra_labels: vec![],
4047
+
}),
4048
+
},
4049
+
4050
+
ParseErrorType::InvalidBitArrayUnit =>
4051
+
Diagnostic {
4052
+
title,
4053
+
text: "See: https://tour.gleam.run/data-types/bit-arrays/".into(),
4054
+
hint: Some("Unit must be an integer literal >= 1 and <= 256.".into()),
4055
+
level: Level::Error,
4056
+
location: Some(Location {
4057
+
label: Label {
4058
+
text: Some("This is not a valid BitArray unit value".into()),
4059
+
span: location
4060
+
},
4061
+
path: path.clone(),
4062
+
src: src.clone(),
4063
+
extra_labels: vec![],
4064
+
}),
4065
+
},
4066
+
4067
+
ParseErrorType::InvalidTailPattern =>
4068
+
Diagnostic {
4069
+
title,
4070
+
text: "".into(),
4071
+
hint: None,
4072
+
level: Level::Error,
4073
+
location: Some(Location {
4074
+
label: Label {
4075
+
text: Some("This part of a list pattern can only be a name or a discard".into()),
4076
+
span: location
4077
+
},
4078
+
path: path.clone(),
4079
+
src: src.clone(),
4080
+
extra_labels: vec![],
4081
+
}),
4082
+
},
4083
+
4084
+
ParseErrorType::InvalidTupleAccess =>
4085
+
Diagnostic {
4086
+
title,
4087
+
text: "".into(),
4088
+
hint: Some("Only non negative integer literals like 0, or 1_000 can be used.".into()),
4089
+
level: Level::Error,
4090
+
location: Some(Location {
4091
+
label: Label {
4092
+
text: Some("This integer is not valid for tuple access".into()),
4093
+
span: location
4094
+
},
4095
+
path: path.clone(),
4096
+
src: src.clone(),
4097
+
extra_labels: vec![],
4098
+
}),
4099
+
},
4100
+
4101
+
ParseErrorType::LexError { error: lex_err } => {
4102
+
let (label_text, text_lines) = lex_err.to_parse_error_info();
4103
+
let text = text_lines.join("\n");
4104
+
Diagnostic {
4105
+
title,
4106
+
text,
4107
+
hint: None,
4108
+
level: Level::Error,
4109
+
location: Some(Location {
4110
+
label: Label {
4111
+
text: Some(label_text.into()),
4112
+
span: location
4113
+
},
4114
+
path: path.clone(),
4115
+
src: src.clone(),
4116
+
extra_labels: vec![],
4117
+
}),
4118
+
}
3781
4119
},
3782
-
path: path.clone(),
3783
-
src: src.clone(),
3784
-
extra_labels: vec![],
3785
-
}),
3786
-
}]
4120
+
4121
+
ParseErrorType::NestedBitArrayPattern =>
4122
+
Diagnostic {
4123
+
title,
4124
+
text: "".into(),
4125
+
hint: None,
4126
+
level: Level::Error,
4127
+
location: Some(Location {
4128
+
label: Label {
4129
+
text: Some("BitArray patterns cannot be nested".into()),
4130
+
span: location
4131
+
},
4132
+
path: path.clone(),
4133
+
src: src.clone(),
4134
+
extra_labels: vec![],
4135
+
}),
4136
+
},
4137
+
4138
+
ParseErrorType::NotConstType =>
4139
+
Diagnostic {
4140
+
title,
4141
+
text: "See: https://tour.gleam.run/basics/constants/".into(),
4142
+
hint: None,
4143
+
level: Level::Error,
4144
+
location: Some(Location {
4145
+
label: Label {
4146
+
text: Some("This type is not allowed in module constants".into()),
4147
+
span: location
4148
+
},
4149
+
path: path.clone(),
4150
+
src: src.clone(),
4151
+
extra_labels: vec![],
4152
+
}),
4153
+
},
4154
+
4155
+
ParseErrorType::NoLetBinding =>
4156
+
Diagnostic {
4157
+
title,
4158
+
text: "See: https://tour.gleam.run/basics/assignments/".into(),
4159
+
hint: Some("Use let for binding.".into()),
4160
+
level: Level::Error,
4161
+
location: Some(Location {
4162
+
label: Label {
4163
+
text: Some("There must be a 'let' to bind variable to value".into()),
4164
+
span: location
4165
+
},
4166
+
path: path.clone(),
4167
+
src: src.clone(),
4168
+
extra_labels: vec![],
4169
+
}),
4170
+
},
4171
+
4172
+
ParseErrorType::NoValueAfterEqual =>
4173
+
Diagnostic {
4174
+
title,
4175
+
text: "".into(),
4176
+
hint: None,
4177
+
level: Level::Error,
4178
+
location: Some(Location {
4179
+
label: Label {
4180
+
text: Some("I was expecting to see a value after this equals sign".into()),
4181
+
span: location
4182
+
},
4183
+
path: path.clone(),
4184
+
src: src.clone(),
4185
+
extra_labels: vec![],
4186
+
}),
4187
+
},
4188
+
4189
+
ParseErrorType::OpaqueTypeAlias =>
4190
+
Diagnostic {
4191
+
title,
4192
+
text: "See: https://tour.gleam.run/basics/type-aliases/".into(),
4193
+
hint: None,
4194
+
level: Level::Error,
4195
+
location: Some(Location {
4196
+
label: Label {
4197
+
text: Some("Type Aliases cannot be opaque".into()),
4198
+
span: location
4199
+
},
4200
+
path: path.clone(),
4201
+
src: src.clone(),
4202
+
extra_labels: vec![],
4203
+
}),
4204
+
},
4205
+
4206
+
ParseErrorType::OpNakedRight =>
4207
+
Diagnostic {
4208
+
title,
4209
+
text: "".into(),
4210
+
hint: Some("Remove it or put a value after it.".into()),
4211
+
level: Level::Error,
4212
+
location: Some(Location {
4213
+
label: Label {
4214
+
text: Some("This operator has no value on its right side".into()),
4215
+
span: location
4216
+
},
4217
+
path: path.clone(),
4218
+
src: src.clone(),
4219
+
extra_labels: vec![],
4220
+
}),
4221
+
},
4222
+
4223
+
ParseErrorType::TooManyArgHoles =>
4224
+
Diagnostic {
4225
+
title,
4226
+
text: "See: https://tour.gleam.run/functions/functions/".into(),
4227
+
hint: Some("Function calls can have at most one argument hole.".into()),
4228
+
level: Level::Error,
4229
+
location: Some(Location {
4230
+
label: Label {
4231
+
text: Some("There is more than 1 argument hole in this function call".into()),
4232
+
span: location
4233
+
},
4234
+
path: path.clone(),
4235
+
src: src.clone(),
4236
+
extra_labels: vec![],
4237
+
}),
4238
+
},
4239
+
4240
+
ParseErrorType::UnexpectedEof =>
4241
+
Diagnostic {
4242
+
title,
4243
+
text: "".into(),
4244
+
hint: None,
4245
+
level: Level::Error,
4246
+
location: Some(Location {
4247
+
label: Label {
4248
+
text: Some("The module ended unexpectedly".into()),
4249
+
span: location
4250
+
},
4251
+
path: path.clone(),
4252
+
src: src.clone(),
4253
+
extra_labels: vec![],
4254
+
}),
4255
+
},
4256
+
4257
+
ParseErrorType::ListSpreadWithoutElements =>
4258
+
Diagnostic {
4259
+
title,
4260
+
text: "See: https://tour.gleam.run/basics/lists/".into(),
4261
+
hint: Some("Try prepending some elements [1, 2, ..list].".into()),
4262
+
level: Level::Error,
4263
+
location: Some(Location {
4264
+
label: Label {
4265
+
text: Some("This spread does nothing".into()),
4266
+
span: location
4267
+
},
4268
+
path: path.clone(),
4269
+
src: src.clone(),
4270
+
extra_labels: vec![],
4271
+
}),
4272
+
},
4273
+
4274
+
ParseErrorType::ListSpreadWithAnotherSpread { first_spread_location, second_spread_location } =>
4275
+
Diagnostic {
4276
+
title,
4277
+
text: vec![
4278
+
"Lists are immutable and singly-linked, so to join two or more lists",
4279
+
"all the elements of the lists would need to be copied into a new list.",
4280
+
"This would be slow, so there is no built-in syntax for it.",
4281
+
].join("\n"),
4282
+
hint: None,
4283
+
level: Level::Error,
4284
+
location: Some(Location {
4285
+
label: Label {
4286
+
text: Some("I wasn't expecting a second spread here".into()),
4287
+
span: *second_spread_location,
4288
+
},
4289
+
path: path.clone(),
4290
+
src: src.clone(),
4291
+
extra_labels: vec![
4292
+
ExtraLabel {
4293
+
src_info: None,
4294
+
label: Label {
4295
+
text: Some("You're using a spread here".into()),
4296
+
span: *first_spread_location,
4297
+
}
4298
+
}
4299
+
],
4300
+
}),
4301
+
},
4302
+
4303
+
ParseErrorType::ListSpreadFollowedByElements =>
4304
+
Diagnostic {
4305
+
title,
4306
+
text: vec![
4307
+
"Lists are immutable and singly-linked, so to append items to them",
4308
+
"all the elements of a list would need to be copied into a new list.",
4309
+
"This would be slow, so there is no built-in syntax for it.",
4310
+
"",
4311
+
].join("\n"),
4312
+
hint: Some("Prepend items to the list and then reverse it once you are done.".into()),
4313
+
level: Level::Error,
4314
+
location: Some(Location {
4315
+
label: Label {
4316
+
text: Some("I wasn't expecting elements after this".into()),
4317
+
span: location,
4318
+
},
4319
+
path: path.clone(),
4320
+
src: src.clone(),
4321
+
extra_labels: vec![],
4322
+
}),
4323
+
},
4324
+
4325
+
4326
+
ParseErrorType::ListPatternSpreadFollowedByElements =>
4327
+
Diagnostic {
4328
+
title,
4329
+
text: vec![
4330
+
"Lists are immutable and singly-linked, so to match on the end",
4331
+
"of a list would require the whole list to be traversed. This",
4332
+
"would be slow, so there is no built-in syntax for it. Pattern",
4333
+
"match on the start of the list instead.",
4334
+
].join("\n"),
4335
+
hint: None,
4336
+
level: Level::Error,
4337
+
location: Some(Location {
4338
+
label: Label {
4339
+
text: Some("I wasn't expecting elements after this".into()),
4340
+
span: location,
4341
+
},
4342
+
path: path.clone(),
4343
+
src: src.clone(),
4344
+
extra_labels: vec![],
4345
+
}),
4346
+
},
4347
+
4348
+
ParseErrorType::UnexpectedReservedWord =>
4349
+
Diagnostic {
4350
+
title,
4351
+
text: "".into(),
4352
+
hint: Some("I was expecting to see a name here.".into()),
4353
+
level: Level::Error,
4354
+
location: Some(Location {
4355
+
label: Label {
4356
+
text: Some("This is a reserved word".into()),
4357
+
span: location,
4358
+
},
4359
+
path: path.clone(),
4360
+
src: src.clone(),
4361
+
extra_labels: vec![],
4362
+
}),
4363
+
},
4364
+
4365
+
ParseErrorType::LowcaseBooleanPattern =>
4366
+
Diagnostic {
4367
+
title,
4368
+
text: "See: https://tour.gleam.run/basics/bools/".into(),
4369
+
hint: Some("In Gleam boolean literals are `True` and `False`.".into()),
4370
+
level: Level::Error,
4371
+
location: Some(Location {
4372
+
label: Label {
4373
+
text: Some("Did you want a Bool instead of a variable?".into()),
4374
+
span: location,
4375
+
},
4376
+
path: path.clone(),
4377
+
src: src.clone(),
4378
+
extra_labels: vec![],
4379
+
}),
4380
+
},
4381
+
4382
+
ParseErrorType::UnexpectedLabel =>
4383
+
Diagnostic {
4384
+
title,
4385
+
text: "Please remove the argument label.".into(),
4386
+
hint: None,
4387
+
level: Level::Error,
4388
+
location: Some(Location {
4389
+
label: Label {
4390
+
text: Some("Argument labels are not allowed for anonymous functions".into()),
4391
+
span: location,
4392
+
},
4393
+
path: path.clone(),
4394
+
src: src.clone(),
4395
+
extra_labels: vec![],
4396
+
}),
4397
+
},
4398
+
4399
+
ParseErrorType::UnexpectedToken {
4400
+
token,
4401
+
expected,
4402
+
hint,
4403
+
} => {
4404
+
let found = match token {
4405
+
Token::Int { .. } => "an Int".to_string(),
4406
+
Token::Float { .. } => "a Float".to_string(),
4407
+
Token::String { .. } => "a String".to_string(),
4408
+
Token::CommentDoc { .. } => "a comment".to_string(),
4409
+
Token::DiscardName { .. } => "a discard name".to_string(),
4410
+
Token::Name { .. } | Token::UpName { .. } => "a name".to_string(),
4411
+
_ if token.is_reserved_word() => format!("the keyword {token}"),
4412
+
_ => token.to_string(),
4413
+
};
4414
+
4415
+
let messages = std::iter::once(format!("Found {found}, expected one of: "))
4416
+
.chain(expected.iter().map(|s| format!("- {s}")));
4417
+
4418
+
let messages = match hint {
4419
+
Some(hint_text) => messages
4420
+
.chain(std::iter::once(format!("Hint: {hint_text}")))
4421
+
.collect_vec(),
4422
+
_ => messages.collect(),
4423
+
};
4424
+
4425
+
Diagnostic {
4426
+
title,
4427
+
text: messages.join("\n"),
4428
+
hint: None,
4429
+
level: Level::Error,
4430
+
location: Some(Location {
4431
+
label: Label {
4432
+
text: Some("I was not expecting this".into()),
4433
+
span: location,
4434
+
},
4435
+
path: path.clone(),
4436
+
src: src.clone(),
4437
+
extra_labels: vec![],
4438
+
}),
4439
+
}
4440
+
}
4441
+
4442
+
ParseErrorType::ConcatPatternVariableLeftHandSide =>
4443
+
Diagnostic {
4444
+
title,
4445
+
text: vec![
4446
+
"We can't tell what size this prefix should be so we don't know",
4447
+
"how to handle this pattern.",
4448
+
"",
4449
+
"If you want to match one character consider using `pop_grapheme`",
4450
+
"from the stdlib's `gleam/string` module.",
4451
+
].join("\n"),
4452
+
hint: None,
4453
+
level: Level::Error,
4454
+
location: Some(Location {
4455
+
label: Label {
4456
+
text: Some("This must be a string literal".into()),
4457
+
span: location,
4458
+
},
4459
+
path: path.clone(),
4460
+
src: src.clone(),
4461
+
extra_labels: vec![],
4462
+
}),
4463
+
},
4464
+
4465
+
ParseErrorType::UnexpectedFunction =>
4466
+
Diagnostic {
4467
+
title,
4468
+
text: "".into(),
4469
+
hint: None,
4470
+
level: Level::Error,
4471
+
location: Some(Location {
4472
+
label: Label {
4473
+
text: Some("Functions can only be called within other functions".into()),
4474
+
span: location,
4475
+
},
4476
+
path: path.clone(),
4477
+
src: src.clone(),
4478
+
extra_labels: vec![],
4479
+
}),
4480
+
},
4481
+
4482
+
ParseErrorType::ListSpreadWithoutTail =>
4483
+
Diagnostic {
4484
+
title,
4485
+
text: "If a list expression has a spread then a tail must also be given.".into(),
4486
+
hint: None,
4487
+
level: Level::Error,
4488
+
location: Some(Location {
4489
+
label: Label {
4490
+
text: Some("I was expecting a value after this spread".into()),
4491
+
span: location,
4492
+
},
4493
+
path: path.clone(),
4494
+
src: src.clone(),
4495
+
extra_labels: vec![],
4496
+
}),
4497
+
},
4498
+
4499
+
ParseErrorType::UnknownAttribute =>
4500
+
Diagnostic {
4501
+
title,
4502
+
text: "".into(),
4503
+
hint: Some("Try `deprecated`, `external` or `target` instead.".into()),
4504
+
level: Level::Error,
4505
+
location: Some(Location {
4506
+
label: Label {
4507
+
text: Some("I don't recognise this attribute".into()),
4508
+
span: location,
4509
+
},
4510
+
path: path.clone(),
4511
+
src: src.clone(),
4512
+
extra_labels: vec![],
4513
+
}),
4514
+
},
4515
+
4516
+
ParseErrorType::DuplicateAttribute =>
4517
+
Diagnostic {
4518
+
title,
4519
+
text: "This attribute has already been given.".into(),
4520
+
hint: None,
4521
+
level: Level::Error,
4522
+
location: Some(Location {
4523
+
label: Label {
4524
+
text: Some("Duplicate attribute".into()),
4525
+
span: location,
4526
+
},
4527
+
path: path.clone(),
4528
+
src: src.clone(),
4529
+
extra_labels: vec![],
4530
+
}),
4531
+
},
4532
+
4533
+
ParseErrorType::UnknownTarget =>
4534
+
Diagnostic {
4535
+
title,
4536
+
text: "Try `erlang`, `javascript`.".into(),
4537
+
hint: None,
4538
+
level: Level::Error,
4539
+
location: Some(Location {
4540
+
label: Label {
4541
+
text: Some("I don't recognise this target".into()),
4542
+
span: location,
4543
+
},
4544
+
path: path.clone(),
4545
+
src: src.clone(),
4546
+
extra_labels: vec![],
4547
+
}),
4548
+
},
4549
+
4550
+
ParseErrorType::ExpectedFunctionBody =>
4551
+
Diagnostic {
4552
+
title,
4553
+
text: "".into(),
4554
+
hint: None,
4555
+
level: Level::Error,
4556
+
location: Some(Location {
4557
+
label: Label {
4558
+
text: Some("This function does not have a body".into()),
4559
+
span: location,
4560
+
},
4561
+
path: path.clone(),
4562
+
src: src.clone(),
4563
+
extra_labels: vec![],
4564
+
}),
4565
+
},
4566
+
4567
+
ParseErrorType::RedundantInternalAttribute =>
4568
+
Diagnostic {
4569
+
title,
4570
+
text: "Only a public definition can be annotated as internal.".into(),
4571
+
hint: Some("Remove the `@internal` annotation.".into()),
4572
+
level: Level::Error,
4573
+
location: Some(Location {
4574
+
label: Label {
4575
+
text: Some("Redundant internal attribute".into()),
4576
+
span: location,
4577
+
},
4578
+
path: path.clone(),
4579
+
src: src.clone(),
4580
+
extra_labels: vec![],
4581
+
}),
4582
+
},
4583
+
4584
+
ParseErrorType::InvalidModuleTypePattern =>
4585
+
Diagnostic {
4586
+
title,
4587
+
text: vec![
4588
+
"I'm expecting a pattern here",
4589
+
"Hint: A pattern can be a constructor name, a literal value",
4590
+
"or a variable to bind a value to, etc.",
4591
+
"See: https://tour.gleam.run/flow-control/case-expressions/",
4592
+
].join("\n"),
4593
+
hint: None,
4594
+
level: Level::Error,
4595
+
location: Some(Location {
4596
+
label: Label {
4597
+
text: Some("Invalid pattern".into()),
4598
+
span: location,
4599
+
},
4600
+
path: path.clone(),
4601
+
src: src.clone(),
4602
+
extra_labels: vec![],
4603
+
}),
4604
+
},
4605
+
4606
+
ParseErrorType::ExpectedRecordConstructor {
4607
+
name,
4608
+
public,
4609
+
opaque,
4610
+
field,
4611
+
field_type,
4612
+
} => {
4613
+
let (accessor, opaque) = match *public {
4614
+
true if *opaque => ("pub ", "opaque "),
4615
+
true => ("pub ", ""),
4616
+
false => ("", ""),
4617
+
};
4618
+
4619
+
let mut annotation = EcoString::new();
4620
+
match field_type {
4621
+
Some(t) => t.print(&mut annotation),
4622
+
None => annotation.push_str("Type"),
4623
+
};
4624
+
4625
+
Diagnostic {
4626
+
title,
4627
+
text: vec![
4628
+
"Each custom type variant must have a constructor:\n".into(),
4629
+
format!("{accessor}{opaque}type {name} {{"),
4630
+
format!(" {name}("),
4631
+
format!(" {field}: {annotation},"),
4632
+
" )".into(),
4633
+
"}".into(),
4634
+
].join("\n"),
4635
+
hint: None,
4636
+
level: Level::Error,
4637
+
location: Some(Location {
4638
+
label: Label {
4639
+
text: Some("I was not expecting this".into()),
4640
+
span: location,
4641
+
},
4642
+
path: path.clone(),
4643
+
src: src.clone(),
4644
+
extra_labels: vec![],
4645
+
}),
4646
+
}
4647
+
}
4648
+
4649
+
ParseErrorType::CallInClauseGuard =>
4650
+
Diagnostic {
4651
+
title,
4652
+
text: "Functions cannot be called in clause guards.".into(),
4653
+
hint: None,
4654
+
level: Level::Error,
4655
+
location: Some(Location {
4656
+
label: Label {
4657
+
text: Some("Unsupported expression".into()),
4658
+
span: location,
4659
+
},
4660
+
path: path.clone(),
4661
+
src: src.clone(),
4662
+
extra_labels: vec![],
4663
+
}),
4664
+
},
4665
+
4666
+
ParseErrorType::IfExpression =>
4667
+
Diagnostic {
4668
+
title,
4669
+
text: vec![
4670
+
"If you want to write a conditional expression you can use a `case`:",
4671
+
"",
4672
+
" case condition {",
4673
+
" True -> todo",
4674
+
" False -> todo",
4675
+
" }",
4676
+
"",
4677
+
"See: https://tour.gleam.run/flow-control/case-expressions/",
4678
+
].join("\n"),
4679
+
hint: None,
4680
+
level: Level::Error,
4681
+
location: Some(Location {
4682
+
label: Label {
4683
+
text: Some("Gleam doesn't have if expressions".into()),
4684
+
span: location,
4685
+
},
4686
+
path: path.clone(),
4687
+
src: src.clone(),
4688
+
extra_labels: vec![],
4689
+
}),
4690
+
},
4691
+
4692
+
ParseErrorType::ConstantRecordConstructorNoArguments =>
4693
+
Diagnostic {
4694
+
title,
4695
+
text: "A record must be passed arguments when constructed.".into(),
4696
+
hint: None,
4697
+
level: Level::Error,
4698
+
location: Some(Location {
4699
+
label: Label {
4700
+
text: Some("I was expecting arguments here".into()),
4701
+
span: location,
4702
+
},
4703
+
path: path.clone(),
4704
+
src: src.clone(),
4705
+
extra_labels: vec![],
4706
+
}),
4707
+
},
4708
+
4709
+
ParseErrorType::TypeConstructorNoArguments =>
4710
+
Diagnostic {
4711
+
title,
4712
+
text: "A type constructor must be passed arguments.".into(),
4713
+
hint: None,
4714
+
level: Level::Error,
4715
+
location: Some(Location {
4716
+
label: Label {
4717
+
text: Some("I was expecting arguments here".into()),
4718
+
span: location,
4719
+
},
4720
+
path: path.clone(),
4721
+
src: src.clone(),
4722
+
extra_labels: vec![],
4723
+
}),
4724
+
},
4725
+
4726
+
ParseErrorType::TypeDefinitionNoArguments =>
4727
+
Diagnostic {
4728
+
title,
4729
+
text: "A generic type must have at least a generic parameter.".into(),
4730
+
hint: Some("If a type is not generic you should omit the `()`.".into()),
4731
+
level: Level::Error,
4732
+
location: Some(Location {
4733
+
label: Label {
4734
+
text: Some("I was expecting generic parameters here".into()),
4735
+
span: location,
4736
+
},
4737
+
path: path.clone(),
4738
+
src: src.clone(),
4739
+
extra_labels: vec![],
4740
+
}),
4741
+
},
4742
+
4743
+
ParseErrorType::UnknownAttributeRecordVariant =>
4744
+
Diagnostic {
4745
+
title,
4746
+
text: "".into(),
4747
+
hint: Some("Did you mean `@deprecated`?".into()),
4748
+
level: Level::Error,
4749
+
location: Some(Location {
4750
+
label: Label {
4751
+
text: Some("This attribute cannot be used on a variant.".into()),
4752
+
span: location,
4753
+
},
4754
+
path: path.clone(),
4755
+
src: src.clone(),
4756
+
extra_labels: vec![],
4757
+
}),
4758
+
},
4759
+
4760
+
ParseErrorType::IncorrectImportModuleSeparator { module, item } =>
4761
+
Diagnostic {
4762
+
title,
4763
+
text: vec![
4764
+
"Perhaps you meant one of:".into(),
4765
+
"".into(),
4766
+
format!(" import {module}/{item}"),
4767
+
format!(" import {module}.{{item}}"),
4768
+
].join("\n"),
4769
+
hint: None,
4770
+
level: Level::Error,
4771
+
location: Some(Location {
4772
+
label: Label {
4773
+
text: Some("I was expecting either `/` or `.{` here.".into()),
4774
+
span: location,
4775
+
},
4776
+
path: path.clone(),
4777
+
src: src.clone(),
4778
+
extra_labels: vec![],
4779
+
}),
4780
+
},
4781
+
};
4782
+
4783
+
vec![diagnostic]
3787
4784
}
3788
4785
3789
4786
Error::ImportCycle { modules } => {
+4
-319
compiler-core/src/parse/error.rs
+4
-319
compiler-core/src/parse/error.rs
···
1
1
use crate::ast::{SrcSpan, TypeAst};
2
-
use crate::error::wrap;
3
2
use crate::parse::Token;
4
3
use ecow::EcoString;
5
4
···
36
35
pub location: SrcSpan,
37
36
}
38
37
39
-
impl ParseError {
40
-
pub fn details(&self) -> (&'static str, Vec<String>) {
41
-
match &self.error {
42
-
ParseErrorType::ExpectedEqual => ("I was expecting a '=' after this", vec![]),
43
-
ParseErrorType::ExpectedExpr => ("I was expecting an expression after this", vec![]),
44
-
ParseErrorType::ExpectedName => ("I was expecting a name here", vec![]),
45
-
ParseErrorType::ExpectedPattern => ("I was expecting a pattern after this", vec![]),
46
-
ParseErrorType::ExpectedType => (
47
-
"I was expecting a type after this",
48
-
vec!["See: https://tour.gleam.run/basics/assignments/".into()],
49
-
),
50
-
ParseErrorType::ExpectedUpName => ("I was expecting a type name here", vec![]),
51
-
ParseErrorType::ExpectedValue => ("I was expecting a value after this", vec![]),
52
-
ParseErrorType::ExpectedDefinition => {
53
-
("I was expecting a definition after this", vec![])
54
-
}
55
-
ParseErrorType::ExpectedDeprecationMessage => (
56
-
"A deprecation attribute must have a string message.",
57
-
vec![],
58
-
),
59
-
ParseErrorType::ExpectedFunctionDefinition => {
60
-
("I was expecting a function definition after this", vec![])
61
-
}
62
-
ParseErrorType::ExpectedTargetName => (
63
-
"I was expecting a target name after this",
64
-
vec!["Try `erlang`, `javascript`.".into()],
65
-
),
66
-
ParseErrorType::ExtraSeparator => (
67
-
"This is an extra delimiter",
68
-
vec!["Hint: Try removing it?".into()],
69
-
),
70
-
ParseErrorType::ExprLparStart => (
71
-
"This parenthesis cannot be understood here",
72
-
vec![
73
-
"Hint: To group expressions in Gleam, use \"{\" and \"}\"; tuples are created with `#(` and `)`.".into(),
74
-
]
75
-
),
76
-
ParseErrorType::IncorrectName => (
77
-
"I'm expecting a lowercase name here",
78
-
vec![wrap(
79
-
"Hint: Variable and module names start with a lowercase letter, \
80
-
and can contain a-z, 0-9, or _.",
81
-
)],
82
-
),
83
-
ParseErrorType::IncorrectUpName => (
84
-
"I'm expecting a type name here",
85
-
vec![wrap(
86
-
"Hint: Type names start with a uppercase letter, and can \
87
-
contain a-z, A-Z, or 0-9.",
88
-
)],
89
-
),
90
-
ParseErrorType::InvalidBitArraySegment => (
91
-
"This is not a valid BitArray segment option",
92
-
vec![
93
-
"Hint: Valid BitArray segment options are:".into(),
94
-
wrap(
95
-
"bits, bytes, int, float, utf8, utf16, utf32, utf8_codepoint, \
96
-
utf16_codepoint, utf32_codepoint, signed, unsigned, big, little, native, size, unit.",
97
-
),
98
-
"See: https://tour.gleam.run/data-types/bit-arrays/".into(),
99
-
],
100
-
),
101
-
ParseErrorType::InvalidBitArrayUnit => (
102
-
"This is not a valid BitArray unit value",
103
-
vec![
104
-
"Hint: unit must be an integer literal >= 1 and <= 256.".into(),
105
-
"See: https://tour.gleam.run/data-types/bit-arrays/".into(),
106
-
],
107
-
),
108
-
ParseErrorType::InvalidTailPattern => (
109
-
"This part of a list pattern can only be a name or a discard",
110
-
vec![],
111
-
),
112
-
ParseErrorType::InvalidTupleAccess => (
113
-
"This integer is not valid for tuple access",
114
-
vec![
115
-
"Hint: Only non negative integer literals like 0, or 1_000 can be used."
116
-
.to_string(),
117
-
],
118
-
),
119
-
ParseErrorType::LexError { error: lex_err } => lex_err.to_parse_error_info(),
120
-
ParseErrorType::NestedBitArrayPattern => ("BitArray patterns cannot be nested", vec![]),
121
-
ParseErrorType::NotConstType => (
122
-
"This type is not allowed in module constants",
123
-
vec!["See: https://tour.gleam.run/basics/constants/".into()],
124
-
),
125
-
ParseErrorType::NoLetBinding => (
126
-
"There must be a 'let' to bind variable to value",
127
-
vec![
128
-
"Hint: Use let for binding.".into(),
129
-
"See: https://tour.gleam.run/basics/assignments/".into(),
130
-
],
131
-
),
132
-
ParseErrorType::NoValueAfterEqual => (
133
-
"I was expecting to see a value after this equals sign",
134
-
vec![],
135
-
),
136
-
ParseErrorType::OpaqueTypeAlias => (
137
-
"Type Aliases cannot be opaque",
138
-
vec!["See: https://tour.gleam.run/basics/type-aliases/".into()],
139
-
),
140
-
ParseErrorType::OpNakedRight => (
141
-
"This operator has no value on its right side",
142
-
vec!["Hint: Remove it or put a value after it.".into()],
143
-
),
144
-
ParseErrorType::TooManyArgHoles => (
145
-
"There is more than 1 argument hole in this function call",
146
-
vec![
147
-
"Hint: Function calls can have at most one argument hole.".into(),
148
-
"See: https://tour.gleam.run/functions/functions/".into(),
149
-
],
150
-
),
151
-
ParseErrorType::UnexpectedEof => ("The module ended unexpectedly", vec![]),
152
-
ParseErrorType::ListSpreadWithoutElements => (
153
-
"This spread does nothing",
154
-
vec![
155
-
"Hint: Try prepending some elements [1, 2, ..list].".into(),
156
-
"See: https://tour.gleam.run/basics/lists/".into(),
157
-
],
158
-
),
159
-
ParseErrorType::ListSpreadWithAnotherSpread => (
160
-
"I wasn't expecting a spread here",
161
-
vec![
162
-
"Lists are immutable and singly-linked, so to join two or more lists".into(),
163
-
"all the elements of the lists would need to be copied into a new list.".into(),
164
-
"This would be slow, so there is no built-in syntax for it.".into(),
165
-
],
166
-
),
167
-
ParseErrorType::ListSpreadFollowedByElements => (
168
-
"I wasn't expecting elements after this",
169
-
vec![
170
-
"Lists are immutable and singly-linked, so to append items to them".into(),
171
-
"all the elements of a list would need to be copied into a new list.".into(),
172
-
"This would be slow, so there is no built-in syntax for it.".into(),
173
-
"".into(),
174
-
"Hint: prepend items to the list and then reverse it once you are done.".into(),
175
-
],
176
-
),
177
-
ParseErrorType::ListPatternSpreadFollowedByElements => (
178
-
"I wasn't expecting elements after this",
179
-
vec![
180
-
"Lists are immutable and singly-linked, so to match on the end".into(),
181
-
"of a list would require the whole list to be traversed. This".into(),
182
-
"would be slow, so there is no built-in syntax for it. Pattern".into(),
183
-
"match on the start of the list instead.".into(),
184
-
],
185
-
),
186
-
ParseErrorType::UnexpectedReservedWord => (
187
-
"This is a reserved word",
188
-
vec!["Hint: I was expecting to see a name here.".into()],
189
-
),
190
-
ParseErrorType::LowcaseBooleanPattern => (
191
-
"Did you want a Bool instead of a variable?",
192
-
vec![
193
-
"Hint: In Gleam boolean literals are `True` and `False`.".into(),
194
-
"See: https://tour.gleam.run/basics/bools/".into(),
195
-
],
196
-
),
197
-
ParseErrorType::UnexpectedLabel => (
198
-
"Argument labels are not allowed for anonymous functions",
199
-
vec!["Please remove the argument label.".into()],
200
-
),
201
-
ParseErrorType::UnexpectedToken {
202
-
token,
203
-
expected,
204
-
hint,
205
-
} => {
206
-
let found = match token {
207
-
Token::Int { .. } => "an Int".to_string(),
208
-
Token::Float { .. } => "a Float".to_string(),
209
-
Token::String { .. } => "a String".to_string(),
210
-
Token::CommentDoc { .. } => "a comment".to_string(),
211
-
Token::DiscardName { .. } => "a discard name".to_string(),
212
-
Token::Name { .. } | Token::UpName { .. } => "a name".to_string(),
213
-
_ if token.is_reserved_word() => format!("the keyword {token}"),
214
-
_ => token.to_string(),
215
-
};
216
-
217
-
let messages = std::iter::once(format!("Found {found}, expected one of: "))
218
-
.chain(expected.iter().map(|s| format!("- {s}")));
219
-
220
-
let messages = match hint {
221
-
Some(hint_text) => messages
222
-
.chain(std::iter::once(format!("Hint: {hint_text}")))
223
-
.collect(),
224
-
_ => messages.collect(),
225
-
};
226
-
227
-
("I was not expecting this", messages)
228
-
}
229
-
ParseErrorType::ConcatPatternVariableLeftHandSide => (
230
-
"This must be a string literal",
231
-
vec![
232
-
"We can't tell what size this prefix should be so we don't know".into(),
233
-
"how to handle this pattern.".into(),
234
-
"".into(),
235
-
"If you want to match one character consider using `pop_grapheme`".into(),
236
-
"from the stdlib's `gleam/string` module.".into(),
237
-
],
238
-
),
239
-
ParseErrorType::UnexpectedFunction => (
240
-
"Functions can only be called within other functions",
241
-
vec![],
242
-
),
243
-
ParseErrorType::ListSpreadWithoutTail => (
244
-
"I was expecting a value after this spread",
245
-
vec!["If a list expression has a spread then a tail must also be given.".into()],
246
-
),
247
-
ParseErrorType::UnknownAttribute => (
248
-
"I don't recognise this attribute",
249
-
vec!["Try `deprecated`, `external` or `target` instead.".into()],
250
-
),
251
-
ParseErrorType::DuplicateAttribute => (
252
-
"Duplicate attribute",
253
-
vec!["This attribute has already been given.".into()],
254
-
),
255
-
ParseErrorType::UnknownTarget => (
256
-
"I don't recognise this target",
257
-
vec!["Try `erlang`, `javascript`.".into()],
258
-
),
259
-
ParseErrorType::ExpectedFunctionBody => ("This function does not have a body", vec![]),
260
-
ParseErrorType::RedundantInternalAttribute => (
261
-
"Redundant internal attribute",
262
-
vec![
263
-
format!("Only a public definition can be annotated as internal."),
264
-
"Hint: remove the `@internal` annotation.".into(),
265
-
],
266
-
),
267
-
ParseErrorType::InvalidModuleTypePattern => (
268
-
"Invalid pattern",
269
-
vec![
270
-
"I'm expecting a pattern here".into(),
271
-
"Hint: A pattern can be a constructor name, a literal value".into(),
272
-
"or a variable to bind a value to, etc.".into(),
273
-
"See: https://tour.gleam.run/flow-control/case-expressions/".into(),
274
-
],
275
-
),
276
-
ParseErrorType::ExpectedRecordConstructor {
277
-
name,
278
-
public,
279
-
opaque,
280
-
field,
281
-
field_type,
282
-
} => {
283
-
let (accessor, opaque) = match *public {
284
-
true if *opaque => ("pub ", "opaque "),
285
-
true => ("pub ", ""),
286
-
false => ("", ""),
287
-
};
288
-
289
-
let mut annotation = EcoString::new();
290
-
match field_type {
291
-
Some(t) => t.print(&mut annotation),
292
-
None => annotation.push_str("Type"),
293
-
};
294
-
295
-
(
296
-
"I was not expecting this",
297
-
vec![
298
-
"Each custom type variant must have a constructor:\n".into(),
299
-
format!("{accessor}{opaque}type {name} {{"),
300
-
format!(" {name}("),
301
-
format!(" {field}: {annotation},"),
302
-
" )".into(),
303
-
"}".into(),
304
-
],
305
-
)
306
-
}
307
-
ParseErrorType::CallInClauseGuard => (
308
-
"Unsupported expression",
309
-
vec!["Functions cannot be called in clause guards.".into()],
310
-
),
311
-
ParseErrorType::IfExpression => (
312
-
"Gleam doesn't have if expressions",
313
-
vec![
314
-
"If you want to write a conditional expression you can use a `case`:".into(),
315
-
"".into(),
316
-
" case condition {".into(),
317
-
" True -> todo".into(),
318
-
" False -> todo".into(),
319
-
" }".into(),
320
-
"".into(),
321
-
"See: https://tour.gleam.run/flow-control/case-expressions/".into(),
322
-
],
323
-
),
324
-
ParseErrorType::ConstantRecordConstructorNoArguments => (
325
-
"I was expecting arguments here",
326
-
vec!["A record must be passed arguments when constructed.".into()],
327
-
),
328
-
ParseErrorType::TypeConstructorNoArguments => (
329
-
"I was expecting arguments here",
330
-
vec!["A type constructor must be passed arguments.".into()],
331
-
),
332
-
ParseErrorType::TypeDefinitionNoArguments => (
333
-
"I was expecting generic parameters here",
334
-
vec![
335
-
"A generic type must have at least a generic parameter.".into(),
336
-
"Hint: If a type is not generic you should omit the `()`.".into(),
337
-
],
338
-
),
339
-
ParseErrorType::UnknownAttributeRecordVariant => (
340
-
"This attribute cannot be used on a variant.",
341
-
vec!["Hint: Did you mean `@deprecated`?".into()],
342
-
),
343
-
ParseErrorType::IncorrectImportModuleSeparator { module, item } => (
344
-
"I was expecting either `/` or `.{` here.",
345
-
vec![
346
-
"Perhaps you meant one of:".into(),
347
-
"".into(),
348
-
format!(" import {module}/{item}"),
349
-
format!(" import {module}.{{item}}"),
350
-
]
351
-
)
352
-
}
353
-
}
354
-
}
355
-
356
38
#[derive(Debug, Clone, PartialEq, Eq)]
357
39
pub enum ParseErrorType {
358
40
ExpectedEqual, // expect "="
···
389
71
UnknownTarget, // an unknown target was used
390
72
ListSpreadWithoutElements, // Pointless spread: `[..xs]`
391
73
ListSpreadFollowedByElements, // trying to append something after the spread: `[..xs, x]`
392
-
ListSpreadWithAnotherSpread, // trying to use multiple spreads: `[..xs, ..ys]`
74
+
ListSpreadWithAnotherSpread {
75
+
first_spread_location: SrcSpan,
76
+
second_spread_location: SrcSpan,
77
+
}, // trying to use multiple spreads: `[..xs, ..ys]`
393
78
LowcaseBooleanPattern, // most likely user meant True or False in patterns
394
79
UnexpectedLabel, // argument labels were provided, but are not supported in this context
395
80
UnexpectedEof,
+2
-2
compiler-core/src/parse/snapshots/gleam_core__parse__tests__error_message_on_variable_starting_with_underscore.snap
+2
-2
compiler-core/src/parse/snapshots/gleam_core__parse__tests__error_message_on_variable_starting_with_underscore.snap
···
15
15
3 │ let val = _func_starting_with_underscore(1)
16
16
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ I'm expecting a lowercase name here
17
17
18
-
Hint: Variable and module names start with a lowercase letter, and can
19
-
contain a-z, 0-9, or _.
18
+
Hint: Variable and module names start with a lowercase letter, and can contain
19
+
a-z, 0-9, or _.
+2
-2
compiler-core/src/parse/snapshots/gleam_core__parse__tests__error_message_on_variable_starting_with_underscore2.snap
+2
-2
compiler-core/src/parse/snapshots/gleam_core__parse__tests__error_message_on_variable_starting_with_underscore2.snap
···
17
17
4 │ 1 -> _with_underscore(1)
18
18
│ ^^^^^^^^^^^^^^^^ I'm expecting a lowercase name here
19
19
20
-
Hint: Variable and module names start with a lowercase letter, and can
21
-
contain a-z, 0-9, or _.
20
+
Hint: Variable and module names start with a lowercase letter, and can contain
21
+
a-z, 0-9, or _.
+1
-1
compiler-core/src/parse/snapshots/gleam_core__parse__tests__list_spread_as_first_item_followed_by_other_items.snap
+1
-1
compiler-core/src/parse/snapshots/gleam_core__parse__tests__list_spread_as_first_item_followed_by_other_items.snap
···
21
21
all the elements of a list would need to be copied into a new list.
22
22
This would be slow, so there is no built-in syntax for it.
23
23
24
-
Hint: prepend items to the list and then reverse it once you are done.
24
+
Hint: Prepend items to the list and then reverse it once you are done.
+1
-1
compiler-core/src/parse/snapshots/gleam_core__parse__tests__list_spread_followed_by_extra_items.snap
+1
-1
compiler-core/src/parse/snapshots/gleam_core__parse__tests__list_spread_followed_by_extra_items.snap
···
21
21
all the elements of a list would need to be copied into a new list.
22
22
This would be slow, so there is no built-in syntax for it.
23
23
24
-
Hint: prepend items to the list and then reverse it once you are done.
24
+
Hint: Prepend items to the list and then reverse it once you are done.
+1
-1
compiler-core/src/parse/snapshots/gleam_core__parse__tests__no_let_binding_snapshot_1.snap
+1
-1
compiler-core/src/parse/snapshots/gleam_core__parse__tests__no_let_binding_snapshot_1.snap
+1
-1
compiler-core/src/parse/snapshots/gleam_core__parse__tests__no_let_binding_snapshot_2.snap
+1
-1
compiler-core/src/parse/snapshots/gleam_core__parse__tests__no_let_binding_snapshot_2.snap
+1
-1
compiler-core/src/parse/snapshots/gleam_core__parse__tests__no_let_binding_snapshot_3.snap
+1
-1
compiler-core/src/parse/snapshots/gleam_core__parse__tests__no_let_binding_snapshot_3.snap
+1
-1
compiler-core/src/parse/snapshots/gleam_core__parse__tests__private_internal_const.snap
+1
-1
compiler-core/src/parse/snapshots/gleam_core__parse__tests__private_internal_const.snap
+1
-1
compiler-core/src/parse/snapshots/gleam_core__parse__tests__private_internal_function.snap
+1
-1
compiler-core/src/parse/snapshots/gleam_core__parse__tests__private_internal_function.snap
+1
-1
compiler-core/src/parse/snapshots/gleam_core__parse__tests__private_internal_type.snap
+1
-1
compiler-core/src/parse/snapshots/gleam_core__parse__tests__private_internal_type.snap
+1
-1
compiler-core/src/parse/snapshots/gleam_core__parse__tests__private_internal_type_alias.snap
+1
-1
compiler-core/src/parse/snapshots/gleam_core__parse__tests__private_internal_type_alias.snap