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
79
80
81
82
83
84
85
86
87
88
{- |
    Module      :  Check.Decl
    Description :  Check and validation for Decl

    This module contains the check function
    and validation functions for Decl.
    The messages are only saved if the check
    is switched ON in the config (`shallCheck Check`)
-}








module Check.Decl (declCheck) where

import AST.Span          (Pos, start)
import AST.SpanAST
import AST.PositionUtils
import Check.Types       (CheckF, Message (..))
import Config.ReadConfig (shallCheck)
import Config.Types      (Check (..))
import Utils             (condMsg)

-- ----------------------------------------------------------------------------
-- Check Function
-- ----------------------------------------------------------------------------

-- |Check Decl
declCheck :: CheckF Decl
declCheck d = case d of
  DataDecl sd _ _ mse cds@(((ConstrDecl _ _ _ _ _ _ _):_)) sbs _ _ _ _ _ -> bars ++ constr ++ comp
    where
      pd   = start sd
      mpe  = case mse of
              Nothing -> Nothing
              Just se -> Just (start se)
      pbs  = map start sbs
      bars
        = condMsg (shallCheck CDataBars && not (validDeclBars mpe pbs))
                  [Message (head pbs) "DataDecl: Bars are not aligned."]
      constr
        = condMsg (shallCheck CDataConstructors && not (validDeclConstr cds))
                  [Message pd "DataDecl: Constructors are not aligned."]
      comp
        = condMsg (shallCheck CDataComponents && not (validDeclComp cds))
                  [Message pd "DataDecl: First components are not aligned."]
  _                                                   -> []

-- ----------------------------------------------------------------------------
-- Validation Functions
-- ----------------------------------------------------------------------------

--- ----------------------------------------------------------------------------
--- The following functions validate the correct alignment of data declarations.
--- The following layouts are considered valid:
---
---         data color = X .. | Y .. | Z ..
---
---         data example = X ..
---                      | Y ..
---                      | Z ..

-- |Valid if "=" and bars are aligned or all in one line.
validDeclBars :: (Maybe Pos) -> [Pos] -> Bool
validDeclBars pe pbs = case pe of
  Nothing -> True
  Just p   -> if (null pbs)
                then True
                else ((col p == col  (head pbs)) && (allColEq pbs))
                  || (line p == line (head pbs)) && (allLinesEq pbs)

-- |Valid if constructor names are aligned or all in one line.
validDeclConstr :: [ConstrDecl] -> Bool
validDeclConstr cds
  | null cds  = True
  | otherwise =    (allColEq   $ map constrDeclPos cds)
                || (allLinesEq $ map constrDeclPos cds)

-- |Valid if components are aligned or all in one line.
validDeclComp :: [ConstrDecl] -> Bool
validDeclComp cds
  | null cds  = True
  | otherwise =    (allColEq   $ map firstCDConstrTypePos cds)
                || (allLinesEq $ map firstCDConstrTypePos cds)