on master help sign in
Put the canonicalization errors in an intermediate state that still works
commitbc755bbe8025661c9505dc49a2015ef6def65993 authorEvan Czaplicki <evancz@users.noreply.github.com> dateMon 15 Jan 2018, 16:03 (9 years ago) parent7130d19
1 file changed+533−397
src/Reporting/Error/Canonicalize.hs+533−397
src/Reporting/Error/Canonicalize.hs+533−397
@@ -2,32 +2,31 @@
22{-# LANGUAGE OverloadedStrings #-}
33module Reporting.Error.Canonicalize
44 ( Error(..)
5− , Args(..)
6− , CtorType(..)
7− , CycleNode(..)
5+ , BadArityContext(..)
86 , InvalidPayload(..)
7+ , DuplicatePatternContext(..)
98 , variable
109 , VarKind(..)
1110 , VarProblem(..)
1211 , toReport
13− , extractSuggestions
1412 )
1513 where
1614
1715
1816import qualified Data.Char as Char
19−import qualified Data.Text as Text
2017import Data.Text (Text)
2118
22−import qualified AST.Expression.Canonical as Can
23−import qualified AST.Type as Type
19+import qualified AST.Canonical as Can
20+import qualified AST.Source as Src
21+import qualified Data.Index as Index
2422import qualified Elm.Name as N
2523import qualified Reporting.Annotation as A
2624import qualified Reporting.Region as R
25+import qualified Reporting.Render.Code as Code
2726import qualified Reporting.Render.Type as RenderType
2827import qualified Reporting.Report as Report
29−import qualified Reporting.Helpers as Help
30−import Reporting.Helpers ( Doc, (<>), dullyellow, fillSep, green, i2t, indent, reflowParagraph, text )
28+import qualified Reporting.Helpers as H
29+import Reporting.Helpers ( Doc, (<>) )
3130
3231
3332
@@ -36,53 +35,49 @@ import Reporting.Helpers ( Doc, (<>), dullyellow, fillSep, green, i2t, indent, r
3635
3736data Error
3837 = Var VarError
39− | Binop N.Name N.Name
40− | DuplicateArg N.Name
41− | DuplicateDecl N.Name
42− | DuplicateType N.Name
43− | DuplicateCtor N.Name CtorType CtorType
44− | DuplicateBinop N.Name
45− | DuplicateField N.Name
46− | DuplicateAliasArg N.Name N.Name [N.Name]
47− | DuplicateUnionArg N.Name N.Name [N.Name]
48− | DuplicateBindingName N.Name
49− | EffectNotFound N.Name
50− | EffectFunctionNotFound N.Name
51− | ExportDuplicate N.Name
52− | ExportNotFound VarKind N.Name [N.Name]
53− | ExportOpenAlias N.Name
54− | ImportNotFound N.Name [N.Name]
55− | ImportCtorNotFound N.Name N.Name
56− | ImportOpenAlias N.Name
57− | ImportExposingNotFound N.Name N.Name [N.Name]
58− | PortPayloadInvalid N.Name Type.Canonical InvalidPayload
59− | PortTypeInvalid N.Name Type.Canonical
60− | RecursiveAlias N.Name [N.Name] Type.Raw [N.Name]
61− | RecursiveDecl R.Region N.Name [N.Name]
62− | RecursiveLet [CycleNode]
63− | Shadowing N.Name
64− | TooFew Args N.Name Int Int
65− | TooMany Args N.Name Int Int R.Region
38+ | AnnotationTooShort R.Region N.Name Index.ZeroBased Int
39+ | BadArity R.Region BadArityContext N.Name Int Int
40+ | Binop R.Region N.Name N.Name
41+ | DuplicateDecl N.Name R.Region R.Region
42+ | DuplicateType N.Name R.Region R.Region
43+ | DuplicateCtor N.Name R.Region R.Region
44+ | DuplicateBinop N.Name R.Region R.Region
45+ | DuplicateField N.Name R.Region R.Region
46+ | DuplicateAliasArg N.Name N.Name R.Region R.Region
47+ | DuplicateUnionArg N.Name N.Name R.Region R.Region
48+ | DuplicatePattern DuplicatePatternContext N.Name R.Region R.Region
49+ | EffectNotFound R.Region N.Name
50+ | EffectFunctionNotFound R.Region N.Name
51+ | ExportDuplicate N.Name R.Region R.Region
52+ | ExportNotFound R.Region VarKind N.Name [N.Name]
53+ | ExportOpenAlias R.Region N.Name
54+ | ImportCtorByName R.Region N.Name N.Name
55+ | ImportNotFound R.Region N.Name [N.Name]
56+ | ImportOpenAlias R.Region N.Name
57+ | ImportExposingNotFound R.Region N.Name N.Name [N.Name]
58+ | PatternHasRecordCtor R.Region N.Name
59+ | PortPayloadInvalid R.Region N.Name Can.Type InvalidPayload
60+ | PortTypeInvalid R.Region N.Name Can.Type
61+ | RecursiveAlias R.Region N.Name [N.Name] Src.Type [N.Name]
62+ | RecursiveDecl [Can.Def]
63+ | RecursiveLet (A.Located N.Name) [N.Name]
64+ | Shadowing N.Name R.Region R.Region
6665 | TupleLargerThanThree R.Region
67− | TypeVarsUnboundInUnion N.Name [N.Name] [A.Located N.Name]
68− | TypeVarsMessedUpInAlias N.Name [N.Name] [A.Located N.Name] [A.Located N.Name]
66+ | TypeVarsUnboundInUnion R.Region N.Name [N.Name] [A.Located N.Name]
67+ | TypeVarsMessedUpInAlias R.Region N.Name [N.Name] [A.Located N.Name] [A.Located N.Name]
6968
7069
71−data Args
72− = UnionArgs
73− | AliasArgs
74− | PatternArgs
70+data BadArityContext
71+ = TypeArity
72+ | PatternArity
7573
7674
77−data CtorType
78− = UnionCtor N.Name
79− | RecordCtor
80−
81−
82−data CycleNode
83− = CycleFunc (A.Located N.Name)
84− | CycleValue (A.Located N.Name)
85− | CyclePattern Can.Pattern
75+data DuplicatePatternContext
76+ = DPLambdaArgs
77+ | DPFuncArgs N.Name
78+ | DPCaseBranch
79+ | DPLetBinding
80+ | DPDestruct
8681
8782
8883data InvalidPayload
@@ -128,335 +123,518 @@ data VarKind
128123 | BadType
129124
130125
131−toKindInfo :: VarKind -> Text -> ( Doc, Doc, Doc )
126+toKindInfo :: VarKind -> N.Name -> ( Doc, Doc, Doc )
132127toKindInfo kind name =
133128 case kind of
134129 BadOp ->
135− ( "an", "operator", text $ "(" <> name <> ")" )
130+ ( "an", "operator", "(" <> H.nameToDoc name <> ")" )
136131
137132 BadVar ->
138− ( "a", "value", text name )
133+ ( "a", "value", "`" <> H.nameToDoc name <> "`" )
139134
140135 BadPattern ->
141− ( "a", "pattern", text name )
136+ ( "a", "pattern", "`" <> H.nameToDoc name <> "`" )
142137
143138 BadType ->
144− ( "a", "type", text name )
139+ ( "a", "type", "`" <> H.nameToDoc name <> "`" )
145140
146141
147142
148−-- EXTRACT SUGGESTIONS
143+-- TO REPORT
149144
150145
151−extractSuggestions :: Error -> Maybe [Text]
152−extractSuggestions err =
146+toReport :: Code.Source -> RenderType.Localizer -> Error -> Report.Report
147+toReport source localizer err =
153148 case err of
154− Var (VarError _ _ _ suggestions) ->
155− Just suggestions
156−
157− Binop _ _ ->
158− Nothing
159−
160− DuplicateArg _ ->
161− Nothing
162−
163− DuplicateDecl _ ->
164− Nothing
165−
166− DuplicateType _ ->
167− Nothing
168−
169− DuplicateCtor _ _ _ ->
170− Nothing
171−
172− DuplicateBinop _ ->
173− Nothing
174−
175− DuplicateField _ ->
176− Nothing
177−
178− DuplicateAliasArg _ _ _ ->
179− Nothing
180−
181− DuplicateUnionArg _ _ _ ->
182− Nothing
183−
184− DuplicateBindingName _ ->
185− Nothing
186−
187− EffectNotFound _ ->
188− Nothing
189−
190− EffectFunctionNotFound _ ->
191− Nothing
192−
193− ExportDuplicate _ ->
194− Nothing
195−
196− ExportNotFound _ _ suggestions ->
197− Just suggestions
198−
199− ExportOpenAlias _ ->
200− Nothing
201−
202− ImportNotFound _ suggestions ->
203− Just suggestions
149+ Var varError ->
150+ error "TODO" varError
204151
205− ImportExposingNotFound _ _ suggestions ->
206− Just suggestions
152+ AnnotationTooShort region name index leftovers ->
153+ let
154+ numTypeArgs = Index.toHuman index
155+ numDefArgs = numTypeArgs + leftovers
156+ in
157+ Report.Report "BAD TYPE ANNOTATION" region [] $
158+ Report.toCodeSnippet source region Nothing
159+ (
160+ H.reflow $
161+ "The type annotation for `" <> N.toString name <> "` says it can accept "
162+ <> H.args numTypeArgs <> ", but the definition says it has "
163+ <> H.args numDefArgs <> ":"
164+ ,
165+ H.reflow $
166+ "Is the type annotation missing something? Should some argument"
167+ <> (if leftovers == 1 then "" else "s")
168+ <> " be deleted? Maybe some parentheses are missing?"
169+ )
207170
208− ImportCtorNotFound _ _ ->
209− Nothing
171+ BadArity region badArityContext name expected actual ->
172+ let
173+ thing =
174+ case badArityContext of
175+ TypeArity -> "type"
176+ PatternArity -> "constructor"
177+ in
178+ if actual < expected then
179+ Report.Report "TOO FEW ARGS" region [] $
180+ Report.toCodeSnippet source region Nothing
181+ (
182+ H.reflow $
183+ "The `" <> N.toString name <> "` " <> thing <> " needs "
184+ <> H.args expected <> ", but I only see " <> show actual <> ":"
185+ ,
186+ "What is missing? Is there some typo?"
187+ )
188+
189+ else
190+ Report.Report "TOO MANY ARGS" region [] $
191+ Report.toCodeSnippet source region Nothing
192+ (
193+ H.reflow $
194+ "The `" <> N.toString name <> "` " <> thing <> " needs "
195+ <> H.args expected <> ", but I see " <> show actual <> " instead:"
196+ ,
197+ if actual - expected == 1 then
198+ "Which is the extra one? Maybe some parentheses are missing?"
199+ else
200+ "Which are the extra ones? Maybe some parentheses are missing?"
201+ )
202+
203+ Binop region op1 op2 ->
204+ Report.Report "INFIX PROBLEM" region [] $
205+ Report.toCodeSnippet source region Nothing
206+ (
207+ H.reflow $
208+ "You cannot mix (" <> N.toString op1 <> ") and (" <> N.toString op2 <> ") without parentheses."
209+ ,
210+ H.reflow
211+ "I do not know how to group these expressions. Add parentheses for me!"
212+ )
210213
211− ImportOpenAlias _ ->
212− Nothing
214+ DuplicateDecl name r1 r2 ->
215+ nameClash source r1 r2 $
216+ "This file has multiple `" <> N.toString name <> "` declarations."
213217
214− PortPayloadInvalid _ _ _ ->
215− Nothing
218+ DuplicateType name r1 r2 ->
219+ nameClash source r1 r2 $
220+ "This file defines multiple `" <> N.toString name <> "` types."
216221
217− PortTypeInvalid _ _ ->
218− Nothing
222+ DuplicateCtor name r1 r2 ->
223+ nameClash source r1 r2 $
224+ "This file defines multiple `" <> N.toString name <> "` type constructors."
219225
220− RecursiveAlias _ _ _ _ ->
221− Nothing
226+ DuplicateBinop name r1 r2 ->
227+ nameClash source r1 r2 $
228+ "This file defines multiple (" <> N.toString name <> ") operators."
222229
223− RecursiveDecl _ _ _ ->
224− Nothing
230+ DuplicateField name r1 r2 ->
231+ nameClash source r1 r2 $
232+ "This record has multiple `" <> N.toString name <> "` fields."
225233
226− RecursiveLet _ ->
227− Nothing
234+ DuplicateAliasArg typeName name r1 r2 ->
235+ nameClash source r1 r2 $
236+ "The `" <> N.toString typeName <> "` type alias has multilpe `" <> N.toString name <> "` type variables."
228237
229− Shadowing _ ->
230− Nothing
238+ DuplicateUnionArg typeName name r1 r2 ->
239+ nameClash source r1 r2 $
240+ "The `" <> N.toString typeName <> "` type has multilpe `" <> N.toString name <> "` type variables."
231241
232− TooFew _ _ _ _ ->
233− Nothing
242+ DuplicatePattern context name r1 r2 ->
243+ nameClash source r1 r2 $
244+ case context of
245+ DPLambdaArgs ->
246+ "This anonymous function has multiple `" <> N.toString name <> "` arguments."
234247
235− TooMany _ _ _ _ _ ->
236− Nothing
248+ DPFuncArgs funcName ->
249+ "The `" <> N.toString funcName <> "` function has multiple `" <> N.toString name <> "` arguments."
237250
238− TupleLargerThanThree _ ->
239− Nothing
251+ DPCaseBranch ->
252+ "This `case` pattern has multiple `" <> N.toString name <> "` variables."
240253
241− TypeVarsUnboundInUnion _ _ _ ->
242− Nothing
254+ DPLetBinding ->
255+ "This `let` expression defines `" <> N.toString name <> "` more than once!"
243256
244− TypeVarsMessedUpInAlias _ _ _ _ ->
245− Nothing
257+ DPDestruct ->
258+ "This pattern contains multiple `" <> N.toString name <> "` variables."
246259
260+ EffectNotFound _ _ ->
261+ error "TODO EffectNotFound"
247262
263+ EffectFunctionNotFound _ _ ->
264+ error "TODO EffectFunctionNotFound"
248265
249−-- TO REPORT
266+ ExportDuplicate name r1 r2 ->
267+ let
268+ messageThatEndsWithPunctuation =
269+ "You are trying to expose `" <> N.toString name <> "` multiple times!"
270+ in
271+ Report.Report "REDUNDANT EXPORT" r2 [] $
272+ Report.toCodePair source r1 r2
273+ (
274+ H.reflow messageThatEndsWithPunctuation
275+ ,
276+ "Remove one of them and you should be all set!"
277+ )
278+ (
279+ H.reflow (messageThatEndsWithPunctuation <> " Once here:")
280+ ,
281+ "And again right here:"
282+ ,
283+ "Remove one of them and you should be all set!"
284+ )
250285
286+ ExportNotFound region kind rawName suggestions ->
287+ Report.Report "UNKNOWN EXPORT" region suggestions $
288+ let (a, thing, name) = toKindInfo kind rawName in
289+ H.stack
290+ [ H.fillSep
291+ ["You","are","trying","to","expose",a,thing,"named"
292+ ,name,"but","I","cannot","find","its","definition."
293+ ]
294+ , H.maybeYouWant Nothing suggestions
295+ ]
251296
252−toReport :: RenderType.Localizer -> Error -> Report.Report
253−toReport localizer err =
254− case err of
255− Var varError ->
256− varErrorToReport varError
297+ ExportOpenAlias region name ->
298+ error "TODO" region name
257299
258− Binop op1 op2 ->
259− Report.report
260− "INFIX PROBLEM"
261− Nothing
262− ("You cannot mix (" <> op1 <> ") and (" <> op2 <> ") without parentheses." )
300+ ImportCtorByName region ctor tipe ->
301+ Report.Report "BAD IMPORT" region [] $
302+ Report.toCodeSnippet source region Nothing
263303 (
264− Help.stack
265− [ reflowParagraph $
266− "I do not know how to group these expressions. Add parentheses for me!"
304+ H.reflow $
305+ "You are trying to import the `" <> N.toString ctor
306+ <> "` type constructor by name:"
307+ ,
308+ H.fillSep
309+ ["Try","importing",H.green (H.nameToDoc tipe <> "(..)"),"instead."
310+ ,"The","dots","mean","“expose","the",H.nameToDoc tipe,"type","and"
311+ ,"all","its","constructors”","so","it","gives","you","access","to"
312+ , H.nameToDoc ctor <> "."
267313 ]
268314 )
269315
270− DuplicateArg _ ->
271− error "TODO DuplicateArg"
272−
273− DuplicateDecl _ ->
274− error "TODO DuplicateDecl"
275−
276− DuplicateType _ ->
277− error "TODO DuplicateType"
278−
279− DuplicateCtor _ _ _ ->
280− error "TODO DuplicateCtor"
281−
282− DuplicateBinop _ ->
283− error "TODO DuplicateBinop"
284−
285− DuplicateField _ ->
286− error "TODO DuplicateField"
287−
288− DuplicateAliasArg _ _ _ ->
289− error "TODO DuplicateAliasArg"
290−
291− DuplicateUnionArg _ _ _ ->
292− error "TODO DuplicateUnionArg"
293−
294− DuplicateBindingName _ ->
295− error "TODO DuplicateBindingName"
296−
297− EffectNotFound _ ->
298− error "TODO EffectNotFound"
299−
300− EffectFunctionNotFound _ ->
301− error "TODO EffectFunctionNotFound"
302−
303− ExportDuplicate name ->
304− Report.report "EXPOSING ERROR" Nothing
305− ("You are trying to expose `" <> name <> "` multiple times!")
306− "Remove duplicates until there is only one listed."
316+ ImportNotFound region name suggestions ->
317+ Report.Report "UNKNOWN IMPORT" region suggestions $
318+ Report.toCodeSnippet source region Nothing
319+ (
320+ H.reflow $
321+ "I could not find a `" <> N.toString name <> "` module to import!"
322+ ,
323+ H.maybeYouWant Nothing suggestions
324+ )
307325
308− ExportNotFound kind rawName suggestions ->
309− let (a, thing, name) = toKindInfo kind rawName in
310− Report.reportDoc "EXPOSING ERROR" Nothing
311− ["You","are","trying","to","expose",a,thing,"named"
312− ,name,"but","I","cannot","find","its","definition."
313− ]
314− (Help.maybeYouWant Nothing suggestions)
315−
316− ExportOpenAlias name ->
317− error "TODO" name
318−
319− ImportNotFound name suggestions ->
320− Report.report "IMPORT ERROR" Nothing
321− ("Could not find a module named `" <> name <> "`")
322− (Help.maybeYouWant Nothing suggestions)
323−
324− ImportCtorNotFound ctor tipe ->
325− Report.report "IMPORT ERROR" Nothing
326− ("This is not the syntax for exposing a `" <> tipe <> "` type constructor:")
327− ( Help.stack
328− [ reflowParagraph $
329− "Delete that. You can expose the `" <> ctor
330− <> "` type constructors by saying:"
331− , indent 4 (green (text (tipe <> "(..)")))
332− , reflowParagraph $
333− "This means that every type constructors of `" <> tipe
334− <> "` is exposed. No need to list them separately."
326+ ImportOpenAlias region name ->
327+ Report.Report "BAD IMPORT" region [] $
328+ Report.toCodeSnippet source region Nothing
329+ (
330+ H.reflow $
331+ "The `" <> N.toString name <> "` type alias cannot be followed by (..) like this:"
332+ ,
333+ H.stack
334+ [ "Remove the (..) and it should work."
335+ , H.link "Hint"
336+ "The distinction between `type` and `type alias` is important here. Read"
337+ "types-vs-type-aliases"
338+ "to learn more."
335339 ]
336340 )
337341
338− ImportOpenAlias name ->
339− Report.report "IMPORT ERROR" Nothing
340− ("Cannot expose `" <> name <> "` like this:")
341− ( reflowParagraph $
342− "The (..) syntax exposes type constructors, but a type alias like `"
343− <> name <> "` has no constructors! It is just an alternate name for\
344− \ an existing type. Remove the (..) part and it should work."
342+ ImportExposingNotFound region name value suggestions ->
343+ Report.Report "BAD IMPORT" region suggestions $
344+ Report.toCodeSnippet source region Nothing
345+ (
346+ H.reflow $
347+ "The `" <> N.toString name
348+ <> "` module does not expose `"
349+ <> N.toString value <> "`:"
350+ ,
351+ H.maybeYouWant Nothing suggestions
345352 )
346− -- TODO add docs about the difference between types and type aliases
347353
348− ImportExposingNotFound name value suggestions ->
349− Report.report "IMPORT ERROR" Nothing
350− ("Module `" <> name <> "` does not expose `" <> value <> "`")
351− (Help.maybeYouWant Nothing suggestions)
354+ PatternHasRecordCtor region name ->
355+ Report.Report "BAD PATTERN" region [] $
356+ Report.toCodeSnippet source region Nothing
357+ (
358+ H.reflow $
359+ "You can construct records by using `" <> N.toString name
360+ <> "` as a function, but it is not available in pattern matching like this:"
361+ ,
362+ H.reflow $
363+ "I recommend matching matching the record as a variable and unpacking it later."
364+ )
352365
353− PortPayloadInvalid portName tipe invalidPayload ->
366+ PortPayloadInvalid region portName badType invalidPayload ->
354367 let
355− context =
368+ (aBadKindOfThing, elaboration) =
356369 case invalidPayload of
357370 ExtendedRecord ->
358− "an extended record"
371+ (
372+ "an extended record"
373+ ,
374+ H.reflow $
375+ "The exact shape of the record must be known at compile time. No type variables!"
376+ )
359377
360378 Function ->
361− "a function"
379+ (
380+ "a function"
381+ ,
382+ H.reflow $
383+ "Functions cannot be sent in and out ports. If we allowed functions in from JS\
384+ \ they may perform some side-effects. If we let functions out, they could produce\
385+ \ incorrect results because Elm optimizations assume there are no side-effects."
386+ )
387+
362388
363389 TypeVariable name ->
364− const "an unknown type" (error "TODO" name)
365− -- "Notice the `" <> name <> "` type variable. It must be a concrete type, like Int or Float."
390+ (
391+ "an unspecified type"
392+ ,
393+ H.reflow $
394+ "Type variables like `" <> N.toString name <> "` cannot flow through ports because\
395+ \ the marshalling code needs to know the exact data that it is going to process."
396+ )
366397
367398 UnsupportedType name ->
368− "a `" <> name <> "` value"
399+ (
400+ "a `" <> N.toString name <> "` value"
401+ ,
402+ H.stack
403+ [ H.reflow $ "The types that can flow in and out of Elm include:"
404+ , H.indent 4 $
405+ H.reflow $
406+ "Ints, Floats, Bools, Strings, Maybes, Lists, Arrays,\
407+ \ tuples, records, and JSON values."
408+ , H.reflow $
409+ "Since JSON values can flow through, you can use JSON encoders and decoders\
410+ \ to allow other types through as well. More advanced users often just do\
411+ \ everything with encoders and decoders for more control and better errors."
412+ ]
413+ )
369414 in
370− Report.report
371− "PORT ERROR"
372− Nothing
373− ("Port `" <> portName <> "` is trying to transmit " <> context <> ":"
415+ Report.Report "PORT ERROR" region [] $
416+ Report.toCodeSnippet source region Nothing
417+ (
418+ H.reflow $
419+ "The `" <> N.toString portName <> "` port is trying to transmit " <> aBadKindOfThing <> ":"
420+ ,
421+ H.stack
422+ [ error "TODO" badType
423+ , elaboration
424+ , H.link "Hint"
425+ "Ports are not a traditional FFI for calling JS functions directly. They need a different mindset! Read"
426+ "ports"
427+ "to learn how to use ports effectively."
428+ ]
429+ )
430+
431+ PortTypeInvalid region name badType ->
432+ Report.Report "BAD PORT" region [] $
433+ Report.toCodeSnippet source region Nothing
434+ (
435+ H.reflow $
436+ "Port `" <> N.toString name <> "` has an invalid type."
437+ ,
438+ error "TODO PortTypeInvalid" badType
374439 )
375− (error "TODO" tipe)
376− {- Help.stack
377− [ text ("The specific unsupported type is" <> context <> ":")
378− , indent 4 (RenderType.toDoc localizer tipe)
379− , text "The types of values that can flow through in and out of Elm include:"
380− , indent 4 $ reflowParagraph $
381− "Ints, Floats, Bools, Strings, Maybes, Lists, Arrays,\
382− \ Tuples, Json.Values, and concrete records."
383− -- TODO add a note about custom decoders and encoders when they exist!
384− ]
385− -}
386440
387− PortTypeInvalid name tipe ->
388− Report.report
389− "PORT ERROR"
390− Nothing
391− ("Port `" <> name <> "` has an invalid type."
392− )
393− ( Help.stack
394− [ text ("You are saying it should be:")
395− , indent 4 (RenderType.toDoc localizer tipe)
396− , reflowParagraph $
397− "But you need to use the particular format described here:\
398− \ <http://guide.elm-lang.org/interop/javascript.html#ports>"
441+ RecursiveAlias region name args tipe others ->
442+ aliasRecursionReport source localizer region name args tipe others
443+
444+ RecursiveDecl cyclicValueDefs ->
445+ error "TODO" cyclicValueDefs
446+
447+ RecursiveLet (A.At region name) names ->
448+ Report.Report "CYCLIC VALUE" region [] $
449+ Report.toCodeSnippet source region Nothing $
450+ case names of
451+ [] ->
452+ (
453+ H.reflow $
454+ "The `" <> N.toString name <> "` value has a direct use of `" <> N.toString name <> "` in its definition."
455+ ,
456+ H.stack
457+ [ H.reflow $
458+ "To know what `" <> N.toString name
459+ <> "` is, I need to know what `" <> N.toString name
460+ <> "` is. Let me recursively figure that out. Hmm, I need to know what `"
461+ <> N.toString name <> "` is..."
462+ , H.link "Hint"
463+ "The root problem is often a typo in some variable name, but I recommend reading"
464+ "bad-recursion"
465+ "for more detailed advice, especially if you actually do need a recursive value."
466+ ]
467+ )
468+
469+ _ ->
470+ (
471+ H.reflow $
472+ "I do not allow cyclic values in `let` expressions."
473+ ,
474+ H.stack
475+ [ H.reflow $
476+ "The `" <> N.toString name
477+ <> "` value depends on itself through the following chain of definitions:"
478+ , H.indent 4 $ H.drawCycle (name:names)
479+ , H.link "Hint"
480+ "The root problem is often a typo in some variable name, but I recommend reading"
481+ "bad-recursion"
482+ "for more detailed advice, especially if you actually do want mutually recursive values."
483+ ]
484+ )
485+
486+ Shadowing name r1 r2 ->
487+ Report.Report "SHADOWING" r2 [] $
488+ Report.toCodePair source r1 r2
489+ ( "These variables cannot have the same name:"
490+ , advice
491+ )
492+ ( H.reflow $ "The name `" <> N.toString name <> "` is first defined here:"
493+ , "But then it is defined AGAIN over here:"
494+ , advice
495+ )
496+ where
497+ advice =
498+ H.stack
499+ [ H.reflow $
500+ "Think of a more helpful name for one of them and you should be all set!"
501+ , H.link "Note"
502+ "Linters advise against shadowing, so Elm makes “best practices” the default. Read"
503+ "shadowing"
504+ "for more details on this choice."
399505 ]
400− )
401−
402− RecursiveAlias name args tipe others ->
403− aliasRecursionReport localizer name args tipe others
404−
405− RecursiveDecl region name names ->
406− error "TODO" region name names
407−
408− RecursiveLet cycles ->
409− case cycles of
410− [] ->
411− error "TODO"
412−
413− [_] ->
414− error "TODO" badSelfRecursion
415−
416− _ ->
417− error "TODO" badMutualRecursion
418−
419− Shadowing _ ->
420− error "TODO Shadowing"
421506
422− TooFew _ _ _ _ ->
423− error "TODO TooFew"
424−
425− TooMany _ _ _ _ _ ->
426− error "TODO TooMany"
427−
428− TupleLargerThanThree _ ->
429− error "TODO TupleLargerThanThree"
430−
431− TypeVarsUnboundInUnion _ _ _ ->
432− error "TODO TypeVarsUnboundInUnion"
507+ TupleLargerThanThree region ->
508+ Report.Report "BAD TUPLE" region [] $
509+ Report.toCodeSnippet source region Nothing
510+ (
511+ "I only accept tuples with two or three items. This has too many:"
512+ ,
513+ H.stack
514+ [ H.reflow $
515+ "I recommend switching to records. Each item will be named, and you can use\
516+ \ the `point.x` syntax to access them."
517+
518+ , H.link "Note" "Read" "tuples"
519+ "for more comprehensive advice on working with large chunks of data in Elm."
520+ ]
521+ )
433522
434− TypeVarsMessedUpInAlias _ _ _ _ ->
435− error "TODO TypeVarsMessedUpInAlias"
523+ TypeVarsUnboundInUnion _ _ _ _ ->
524+ error "TODO TypeVarsUnboundInUnion"
525+
526+ TypeVarsMessedUpInAlias _ _ _ _ _ ->
527+ error "TODO TypeVarsMessedUpInAlias"
528+
529+
530+
531+
532+-- UnboundTypeVarsInUnion typeName givenVars unbound ->
533+-- unboundTypeVars "type" typeName givenVars unbound
534+
535+-- UnboundTypeVarsInAlias typeName givenVars unbound ->
536+-- unboundTypeVars "type alias" typeName givenVars unbound
537+
538+-- UnusedTypeVarsInAlias typeName givenVars unused ->
539+-- Report.report
540+-- "UNUSED TYPE VARIABLES"
541+-- Nothing
542+-- ( "Type alias `" <> typeName <> "` cannot have unused type variables: "
543+-- <> H.commaSep unused
544+-- )
545+-- ( H.stack
546+-- [ text "You probably need to change the declaration like this:"
547+-- , H.dullyellow $ hsep $
548+-- map text ("type" : "alias" : typeName : filter (`notElem` unused) givenVars ++ ["=", "..."])
549+-- ]
550+-- )
551+
552+-- MessyTypeVarsInAlias typeName givenVars unused unbound ->
553+-- Report.report
554+-- "TYPE VARIABLE PROBLEMS"
555+-- Nothing
556+-- ( "Type alias `" <> typeName <> "` has some problems with type variables."
557+-- )
558+-- ( H.stack
559+-- [ H.reflow $
560+-- "The declaration says it uses certain type variables ("
561+-- <> H.commaSep unused <> ") but they do not appear in the aliased type. "
562+-- <> "Furthermore, the aliased type says it uses type variables ("
563+-- <> H.commaSep unbound
564+-- <> ") that do not appear in the declaration."
565+-- , text "You probably need to change the declaration like this:"
566+-- , H.dullyellow $ hsep $
567+-- map text ("type" : "alias" : typeName : filter (`notElem` unused) givenVars ++ unbound ++ ["=", "..."])
568+-- ]
569+-- )
570+
571+
572+--unboundTypeVars :: Text -> Text -> [Text] -> [Text] -> Report.Report
573+--unboundTypeVars declKind typeName givenVars unboundVars =
574+-- Report.report
575+-- "UNBOUND TYPE VARIABLES"
576+-- Nothing
577+-- ( H.capitalize declKind <> " `" <> typeName <> "` must declare its use of type variable"
578+-- <> H.commaSep unboundVars
579+-- )
580+-- ( H.stack
581+-- [ text "You probably need to change the declaration like this:"
582+-- , hsep $
583+-- map text (declKind : typeName : givenVars)
584+-- ++ map (H.dullyellow . text) unboundVars
585+-- ++ map text ["=", "..."]
586+-- , reflow $
587+-- "Here's why. Imagine one `" <> typeName <> "` where `" <> head unboundVars <>
588+-- "` is an Int and another where it is a Bool. When we explicitly list the type\
589+-- \ variables, the type checker can see that they are actually different types."
590+-- ]
591+-- )
592+
593+
594+
595+-- NAME CLASH
596+
597+
598+nameClash :: Code.Source -> R.Region -> R.Region -> String -> Report.Report
599+nameClash source r1 r2 messageThatEndsWithPunctuation =
600+ Report.Report "NAME CLASH" r2 [] $
601+ Report.toCodePair source r1 r2
602+ (
603+ H.reflow messageThatEndsWithPunctuation
604+ ,
605+ "How can I know which one you want? Rename one of them!"
606+ )
607+ (
608+ H.reflow (messageThatEndsWithPunctuation <> " One here:")
609+ ,
610+ "And another one here:"
611+ ,
612+ "How can I know which one you want? Rename one of them!"
613+ )
436614
437615
438616
439−-- VAR ERROR
617+{-- VAR ERROR
440618
441619
442620varErrorToReport :: VarError -> Report.Report
443621varErrorToReport (VarError kind name problem suggestions) =
444622 let
445623 learnMore orMaybe =
446− Help.reflowParagraph $
624+ H.reflow $
447625 orMaybe <> " `import` works different than you expect? Learn all about it here: "
448− <> Help.hintLink "imports"
626+ <> H.hintLink "imports"
449627
450628 namingError overview maybeStarter specializedSuggestions =
451629 Report.reportDoc "NAMING ERROR" Nothing overview $
452− case Help.maybeYouWant' maybeStarter specializedSuggestions of
630+ case H.maybeYouWant' maybeStarter specializedSuggestions of
453631 Nothing ->
454632 learnMore "Maybe"
455633 Just doc ->
456− Help.stack [ doc, learnMore "Or maybe" ]
634+ H.stack [ doc, learnMore "Or maybe" ]
457635
458636 specialNamingError specialHint =
459− Report.reportDoc "NAMING ERROR" Nothing (cannotFind kind name) (Help.hsep specialHint)
637+ Report.reportDoc "NAMING ERROR" Nothing (cannotFind kind name) (H.hsep specialHint)
460638 in
461639 case problem of
462640 Ambiguous ->
@@ -486,145 +664,103 @@ varErrorToReport (VarError kind name problem suggestions) =
486664cannotFind :: VarKind -> Text -> [Doc]
487665cannotFind kind rawName =
488666 let ( a, thing, name ) = toKindInfo kind rawName in
489− [ "Cannot", "find", a, thing, "named", dullyellow name <> ":" ]
667+ [ "Cannot", "find", a, thing, "named", H.dullyellow name <> ":" ]
490668
491669
492670ambiguous :: VarKind -> Text -> [Doc]
493671ambiguous kind rawName =
494672 let ( _a, thing, name ) = toKindInfo kind rawName in
495− [ "This", "usage", "of", "the", dullyellow name, thing, "is", "ambiguous." ]
673+ [ "This", "usage", "of", "the", H.dullyellow name, thing, "is", "ambiguous." ]
496674
497675
498676notEqualsHint :: Text -> [Doc]
499677notEqualsHint op =
500678 [ "Looking", "for", "the", "“not", "equal”", "operator?", "The", "traditional"
501− , dullyellow $ text $ "(" <> op <> ")"
502− , "is", "replaced", "by", green "(/=)", "in", "Elm.", "It", "is", "meant"
679+ , H.dullyellow $ text $ "(" <> op <> ")"
680+ , "is", "replaced", "by", H.green "(/=)", "in", "Elm.", "It", "is", "meant"
503681 , "to", "look", "like", "the", "“not", "equal”", "sign", "from", "math!", "(≠)"
504682 ]
505683
506684
507685equalsHint :: [Doc]
508686equalsHint =
509− [ "A", "special", dullyellow "(===)", "operator", "is", "not", "needed"
510− , "in", "Elm.", "We", "use", green "(==)", "for", "everything!"
687+ [ "A", "special", H.dullyellow "(===)", "operator", "is", "not", "needed"
688+ , "in", "Elm.", "We", "use", H.green "(==)", "for", "everything!"
511689 ]
512690
513691
514692modHint :: [Doc]
515693modHint =
516− [ "Rather", "than", "a", dullyellow "(%)", "operator,"
517− , "Elm", "has", "a", green "modBy", "function."
694+ [ "Rather", "than", "a", H.dullyellow "(%)", "operator,"
695+ , "Elm", "has", "a", H.green "modBy", "function."
518696 , "Learn", "more", "here:"
519697 , "<https://package.elm-lang.org/packages/elm-lang/core/latest/Basics#modBy>"
520698 ]
521699
522700
701+-}
702+
523703
524704-- ARG MISMATCH
525705
526706
527−_argMismatchReport :: Text -> N.Name -> Int -> Int -> Report.Report
528−_argMismatchReport kind name expected actual =
707+_argMismatchReport :: Code.Source -> R.Region -> String -> N.Name -> Int -> Int -> Report.Report
708+_argMismatchReport source region kind name expected actual =
529709 let
530710 numArgs =
531711 "too "
532712 <> (if actual < expected then "few" else "many")
533713 <> " arguments"
534714 in
535− Report.report
536− (Text.map Char.toUpper numArgs)
537− Nothing
538− ( kind <> " " <> name <> " has " <> numArgs <> "."
539− )
540− ( text $
541− "Expecting " <> i2t expected <> ", but got " <> i2t actual <> "."
542− )
543−
544−
545−
546−-- BAD RECURSION
547−
548−
549−badSelfRecursion :: R.Region -> Text -> Report.Report
550−badSelfRecursion region name =
551− let
552− header =
553− Help.functionName name <> " is defined directly in terms of itself, causing an infinite loop."
554− in
555− Report.report "BAD RECURSION" (Just region) header $
556− Help.stack
557− [ badSelfRecursionHelp "Maybe you are trying to mutate a variable?" $
558− "Elm does not have mutation, so when I see " <> Help.functionName name
559− <> " defined in terms of " <> Help.functionName name
560− <> ", I treat it as a recursive definition. Try giving the new value a new name!"
561− , badSelfRecursionHelp "Maybe you DO want a recursive value?" $
562− "To define " <> Help.functionName name <> " we need to know what " <> Help.functionName name
563− <> " is, so let’s expand it. Wait, but now we need to know what " <> Help.functionName name
564− <> " is, so let’s expand it... This will keep going infinitely!"
565− , badSelfRecursionHelp "To really learn what is going on and how to fix it, check out:" $
566− Help.hintLink "bad-recursion"
567− ]
568−
569−
570−badSelfRecursionHelp :: Text -> Text -> Doc
571−badSelfRecursionHelp intro body =
572− fillSep $
573− map (dullyellow . text) (Text.words intro)
574− ++ map text (Text.words body)
575−
576−
577−badMutualRecursion :: R.Region -> Text -> [Text] -> Report.Report
578−badMutualRecursion region name names =
579− let
580− header =
581− Help.functionName name <> " is defined in terms of itself in a sneaky way, causing an infinite loop."
582− in
583− Report.report "BAD RECURSION" (Just region) header $
584− Help.stack
585− [ reflowParagraph $
586− "The following definitions depend directly on each other:"
587− , indent 4 $ Help.drawCycle (name : names)
588− , reflowParagraph $
589− "You seem to have a fairly tricky case, so I very highly recommend reading this: "
590− <> Help.hintLink "bad-recursion"
591− <> " It will help you really understand the problem and how to fix it. Read it!"
592− ]
715+ Report.Report (map Char.toUpper numArgs) region [] $
716+ Report.toCodeSnippet source region Nothing
717+ (
718+ H.reflow $
719+ kind <> " " <> N.toString name <> " has " <> numArgs <> "."
720+ ,
721+ H.reflow $
722+ "Expecting " <> show expected <> ", but got " <> show actual <> "."
723+ )
593724
594725
595726
596727-- BAD ALIAS RECURSION
597728
598729
599−aliasRecursionReport :: RenderType.Localizer -> N.Name -> [N.Name] -> Type.Raw -> [N.Name] -> Report.Report
600−aliasRecursionReport localizer name args tipe others =
730+aliasRecursionReport :: Code.Source -> RenderType.Localizer -> R.Region -> N.Name -> [N.Name] -> Src.Type -> [N.Name] -> Report.Report
731+aliasRecursionReport source localizer region name args tipe others =
601732 case others of
602733 [] ->
603− Report.report "ALIAS PROBLEM" Nothing
604− "This type alias is recursive, forming an infinite type!"
605− (
606− Help.stack
607− [ reflowParagraph $
608− "When I expand a recursive type alias, it just keeps getting bigger and bigger.\
609− \ So dealiasing results in an infinitely large type! Try this instead:"
610− , indent 4 $
611− RenderType.decl localizer name args [(name, [error "TODO" tipe])]
612− , text $
613− "This is kind of a subtle distinction. I suggested the naive fix, but you can\n"
614− <> "often do something a bit nicer. So I would recommend reading more at:\n"
615− <> Help.hintLink "recursive-alias"
616− ]
617− )
734+ Report.Report "ALIAS PROBLEM" region [] $
735+ Report.toCodeSnippet source region Nothing
736+ (
737+ "This type alias is recursive, forming an infinite type!"
738+ ,
739+ H.stack
740+ [ H.reflow $
741+ "When I expand a recursive type alias, it just keeps getting bigger and bigger.\
742+ \ So dealiasing results in an infinitely large type! Try this instead:"
743+ , H.indent 4 $
744+ RenderType.decl localizer name args [(name, [error "TODO" tipe])]
745+ , H.link "Hint"
746+ "This is kind of a subtle distinction. I suggested the naive fix, but I recommend reading"
747+ "recursive-alias"
748+ "for ideas on how to do better."
749+ ]
750+ )
618751
619752 _ ->
620− Report.report "ALIAS PROBLEM" Nothing
621− "This type alias is part of a mutually recursive set of type aliases."
622− ( Help.stack
623− [ text "The following type aliases are mutually recursive:"
624− , indent 4 (Help.drawCycle (name:others))
625− , reflowParagraph $
626− "You need to convert at least one `type alias` into a `type`. This is a kind of\
627− \ subtle distinction, so definitely read up on this before you make a fix: "
628− <> Help.hintLink "recursive-alias"
629− ]
630− )
753+ Report.Report "ALIAS PROBLEM" region [] $
754+ Report.toCodeSnippet source region Nothing
755+ (
756+ "This type alias is part of a mutually recursive set of type aliases."
757+ ,
758+ H.stack
759+ [ "It is part of this cycle of type aliases:"
760+ , H.indent 4 (H.drawCycle (name:others))
761+ , H.reflow $
762+ "You need to convert at least one of these type aliases into a `type`."
763+ , H.link "Note" "Read" "recursive-alias"
764+ "to learn why this `type` vs `type alias` distinction matters. It is subtle but important!"
765+ ]
766+ )