@@ -10,91 +10,93 @@ import Data.Newtype (unwrap)
1010import Data.Traversable (traverse)
1111import Effect (Effect)
1212import Effect.Class.Console (log)
13−import Purelint.Fix (applyAllFixes)
14−import Purelint.Tidy (formatExpr, formatModule)
15−import Purelint.Rules.MapIdentity (mapIdentityRule)
16−import Purelint.Rules.MapFusion (mapFusionRule)
17−import Purelint.Rules.UseTraverse (useTraverseRule)
18−import Purelint.Rules.ConcatMap (concatMapRule)
19−import Purelint.Rules.NotEqual (notEqualRule)
20−import Purelint.Rules.UseGuard (useGuardRule)
21−import Purelint.Rules.EtaReduce (etaReduceRule)
22−import Purelint.Rules.EtaReduceDecl (etaReduceDeclRule)
23−import Purelint.Rules.RedundantBind (redundantBindRule)
24−import Purelint.Rules.LetToWhere (letToWhereRule)
25−import Purelint.Rules.LetToDo (letToDoRule)
26−import Purelint.Rules.RedundantIf (redundantIfRule)
27−import Purelint.Rules.FunctorLaw (functorLawRule)
28−import Purelint.Rules.UseVoid (useVoidRule)
29−import Purelint.Rules.UseJoin (useJoinRule)
30−import Purelint.Rules.UseAny (useAnyRule)
31−import Purelint.Rules.UseAll (useAllRule)
32−import Purelint.Rules.BooleanSimplify (booleanSimplifyRule)
33−import Purelint.Rules.CollapseLambdas (collapseLambdasRule)
34−import Purelint.Rules.UseConst (useConstRule)
35−import Purelint.Rules.UseNull (useNullRule)
36−import Purelint.Rules.UseFromMaybe (useFromMaybeRule)
37−import Purelint.Rules.UseIsJust (useIsJustRule)
38−import Purelint.Rules.UseIsNothing (useIsNothingRule)
39−import Purelint.Rules.UseWhen (useWhenRule)
40−import Purelint.Rules.UseUnless (useUnlessRule)
41−import Purelint.Rules.RedundantFlip (redundantFlipRule)
42−import Purelint.Rules.UseNotElem (useNotElemRule)
43−import Purelint.Rules.UseMinMax (useMinMaxRule)
44−import Purelint.Rules.MonoidIdentity (monoidIdentityRule)
45−import Purelint.Rules.UseFold (useFoldRule)
46−import Purelint.Rules.UseSequence (useSequenceRule)
47−import Purelint.Rules.UseTraverseSequence (useTraverseSequenceRule)
48−import Purelint.Rules.RedundantNot (redundantNotRule)
49−import Purelint.Rules.UseFstSnd (useFstSndRule)
50−import Purelint.Rules.UseMapMaybe (useMapMaybeRule)
51−import Purelint.Rules.UseGuardMaybe (useGuardMaybeRule)
52−import Purelint.Rules.UseMaybeMap (useMaybeMapRule)
53−import Purelint.Rules.UseApplicative (useApplicativeRule)
54−import Purelint.Rules.UseBindFlip (useBindFlipRule)
55−import Purelint.Rules.UseFor (useForRule)
56−import Purelint.Rules.RedundantGuard (redundantGuardRule)
57−import Purelint.Rules.UseComparing (useComparingRule)
58−import Purelint.Rules.UseOn (useOnRule)
59−import Purelint.Rules.UseFindMap (useFindMapRule)
60−import Purelint.Rules.UseLastReverse (useLastReverseRule)
61−import Purelint.Rules.RedundantReverse (redundantReverseRule)
62−import Purelint.Rules.UseBreak (useBreakRule)
63−import Purelint.Rules.UseSpan (useSpanRule)
64−import Purelint.Rules.UseMinimumSort (useMinimumSortRule)
65−import Purelint.Rules.UseBimap (useBimapRule)
66−import Purelint.Rules.UseEitherMap (useEitherMapRule)
67−import Purelint.Rules.EvaluateFst (evaluateFstRule)
68−import Purelint.Rules.EvaluateConst (evaluateConstRule)
69−import Purelint.Rules.UseOr (useOrRule)
70−import Purelint.Rules.UseAnd (useAndRule)
71−import Purelint.Rules.UseFoldMap (useFoldMapRule)
72−import Purelint.Rules.UseFoldMapId (useFoldMapIdRule)
73−import Purelint.Rules.UseApplyFlipped (useApplyFlippedRule)
74−import Purelint.Rules.WhenNot (whenNotRule)
75−import Purelint.Rules.UnlessNot (unlessNotRule)
76−import Purelint.Rules.UseZip (useZipRule)
77−import Purelint.Rules.UseReplicate (useReplicateRule)
78−import Purelint.Rules.UseUncurry (useUncurryRule)
79−import Purelint.Rules.RedundantNegate (redundantNegateRule)
80−import Purelint.Rules.UseFromJust (useFromJustRule)
81−import Purelint.Rules.UseHead (useHeadRule)
82−import Purelint.Rules.RedundantId (redundantIdRule)
83−import Purelint.Rules.NothingBind (nothingBindRule)
84−import Purelint.Rules.UseElemIndex (useElemIndexRule)
85−import Purelint.Rules.MonadLaw (monadLawRule)
86−import Purelint.Rules.EvaluateBool (evaluateBoolRule)
87−import Purelint.Rules.UseFoldBool (useFoldBoolRule)
88−import Purelint.Rules.AlternativeLaw (alternativeLawRule)
89−import Purelint.Rules.EvaluateEither (evaluateEitherRule)
90−import Purelint.Rules.UseCaseOf (useCaseOfRule)
91−import Purelint.Rules.FlattenCase (flattenCaseRule)
92−import Purelint.Rules.UsePatternGuards (usePatternGuardsRule)
93−import Purelint.Rules.RedundantParens (redundantParensRule)
94−import Purelint.Rule (Rule)
95−import Purelint.Runner (runRules, getImportsFromSource, getModuleNames)
96−import Purelint.Imports (hasValue, isPreludeModule)
97−import Purelint.Types (LintResult(..), LintWarning(..), RuleId(..), SourceCode(..), Suggestion(..))
13+import Purslint.Fix (applyAllFixes)
14+import Purslint.Tidy (formatExpr, formatModule)
15+import Purslint.Rules.MapIdentity (mapIdentityRule)
16+import Purslint.Rules.MapFusion (mapFusionRule)
17+import Purslint.Rules.UseTraverse (useTraverseRule)
18+import Purslint.Rules.ConcatMap (concatMapRule)
19+import Purslint.Rules.NotEqual (notEqualRule)
20+import Purslint.Rules.UseGuard (useGuardRule)
21+import Purslint.Rules.EtaReduce (etaReduceRule)
22+import Purslint.Rules.EtaReduceDecl (etaReduceDeclRule)
23+import Purslint.Rules.RedundantBind (redundantBindRule)
24+import Purslint.Rules.LetToWhere (letToWhereRule)
25+import Purslint.Rules.LetToDo (letToDoRule)
26+import Purslint.Rules.RedundantIf (redundantIfRule)
27+import Purslint.Rules.FunctorLaw (functorLawRule)
28+import Purslint.Rules.UseVoid (useVoidRule)
29+import Purslint.Rules.UseJoin (useJoinRule)
30+import Purslint.Rules.UseAny (useAnyRule)
31+import Purslint.Rules.UseAll (useAllRule)
32+import Purslint.Rules.BooleanSimplify (booleanSimplifyRule)
33+import Purslint.Rules.CollapseLambdas (collapseLambdasRule)
34+import Purslint.Rules.UseConst (useConstRule)
35+import Purslint.Rules.UseDollar (useDollarRule)
36+import Purslint.Rules.UseNull (useNullRule)
37+import Purslint.Rules.UseFromMaybe (useFromMaybeRule)
38+import Purslint.Rules.UseIsJust (useIsJustRule)
39+import Purslint.Rules.UseIsNothing (useIsNothingRule)
40+import Purslint.Rules.UseWhen (useWhenRule)
41+import Purslint.Rules.UseUnless (useUnlessRule)
42+import Purslint.Rules.RedundantFlip (redundantFlipRule)
43+import Purslint.Rules.UseNotElem (useNotElemRule)
44+import Purslint.Rules.UseMinMax (useMinMaxRule)
45+import Purslint.Rules.MonoidIdentity (monoidIdentityRule)
46+import Purslint.Rules.UseFold (useFoldRule)
47+import Purslint.Rules.UseSequence (useSequenceRule)
48+import Purslint.Rules.UseTraverseSequence (useTraverseSequenceRule)
49+import Purslint.Rules.RedundantNot (redundantNotRule)
50+import Purslint.Rules.UseFstSnd (useFstSndRule)
51+import Purslint.Rules.UseMapMaybe (useMapMaybeRule)
52+import Purslint.Rules.UseGuardMaybe (useGuardMaybeRule)
53+import Purslint.Rules.UseMaybeMap (useMaybeMapRule)
54+import Purslint.Rules.UseApplicative (useApplicativeRule)
55+import Purslint.Rules.UseBindFlip (useBindFlipRule)
56+import Purslint.Rules.UseFor (useForRule)
57+import Purslint.Rules.UseUnwrap (useUnwrapRule)
58+import Purslint.Rules.RedundantGuard (redundantGuardRule)
59+import Purslint.Rules.UseComparing (useComparingRule)
60+import Purslint.Rules.UseOn (useOnRule)
61+import Purslint.Rules.UseFindMap (useFindMapRule)
62+import Purslint.Rules.UseLastReverse (useLastReverseRule)
63+import Purslint.Rules.RedundantReverse (redundantReverseRule)
64+import Purslint.Rules.UseBreak (useBreakRule)
65+import Purslint.Rules.UseSpan (useSpanRule)
66+import Purslint.Rules.UseMinimumSort (useMinimumSortRule)
67+import Purslint.Rules.UseBimap (useBimapRule)
68+import Purslint.Rules.UseEitherMap (useEitherMapRule)
69+import Purslint.Rules.EvaluateFst (evaluateFstRule)
70+import Purslint.Rules.EvaluateConst (evaluateConstRule)
71+import Purslint.Rules.UseOr (useOrRule)
72+import Purslint.Rules.UseAnd (useAndRule)
73+import Purslint.Rules.UseFoldMap (useFoldMapRule)
74+import Purslint.Rules.UseFoldMapId (useFoldMapIdRule)
75+import Purslint.Rules.UseApplyFlipped (useApplyFlippedRule)
76+import Purslint.Rules.WhenNot (whenNotRule)
77+import Purslint.Rules.UnlessNot (unlessNotRule)
78+import Purslint.Rules.UseZip (useZipRule)
79+import Purslint.Rules.UseReplicate (useReplicateRule)
80+import Purslint.Rules.UseUncurry (useUncurryRule)
81+import Purslint.Rules.RedundantNegate (redundantNegateRule)
82+import Purslint.Rules.UseFromJust (useFromJustRule)
83+import Purslint.Rules.UseHead (useHeadRule)
84+import Purslint.Rules.RedundantId (redundantIdRule)
85+import Purslint.Rules.NothingBind (nothingBindRule)
86+import Purslint.Rules.UseElemIndex (useElemIndexRule)
87+import Purslint.Rules.MonadLaw (monadLawRule)
88+import Purslint.Rules.EvaluateBool (evaluateBoolRule)
89+import Purslint.Rules.UseFoldBool (useFoldBoolRule)
90+import Purslint.Rules.AlternativeLaw (alternativeLawRule)
91+import Purslint.Rules.EvaluateEither (evaluateEitherRule)
92+import Purslint.Rules.UseCaseOf (useCaseOfRule)
93+import Purslint.Rules.FlattenCase (flattenCaseRule)
94+import Purslint.Rules.UsePatternGuards (usePatternGuardsRule)
95+import Purslint.Rules.RedundantParens (redundantParensRule)
96+import Purslint.Rule (Rule)
97+import Purslint.Runner (runRules, getImportsFromSource, getModuleNames)
98+import Purslint.Imports (hasValue, isPreludeModule)
99+import Purslint.Types (LintResult(..), LintWarning(..), RuleId(..), SourceCode(..), Suggestion(..))
98100
99101-- | Simple test framework
100102type TestResult = { passed :: Boolean, name :: String, message :: String }
@@ -173,7 +175,7 @@ assertFixFormatted name rules source expectedFixed =
173175-- | Run all tests and report results
174176main :: Effect Unit
175177main = do
176− log "Running purelint tests...\n"
178+ log "Running purslint tests...\n"
177179
178180 let results = mapIdentityTests
179181 <> mapFusionTests
@@ -231,6 +233,15 @@ main = do
231233 <> whenNotTests
232234 <> unlessNotTests
233235 <> useZipTests
236+ <> useReplicateTests
237+ <> useUncurryTests
238+ <> useFromJustTests
239+ <> useHeadTests
240+ <> useElemIndexTests
241+ <> useBreakTests
242+ <> useSpanTests
243+ <> useDollarTests
244+ <> useUnwrapTests
234245 <> redundantNegateTests
235246 <> redundantIdTests
236247 <> nothingBindTests
@@ -1338,6 +1349,162 @@ useZipTests =
13381349 (withPrelude "x = zipWith Tuple [1] [2]") "zip [ 1 ] [ 2 ]"
13391350 ]
13401351
1352+-- ============================================================================
1353+-- UseReplicate Tests
1354+-- ============================================================================
1355+
1356+useReplicateTests :: Array TestResult
1357+useReplicateTests =
1358+ [ assertWarningCount "UseReplicate: take n (repeat x)" [useReplicateRule]
1359+ (withPrelude "x = take 3 (repeat 1)") 1
1360+ , assertRuleId "UseReplicate: correct rule id" [useReplicateRule]
1361+ (withPrelude "x = take 3 (repeat 1)") "UseReplicate"
1362+ , assertSuggestion "UseReplicate: suggests replicate" [useReplicateRule]
1363+ (withPrelude "x = take 3 (repeat 1)") "replicate 3 1"
1364+ , assertWarningCount "UseReplicate: no fire on take n xs" [useReplicateRule]
1365+ (withPrelude "x = take 3 xs") 0
1366+ , assertWarningCount "UseReplicate: no fire without import" [useReplicateRule]
1367+ (withoutImports "x = take 3 (repeat 1)") 0
1368+ ]
1369+
1370+-- ============================================================================
1371+-- UseUncurry Tests
1372+-- ============================================================================
1373+
1374+useUncurryTests :: Array TestResult
1375+useUncurryTests =
1376+ [ assertWarningCount "UseUncurry: f (fst p) (snd p)" [useUncurryRule]
1377+ (withPrelude "x = f (fst p) (snd p)") 1
1378+ , assertRuleId "UseUncurry: correct rule id" [useUncurryRule]
1379+ (withPrelude "x = f (fst p) (snd p)") "UseUncurry"
1380+ , assertSuggestion "UseUncurry: suggests uncurry" [useUncurryRule]
1381+ (withPrelude "x = f (fst p) (snd p)") "uncurry f p"
1382+ , assertWarningCount "UseUncurry: no fire on different args" [useUncurryRule]
1383+ (withPrelude "x = f (fst p) (snd q)") 0
1384+ , assertWarningCount "UseUncurry: no fire without import" [useUncurryRule]
1385+ (withoutImports "x = f (fst p) (snd p)") 0
1386+ ]
1387+
1388+-- ============================================================================
1389+-- UseFromJust Tests
1390+-- ============================================================================
1391+
1392+useFromJustTests :: Array TestResult
1393+useFromJustTests =
1394+ [ assertWarningCount "UseFromJust: fromMaybe d (Just x)" [useFromJustRule]
1395+ (withPrelude "x = fromMaybe 0 (Just 1)") 1
1396+ , assertRuleId "UseFromJust: correct rule id" [useFromJustRule]
1397+ (withPrelude "x = fromMaybe 0 (Just 1)") "UseFromJust"
1398+ , assertSuggestion "UseFromJust: simplifies Just" [useFromJustRule]
1399+ (withPrelude "x = fromMaybe 0 (Just 1)") "1"
1400+ , assertWarningCount "UseFromJust: fromMaybe d Nothing" [useFromJustRule]
1401+ (withPrelude "x = fromMaybe 0 Nothing") 1
1402+ , assertSuggestion "UseFromJust: simplifies Nothing" [useFromJustRule]
1403+ (withPrelude "x = fromMaybe 0 Nothing") "0"
1404+ , assertWarningCount "UseFromJust: no fire without import" [useFromJustRule]
1405+ (withoutImports "x = fromMaybe 0 (Just 1)") 0
1406+ ]
1407+
1408+-- ============================================================================
1409+-- UseHead Tests
1410+-- ============================================================================
1411+
1412+useHeadTests :: Array TestResult
1413+useHeadTests =
1414+ [ assertWarningCount "UseHead: xs !! 0" [useHeadRule]
1415+ (withPrelude "x = xs !! 0") 1
1416+ , assertRuleId "UseHead: correct rule id" [useHeadRule]
1417+ (withPrelude "x = xs !! 0") "UseHead"
1418+ , assertSuggestion "UseHead: suggests head" [useHeadRule]
1419+ (withPrelude "x = xs !! 0") "head"
1420+ , assertWarningCount "UseHead: no fire on xs !! 1" [useHeadRule]
1421+ (withPrelude "x = xs !! 1") 0
1422+ , assertWarningCount "UseHead: no fire without import" [useHeadRule]
1423+ (withoutImports "x = xs !! 0") 0
1424+ ]
1425+
1426+-- ============================================================================
1427+-- UseElemIndex Tests
1428+-- ============================================================================
1429+
1430+useElemIndexTests :: Array TestResult
1431+useElemIndexTests =
1432+ [ assertWarningCount "UseElemIndex: findIndex (\\x -> x == a) xs" [useElemIndexRule]
1433+ (withPrelude "x = findIndex (\\y -> y == a) xs") 1
1434+ , assertRuleId "UseElemIndex: correct rule id" [useElemIndexRule]
1435+ (withPrelude "x = findIndex (\\y -> y == a) xs") "UseElemIndex"
1436+ , assertSuggestion "UseElemIndex: suggests elemIndex" [useElemIndexRule]
1437+ (withPrelude "x = findIndex (\\y -> y == a) xs") "elemIndex a xs"
1438+ , assertWarningCount "UseElemIndex: no fire on other predicate" [useElemIndexRule]
1439+ (withPrelude "x = findIndex (\\y -> y > a) xs") 0
1440+ , assertWarningCount "UseElemIndex: no fire without import" [useElemIndexRule]
1441+ (withoutImports "x = findIndex (\\y -> y == a) xs") 0
1442+ ]
1443+
1444+-- ============================================================================
1445+-- UseBreak Tests
1446+-- ============================================================================
1447+
1448+useBreakTests :: Array TestResult
1449+useBreakTests =
1450+ [ assertWarningCount "UseBreak: span (not p) xs" [useBreakRule]
1451+ (withPrelude "x = span (not p) xs") 1
1452+ , assertRuleId "UseBreak: correct rule id" [useBreakRule]
1453+ (withPrelude "x = span (not p) xs") "UseBreak"
1454+ , assertSuggestion "UseBreak: suggests break" [useBreakRule]
1455+ (withPrelude "x = span (not p) xs") "break p xs"
1456+ , assertWarningCount "UseBreak: no fire without import" [useBreakRule]
1457+ (withoutImports "x = span (not p) xs") 0
1458+ ]
1459+
1460+-- ============================================================================
1461+-- UseSpan Tests
1462+-- ============================================================================
1463+
1464+useSpanTests :: Array TestResult
1465+useSpanTests =
1466+ [ assertWarningCount "UseSpan: break (not p) xs" [useSpanRule]
1467+ (withPrelude "x = break (not p) xs") 1
1468+ , assertRuleId "UseSpan: correct rule id" [useSpanRule]
1469+ (withPrelude "x = break (not p) xs") "UseSpan"
1470+ , assertSuggestion "UseSpan: suggests span" [useSpanRule]
1471+ (withPrelude "x = break (not p) xs") "span p xs"
1472+ , assertWarningCount "UseSpan: no fire without import" [useSpanRule]
1473+ (withoutImports "x = break (not p) xs") 0
1474+ ]
1475+
1476+-- ============================================================================
1477+-- UseDollar Tests
1478+-- ============================================================================
1479+
1480+useDollarTests :: Array TestResult
1481+useDollarTests =
1482+ [ assertWarningCount "UseDollar: map f (filter g xs)" [useDollarRule]
1483+ (withPrelude "x = map f (filter g xs)") 1
1484+ , assertRuleId "UseDollar: correct rule id" [useDollarRule]
1485+ (withPrelude "x = map f (filter g xs)") "UseDollar"
1486+ , assertSuggestion "UseDollar: suggests $" [useDollarRule]
1487+ (withPrelude "x = map f (filter g xs)") "map f $ filter g xs"
1488+ , assertWarningCount "UseDollar: no fire on atomic arg" [useDollarRule]
1489+ (withPrelude "x = f (1)") 0
1490+ ]
1491+
1492+-- ============================================================================
1493+-- UseUnwrap Tests
1494+-- ============================================================================
1495+
1496+useUnwrapTests :: Array TestResult
1497+useUnwrapTests =
1498+ [ assertRuleId "UseUnwrap: correct rule id" [useUnwrapRule]
1499+ (withPrelude "x = unwrap foo") "UseUnwrap"
1500+ , assertSuggestion "UseUnwrap: suggests un ?Constructor" [useUnwrapRule]
1501+ (withPrelude "x = unwrap foo") "un ?Constructor foo"
1502+ , assertWarningCount "UseUnwrap: unwrap partial" [useUnwrapRule]
1503+ (withPrelude "x = unwrap") 1
1504+ , assertSuggestion "UseUnwrap: unwrap partial suggestion" [useUnwrapRule]
1505+ (withPrelude "x = unwrap") "un ?Constructor"
1506+ ]
1507+
13411508-- ============================================================================
13421509-- RedundantNegate Tests
13431510-- ============================================================================