on master help sign in
Finish TODO for error messages when names are not found
commitfcd5528f47376e2f159e5cb98a1d3d2a1e99706a authorEvan Czaplicki <evancz@users.noreply.github.com> dateSun 4 Feb 2018, 20:06 (9 years ago) parent5aa5636
7 files changed+231−111
src/Canonicalize/Environment.hs+6−6 src/Canonicalize/Environment/Foreign.hs+28−46 src/Canonicalize/Expression.hs+3−3 src/Elm/Package.hs+21 src/Reporting/Error/Canonicalize.hs+165−30 src/Reporting/Helpers.hs+7−24 src/Reporting/Report.hs+1−2
src/Canonicalize/Environment.hs+6−6
@@ -163,7 +163,7 @@ findType region (Env _ _ ts _ _ _ qts _) name =
163163 Result.throw (Error.AmbiguousType region Nothing name (Map.keys homes))
164164
165165 Nothing ->
166− Result.throw (Error.NotFoundType region name (toPossibleNames ts qts))
166+ Result.throw (Error.NotFoundType region Nothing name (toPossibleNames ts qts))
167167
168168
169169findTypeQual :: R.Region -> Env -> N.Name -> N.Name -> Result i w Type
@@ -178,10 +178,10 @@ findTypeQual region (Env _ _ ts _ _ _ qts _) prefix name =
178178 Result.throw (Error.AmbiguousType region (Just prefix) name (Map.keys homes))
179179
180180 Nothing ->
181− Result.throw (Error.NotFoundTypeQual region prefix name (toPossibleNames ts qts))
181+ Result.throw (Error.NotFoundType region (Just prefix) name (toPossibleNames ts qts))
182182
183183 Nothing ->
184− Result.throw (Error.NotFoundTypeQual region prefix name (toPossibleNames ts qts))
184+ Result.throw (Error.NotFoundType region (Just prefix) name (toPossibleNames ts qts))
185185
186186
187187
@@ -198,7 +198,7 @@ findCtor region (Env _ _ _ cs _ _ _ qcs) name =
198198 Result.throw (Error.AmbiguousCtor region Nothing name (Map.keys homes))
199199
200200 Nothing ->
201− Result.throw (Error.NotFoundCtor region name (toPossibleNames cs qcs))
201+ Result.throw (Error.NotFoundCtor region Nothing name (toPossibleNames cs qcs))
202202
203203
204204findCtorQual :: R.Region -> Env -> N.Name -> N.Name -> Result i w Ctor
@@ -213,10 +213,10 @@ findCtorQual region (Env _ _ _ cs _ _ _ qcs) prefix name =
213213 Result.throw (Error.AmbiguousCtor region (Just prefix) name (Map.keys homes))
214214
215215 Nothing ->
216− Result.throw (Error.NotFoundCtorQual region prefix name (toPossibleNames cs qcs))
216+ Result.throw (Error.NotFoundCtor region (Just prefix) name (toPossibleNames cs qcs))
217217
218218 Nothing ->
219− Result.throw (Error.NotFoundCtorQual region prefix name (toPossibleNames cs qcs))
219+ Result.throw (Error.NotFoundCtor region (Just prefix) name (toPossibleNames cs qcs))
220220
221221
222222
src/Canonicalize/Environment/Foreign.hs+28−46
@@ -18,8 +18,6 @@ import qualified Elm.Interface as I
1818import qualified Elm.Name as N
1919import qualified Reporting.Annotation as A
2020import qualified Reporting.Error.Canonicalize as Error
21−import qualified Reporting.Helpers as Help (nearbyNames)
22−import qualified Reporting.Region as R
2321import qualified Reporting.Result as Result
2422
2523
@@ -186,7 +184,7 @@ addExposedValue home vars types binops (State vs ts cs bs qvs qts qcs) (A.At reg
186184 Result.ok (State (Map.insert name info vs) ts cs bs qvs qts qcs)
187185
188186 Nothing ->
189− throwExposingNotFound region name
187+ Result.throw (Error.ImportExposingNotFound region home name (Map.keys vars))
190188
191189 Src.Upper name privacy ->
192190 case privacy of
@@ -208,7 +206,12 @@ addExposedValue home vars types binops (State vs ts cs bs qvs qts qcs) (A.At reg
208206 Result.ok (State vs ts2 cs2 bs qvs qts qcs)
209207
210208 Nothing ->
211− throwExposingNotFound region name
209+ case Map.lookup name (toCtors types) of
210+ Just tipe ->
211+ Result.throw $ Error.ImportCtorByName region name tipe
212+
213+ Nothing ->
214+ Result.throw $ Error.ImportExposingNotFound region home name (Map.keys types)
212215
213216 Src.Public ->
214217 case Map.lookup name types of
@@ -225,7 +228,7 @@ addExposedValue home vars types binops (State vs ts cs bs qvs qts qcs) (A.At reg
225228 Result.throw (Error.ImportOpenAlias region name)
226229
227230 Nothing ->
228− throwExposingNotFound region name
231+ Result.throw (Error.ImportExposingNotFound region home name (Map.keys types))
229232
230233 Src.Operator op ->
231234 case Map.lookup op binops of
@@ -236,7 +239,24 @@ addExposedValue home vars types binops (State vs ts cs bs qvs qts qcs) (A.At reg
236239 Result.ok (State vs ts cs bs2 qvs qts qcs)
237240
238241 Nothing ->
239− throwExposingNotFound region op
242+ Result.throw (Error.ImportExposingNotFound region home op (Map.keys binops))
243+
244+
245+
246+toCtors :: Map.Map N.Name (Env.Type, Env.Exposed Env.Ctor) -> Map.Map N.Name N.Name
247+toCtors types =
248+ Map.foldr addCtors Map.empty types
249+ where
250+ addCtors (_, exposedCtors) dict =
251+ Map.foldrWithKey addCtor dict exposedCtors
252+
253+ addCtor ctorName homes dict =
254+ case Map.elems homes of
255+ [Env.Ctor _ tipeName _ _ _] ->
256+ Map.insert ctorName tipeName dict
257+
258+ _ ->
259+ dict
240260
241261
242262
@@ -261,45 +281,7 @@ verifyImport importDict interfaces (Src.Import (A.At region name) alias exposing
261281 Result.ok (Import canonicalName interface (maybe name id alias) exposing)
262282
263283 Nothing ->
264− throwImportNotFound region name (Map.keys interfaces)
265−
266− Nothing ->
267− throwImportNotFound region name (Map.elems importDict)
268−
269−
270−throwImportNotFound :: R.Region -> N.Name -> [ModuleName.Canonical] -> Result i w a
271−throwImportNotFound region name knownModules =
272− Result.throw $ Error.ImportNotFound region name $
273− Help.nearbyNames N.toString name $
274− map ModuleName._module knownModules
275−
276−
277−throwExposingNotFound :: R.Region -> N.Name -> Result i w a
278−throwExposingNotFound region name =
279− Result.throw (error ("TODO throwExposingNotFound " ++ N.toString name) region name)
280−
281−{-
282− let
283− ctorDict =
284− Map.fromList (concatMap toCtorPairs (Map.toList unions))
285−
286− toCtorPairs (tipe, union) =
287− case union of
288− Can.Union _ _ ctors ->
289− map (\(Can.Ctor ctor _ _) -> (ctor, tipe)) ctors
290−
291− Can.Enum _ _ names ->
292− map (\ctor -> (ctor, tipe)) names
293−
294− Can.Box _ ctor _ ->
295− [(ctor, tipe)]
296− in
297− case Map.lookup name ctorDict of
298− Just tipe ->
299− Result.throw $ Error.ImportCtorByName region name tipe
284+ Result.throw $ Error.ImportNotFound region name (Map.keys interfaces)
300285
301286 Nothing ->
302− Result.throw $ Error.ImportExposingNotFound region moduleName name $
303− Help.nearbyNames N.toString name $ Set.toList $
304− Set.unions [ Map.keysSet types, Map.keysSet unions, Map.keysSet aliases ]
305−-}
287+ Result.throw $ Error.ImportNotFound region name (Map.elems importDict)
src/Canonicalize/Expression.hs+3−3
@@ -705,7 +705,7 @@ findVar region (Env.Env localHome vs _ _ _ qvs _ _) name =
705705 Result.throw (Error.AmbiguousVar region Nothing name (Map.keys homes))
706706
707707 Nothing ->
708− Result.throw (Error.NotFoundVar region name (toPossibleNames vs qvs))
708+ Result.throw (Error.NotFoundVar region Nothing name (toPossibleNames vs qvs))
709709
710710
711711findVarQual :: R.Region -> Env.Env -> N.Name -> N.Name -> Result FreeLocals w Can.Expr_
@@ -724,13 +724,13 @@ findVarQual region (Env.Env localHome vs _ _ _ qvs _ _) prefix name =
724724 Result.throw (Error.AmbiguousVar region (Just prefix) name (Map.keys homes))
725725
726726 Nothing ->
727− Result.throw (Error.NotFoundVarQual region prefix name (toPossibleNames vs qvs))
727+ Result.throw (Error.NotFoundVar region (Just prefix) name (toPossibleNames vs qvs))
728728
729729 Nothing ->
730730 if ModuleName.isKernel prefix then
731731 Result.ok $ Can.VarKernel (ModuleName.getKernel prefix) name
732732 else
733− Result.throw (Error.NotFoundVarQual region prefix name (toPossibleNames vs qvs))
733+ Result.throw (Error.NotFoundVar region (Just prefix) name (toPossibleNames vs qvs))
734734
735735
736736toPossibleNames :: Map.Map N.Name Env.Var -> Env.Qualified Can.Annotation -> Error.PossibleNames
src/Elm/Package.hs+21
@@ -10,6 +10,7 @@ module Elm.Package
1010 , browser, virtualDom, html
1111 , json, http, url
1212 , webgl, linearAlgebra
13+ , suggestions
1314 , Version(..)
1415 , initialVersion, dummyVersion
1516 , bumpPatch, bumpMinor, bumpMajor
@@ -28,6 +29,7 @@ import Data.Binary (Binary, get, getWord8, put, putWord8)
2829import qualified Data.Char as Char
2930import Data.Function (on)
3031import qualified Data.List as List
32+import qualified Data.Map as Map
3133import Data.Monoid ((<>))
3234import qualified Data.Text as Text
3335import qualified Data.Text.Read as Text
@@ -37,6 +39,8 @@ import qualified Data.Text.Lazy.Builder.Int as B (decimal)
3739import Data.Text (Text)
3840import Data.Word (Word16)
3941import System.FilePath ((</>))
42+
43+import qualified Elm.Name as N
4044import qualified Json.Decode.Internals as Decode
4145import qualified Json.Encode as Encode
4246
@@ -195,6 +199,23 @@ linearAlgebra =
195199
196200
197201
202+-- PACKAGE SUGGESTIONS
203+
204+
205+suggestions :: Map.Map N.Name Name
206+suggestions =
207+ Map.fromList
208+ [ ("Browser", browser)
209+ , ("Html", html)
210+ , ("Http", http)
211+ , ("Json.Decode", json)
212+ , ("Json.Encode", json)
213+ , ("Url.Parser", url)
214+ , ("Url", url)
215+ ]
216+
217+
218+
198219-- PACKAGE VERSIONS
199220
200221
src/Reporting/Error/Canonicalize.hs+165−30
@@ -57,16 +57,13 @@ data Error
5757 | ExportNotFound R.Region VarKind N.Name [N.Name]
5858 | ExportOpenAlias R.Region N.Name
5959 | ImportCtorByName R.Region N.Name N.Name
60− | ImportNotFound R.Region N.Name [N.Name]
60+ | ImportNotFound R.Region N.Name [ModuleName.Canonical]
6161 | ImportOpenAlias R.Region N.Name
62− | ImportExposingNotFound R.Region N.Name N.Name [N.Name]
63− | NotFoundVar R.Region N.Name PossibleNames
64− | NotFoundType R.Region N.Name PossibleNames
65− | NotFoundCtor R.Region N.Name PossibleNames
62+ | ImportExposingNotFound R.Region ModuleName.Canonical N.Name [N.Name]
63+ | NotFoundVar R.Region (Maybe N.Name) N.Name PossibleNames
64+ | NotFoundType R.Region (Maybe N.Name) N.Name PossibleNames
65+ | NotFoundCtor R.Region (Maybe N.Name) N.Name PossibleNames
6666 | NotFoundBinop R.Region N.Name (Set.Set N.Name)
67− | NotFoundVarQual R.Region N.Name N.Name PossibleNames
68− | NotFoundTypeQual R.Region N.Name N.Name PossibleNames
69− | NotFoundCtorQual R.Region N.Name N.Name PossibleNames
7067 | PatternHasRecordCtor R.Region N.Name
7168 | PortPayloadInvalid R.Region N.Name Can.Type InvalidPayload
7269 | PortTypeInvalid R.Region N.Name PortProblem
@@ -311,7 +308,11 @@ toReport source localizer err =
311308 "Remove one of them and you should be all set!"
312309 )
313310
314− ExportNotFound region kind rawName suggestions ->
311+ ExportNotFound region kind rawName possibleNames ->
312+ let
313+ suggestions =
314+ take 4 (H.nearbyNames (N.toString rawName) (map N.toString possibleNames))
315+ in
315316 Report.Report "UNKNOWN EXPORT" region suggestions $
316317 let (a, thing, name) = toKindInfo kind rawName in
317318 H.stack
@@ -319,7 +320,19 @@ toReport source localizer err =
319320 ["You","are","trying","to","expose",a,thing,"named"
320321 ,name,"but","I","cannot","find","its","definition."
321322 ]
322− , H.maybeYouWant Nothing suggestions
323+ , case map H.text suggestions of
324+ [] ->
325+ H.reflow $
326+ "I do not see any super similar names in this file. Is the definition missing?"
327+
328+ [alt] ->
329+ H.fillSep ["Maybe","you","want",H.dullyellow alt,"instead?"]
330+
331+ alts ->
332+ H.stack
333+ [ "These names seem close though:"
334+ , H.indent 4 $ H.vcat $ map H.dullyellow alts
335+ ]
323336 ]
324337
325338 ExportOpenAlias region name ->
@@ -350,14 +363,18 @@ toReport source localizer err =
350363 ]
351364 )
352365
353− ImportNotFound region name suggestions ->
354− Report.Report "UNKNOWN IMPORT" region suggestions $
366+ ImportNotFound region name _ ->
367+ --
368+ -- NOTE: this should always be detected by `builder`
369+ -- So this error should never actually get printed out.
370+ --
371+ Report.Report "UNKNOWN IMPORT" region [] $
355372 Report.toCodeSnippet source region Nothing
356373 (
357374 H.reflow $
358375 "I could not find a `" <> N.toString name <> "` module to import!"
359376 ,
360− H.maybeYouWant Nothing suggestions
377+ mempty
361378 )
362379
363380 ImportOpenAlias region name ->
@@ -376,38 +393,89 @@ toReport source localizer err =
376393 ]
377394 )
378395
379− ImportExposingNotFound region name value suggestions ->
396+ ImportExposingNotFound region (ModuleName.Canonical _ home) value possibleNames ->
397+ let
398+ suggestions =
399+ take 4 $ H.nearbyNames (N.toString home) (map N.toString possibleNames)
400+ in
380401 Report.Report "BAD IMPORT" region suggestions $
381402 Report.toCodeSnippet source region Nothing
382403 (
383404 H.reflow $
384− "The `" <> N.toString name
405+ "The `" <> N.toString home
385406 <> "` module does not expose `"
386407 <> N.toString value <> "`:"
387408 ,
388− H.maybeYouWant Nothing suggestions
409+ case map H.text suggestions of
410+ [] ->
411+ "I cannot find an super similar exposed names. Maybe it is private?"
412+
413+ [alt] ->
414+ H.fillSep ["Maybe","you","want",H.dullyellow alt,"instead?"]
415+
416+ alts ->
417+ H.stack
418+ [ "These names seem close though:"
419+ , H.indent 4 $ H.vcat $ map H.dullyellow alts
420+ ]
389421 )
390422
391− NotFoundVar region name possibleNames ->
392− error "TODO" region name possibleNames
423+ NotFoundVar region prefix name possibleNames ->
424+ notFound source region prefix name "variable" possibleNames
393425
394− NotFoundType region name possibleNames ->
395− error "TODO" region name possibleNames
426+ NotFoundType region prefix name possibleNames ->
427+ notFound source region prefix name "type" possibleNames
396428
397− NotFoundCtor region name possibleNames ->
398− error "TODO" region name possibleNames
429+ NotFoundCtor region prefix name possibleNames ->
430+ notFound source region prefix name "constructor" possibleNames
399431
400− NotFoundBinop region name locals ->
401− error "TODO" region name locals
432+ NotFoundBinop region op locals ->
433+ if op == "===" then
434+ Report.Report "TRIPLE EQUALS" region ["=="] $
435+ Report.toCodeSnippet source region Nothing
436+ (
437+ "Elm does not have a (===) operator like JavaScript."
438+ ,
439+ "Switch to (==) instead."
440+ )
402441
403− NotFoundVarQual region prefix name possibleNames ->
404− error "TODO" region prefix name possibleNames
442+ else if op == "!=" || op == "!==" then
443+ Report.Report "NOT EQUALS" region ["/="] $
444+ Report.toCodeSnippet source region Nothing
445+ (
446+ H.reflow $
447+ "Elm uses a different name for the “not equal” operator:"
448+ ,
449+ H.stack
450+ [ H.reflow "Switch to (/=) instead."
451+ , H.toSimpleNote $
452+ "Our (/=) operator is supposed to look like a real “not equal” sign (≠). I hope that history will remember ("
453+ ++ N.toString op ++ ") as a werid and temporary choice."
454+ ]
455+ )
405456
406− NotFoundTypeQual region prefix name possibleNames ->
407− error "TODO" region prefix name possibleNames
457+ else
458+ let
459+ suggestions =
460+ take 2 $ H.nearbyNames (N.toString op) (map N.toString (Set.toList locals))
461+
462+ format altOp =
463+ H.dullyellow $ "(" <> altOp <> ")"
464+ in
465+ Report.Report "UNKNOWN OPERATOR" region suggestions $
466+ Report.toCodeSnippet source region Nothing
467+ (
468+ H.reflow $
469+ "I do not recognize this (" ++ N.toString op ++ ") operator."
470+ ,
471+ case map H.text suggestions of
472+ [] ->
473+ H.reflow "Is there an `import` and `exposing` entry for it?"
408474
409− NotFoundCtorQual region prefix name possibleNames ->
410− error "TODO" region prefix name possibleNames
475+ alts ->
476+ H.fillSep $
477+ ["Maybe","you","want"] ++ H.commaSep "or" format alts ++ ["instead?"]
478+ )
411479
412480 PatternHasRecordCtor region name ->
413481 Report.Report "BAD PATTERN" region [] $
@@ -738,6 +806,73 @@ nameClash source r1 r2 messageThatEndsWithPunctuation =
738806
739807
740808
809+-- NOT FOUND
810+
811+
812+notFound :: Code.Source -> R.Region -> Maybe N.Name -> N.Name -> String -> PossibleNames -> Report.Report
813+notFound source region maybePrefix name thing (PossibleNames locals quals) =
814+ let
815+ givenName =
816+ maybe N.toString toQualString maybePrefix name
817+
818+ possibleNames =
819+ let
820+ addQuals prefix localSet allNames =
821+ Set.foldr (\x xs -> toQualString prefix x : xs) allNames localSet
822+ in
823+ Map.foldrWithKey addQuals (map N.toString (Set.toList locals)) quals
824+
825+ nearbyNames =
826+ take 4 (H.nearbyNames givenName possibleNames)
827+
828+ toDetails noSuggestionDetails yesSuggestionDetails =
829+ case nearbyNames of
830+ [] ->
831+ H.stack
832+ [ H.reflow noSuggestionDetails
833+ , H.link "Hint" "Read" "imports" "to see how `import` declarations work in Elm."
834+ ]
835+
836+ suggestions ->
837+ H.stack
838+ [ H.reflow yesSuggestionDetails
839+ , H.indent 4 $ H.vcat $ map H.dullyellow $ map H.text suggestions
840+ , H.link "Hint" "Read" "imports" "to see how `import` declarations work in Elm."
841+ ]
842+
843+ in
844+ Report.Report "NAMING ERROR" region nearbyNames $
845+ Report.toCodeSnippet source region Nothing
846+ (
847+ H.reflow $
848+ "I cannot find a `" ++ givenName ++ "` " ++ thing ++ ":"
849+ ,
850+ case maybePrefix of
851+ Nothing ->
852+ toDetails
853+ "Is there an `import` or `exposing` missing up top?"
854+ "These names seem close though:"
855+
856+ Just prefix ->
857+ case Map.lookup prefix quals of
858+ Nothing ->
859+ toDetails
860+ ("I cannot find a `" ++ N.toString prefix ++ "` module. Is there an `import` for it?")
861+ ("I cannot find a `" ++ N.toString prefix ++ "` import. These names seem close though:")
862+
863+ Just _ ->
864+ toDetails
865+ ("The `" ++ N.toString prefix ++ "` module does not expose a `" ++ N.toString name ++ "` " ++ thing ++ ".")
866+ ("The `" ++ N.toString prefix ++ "` module does not expose a `" ++ N.toString name ++ "` " ++ thing ++ ". These names seem close though:")
867+ )
868+
869+
870+toQualString :: N.Name -> N.Name -> String
871+toQualString prefix name =
872+ N.toString prefix ++ "." ++ N.toString name
873+
874+
875+
741876{-- VAR ERROR
742877
743878
src/Reporting/Helpers.hs+7−24
@@ -9,7 +9,7 @@ module Reporting.Helpers
99 , stack, reflow
1010 , commaSep, capitalize, ordinalize, drawCycle
1111 , findPotentialTypos, findTypoPairs, vetTypos
12− , nearbyNames, distance, maybeYouWant, maybeYouWant'
12+ , nearbyNames, distance
1313 -- re-exports
1414 , Doc, (<+>), (<>), black, cat, dullyellow, fillSep, green, hang, hardline
1515 , hcat, hsep, indent, magenta, parens, sep, text, underline, vcat
@@ -218,35 +218,18 @@ vetTypos potentialTypos =
218218-- NEARBY NAMES
219219
220220
221−nearbyNames :: (a -> String) -> a -> [a] -> [a]
222−nearbyNames format name names =
223− let editDistance =
224− if length (format name) < 3 then 1 else 2
221+nearbyNames :: String -> [String] -> [String]
222+nearbyNames name names =
223+ let
224+ editDistance =
225+ if length name < 3 then 1 else 2
225226 in
226227 map snd $
227228 filter ( (<= editDistance) . abs . fst ) $
228229 List.sortBy (compare `on` fst) $
229− map (\x -> (distance (format name) (format x), x)) names
230+ map (\x -> (distance name x, x)) names
230231
231232
232233distance :: String -> String -> Int
233234distance x y =
234235 Dist.restrictedDamerauLevenshteinDistance Dist.defaultEditCosts x y
235−
236−
237−maybeYouWant :: Maybe Doc -> [N.Name] -> Doc
238−maybeYouWant maybeStarter suggestions =
239− maybe P.empty id (maybeYouWant' maybeStarter suggestions)
240−
241−
242−maybeYouWant' :: Maybe Doc -> [N.Name] -> Maybe Doc
243−maybeYouWant' maybeStarter suggestions =
244− case suggestions of
245− [] ->
246− maybeStarter
247−
248− _:_ ->
249− Just $ stack $
250− [ maybe id (<+>) maybeStarter "Maybe you want one of the following?"
251− , P.indent 4 $ P.vcat $ map (P.dullyellow . nameToDoc) (take 4 suggestions)
252− ]
src/Reporting/Report.hs+1−2
@@ -11,7 +11,6 @@ module Reporting.Report
1111
1212import Text.PrettyPrint.ANSI.Leijen (Doc, (<>), hardline, dullcyan, text)
1313
14−import qualified Elm.Name as N
1514import qualified Reporting.Region as R
1615import qualified Reporting.Render.Code as Code
1716
@@ -24,7 +23,7 @@ data Report =
2423 Report
2524 { _title :: String
2625 , _region :: R.Region
27− , _sgstns :: [N.Name]
26+ , _sgstns :: [String]
2827 , _message :: Doc
2928 }
3029