@@ -58,6 +58,8 @@ inductive StyleError where
58
58
| windowsLineEnding
59
59
/-- A line contains trailing whitespace. -/
60
60
| trailingWhitespace
61
+ /-- A line contains the string " ;" -/
62
+ | semicolon
61
63
deriving BEq
62
64
63
65
/-- How to format style errors -/
@@ -79,6 +81,7 @@ def StyleError.errorMessage (err : StyleError) : String := match err with
79
81
| windowsLineEnding => "This line ends with a windows line ending (\r\n ): please use Unix line\
80
82
endings (\n ) instead"
81
83
| trailingWhitespace => "This line ends with some whitespace: please remove this"
84
+ | semicolon => "This line contains a space before a semicolon"
82
85
83
86
/-- The error code for a given style error. Keep this in sync with `parse?_errorContext` below! -/
84
87
-- FUTURE: we're matching the old codes in `lint-style.py` for compatibility;
@@ -87,6 +90,7 @@ def StyleError.errorCode (err : StyleError) : String := match err with
87
90
| StyleError.adaptationNote => "ERR_ADN"
88
91
| StyleError.windowsLineEnding => "ERR_WIN"
89
92
| StyleError.trailingWhitespace => "ERR_TWS"
93
+ | StyleError.semicolon => "ERR_SEM"
90
94
91
95
/-- Context for a style error: the actual error, the line number in the file we're reading
92
96
and the path to the file. -/
@@ -164,6 +168,7 @@ def parse?_errorContext (line : String) : Option ErrorContext := Id.run do
164
168
-- Use default values for parameters which are ignored for comparing style exceptions.
165
169
-- NB: keep this in sync with `compare` above!
166
170
| "ERR_ADN" => some (StyleError.adaptationNote)
171
+ | "ERR_SEM" => some (StyleError.semicolon)
167
172
| "ERR_TWS" => some (StyleError.trailingWhitespace)
168
173
| "ERR_WIN" => some (StyleError.windowsLineEnding)
169
174
| _ => none
@@ -219,6 +224,22 @@ def trailingWhitespaceLinter : TextbasedLinter := fun lines ↦ Id.run do
219
224
return (errors, if errors.size > 0 then some fixedLines else none)
220
225
221
226
227
+ /-- Lint a collection of input strings for the substring " ;". -/
228
+ def semicolonLinter : TextbasedLinter := fun lines ↦ Id.run do
229
+ let mut errors := Array.mkEmpty 0
230
+ let mut fixedLines := lines
231
+ for (line, idx) in lines.zipWithIndex do
232
+ let pos := line.find (· == ';' )
233
+ if pos != line.endPos && line.get (line.prev pos) == ' ' then
234
+ let indent := line.length - line.trimLeft.length
235
+ let replaced := (line.trimLeft.replace " ;" "; " ).replace " " " "
236
+ errors := errors.push (StyleError.semicolon, idx + 1 )
237
+ -- Concatenate "indent" spaces... better ways to do so welcome!
238
+ let space := "" .intercalate (List.replicate indent " " )
239
+ fixedLines := fixedLines.set! idx s! "{ space}{ replaced} "
240
+ return (errors, if errors.size > 0 then some fixedLines else none)
241
+
242
+
222
243
/-- Whether a collection of lines consists *only* of imports, blank lines and single-line comments.
223
244
In practice, this means it's an imports-only file and exempt from almost all linting. -/
224
245
def isImportsOnlyFile (lines : Array String) : Bool :=
230
251
231
252
/-- All text-based linters registered in this file. -/
232
253
def allLinters : Array TextbasedLinter := #[
233
- adaptationNoteLinter, trailingWhitespaceLinter
254
+ adaptationNoteLinter, semicolonLinter, trailingWhitespaceLinter
234
255
]
235
256
236
257
0 commit comments