1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
module Check.AST.Indent.Header where

import List (last)

import Curry.SpanInfo
import Curry.Span
import Curry.Position
import Curry.Types
import Curry.Ident
import Text.Pretty

import Types

-- applies actual check on modules
checkModuleHeader :: Module a -> Int -> CSM ()
checkModuleHeader e i =
  case e of
    (Module sI _ (ModuleIdent sII _) (Just exports) _ _) -> checkModuleHeader' sI sII exports i
    _                -> return ()

-- check formatting of module header
checkModuleHeader' :: SpanInfo -> SpanInfo -> ExportSpec -> Int -> CSM ()
checkModuleHeader' (SpanInfo _ ((Span start@(Position modL modC) _):(Span _ end@(Position wheL _):_))) spanInfoIdent exp i =
  unlessM (modL == wheL) -- one line
    (if (checkExportLines exp) -- aligment exports lines
       then (if (not (modL == (getLi (getSpanInfo exp))) && (getLi spanInfoIdent == modL)) -- 'module' and module name in one line
               then
                 (if wheL == (getEndLi (getSpanInfo exp)) -- where formatting
                    then (unlessM ((getCol (getSpanInfo exp)) == (modC + 2)) -- exports indentation
                            (report (Message (Span start end)
                                             (colorizeKey "module exports" <+> text "wrong indentation")
                                             ( text "indent by 2 from"
                                              <+> colorizeKey "module <modulename>")
                                    )
                            )
                         )
                    else
                      (report (Message (Span start end)
                                        (colorizeKey "where" <+> text "wrong formatting")
                                        ( text "write keyword"
                                        <+> colorizeKey "where"
                                        <+> text "and last line of exports in one line" )
                                )
                      )
                 )
               else
                 (report (Message (Span start end)
                                  (colorizeKey "module <modulename> (...)" <+> text "wrong formatting")
                                  ( text "if not fitting header in one line: break after"
                                  <+> colorizeKey "module <modulename>"
                                  <> text ", write keyword"
                                  <+> colorizeKey "module"
                                  <+> text "and name of module in one line" )
                         )
                 )
            )
       else
         (report (Message (Span start end)
                          (colorizeKey "module exports" <+> text "wrong alignment")
                          ( text "start lines with commata or braces, align these" )
                  )
         )
    )

 --check if lines are aligned
checkExportLines :: ExportSpec -> Bool
checkExportLines (Exporting (SpanInfo _ sp@((Span (Position _ c) _):ss)) _) = checkAlign $ c:(getListOfNewLineStart(sp))
 where
  checkAlign :: [Int] -> Bool
  checkAlign (_:[]) = True
  checkAlign (i1:i2:is) = (i1==i2) && (checkAlign (i2:is))

-- get list of line column start position
getListOfNewLineStart :: [Span] -> [Int]
getListOfNewLineStart (_:[]) = []
getListOfNewLineStart ((Span (Position l1 _) _):s2@(Span (Position l2 c2) _):sps)
  | l1 == l2  = getListOfNewLineStart (s2:sps)
  | otherwise = c2 : (getListOfNewLineStart (s2:sps))