mirror of
https://github.com/jfmengels/elm-review.git
synced 2024-12-24 18:23:09 +03:00
Example: Use reporter from elm-lint-reporter
Basically, the contents of Reporter and Text were moved there. This will be useful to share the reporter with the CLI.
This commit is contained in:
parent
e937feb91f
commit
02985ff109
@ -1,18 +0,0 @@
|
||||
module File exposing (File)
|
||||
|
||||
{-| Represents a file
|
||||
|
||||
|
||||
# Definition
|
||||
|
||||
@docs File
|
||||
|
||||
-}
|
||||
|
||||
-- DEFINITION
|
||||
|
||||
|
||||
type alias File =
|
||||
{ name : String
|
||||
, source : String
|
||||
}
|
@ -12,7 +12,6 @@ import Lint.Rule.NoImportingEverything
|
||||
import Lint.Rule.NoUnusedTypeConstructors
|
||||
import Lint.Rule.NoUnusedVariables
|
||||
import Reporter
|
||||
import Text exposing (Text)
|
||||
|
||||
|
||||
|
||||
@ -185,8 +184,7 @@ view model =
|
||||
, Attr.style "font-size" "12px"
|
||||
, Attr.style "background-color" "black"
|
||||
]
|
||||
[ lintErrors model
|
||||
|> Text.view
|
||||
[ viewLintErrors model
|
||||
]
|
||||
]
|
||||
, div
|
||||
@ -321,19 +319,56 @@ viewCheckbox onClick name checked =
|
||||
]
|
||||
|
||||
|
||||
lintErrors : Model -> List Text
|
||||
viewLintErrors : Model -> Html msg
|
||||
viewLintErrors model =
|
||||
lintErrors model
|
||||
|> List.map viewPart
|
||||
|> Html.div []
|
||||
|
||||
|
||||
viewPart : { str : String, color : Maybe ( Int, Int, Int ) } -> Html msg
|
||||
viewPart { str, color } =
|
||||
Html.span
|
||||
[ case color of
|
||||
Just ( red, green, blue ) ->
|
||||
Attr.style "color" <| "rgb(" ++ String.fromInt red ++ "," ++ String.fromInt green ++ "," ++ String.fromInt blue ++ ")"
|
||||
|
||||
Nothing ->
|
||||
Attr.classList []
|
||||
]
|
||||
(str
|
||||
|> String.lines
|
||||
|> List.map Html.text
|
||||
|> List.intersperse (Html.br [] [])
|
||||
)
|
||||
|
||||
|
||||
lintErrors : Model -> List { str : String, color : Maybe ( Int, Int, Int ) }
|
||||
lintErrors model =
|
||||
if List.isEmpty model.lintErrors then
|
||||
[ Text.from "I found no linting errors.\nYou're all good!" ]
|
||||
[ { str = "I found no linting errors.\nYou're all good!"
|
||||
, color = Nothing
|
||||
}
|
||||
]
|
||||
|
||||
else
|
||||
Reporter.formatReport
|
||||
[ ( { name = "Source code"
|
||||
, source = model.sourceCode
|
||||
}
|
||||
, model.lintErrors
|
||||
)
|
||||
]
|
||||
[ ( { name = "Source code"
|
||||
, source = model.sourceCode
|
||||
}
|
||||
, model.lintErrors
|
||||
|> List.map fromLintError
|
||||
)
|
||||
]
|
||||
|> Reporter.formatReport
|
||||
|
||||
|
||||
fromLintError : LintError -> Reporter.Error
|
||||
fromLintError error =
|
||||
{ ruleName = Lint.errorRuleName error
|
||||
, message = Lint.errorMessage error
|
||||
, details = Lint.errorDetails error
|
||||
, range = Lint.errorRange error
|
||||
}
|
||||
|
||||
|
||||
main : Program () Model Msg
|
||||
|
@ -1,252 +0,0 @@
|
||||
module Reporter exposing (formatReport)
|
||||
|
||||
import Array exposing (Array)
|
||||
import Elm.Syntax.Range exposing (Range)
|
||||
import File exposing (File)
|
||||
import Lint exposing (LintError)
|
||||
import Text exposing (Text)
|
||||
|
||||
|
||||
type alias Error =
|
||||
{ ruleName : String
|
||||
, message : String
|
||||
, details : List String
|
||||
, range : Range
|
||||
}
|
||||
|
||||
|
||||
formatReportForFileWithExtract : ( File, List Error ) -> List Text
|
||||
formatReportForFileWithExtract ( file, errors ) =
|
||||
let
|
||||
formattedErrors : List (List Text)
|
||||
formattedErrors =
|
||||
List.map (formatErrorWithExtract file) errors
|
||||
|
||||
prefix : String
|
||||
prefix =
|
||||
"-- ELM-LINT ERROR "
|
||||
|
||||
header : Text
|
||||
header =
|
||||
(prefix ++ String.padLeft (80 - String.length prefix) '-' (" " ++ file.name))
|
||||
|> Text.from
|
||||
|> Text.inBlue
|
||||
in
|
||||
header :: Text.from "\n\n" :: Text.join "\n\n\n" formattedErrors
|
||||
|
||||
|
||||
formatErrorWithExtract : File -> Error -> List Text
|
||||
formatErrorWithExtract file { ruleName, message, details, range } =
|
||||
let
|
||||
title : List Text
|
||||
title =
|
||||
[ Text.from ruleName
|
||||
|> Text.inRed
|
||||
, Text.from <| ": " ++ message
|
||||
]
|
||||
|
||||
codeExtract_ : List Text
|
||||
codeExtract_ =
|
||||
codeExtract file range
|
||||
|
||||
details_ : List Text
|
||||
details_ =
|
||||
List.map Text.from details
|
||||
|> List.intersperse (Text.from "\n\n")
|
||||
in
|
||||
[ title, codeExtract_, details_ ]
|
||||
|> List.filter (List.isEmpty >> not)
|
||||
|> List.intersperse [ Text.from "\n\n" ]
|
||||
|> List.concat
|
||||
|
||||
|
||||
codeExtract : File -> Range -> List Text
|
||||
codeExtract file =
|
||||
let
|
||||
getRowAtLine_ : Int -> String
|
||||
getRowAtLine_ =
|
||||
getRowAtLine file
|
||||
in
|
||||
\({ start, end } as range) ->
|
||||
if range.start == range.end then
|
||||
[]
|
||||
|
||||
else if start.row == end.row then
|
||||
[ Text.from <| getRowAtLine_ (start.row - 2)
|
||||
, Text.from <| getRowAtLine_ (start.row - 1)
|
||||
, underlineError (start.row - 1) { start = start.column, end = end.column }
|
||||
, Text.from <| getRowAtLine_ end.row
|
||||
]
|
||||
|
||||
else
|
||||
let
|
||||
startLine : String
|
||||
startLine =
|
||||
getRowAtLine_ (start.row - 1)
|
||||
|
||||
linesBetweenStartAndEnd : List String
|
||||
linesBetweenStartAndEnd =
|
||||
List.range start.row (end.row - 2)
|
||||
|> List.map getRowAtLine_
|
||||
|
||||
endLine : String
|
||||
endLine =
|
||||
getRowAtLine_ (end.row - 1)
|
||||
in
|
||||
List.concat
|
||||
[ [ Text.from <| getRowAtLine_ (start.row - 2)
|
||||
, Text.from <| startLine
|
||||
, underlineError
|
||||
(start.row - 1)
|
||||
{ start = start.column
|
||||
, end = String.length startLine - offsetBecauseOfLineNumber (start.row - 1)
|
||||
}
|
||||
]
|
||||
, linesBetweenStartAndEnd
|
||||
|> List.indexedMap Tuple.pair
|
||||
|> List.concatMap
|
||||
(\( lineNumber, line ) ->
|
||||
[ Text.from <| line
|
||||
, underlineError
|
||||
lineNumber
|
||||
{ start = getIndexOfFirstNonSpace (offsetBecauseOfLineNumber lineNumber) line
|
||||
, end = String.length line - offsetBecauseOfLineNumber lineNumber
|
||||
}
|
||||
]
|
||||
)
|
||||
, [ Text.from <| endLine
|
||||
, underlineError
|
||||
(end.row - 1)
|
||||
{ start = getIndexOfFirstNonSpace (offsetBecauseOfLineNumber (end.row - 1)) endLine
|
||||
, end = String.length endLine - offsetBecauseOfLineNumber (end.row - 1)
|
||||
}
|
||||
, Text.from <| getRowAtLine_ end.row
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
getIndexOfFirstNonSpace : Int -> String -> Int
|
||||
getIndexOfFirstNonSpace offset string =
|
||||
string
|
||||
|> String.indexes (String.trim <| String.dropLeft offset string)
|
||||
|> List.head
|
||||
|> Maybe.withDefault 0
|
||||
|> (\n -> n - offset + 1)
|
||||
|
||||
|
||||
getRowAtLine : File -> Int -> String
|
||||
getRowAtLine file =
|
||||
let
|
||||
lines : Array String
|
||||
lines =
|
||||
file.source
|
||||
|> String.lines
|
||||
|> Array.fromList
|
||||
in
|
||||
\rowIndex ->
|
||||
case Array.get rowIndex lines of
|
||||
Just line ->
|
||||
if String.trim line /= "" then
|
||||
String.fromInt (rowIndex + 1) ++ "| " ++ line ++ "\n"
|
||||
|
||||
else
|
||||
""
|
||||
|
||||
Nothing ->
|
||||
""
|
||||
|
||||
|
||||
underlineError : Int -> { start : Int, end : Int } -> Text
|
||||
underlineError lineNumber { start, end } =
|
||||
let
|
||||
baseText : String
|
||||
baseText =
|
||||
String.repeat (offsetBecauseOfLineNumber lineNumber + start - 1) " " ++ String.repeat (end - start) "^" ++ "\n"
|
||||
in
|
||||
baseText
|
||||
|> Text.from
|
||||
|> Text.inRed
|
||||
|
||||
|
||||
offsetBecauseOfLineNumber : Int -> Int
|
||||
offsetBecauseOfLineNumber lineNumber =
|
||||
lineNumber
|
||||
|> String.fromInt
|
||||
|> String.length
|
||||
|> (+) 2
|
||||
|
||||
|
||||
summary : List ( File, List LintError ) -> String
|
||||
summary errors =
|
||||
let
|
||||
errorCount : Int
|
||||
errorCount =
|
||||
errors
|
||||
|> List.concatMap Tuple.second
|
||||
|> List.length
|
||||
in
|
||||
if errorCount == 0 then
|
||||
""
|
||||
|
||||
else
|
||||
String.fromInt errorCount ++ " problem(s)."
|
||||
|
||||
|
||||
formatReport : List ( File, List LintError ) -> List Text
|
||||
formatReport errors =
|
||||
case List.isEmpty errors of
|
||||
True ->
|
||||
[ Text.from "I found no linting errors.\nYou're all good!" ]
|
||||
|
||||
False ->
|
||||
List.concat
|
||||
[ formatReports <| fromLintErrors errors
|
||||
, [ Text.from <| "\n\n\n\n" ++ summary errors ]
|
||||
]
|
||||
|
||||
|
||||
formatReports : List ( File, List Error ) -> List Text
|
||||
formatReports errors =
|
||||
case errors of
|
||||
[] ->
|
||||
[]
|
||||
|
||||
[ error ] ->
|
||||
formatReportForFileWithExtract error
|
||||
|
||||
(( fileA, error ) as a) :: (( fileB, _ ) as b) :: restOfErrors ->
|
||||
List.concat
|
||||
[ formatReportForFileWithExtract a
|
||||
, [ fileSeparator fileA fileB ]
|
||||
, formatReports (b :: restOfErrors)
|
||||
]
|
||||
|
||||
|
||||
fileSeparator : File -> File -> Text
|
||||
fileSeparator file1 file2 =
|
||||
let
|
||||
str : String
|
||||
str =
|
||||
"\n\n"
|
||||
++ String.padLeft 80 ' ' (file1.name ++ " ↑ ")
|
||||
++ "\n====o======================================================================o===="
|
||||
++ "\n ↓ "
|
||||
++ file2.name
|
||||
++ "\n\n\n"
|
||||
in
|
||||
Text.from str
|
||||
|> Text.inRed
|
||||
|
||||
|
||||
fromLintErrors : List ( File, List LintError ) -> List ( File, List Error )
|
||||
fromLintErrors errors =
|
||||
(List.map <| Tuple.mapSecond <| List.map fromLintError) errors
|
||||
|
||||
|
||||
fromLintError : LintError -> Error
|
||||
fromLintError error =
|
||||
{ ruleName = Lint.errorRuleName error
|
||||
, message = Lint.errorMessage error
|
||||
, details = Lint.errorDetails error
|
||||
, range = Lint.errorRange error
|
||||
}
|
131
example/Text.elm
131
example/Text.elm
@ -1,131 +0,0 @@
|
||||
module Text exposing
|
||||
( Text
|
||||
, from
|
||||
, inBlue, inRed
|
||||
, join
|
||||
, view
|
||||
)
|
||||
|
||||
{-| Represents text with some styling applied to it.
|
||||
|
||||
text : List Text
|
||||
text =
|
||||
[ Text.from "My name is "
|
||||
, Text.from "John"
|
||||
|> Text.withColor
|
||||
, Text.from "."
|
||||
]
|
||||
|
||||
|
||||
# Definition
|
||||
|
||||
@docs Text
|
||||
|
||||
|
||||
# Constructors
|
||||
|
||||
@docs from
|
||||
|
||||
|
||||
# Modifiers
|
||||
|
||||
@docs inBlue, inRed
|
||||
|
||||
|
||||
# Working with lists
|
||||
|
||||
@docs join
|
||||
|
||||
|
||||
# ACCESS
|
||||
|
||||
@docs length
|
||||
|
||||
|
||||
# Encoding
|
||||
|
||||
@docs encode
|
||||
|
||||
-}
|
||||
|
||||
import Html exposing (Html)
|
||||
import Html.Attributes as Attr
|
||||
|
||||
|
||||
|
||||
-- DEFINITION
|
||||
|
||||
|
||||
{-| Represents text with some styling applied to it.
|
||||
-}
|
||||
type Text
|
||||
= Text
|
||||
{ str : String
|
||||
, color : Maybe ( Int, Int, Int )
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- CONSTRUCTORS
|
||||
|
||||
|
||||
{-| Create an unstyled `Text` from a string.
|
||||
-}
|
||||
from : String -> Text
|
||||
from value =
|
||||
Text
|
||||
{ str = value
|
||||
, color = Nothing
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- MODIFIERS
|
||||
|
||||
|
||||
inBlue : Text -> Text
|
||||
inBlue (Text text) =
|
||||
Text { text | color = Just ( 51, 187, 200 ) }
|
||||
|
||||
|
||||
inRed : Text -> Text
|
||||
inRed (Text text) =
|
||||
Text { text | color = Just ( 255, 0, 0 ) }
|
||||
|
||||
|
||||
|
||||
-- WORKING WITH LISTS
|
||||
|
||||
|
||||
join : String -> List (List Text) -> List Text
|
||||
join sep chunks =
|
||||
List.intersperse [ from sep ] chunks
|
||||
|> List.concatMap identity
|
||||
|
||||
|
||||
|
||||
-- VIEW
|
||||
|
||||
|
||||
view : List Text -> Html msg
|
||||
view texts =
|
||||
Html.div
|
||||
[]
|
||||
(List.map viewPart texts)
|
||||
|
||||
|
||||
viewPart : Text -> Html msg
|
||||
viewPart (Text text) =
|
||||
Html.span
|
||||
[ case text.color of
|
||||
Just ( red, green, blue ) ->
|
||||
Attr.style "color" <| "rgb(" ++ String.fromInt red ++ "," ++ String.fromInt green ++ "," ++ String.fromInt blue ++ ")"
|
||||
|
||||
Nothing ->
|
||||
Attr.classList []
|
||||
]
|
||||
(text.str
|
||||
|> String.lines
|
||||
|> List.map Html.text
|
||||
|> List.intersperse (Html.br [] [])
|
||||
)
|
@ -1,8 +1,9 @@
|
||||
{
|
||||
"type": "application",
|
||||
"source-directories": [
|
||||
".",
|
||||
"../src",
|
||||
"."
|
||||
"../../elm-lint-reporter/src"
|
||||
],
|
||||
"elm-version": "0.19.0",
|
||||
"dependencies": {
|
||||
|
Loading…
Reference in New Issue
Block a user