Skip to content

Commit 1e93d54

Browse files
authored
Merge pull request #188 from pete-murphy/pete/117-elm-review-rule-for-version-match
`elm-review` rule to fix version mismatch
2 parents 56161a9 + cbe0a55 commit 1e93d54

File tree

3 files changed

+186
-1
lines changed

3 files changed

+186
-1
lines changed
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
module NoMismatchedCliVersion exposing (rule)
2+
3+
import Dict exposing (Dict)
4+
import Elm.Syntax.Expression as Expression exposing (Expression)
5+
import Elm.Syntax.ModuleName exposing (ModuleName)
6+
import Elm.Syntax.Node as Node exposing (Node(..))
7+
import Elm.Syntax.Range as Range
8+
import Json.Decode
9+
import Review.FilePattern as FilePattern
10+
import Review.Fix as Fix
11+
import Review.Rule as Rule exposing (ModuleKey, Rule)
12+
import String
13+
14+
15+
rule : Rule
16+
rule =
17+
Rule.newProjectRuleSchema "NoMismatchedCliVersion" initialContext
18+
|> Rule.withExtraFilesProjectVisitor staticFilesVisitor
19+
[ FilePattern.include "package.json" ]
20+
|> Rule.withModuleVisitor (Rule.withExpressionEnterVisitor expressionVisitor)
21+
|> Rule.withModuleContext
22+
{ fromProjectToModule = fromProjectToModule
23+
, fromModuleToProject = fromModuleToProject
24+
, foldProjectContexts = foldProjectContexts
25+
}
26+
|> Rule.fromProjectRuleSchema
27+
28+
29+
type alias ProjectContext =
30+
{ versionFromPackageJson : Maybe String
31+
}
32+
33+
34+
type alias ModuleContext =
35+
{ versionFromPackageJson : Maybe String
36+
, isCliModule : Bool
37+
}
38+
39+
40+
initialContext : ProjectContext
41+
initialContext =
42+
{ versionFromPackageJson = Nothing
43+
}
44+
45+
46+
staticFilesVisitor :
47+
Dict String { fileKey : Rule.ExtraFileKey, content : String }
48+
-> ProjectContext
49+
-> ( List (Rule.Error { useErrorForModule : () }), ProjectContext )
50+
staticFilesVisitor files context =
51+
case Dict.values files of
52+
packageJson :: [] ->
53+
case Json.Decode.decodeString (Json.Decode.field "version" Json.Decode.string) packageJson.content of
54+
Ok version ->
55+
( []
56+
, { context
57+
| versionFromPackageJson = Just version
58+
}
59+
)
60+
61+
Err err ->
62+
( [ Rule.errorForExtraFile packageJson.fileKey
63+
{ message = "Failed to decode package.json"
64+
, details = [ Json.Decode.errorToString err ]
65+
}
66+
Range.empty
67+
]
68+
, context
69+
)
70+
71+
_ ->
72+
( [ Rule.globalError
73+
{ message = "Missing package.json"
74+
, details = []
75+
}
76+
]
77+
, context
78+
)
79+
80+
81+
expressionVisitor : Node Expression -> ModuleContext -> ( List (Rule.Error {}), ModuleContext )
82+
expressionVisitor node context =
83+
case ( context.isCliModule, context.versionFromPackageJson, Node.value node ) of
84+
( True, Just version, Expression.Application [ Node _ (Expression.FunctionOrValue _ "withDoc"), Node range (Expression.Literal doc) ] ) ->
85+
case String.lines doc of
86+
"" :: firstLine :: _ ->
87+
let
88+
prefix =
89+
"version: "
90+
in
91+
if firstLine == prefix ++ version then
92+
( [], context )
93+
94+
else if String.startsWith prefix firstLine then
95+
let
96+
versionRange =
97+
{ start =
98+
{ row = range.start.row + 1
99+
, column = String.length prefix + 1
100+
}
101+
, end =
102+
{ row = range.start.row + 1
103+
, column = String.length prefix + String.length version + 1
104+
}
105+
}
106+
in
107+
( [ Rule.errorWithFix
108+
{ message = "Mismatched version"
109+
, details = [ "Expected: " ++ version ]
110+
}
111+
versionRange
112+
[ Fix.replaceRangeBy versionRange version ]
113+
]
114+
, context
115+
)
116+
117+
else
118+
let
119+
firstLineRange =
120+
{ start =
121+
{ row = range.start.row + 1
122+
, column = 1
123+
}
124+
, end =
125+
{ row = range.start.row + 1
126+
, column = String.length firstLine
127+
}
128+
}
129+
in
130+
( [ Rule.error
131+
{ message = "Missing version line"
132+
, details = [ "Expected first line to start with \"" ++ prefix ++ "\"" ]
133+
}
134+
firstLineRange
135+
]
136+
, context
137+
)
138+
139+
_ ->
140+
( [ Rule.error
141+
{ message = "Unexpected documentation format"
142+
, details = [ "Expected a multi-line string, starting with a newline character" ]
143+
}
144+
range
145+
]
146+
, context
147+
)
148+
149+
_ ->
150+
( [], context )
151+
152+
153+
fromProjectToModule : ModuleKey -> Node ModuleName -> ProjectContext -> ModuleContext
154+
fromProjectToModule _ moduleName context =
155+
{ versionFromPackageJson = context.versionFromPackageJson
156+
, isCliModule = Node.value moduleName == [ "Cli" ]
157+
}
158+
159+
160+
fromModuleToProject : ModuleKey -> Node ModuleName -> ModuleContext -> ProjectContext
161+
fromModuleToProject _ _ context =
162+
{ versionFromPackageJson = context.versionFromPackageJson
163+
}
164+
165+
166+
foldProjectContexts : ProjectContext -> ProjectContext -> ProjectContext
167+
foldProjectContexts x y =
168+
let
169+
versionFromPackageJson =
170+
case
171+
( x.versionFromPackageJson, y.versionFromPackageJson )
172+
of
173+
( Just version, _ ) ->
174+
Just version
175+
176+
( _, Just version ) ->
177+
Just version
178+
179+
_ ->
180+
Nothing
181+
in
182+
{ versionFromPackageJson = versionFromPackageJson
183+
}

review/src/ReviewConfig.elm

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import NoDebug.Log
99
import NoDebug.TodoOrToString
1010
import NoExposingEverything
1111
import NoImportingEverything
12+
import NoMismatchedCliVersion
1213
import NoMissingTypeAnnotation
1314
import NoMissingTypeAnnotationInLetIn
1415
import NoMissingTypeExpose
@@ -64,6 +65,7 @@ exceptCodegenRules =
6465
|> Rule.ignoreErrorsForDirectories [ "src/Gen" ]
6566
, Review.ImportSimple.rule
6667
|> Rule.ignoreErrorsForDirectories [ "src/Gen" ]
68+
, NoMismatchedCliVersion.rule
6769
]
6870

6971

src/Cli.elm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ program =
9191
|> Cli.OptionsParser.with
9292
(Cli.Option.optionalKeywordArg "write-merged-to")
9393
|> Cli.OptionsParser.withDoc """
94-
version: 0.6.1
94+
version: 0.7.0
9595
9696
options:
9797

0 commit comments

Comments
 (0)