on 7324fca help sign in
1813 lines 50 kB history raw
1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
3module Reporting.Error.Syntax
4 ( Error(..)
5 --
6 , Module(..)
7 , Exposing(..)
8 --
9 , Decl(..)
10 , DeclType(..)
11 , TypeAlias(..)
12 , CustomType(..)
13 , DeclDef(..)
14 , Port(..)
15 --
16 , Expr(..)
17 , Record(..)
18 , Tuple(..)
19 , List(..)
20 , Func(..)
21 , Case(..)
22 , If(..)
23 , Let(..)
24 , Def(..)
25 , Destruct(..)
26 --
27 , Pattern(..)
28 , PRecord(..)
29 , PTuple(..)
30 , PList(..)
31 --
32 , Type(..)
33 , TRecord(..)
34 , TTuple(..)
35 --
36 , Char(..)
37 , String(..)
38 , Escape(..)
39 , Number(..)
40 --
41 , Space(..)
42 , Operator(..)
43 , toReport
44 )
45 where
48import Prelude hiding (Char, String)
49import qualified Data.Char as Char
50import qualified Data.Name as Name
51import Data.Word (Word16)
52import Numeric (showHex)
54import qualified Elm.ModuleName as ModuleName
55import Parse.Primitives (Row, Col)
56import qualified Reporting.Annotation as A
57import qualified Reporting.Doc as D
58import qualified Reporting.Report as Report
59import qualified Reporting.Render.Code as Code
63-- ALL SYNTAX ERRORS
66data Error
67 = ModuleNameUnspecified ModuleName.Raw
68 | ModuleNameMismatch ModuleName.Raw (A.Located ModuleName.Raw)
69 | UnexpectedPort A.Region
70 | NoPorts A.Region
71 | ParseError Module
75-- MODULE
78data Module
79 = ModuleSpace Space Row Col
80 | ModuleEndOfFile Row Col
81 | Module Row Col
82 | ModuleName Row Col
83 | ModuleExposing Row Col
84 | ModuleExposingList Exposing Row Col
85 --
86 | ModulePortModule Row Col
87 | ModuleEffect Row Col
88 --
89 | ModuleIndentStart Row Col
90 | ModuleIndentName Row Col
91 | ModuleIndentExposing Row Col
92 | ModuleIndentExposingList Row Col
93 | ModuleIndentPortModule Row Col
94 --
95 | FreshLineModuleStart Row Col
96 | FreshLineAfterModuleLine Row Col
97 | FreshLineAfterDocComment Row Col
98 --
99 | ImportStart Row Col
100 | ImportName Row Col
101 | ImportAs Row Col
102 | ImportAlias Row Col
103 | ImportExposing Row Col
104 | ImportExposingList Exposing Row Col
105 | ImportEnd Row Col -- different based on col=1 or if greater
106 --
107 | ImportIndentName Row Col
108 | ImportIndentAs Row Col
109 | ImportIndentAlias Row Col
110 | ImportIndentExposing Row Col
111 | ImportIndentExposingList Row Col
112 --
113 | Infix Row Col
114 --
115 | Declarations Decl Row Col
118data Exposing
119 = ExposingSpace Space Row Col
120 | ExposingStart Row Col
121 | ExposingValue Row Col
122 | ExposingOperator Row Col
123 | ExposingOperatorReserved Operator Row Col
124 | ExposingOperatorRightParen Row Col
125 | ExposingEnd Row Col
126 --
127 | ExposingTypePrivacy Row Col
128 | ExposingTypePrivacyDots Row Col
129 | ExposingTypePrivacyEnd Row Col
130 --
131 | ExposingIndentEnd Row Col
132 | ExposingIndentValue Row Col
133 | ExposingIndentValueEnd Row Col
134 | ExposingIndentTypePrivacy Row Col
135 | ExposingIndentTypePrivacyDots Row Col
136 | ExposingIndentTypePrivacyEnd Row Col
140-- DECLARATIONS
143data Decl
144 = DeclStart Row Col
145 | DeclSpace Space Row Col
146 --
147 | Port Port Row Col
148 | DeclType DeclType Row Col
149 | DeclDef Name.Name DeclDef Row Col
150 --
151 | DeclFreshLineStart Row Col
152 | DeclFreshLineAfterDocComment Row Col
155data DeclDef
156 = DeclDefSpace Space Row Col
157 | DeclDefEquals Row Col
158 | DeclDefType Type Row Col
159 | DeclDefArg Pattern Row Col
160 | DeclDefBody Expr Row Col
161 | DeclDefNameRepeat Row Col
162 | DeclDefNameMatch Name.Name Row Col
163 --
164 | DeclDefIndentType Row Col
165 | DeclDefIndentEquals Row Col
166 | DeclDefIndentBody Row Col
167 --
168 | DeclDefFreshLineAfterType Row Col
171data Port
172 = PortSpace Space Row Col
173 | PortName Row Col
174 | PortColon Row Col
175 | PortType Type Row Col
176 | PortIndentName Row Col
177 | PortIndentColon Row Col
178 | PortIndentType Row Col
182-- TYPE DECLARATIONS
185data DeclType
186 = DT_Space Space Row Col
187 | DT_Name Row Col
188 | DT_Alias TypeAlias Row Col
189 | DT_Union CustomType Row Col
190 --
191 | DT_IndentName Row Col
194data TypeAlias
195 = AliasSpace Space Row Col
196 | AliasName Row Col
197 | AliasEquals Row Col
198 | AliasBody Type Row Col
199 --
200 | AliasIndentEquals Row Col
201 | AliasIndentBody Row Col
204data CustomType
205 = CT_Space Space Row Col
206 | CT_Name Row Col
207 | CT_Equals Row Col
208 | CT_Bar Row Col
209 | CT_Variant Row Col
210 | CT_VariantArg Type Row Col
211 --
212 | CT_IndentEquals Row Col
213 | CT_IndentBar Row Col
214 | CT_IndentAfterBar Row Col
215 | CT_IndentAfterEquals Row Col
219-- EXPRESSIONS
222data Expr
223 = Let Let Row Col
224 | Case Case Row Col
225 | If If Row Col
226 | List List Row Col
227 | Record Record Row Col
228 | Update Expr Row Col
229 | Tuple Tuple Row Col
230 | Func Func Row Col
231 --
232 | Dot Row Col
233 | Access Row Col
234 | OperatorRHS Row Col
235 | OperatorRight Row Col
236 | OperatorReserved Operator Row Col
237 --
238 | Start Row Col
239 | Char Char Row Col
240 | String String Row Col
241 | Number Number Row Col
242 | Space Space Row Col
243 | EndlessShader Row Col
244 | ShaderProblem [Char.Char] Row Col
245 | IndentOperatorRight Row Col
246 | IndentMoreExpr Row Col
249data Record
250 = RecordOpen Row Col
251 | RecordEnd Row Col
252 | RecordField Row Col
253 | RecordEquals Row Col
254 | RecordExpr Expr Row Col
255 | RecordSpace Space Row Col
256 --
257 | RecordIndentOpen Row Col
258 | RecordIndentEnd Row Col
259 | RecordIndentField Row Col
260 | RecordIndentEquals Row Col
261 | RecordIndentExpr Row Col
264data Tuple
265 = TupleOpen Row Col
266 | TupleExpr Expr Row Col
267 | TupleSpace Space Row Col
268 | TupleEnd Row Col
269 | TupleOperatorClose Row Col
270 | TupleOperatorReserved Operator Row Col
271 --
272 | TupleIndentExpr Row Col
273 | TupleIndentEnd Row Col
276data List
277 = ListSpace Space Row Col
278 | ListOpen Row Col
279 | ListExpr Expr Row Col
280 | ListEnd Row Col
281 --
282 | ListIndentOpen Row Col
283 | ListIndentEnd Row Col
284 | ListIndentExpr Row Col
287data Func
288 = FuncSpace Space Row Col
289 | FuncArg Pattern Row Col
290 | FuncBody Expr Row Col
291 | FuncArrow Row Col
292 --
293 | FuncIndentArg Row Col
294 | FuncIndentArrow Row Col
295 | FuncIndentBody Row Col
298data Case
299 = CaseSpace Space Row Col
300 | CaseOf Row Col
301 | CasePattern Pattern Row Col
302 | CaseArrow Row Col
303 | CaseExpr Expr Row Col
304 | CaseBranch Expr Row Col
305 --
306 | CaseIndentOf Row Col
307 | CaseIndentExpr Row Col
308 | CaseIndentPattern Row Col
309 | CaseIndentArrow Row Col
310 | CaseIndentBranch Row Col
311 | CasePatternAlignment Word16 Row Col
314data If
315 = IfSpace Space Row Col
316 | IfThen Row Col
317 | IfElse Row Col
318 | IfElseBranchStart Row Col
319 --
320 | IfCondition Expr Row Col
321 | IfThenBranch Expr Row Col
322 | IfElseBranch Expr Row Col
323 --
324 | IfIndentCondition Row Col
325 | IfIndentThen Row Col
326 | IfIndentThenBranch Row Col
327 | IfIndentElseBranch Row Col
328 | IfIndentElse Row Col
331data Let
332 = LetSpace Space Row Col
333 | LetIn Row Col
334 | LetDefAlignment Word16 Row Col
335 | LetDefName Row Col
336 | LetDef Name.Name Def Row Col
337 | LetDestruct Destruct Row Col
338 | LetBody Expr Row Col
339 | LetIndentDef Row Col
340 | LetIndentIn Row Col
341 | LetIndentBody Row Col
344data Def
345 = DefSpace Space Row Col
346 | DefType Type Row Col
347 | DefNameRepeat Name.Name Row Col
348 | DefNameMatch Name.Name Name.Name Row Col
349 | DefArg Pattern Row Col
350 | DefEquals Row Col
351 | DefBody Expr Row Col
352 | DefIndentEquals Row Col
353 | DefIndentType Row Col
354 | DefIndentBody Row Col
355 | DefAlignment Word16 Row Col
358data Destruct
359 = DestructSpace Space Row Col
360 | DestructPattern Pattern Row Col
361 | DestructEquals Row Col
362 | DestructBody Expr Row Col
363 | DestructIndentEquals Row Col
364 | DestructIndentBody Row Col
368-- PATTERNS
371data Pattern
372 = PRecord PRecord Row Col
373 | PTuple PTuple Row Col
374 | PList PList Row Col
375 --
376 | PStart Row Col
377 | PChar Char Row Col
378 | PString String Row Col
379 | PNumber Number Row Col
380 | PFloat Int Row Col
381 | PAlias Row Col
382 | PWildcardNotVar Int Row Col
383 | PSpace Space Row Col
384 --
385 | PIndentStart Row Col
386 | PIndentAlias Row Col
389data PRecord
390 = PRecordOpen Row Col
391 | PRecordEnd Row Col
392 | PRecordField Row Col
393 | PRecordSpace Space Row Col
394 --
395 | PRecordIndentOpen Row Col
396 | PRecordIndentEnd Row Col
397 | PRecordIndentField Row Col
400data PTuple
401 = PTupleOpen Row Col
402 | PTupleEnd Row Col
403 | PTupleExpr Pattern Row Col
404 | PTupleSpace Space Row Col
405 --
406 | PTupleIndentOpen Row Col
407 | PTupleIndentEnd Row Col
408 | PTupleIndentExpr Row Col
411data PList
412 = PListOpen Row Col
413 | PListEnd Row Col
414 | PListExpr Pattern Row Col
415 | PListSpace Space Row Col
416 --
417 | PListIndentOpen Row Col
418 | PListIndentEnd Row Col
419 | PListIndentExpr Row Col
423-- TYPES
426data Type
427 = TRecord TRecord Row Col
428 | TTuple TTuple Row Col
429 | TVariant Row Col
430 | TArrow Row Col
431 --
432 | TStart Row Col
433 | TSpace Space Row Col
434 --
435 | TIndentStart Row Col
438data TRecord
439 = TRecordOpen Row Col
440 | TRecordEnd Row Col
441 --
442 | TRecordField Row Col
443 | TRecordColon Row Col
444 | TRecordType Type Row Col
445 --
446 | TRecordSpace Space Row Col
447 --
448 | TRecordIndentOpen Row Col
449 | TRecordIndentField Row Col
450 | TRecordIndentColon Row Col
451 | TRecordIndentType Row Col
452 | TRecordIndentEnd Row Col
455data TTuple
456 = TTupleOpen Row Col
457 | TTupleEnd Row Col
458 | TTupleType Type Row Col
459 | TTupleSpace Space Row Col
460 --
461 | TTupleIndentOpen Row Col
462 | TTupleIndentType Row Col
463 | TTupleIndentEnd Row Col
467-- LITERALS
470data Char
471 = CharEndless
472 | CharEscape Escape
473 | CharNotString Word16
476data String
477 = StringEndless_Single
478 | StringEndless_Multi
479 | StringEscape Escape
482data Escape
483 = EscapeUnknown
484 | BadUnicodeFormat Word16
485 | BadUnicodeCode Word16
486 | BadUnicodeLength Word16 Int Int
489data Number
490 = NumberEnd
491 | NumberDot Int
492 | NumberHexDigit
493 | NumberNoLeadingZero
497-- MISC
500data Space
501 = HasTab
502 | EndlessMultiComment
505data Operator
506 = OpDot
507 | OpPipe
508 | OpArrow
509 | OpEquals
510 | OpHasType
514-- TO REPORT
517toReport :: Code.Source -> Error -> Report.Report
518toReport source err =
519 case err of
520 ModuleNameUnspecified name ->
521 let
522 region = toRegion 1 1
523 in
524 Report.Report "MODULE NAME MISSING" region [] $
525 D.stack
526 [ D.reflow $
527 "I need the module name to be declared at the top of this file, like this:"
528 , D.indent 4 $ D.green $ D.fromChars $
529 "module " ++ ModuleName.toChars name ++ " exposing (..)"
530 , D.reflow $
531 "Try adding that as the first line of your file!"
532 , D.toSimpleNote $
533 "It is best to replace (..) with an explicit list of types and\
534 \ functions you want to expose. When you know a value is only used\
535 \ within this module, you can refactor without worrying about uses\
536 \ elsewhere. Limiting exposed values can also speed up compilation\
537 \ because I can skip a bunch of work if I see that the exposed API\
538 \ has not changed."
539 ]
541 ModuleNameMismatch expectedName (A.At region actualName) ->
542 Report.Report "MODULE NAME MISMATCH" region [ModuleName.toChars expectedName] $
543 Report.toCodeSnippet source region Nothing
544 (
545 "It looks like this module name is out of sync:"
546 ,
547 D.stack
548 [ D.reflow $
549 "I need it to match the file path, so I was expecting it to see `"
550 ++ ModuleName.toChars expectedName
551 ++ "` here. Make the following change, and you should be all set!"
552 , D.indent 4 $
553 D.dullyellow (D.fromName actualName) <> " -> " <> D.green (D.fromName expectedName)
554 , D.toSimpleNote $
555 "I require that module names correspond to file paths. This makes it much\
556 \ easier to explore unfamiliar codebases! So if you want to keep the current\
557 \ module name, try renaming the file instead."
558 ]
559 )
561 UnexpectedPort region ->
562 error "TODO UnexpectedPort" region
564 NoPorts region ->
565 error "TODO NoPorts" region
567 ParseError modul ->
568 toParseErrorReport source modul
571toParseErrorReport :: Code.Source -> Module -> Report.Report
572toParseErrorReport source modul =
573 case modul of
574 ModuleSpace space row col ->
575 toSpaceReport source space row col
577 ModuleEndOfFile row col ->
578 let
579 region = toRegion row col
580 in
581 Report.Report "EXPECTING END OF FILE" region [] $
582 Report.toCodeSnippet source region Nothing
583 (
584 D.reflow $
585 "I was not expecting to see anything more here:"
586 ,
587 D.reflow $
588 "I think I have read all the declarations in the file and that there is nothing\
589 \ left to see, so whatever I am running into is confusing me a lot!"
590 )
592 Module row col ->
593 error "TODO Module" row col
595 ModuleName row col ->
596 error "TODO ModuleName" row col
598 ModuleExposing row col ->
599 error "TODO ModuleExposing" row col
601 ModuleExposingList exposing row col ->
602 error "TODO ModuleExposingList" exposing row col
604 --
605 ModulePortModule row col ->
606 error "TODO ModulePortModule" row col
608 ModuleEffect row col ->
609 error "TODO ModuleEffect" row col
611 ModuleIndentStart row col ->
612 error "TODO ModuleIndentStart" row col
614 ModuleIndentName row col ->
615 error "TODO ModuleIndentName" row col
617 ModuleIndentExposing row col ->
618 error "TODO ModuleIndentExposing" row col
620 ModuleIndentExposingList row col ->
621 error "TODO ModuleIndentExposingList" row col
623 ModuleIndentPortModule row col ->
624 error "TODO ModuleIndentPortModule" row col
626 FreshLineModuleStart row col ->
627 error "TODO FreshLineModuleStart" row col
629 FreshLineAfterModuleLine row col ->
630 error "TODO FreshLineAfterModuleLine" row col
632 FreshLineAfterDocComment row col ->
633 error "TODO FreshLineAfterDocComment" row col
635 ImportStart row col ->
636 error "TODO ImportStart" row col
638 ImportName row col ->
639 error "TODO ImportName" row col
641 ImportAs row col ->
642 error "TODO ImportAs" row col
644 ImportAlias row col ->
645 error "TODO ImportAlias" row col
647 ImportExposing row col ->
648 error "TODO ImportExposing" row col
650 ImportExposingList exposing row col ->
651 error "TODO ImportExposingList" exposing row col
653 ImportEnd row col ->
654 error "TODO ImportEnd" row col
656 ImportIndentName row col ->
657 error "TODO ImportIndentName" row col
659 ImportIndentAs row col ->
660 error "TODO ImportIndentAs" row col
662 ImportIndentAlias row col ->
663 error "TODO ImportIndentAlias" row col
665 ImportIndentExposing row col ->
666 error "TODO ImportIndentExposing" row col
668 ImportIndentExposingList row col ->
669 error "TODO ImportIndentExposingList" row col
671 Infix row col ->
672 error "TODO Infix" row col
674 Declarations decl _ _ ->
675 toDeclarationsReport source decl
678toSpaceReport :: Code.Source -> Space -> Row -> Col -> Report.Report
679toSpaceReport source space row col =
680 case space of
681 HasTab ->
682 let
683 region = toRegion row col
684 in
685 Report.Report "NO TABS" region [] $
686 Report.toCodeSnippet source region Nothing
687 (
688 D.reflow $
689 "I ran into a tab, but tabs are not allowed in Elm files."
690 ,
691 D.reflow $
692 "Replace the tab with spaces."
693 )
695 EndlessMultiComment ->
696 let
697 region = toWiderRegion row col 2
698 in
699 Report.Report "ENDLESS COMMENT" region [] $
700 Report.toCodeSnippet source region Nothing
701 (
702 D.reflow $
703 "I cannot find the end of this multi-line comment:"
704 ,
705 D.stack -- "{-"
706 [ D.reflow "Add a -} somewhere after this to end the comment."
707 , D.toSimpleHint
708 "Multi-line comments can be nested in Elm, so {- {- -} -} is a comment\
709 \ that happens to contain another comment. Like parentheses and curly braces,\
710 \ the start and end markers must always be balanced. Maybe that is the problem?"
711 ]
712 )
715toRegion :: Row -> Col -> A.Region
716toRegion row col =
717 let
718 pos = A.Position row col
719 in
720 A.Region pos pos
723toWiderRegion :: Row -> Col -> Word16 -> A.Region
724toWiderRegion row col extra =
725 A.Region
726 (A.Position row col)
727 (A.Position row (col + extra))
730toDeclarationsReport :: Code.Source -> Decl -> Report.Report
731toDeclarationsReport source decl =
732 case decl of
733 DeclStart row col ->
734 error "TODO DeclStart" row col
736 DeclSpace space row col ->
737 toSpaceReport source space row col
739 Port port row col ->
740 error "TODO Port" port row col
742 DeclType declType row col ->
743 error "TODO DeclType" declType row col
745 DeclDef name declDef row col ->
746 toDeclDefReport source name declDef row col
748 DeclFreshLineStart row col ->
749 error "TODO DeclFreshLineStart" row col
751 DeclFreshLineAfterDocComment row col ->
752 error "TODO DeclFreshLineAfterDocComment" row col
755toDeclDefReport :: Code.Source -> Name.Name -> DeclDef -> Row -> Col -> Report.Report
756toDeclDefReport source name declDef _ _ =
757 case declDef of
758 DeclDefSpace space row col ->
759 toSpaceReport source space row col
761 DeclDefEquals row col ->
762 error "TODO DeclDefEquals" row col
764 DeclDefType tipe row col ->
765 error "TODO DeclDefType" tipe row col
767 DeclDefArg pattern row col ->
768 error "TODO DeclDefArg" pattern row col
770 DeclDefBody expr row col ->
771 toExprReport source name expr row col
773 DeclDefNameRepeat row col ->
774 error "TODO DeclDefNameRepeat" name row col
776 DeclDefNameMatch defName row col ->
777 error "TODO DeclDefNameMatch" name defName row col
779 DeclDefIndentType row col ->
780 error "TODO DeclDefIndentType" row col
782 DeclDefIndentEquals row col ->
783 error "TODO DeclDefIndentEquals" row col
785 DeclDefIndentBody row col ->
786 error "TODO DeclDefIndentBody" row col
788 DeclDefFreshLineAfterType row col ->
789 error "TODO DeclDefFreshLineAfterType" row col
793toExprReport :: Code.Source -> Name.Name -> Expr -> Row -> Col -> Report.Report
794toExprReport source _ expr _ _ =
795 case expr of
796 Let _ _ _ ->
797 error "TODO Let"
799 Case _ _ _ ->
800 error "TODO Case"
802 If _ _ _ ->
803 error "TODO If"
805 List _ _ _ ->
806 error "TODO List"
808 Record _ _ _ ->
809 error "TODO Record"
811 Update _ _ _ ->
812 error "TODO Update"
814 Tuple _ _ _ ->
815 error "TODO Tuple"
817 Func _ _ _ ->
818 error "TODO Func"
820 Dot _ _ ->
821 error "TODO Dot"
823 Access _ _ ->
824 error "TODO Access"
826 OperatorRHS _ _ ->
827 error "TODO OperatorRHS"
829 OperatorRight _ _ ->
830 error "TODO OperatorRight"
832 OperatorReserved _ _ _ ->
833 error "TODO OperatorReserved"
835 Start _ _ ->
836 error "TODO Start"
838 Char char row col ->
839 toCharReport source char row col
841 String string row col ->
842 toStringReport source string row col
844 Number number row col ->
845 toNumberReport source number row col
847 Space space row col ->
848 toSpaceReport source space row col
850 EndlessShader row col ->
851 let
852 region = toWiderRegion row col 6
853 in
854 Report.Report "ENDLESS SHADER" region [] $
855 Report.toCodeSnippet source region Nothing
856 (
857 D.reflow "I cannot find the end of this shader:"
858 ,
859 D.reflow "Add a |] somewhere after this to end the shader."
860 )
862 ShaderProblem problem row col ->
863 let
864 region = toRegion row col
865 in
866 Report.Report "SHADER PROBLEM" region [] $
867 Report.toCodeSnippet source region Nothing
868 (
869 D.reflow $
870 "I ran into a problem while parsing this GLSL block."
871 ,
872 D.stack
873 [ D.reflow $
874 "I use a 3rd party GLSL parser for now, and I did my best to extract their error message:"
875 , D.indent 4 $ D.vcat $
876 map D.fromChars (filter (/="") (lines problem))
877 ]
878 )
880 IndentOperatorRight _ _ ->
881 error "TODO IndentOperatorRight"
883 IndentMoreExpr _ _ ->
884 error "TODO IndentMoreExpr"
887toCharReport :: Code.Source -> Char -> Row -> Col -> Report.Report
888toCharReport source char row col =
889 case char of
890 CharEndless ->
891 let
892 region = toRegion row col
893 in
894 Report.Report "MISSING SINGLE QUOTE" region [] $
895 Report.toCodeSnippet source region Nothing
896 (
897 D.reflow $
898 "I thought I was parsing a character, but I got to the end of\
899 \ the line without seeing the closing single quote:"
900 ,
901 D.reflow $
902 "Add a closing single quote here!"
903 )
905 CharEscape escape ->
906 toEscapeReport source escape row col
908 CharNotString width ->
909 let
910 region = toWiderRegion row col width
911 in
912 Report.Report "NEEDS DOUBLE QUOTES" region [] $
913 Report.toCodeSnippet source region Nothing
914 (
915 "The following string uses single quotes:"
916 ,
917 D.stack
918 [ "Please switch to double quotes instead:"
919 , D.indent 4 $
920 D.dullyellow "'this'" <> " => " <> D.green "\"this\""
921 , D.toSimpleNote $
922 "Elm uses double quotes for strings like \"hello\", whereas it uses single\
923 \ quotes for individual characters like 'a' and 'ø'. This distinction helps with\
924 \ code like (String.any (\\c -> c == 'X') \"90210\") where you are inspecting\
925 \ individual characters."
926 ]
927 )
930toStringReport :: Code.Source -> String -> Row -> Col -> Report.Report
931toStringReport source string row col =
932 case string of
933 StringEndless_Single ->
934 let
935 region = toRegion row col
936 in
937 Report.Report "ENDLESS STRING" region [] $
938 Report.toCodeSnippet source region Nothing
939 (
940 D.reflow $
941 "I got to the end of the line without seeing the closing double quote:"
942 ,
943 D.stack
944 [ D.fillSep $
945 ["Strings","look","like",D.green "\"this\"","with","double"
946 ,"quotes","on","each","end.","Is","the","closing","double"
947 ,"quote","missing","in","your","code?"
948 ]
949 , D.link "Note" "Read" "TODO" "if you want a string that spans multiple lines."
950 ]
951 )
953 StringEndless_Multi ->
954 let
955 region = toWiderRegion row col 3
956 in
957 Report.Report "ENDLESS STRING" region [] $
958 Report.toCodeSnippet source region Nothing
959 (
960 D.reflow $
961 "I cannot find the end of this multi-line string:"
962 ,
963 D.stack
964 [ D.reflow "Add a \"\"\" somewhere after this to end the string."
965 , D.link "Hint" "Read" "TODO" "for more information on strings and multi-line strings."
966 ]
967 )
969 StringEscape escape ->
970 toEscapeReport source escape row col
973toEscapeReport :: Code.Source -> Escape -> Row -> Col -> Report.Report
974toEscapeReport source escape row col =
975 case escape of
976 EscapeUnknown ->
977 let
978 region = toWiderRegion row col 2
979 in
980 Report.Report "UNKNOWN ESCAPE" region [] $
981 Report.toCodeSnippet source region Nothing
982 (
983 D.reflow $
984 "Backslashes always start escaped characters, but I do not recognize this one:"
985 ,
986 D.stack
987 [ D.reflow $
988 "Valid escape characters include:"
989 , D.dullyellow $ D.indent 4 $ D.vcat $
990 [ "\\n"
991 , "\\r"
992 , "\\t"
993 , "\\\""
994 , "\\\'"
995 , "\\\\"
996 , "\\u{003D}"
997 ]
998 , D.reflow $
999 "Do you want one of those instead? Maybe you need \\\\ to escape a backslash?"
1000 , D.toSimpleNote $
1001 "The last style lets encode ANY character by its Unicode code\
1002 \ point. That means \\u{0009} and \\t are the same. You can use\
1003 \ that style for anything not covered by the other six escapes!"
1007 BadUnicodeFormat width ->
1008 let
1009 region = toWiderRegion row col width
1010 in
1011 Report.Report "BAD UNICODE ESCAPE" region [] $
1012 Report.toCodeSnippet source region Nothing
1014 D.reflow $
1015 "I ran into an invalid Unicode escape:"
1017 D.stack
1018 [ D.reflow $
1019 "Here are some examples of valid Unicode escapes:"
1020 , D.dullyellow $ D.indent 4 $ D.vcat $
1021 [ "\\u{0041}"
1022 , "\\u{03BB}"
1023 , "\\u{6728}"
1024 , "\\u{1F60A}"
1026 , D.reflow $
1027 "Notice that the code point is always surrounded by curly braces.\
1028 \ Maybe you are missing the opening or closing curly brace?"
1031 BadUnicodeCode width ->
1032 let
1033 region = toWiderRegion row col width
1034 in
1035 Report.Report "BAD UNICODE ESCAPE" region [] $
1036 Report.toCodeSnippet source region Nothing
1038 D.reflow $
1039 "This is not a valid code point:"
1041 D.reflow $
1042 "The valid code points are between 0 and 10FFFF inclusive."
1045 BadUnicodeLength width numDigits badCode ->
1046 let
1047 region = toWiderRegion row col width
1048 in
1049 Report.Report "BAD UNICODE ESCAPE" region [] $
1050 Report.toCodeSnippet source region Nothing $
1051 if numDigits < 4 then
1053 D.reflow $
1054 "Every code point needs at least four digits:"
1056 let
1057 goodCode = replicate (4 - numDigits) '0' ++ map Char.toUpper (showHex badCode "")
1058 suggestion = "\\u{" <> D.fromChars goodCode <> "}"
1059 in
1060 D.fillSep ["Try",D.green suggestion,"instead?"]
1063 else
1065 D.reflow $
1066 "This code point has too many digits:"
1068 D.fillSep $
1069 ["Valid","code","points","are","between"
1070 ,D.green "\\u{0000}","and",D.green "\\u{10FFFF}" <> ","
1071 ,"so","try","trimming","any","leading","zeros","until"
1072 ,"you","have","between","four","and","six","digits."
1077toNumberReport :: Code.Source -> Number -> Row -> Col -> Report.Report
1078toNumberReport source number row col =
1079 let
1080 region = toRegion row col
1081 in
1082 case number of
1083 NumberEnd ->
1084 Report.Report "WEIRD NUMBER" region [] $
1085 Report.toCodeSnippet source region Nothing
1087 D.reflow $
1088 "I thought I was reading a number, but I ran into some weird stuff here:"
1090 D.stack
1091 [ D.reflow $
1092 "I recognize numbers in the following formats:"
1093 , D.indent 4 $ D.vcat [ "42", "3.14", "6.022e23", "0x002B" ]
1094 , D.reflow $
1095 "So is there a way to write it like one of those?"
1099 NumberDot int ->
1100 Report.Report "WEIRD NUMBER" region [] $
1101 Report.toCodeSnippet source region Nothing
1103 D.reflow $
1104 "Numbers cannot end with a dot like this:"
1106 D.fillSep
1107 ["Switching","to",D.green (D.fromChars (show int))
1108 ,"or",D.green (D.fromChars (show int ++ ".0"))
1109 ,"will","work","though!"
1113 NumberHexDigit ->
1114 Report.Report "WEIRD HEXIDECIMAL" region [] $
1115 Report.toCodeSnippet source region Nothing
1117 D.reflow $
1118 "I thought I was reading a hexidecimal number until I got here:"
1120 D.stack
1121 [ D.reflow $
1122 "Valid hexidecimal digits include 0123456789abcdefABCDEF, so I can\
1123 \ only recognize things like this:"
1124 , D.indent 4 $ D.vcat [ "0x2B", "0x002B", "0x00ffb3" ]
1128 NumberNoLeadingZero ->
1129 Report.Report "LEADING ZEROS" region [] $
1130 Report.toCodeSnippet source region Nothing
1132 D.reflow $
1133 "I do not accept numbers with leading zeros:"
1135 D.stack
1136 [ D.reflow $
1137 "Just delete the leading zeros and it should work!"
1138 , D.toSimpleNote $
1139 "Some languages let you to specify octal numbers by adding a leading zero.\
1140 \ So in C, writing 0111 is the same as writing 73. Some people are used to\
1141 \ that, but others probably want it to equal 111. Either path is going to\
1142 \ surprise people from certain backgrounds, so Elm tries to avoid this whole\
1143 \ situation."
1150 case err of
1151 CommentOnNothing region ->
1152 Report.Report "STRAY COMMENT" region [] $
1153 Report.toCodeSnippet source region Nothing
1155 "This documentation comment is not followed by anything."
1157 D.reflow $
1158 "All documentation comments need to be right above the declaration they\
1159 \ describe. Maybe some code got deleted or commented out by accident? Or\
1160 \ maybe this comment is here by accident?"
1163 UnexpectedPort region ->
1164 Report.Report "UNEXPECTED PORTS" region [] $
1165 Report.toCodeSnippet source region Nothing
1167 D.reflow $
1168 "You are declaring ports in a normal module."
1170 D.stack
1171 [ D.fillSep
1172 ["Switch","this","to","say",D.green "port module","instead,"
1173 ,"marking","that","this","module","contains","port","declarations."
1175 , D.link "Note"
1176 "Ports are not a traditional FFI for calling JS functions directly. They need a different mindset! Read"
1177 "ports"
1178 "to learn the syntax and how to use it effectively."
1182 NoPorts region ->
1183 Report.Report "NO PORTS" region [] $
1184 Report.toCodeSnippet source region Nothing
1186 D.reflow $
1187 "This module does not declare any ports, but it says it will:"
1189 D.fillSep
1190 ["Switch","this","to",D.green "module"
1191 ,"and","you","should","be","all","set!"
1195 ParseError row col context expectation ->
1196 let
1197 pos = A.Position row col
1198 region = A.Region pos pos
1199 in
1200 case expectation of
1201 TODO ->
1202 error "TODO no parse error yet"
1204 XXX ->
1205 error "TODO no parse error yet"
1207 -- Parse.Utils
1209 HasTab ->
1210 Report.Report "NO TABS" region [] $
1211 Report.toCodeSnippet source region Nothing
1213 D.reflow $
1214 "I ran into a tab, but tabs are not allowed in Elm files."
1216 D.reflow $
1217 "Replace the tab with spaces."
1220 DocComment ->
1221 Report.Report "EXPECTING DOC COMMENT" region [] $
1222 Report.toCodeSnippet source region Nothing
1224 D.reflow $
1225 "I was expecting a doc comment here:"
1227 D.reflowLink
1228 "Check out" "TODO" "for examples of doc comments."
1231 -- Parse.Number
1233 Precedence ->
1234 Report.Report "EXPECTING PRECEDENCE" region [] $
1235 Report.toCodeSnippet source region Nothing
1237 D.reflow $
1238 "I was expecting the precedence here:"
1240 D.reflow $
1241 "I need a single digit between 0 and 9 inclusive."
1244 Operator ->
1245 Report.Report "EXPECTING AN OPERATOR" region [] $
1246 Report.toCodeSnippet source region Nothing
1248 D.reflow $
1249 "I was expecting an operator here:"
1251 D.stack
1252 [ D.reflow "Some of the most common operators are:"
1253 , D.indent 4 $ D.vcat ["+","-","*","&&","||"]
1254 , D.reflow "Something like that!"
1258 ReservedOperator op ->
1259 error "TODO ReservedOperator" op
1261 Wildcard ->
1262 Report.Report "EXPECTING A WILDCARD" region [] $
1263 Report.toCodeSnippet source region Nothing
1265 D.reflow $
1266 "I was expecting a _ here:"
1268 D.reflow $
1269 "An underscore indicates that “I do not care about this value” and is\
1270 \ called a wildcard pattern because it will match with any type of values."
1273 WildcardNotVar startCol endCol ->
1274 let
1275 badRegion =
1276 A.Region (A.Position row startCol) (A.Position row endCol)
1277 in
1278 Report.Report "INVALID PATTERN" badRegion [] $
1279 Report.toCodeSnippet source badRegion Nothing
1281 D.reflow $
1282 "I was expecting to see an underscore without any additional characters:"
1284 D.reflow $
1285 "There are two options. Either (1) remove the extra characters and ignore the\
1286 \ value or (2) remove the starting underscore to give the value a normal name."
1289 -- Parse.Pattern
1291 FloatInPattern ->
1292 Report.Report "INVALID PATTERN" region [] $
1293 Report.toCodeSnippet source region Nothing
1295 D.reflow $
1296 "I cannot pattern match with floating point numbers:"
1298 D.reflow $
1299 "Equality on floats can be unreliable, so you usually want to check that they\
1300 \ are nearby with some sort of (abs (actual - expected) < 0.001) check."
1303 FieldNamePattern ->
1304 Report.Report "EXPECTING A FIELD NAME" region [] $
1305 Report.toCodeSnippet source region Nothing
1307 D.reflow $
1308 "I was expecting a field name here:"
1310 D.fillSep $
1311 ["A","name","like",D.dullyellow "id" <> ",",D.dullyellow "status" <> ","
1312 ,"or","whatever","field","you","want","to","access."
1316 -- Parse.Expression
1318 MatchingName name ->
1319 Report.Report "EXPECTING A DEFINITION" region [] $
1320 Report.toCodeSnippet source region Nothing
1322 D.reflow $
1323 "I just saw the type annotation for `" ++ Name.toChars name
1324 ++ "` so I was expecting to see its definition here:"
1326 D.reflow $
1327 "Type annotations always appear directly above the relevant\
1328 \ definition, without anything else (even doc comments) in between."
1334 TypeWithBadDefinition region annName defName ->
1335 Report.Report "ANNOTATION MISMATCH" region [] $
1336 Report.toCodeSnippet source region Nothing
1338 D.reflow $
1339 "I see a `" <> Name.toChars annName
1340 <> "` annotation, but it is followed by a `"
1341 <> Name.toChars defName <> "` definition."
1343 D.fillSep
1344 ["The","annotation","and","definition","names","must","match!"
1345 ,"Is","there","a","typo","between"
1346 , D.dullyellow (D.fromName annName)
1347 ,"and"
1348 , D.dullyellow (D.fromName defName) <> "?"
1353-- PARSE ERROR TO DOCS
1356problemToDocs :: Problem -> (D.Doc, D.Doc)
1357problemToDocs problem =
1358 case problem of
1359 Tab ->
1361 "I ran into a tab, but tabs are not allowed in Elm files."
1363 "Replace the tab with spaces."
1366 EndOfFile_Comment ->
1368 "I got to the end of the file while parsing a multi-line comment."
1371 "Multi-line comments look like {- comment -}, and it looks like\
1372 \ you are missing the closing marker."
1374 D.toSimpleHint $
1375 "Nested multi-line comments like {- this {- and this -} -} are allowed.\
1376 \ The opening and closing markers must be balanced though, just\
1377 \ like parentheses in normal code. Maybe that is the problem?"
1381 EndOfFile_String ->
1383 "I got to the end of the file while parsing a string."
1385 "Strings look like \"this\" with double quotes on each end.\
1386 \ Is the closing double quote missing in your code?"
1389 EndOfFile_MultiString ->
1391 "I got to the end of the file while parsing a multi-line string."
1393 "Multi-line strings look like \"\"\"this\"\"\" with three double quotes\
1394 \ on each end. Is the closing triple quote missing in your code?"
1397 EndOfFile_Char ->
1399 "I got to the end of the file while parsing a character."
1401 "Characters look like 'c' with single quotes on each end.\
1402 \ Is the closing single quote missing in your code?"
1405 NewLineInString ->
1407 "This string is missing the closing quote."
1410 "Elm strings like \"this\" cannot contain newlines."
1412 D.toSimpleHint $
1413 "For strings that CAN contain newlines, say \"\"\"this\"\"\" for Elm’s\
1414 \ multi-line string syntax. It allows unescaped newlines and double quotes."
1418 NewLineInChar ->
1420 "This character is missing the closing quote."
1422 "Elm characters must start and end with a single quote. Valid examples\n\
1423 \ include 'a', 'b', '\n', 'ø', and '\\u{00F8}' for unicode code points."
1426 BadNumberDot numberBeforeDot ->
1428 "Numbers cannot end with a decimal points."
1430 let
1431 number =
1432 D.fromString (show numberBeforeDot)
1433 in
1434 "Saying " <> D.green number <> " or " <> D.green (number <> ".0") <> " will work though!"
1437 BadNumberEnd ->
1439 "Numbers cannot have letters or underscores in them."
1441 "Maybe a space is missing between a number and a variable?"
1444 BadNumberExp ->
1446 "If you put the letter E in a number, it should followed by more digits."
1448 "If you want to say 1000, you can also say 1e3.\
1449 \ You cannot just end it with an E though!"
1452 BadNumberHex ->
1454 "I see the start of a hex number, but not the end."
1456 "A hex number looks like 0x123ABC, where the 0x is followed by hexidecimal\
1457 \ digits. Valid hexidecimal digits include: 0123456789abcdefABCDEF"
1460 BadNumberZero ->
1462 "Normal numbers cannot start with zeros. Take the zeros off the front."
1464 "Only numbers like 0x0040 or 0.25 can start with a zero."
1467 BadUnderscore _ ->
1469 "Variable names cannot start with an underscore like this:"
1471 "Delete the underscore and it shoulld be fine!"
1474 BadOp op stack ->
1475 case op of
1476 HasType ->
1477 badOp stack "A" "\"has type\" operator"
1478 "type annotations and record types"
1479 "Maybe you want :: instead? Or maybe something is indented too much?"
1481 Equals ->
1483 "I was not expecting this equals sign"
1484 <> contextToString " here" " while parsing " stack <> "."
1486 toBadEqualsHint stack
1489 Arrow ->
1490 if isCaseRelated stack then
1492 "I ran into a stray arrow while parsing this `case` expression."
1494 D.reflow $
1495 "All branches in a `case` must be indented the exact\
1496 \ same amount, so the patterns are vertically\
1497 \ aligned. Maybe this branch is indented too much?"
1500 else
1501 badOp stack "An" "arrow"
1502 "cases expressions and anonymous functions"
1503 "Maybe you want > or >= instead?"
1505 Pipe ->
1506 badOp stack "A" "vertical bar"
1507 "type declarations"
1508 "Maybe you want || instead?"
1510 Dot ->
1512 "I was not expecting this dot."
1514 D.reflow $
1515 "Dots are for record access and decimal points, so\
1516 \ they cannot float around on their own. Maybe\
1517 \ there is some extra whitespace?"
1520 Theories stack allTheories ->
1522 D.reflow $
1523 "Something went wrong while parsing " <> contextToString "your code" "" stack <> "."
1525 case Set.toList (Set.fromList allTheories) of
1526 [] ->
1527 D.stack
1528 [ D.reflow $
1529 "I do not have any suggestions though!"
1530 , D.reflow $
1531 "Can you get it down to a <http://sscce.org> and share it at\
1532 \ <https://github.com/elm/error-message-catalog/issues>?\
1533 \ That way we can figure out how to give better advice!"
1536 [theory] ->
1537 D.reflow $
1538 "I was expecting to see "
1539 <> addPeriod (theoryToString stack theory)
1541 theories ->
1542 D.vcat $
1543 [ "I was expecting:"
1544 , ""
1546 ++ map (bullet . theoryToString stack) theories
1551-- BAD OP HELPERS
1554badOp :: ContextStack -> String -> String -> String -> String -> ( D.Doc, D.Doc )
1555badOp stack article opName setting hint =
1557 D.reflow $
1558 "I was not expecting this " <> opName
1559 <> contextToString " here" " while parsing " stack <> "."
1561 D.reflow $
1562 article <> " " <> opName <> " should only appear in "
1563 <> setting <> ". " <> hint
1567toBadEqualsHint :: ContextStack -> D.Doc
1568toBadEqualsHint stack =
1569 case stack of
1570 [] ->
1571 D.reflow $
1572 "Maybe you want == instead? Or maybe something is indented too much?"
1574 (ExprRecord, _) : _ ->
1575 D.reflow $
1576 "Records look like { x = 3, y = 4 } with the equals sign right\
1577 \ after the field name. Maybe you forgot a comma?"
1579 (Definition _, _) : rest ->
1580 D.reflow $
1581 "Maybe this is supposed to be a separate definition? If so, it\
1582 \ is indented too far. "
1583 <>
1584 if any ((==) ExprLet . fst) rest then
1585 "All definitions in a `let` expression must be vertically aligned."
1586 else
1587 "Spaces are not allowed before top-level definitions."
1589 _ : rest ->
1590 toBadEqualsHint rest
1594isCaseRelated :: ContextStack -> Bool
1595isCaseRelated stack =
1596 case stack of
1597 [] ->
1598 False
1600 (context, _) : rest ->
1601 context == ExprCase || isCaseRelated rest
1605-- CONTEXT
1608contextToString :: String -> String -> ContextStack -> String
1609contextToString defaultString prefixString stack =
1610 case stack of
1611 [] ->
1612 defaultString
1614 (context, _) : rest ->
1615 let anchor = getAnchor rest in
1616 prefixString <>
1617 case context of
1618 ExprIf -> "an `if` expression" <> anchor
1619 ExprLet -> "a `let` expression" <> anchor
1620 ExprFunc -> "an anonymous function" <> anchor
1621 ExprCase -> "a `case` expression" <> anchor
1622 ExprList -> "a list" <> anchor
1623 ExprTuple -> "an expression (in parentheses)" <> anchor
1624 ExprRecord -> "a record" <> anchor
1625 Definition name -> Name.toChars name <> "'s definition"
1626 Annotation name -> Name.toChars name <> "'s type annotation"
1627 TypeTuple -> "a type (in parentheses)" <> anchor
1628 TypeRecord -> "a record type" <> anchor
1629 PatternList -> "a list pattern" <> anchor
1630 PatternTuple -> "a pattern (in parentheses)" <> anchor
1631 PatternRecord -> "a record pattern" <> anchor
1632 Module -> "a module declaration"
1633 Import -> "an import"
1634 TypeUnion -> "a union type"
1635 TypeAlias -> "a type alias"
1636 Infix -> "an infix declaration"
1637 Port -> "a port declaration"
1640getAnchor :: ContextStack -> String
1641getAnchor stack =
1642 case stack of
1643 [] ->
1644 ""
1646 (context, _) : rest ->
1647 case context of
1648 Definition name ->
1649 " in " <> Name.toChars name <> "'s definition"
1651 Annotation name ->
1652 " in " <> Name.toChars name <> "'s type annotation"
1654 _ ->
1655 getAnchor rest
1659-- THEORY HELPERS
1662bullet :: String -> D.Doc
1663bullet point =
1664 D.hang 4 (" - " <> D.fillSep (map D.fromString (words point)))
1667addPeriod :: String -> String
1668addPeriod msg =
1669 if last msg `elem` ['`', ')', '.', '!', '?'] then
1670 msg
1671 else
1672 msg <> "."
1675theoryToString :: ContextStack -> Theory -> String
1676theoryToString context theory =
1677 case theory of
1678 Keyword keyword ->
1679 "the `" <> keyword <> "` keyword"
1681 Symbol symbol ->
1682 case symbol of
1683 "=" -> equalsTheory context
1684 "->" -> "an arrow (->) followed by an expression"
1685 ":" -> "the \"has type\" symbol (:) followed by a type"
1686 "," -> "a comma"
1687 "|" -> barTheory context
1688 "::" -> "the cons operator (::) followed by more list elements"
1689 "." -> "a dot (.)"
1690 "-" -> "a minus sign (-)"
1691 "_" -> "an underscore"
1692 "(" -> "a left paren, for grouping or starting tuples"
1693 ")" -> "a closing paren"
1694 "[" -> "a left square bracket, for starting lists"
1695 "]" -> "a right square bracket, to end a list"
1696 "{" -> "a left curly brace, for starting records"
1697 "}" -> "a right curly brace, to end a record"
1698 "{-|" -> "a doc comment, like {-| this -}" --}
1699 _ -> "the (" <> symbol <> ") symbol"
1701 LowVar ->
1702 "a lower-case variable, like `x` or `user`"
1704 CapVar ->
1705 "an upper-case variable, like `Maybe` or `Just`"
1707 InfixOp ->
1708 "an infix operator, like (+) or (==)"
1710 Digit ->
1711 "a digit from 0 to 9"
1713 BadSpace ->
1714 badSpace context
1716 Expecting next ->
1717 case next of
1718 Decl -> "a declaration, like `x = 5` or `type alias Model = { ... }`"
1719 Expr -> "an expression, like x or 42"
1720 AfterOpExpr op -> "an expression after that (" <> Name.toChars op <> ") operator, like x or 42"
1721 ElseBranch -> "an `else` branch. An `if` must handle both possibilities."
1722 Arg -> "an argument, like `name` or `total`"
1723 Pattern -> "a pattern, like `name` or (Just x)"
1724 Type -> "a type, like Int or (List String)"
1725 Listing -> "a list of exposed values and types, like (..) or (x,y,z)"
1726 Exposing -> "something like `exposing (..)`"
1729equalsTheory :: ContextStack -> String
1730equalsTheory stack =
1731 case stack of
1732 [] ->
1733 "an equals sign (=)"
1735 (context, _) : rest ->
1736 case context of
1737 ExprRecord -> "an equals sign (=) followed by an expression"
1738 Definition name -> "an equals sign (=) followed by " <> Name.toChars name <> "'s definition"
1739 TypeUnion -> "an equals sign (=) followed by the first union type constructor"
1740 TypeAlias -> "an equals sign (=) followed by the aliased type"
1741 _ -> equalsTheory rest
1744barTheory :: ContextStack -> String
1745barTheory stack =
1746 case stack of
1747 [] ->
1748 "a vertical bar (|)"
1750 (context, _) : rest ->
1751 case context of
1752 ExprRecord -> "a vertical bar (|) followed by the record fields you want to update"
1753 TypeRecord -> "a vertical bar (|) followed by some record field types"
1754 TypeUnion -> "a vertical bar (|) followed by more union type constructors"
1755 _ -> barTheory rest
1758badSpace :: ContextStack -> String
1759badSpace stack =
1760 case stack of
1761 [] ->
1762 "more indentation? I was not done with that last thing yet."
1764 (context, _) : rest ->
1765 case context of
1766 ExprIf -> "the end of that `if`" <> badSpaceExprEnd rest
1767 ExprLet -> "the end of that `let`" <> badSpaceExprEnd rest
1768 ExprFunc -> badSpace rest
1769 ExprCase -> "more of that `case`" <> badSpaceExprEnd rest
1770 ExprList -> "the end of that list" <> badSpaceExprEnd rest
1771 ExprTuple -> "a closing paren" <> badSpaceExprEnd rest
1772 ExprRecord -> "the end of that record" <> badSpaceExprEnd rest
1773 Definition name -> "the rest of " <> Name.toChars name <> "'s definition" <> badSpaceExprEnd stack
1774 Annotation name -> "the rest of " <> Name.toChars name <> "'s type annotation" <> badSpaceEnd
1775 TypeTuple -> "a closing paren" <> badSpaceEnd
1776 TypeRecord -> "the end of that record" <> badSpaceEnd
1777 PatternList -> "the end of that list" <> badSpaceEnd
1778 PatternTuple -> "a closing paren" <> badSpaceEnd
1779 PatternRecord -> "the end of that record" <> badSpaceEnd
1780 Module -> "something like `module Main exposing (..)`"
1781 Import -> "something like `import Html exposing (..)`"
1782 TypeUnion -> "more of that union type" <> badSpaceEnd
1783 TypeAlias -> "more of that type alias" <> badSpaceEnd
1784 Infix -> "more of that infix declaration" <> badSpaceEnd
1785 Port -> "more of that port declaration" <> badSpaceEnd
1788badSpaceEnd :: String
1789badSpaceEnd =
1790 ". Maybe you forgot some code? Or you need more indentation?"
1793badSpaceExprEnd :: ContextStack -> String
1794badSpaceExprEnd stack =
1795 case stack of
1796 [] ->
1797 badSpaceEnd
1799 (Definition name, A.Position _ column) : _ ->
1800 let
1801 ending =
1802 if column <= 1 then
1803 "to be indented?"
1804 else
1805 "more indentation? (Try " <> show (column + 1) <> "+ spaces.)"
1806 in
1807 ". Maybe you forgot some code? Or maybe the body of `"
1808 <> Name.toChars name
1809 <> "` needs " <> ending
1811 _ : rest ->
1812 badSpaceExprEnd rest