{-# LANGUAGE LambdaCase #-}

module GLuaFixer.BadSequenceFinder (sequenceWarnings, checkFromString) where

import GLua.AG.Token
import qualified GLua.Lexer as Lexer
import GLua.Parser
import GLua.Position (Region)
import GLuaFixer.LintMessage
import GLuaFixer.LintSettings
import Text.Parsec

-- | Satisfy for normal tokens
pTSatisfy :: (Token -> Bool) -> AParser MToken
pTSatisfy :: (Token -> Bool) -> AParser MToken
pTSatisfy Token -> Bool
f = (MToken -> Bool) -> AParser MToken
pMSatisfy MToken -> Bool
f'
  where
    f' :: MToken -> Bool
    f' :: MToken -> Bool
f' (MToken Region
_ Token
t) = Token -> Bool
f Token
t

-- | Parse an identifier
ident :: String -> AParser MToken
ident :: String -> AParser MToken
ident String
s = (MToken -> Bool) -> AParser MToken
pMSatisfy MToken -> Bool
isIdent
  where
    isIdent :: MToken -> Bool
    isIdent :: MToken -> Bool
isIdent (MToken Region
_ (Identifier String
s')) = String
s forall a. Eq a => a -> a -> Bool
== String
s'
    isIdent MToken
_ = Bool
False

-- | Parse any kind of whitespace
whitespace :: AParser MToken
whitespace :: AParser MToken
whitespace = (Token -> Bool) -> AParser MToken
pTSatisfy Token -> Bool
isWhitespace

-- | Whether a token is whitespace
isWhitespace :: Token -> Bool
isWhitespace :: Token -> Bool
isWhitespace (Whitespace String
_) = Bool
True
isWhitespace Token
_ = Bool
False

-- | Whether a token consists of spaces
isSpaces :: Token -> Bool
isSpaces :: Token -> Bool
isSpaces (Whitespace String
str) = forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (forall a. Eq a => a -> a -> Bool
== Char
' ') String
str
isSpaces Token
_ = Bool
False

-- | Parse anything that isn't whitespace
notWhitespace :: AParser MToken
notWhitespace :: AParser MToken
notWhitespace = (MToken -> Bool) -> AParser MToken
pMSatisfy MToken -> Bool
isNotWhitespace
  where
    isNotWhitespace :: MToken -> Bool
    isNotWhitespace :: MToken -> Bool
isNotWhitespace (MToken Region
_ (Whitespace String
_)) = Bool
False
    isNotWhitespace MToken
_ = Bool
True

-- | Warnings for deprecated library functions
libraryWarnings :: String -> AParser String -> AParser String
libraryWarnings :: String -> AParser String -> AParser String
libraryWarnings String
s AParser String
p = do
  String -> AParser MToken
ident String
s
  Token -> AParser MToken
pMTok Token
Dot

  AParser String
p

-- | Warnings for the ai library
aiWarnings :: AParser String
aiWarnings :: AParser String
aiWarnings =
  String -> AParser String -> AParser String
libraryWarnings String
"ai" forall a b. (a -> b) -> a -> b
$
    String
"The function is broken" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"GetScheduleID"
      forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"The function is broken" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"GetTaskID"

-- | Warnings for the math library
mathWarnings :: AParser String
mathWarnings :: AParser String
mathWarnings =
  String -> AParser String -> AParser String
libraryWarnings String
"math" forall a b. (a -> b) -> a -> b
$
    String
"Use math.Distance instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"Dist"
      forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use math.fmod instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"mod"

-- | Warnings for the spawnmenu library
spawnmenuWarnings :: AParser String
spawnmenuWarnings :: AParser String
spawnmenuWarnings =
  String -> AParser String -> AParser String
libraryWarnings String
"spawnmenu" forall a b. (a -> b) -> a -> b
$
    String
"Use spawnmenu.SaveToTextFiles instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"DoSaveToTextFiles"
      forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use spawnmenu.PopulateFromTextFiles instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"PopulateFromEngineTextFiles"
      forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"The function is broken" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"SwitchToolTab"

-- | Warnings for the string library
stringWarnings :: AParser String
stringWarnings :: AParser String
stringWarnings =
  String -> AParser String -> AParser String
libraryWarnings String
"string" forall a b. (a -> b) -> a -> b
$
    String
"Use either string.sub(str, index, index) or str[index]" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"GetChar"
      forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use string.gmatch instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"gfind"

-- | Warnings for the surface library
surfaceWarnings :: AParser String
surfaceWarnings :: AParser String
surfaceWarnings =
  String -> AParser String -> AParser String
libraryWarnings String
"surface" forall a b. (a -> b) -> a -> b
$
    String
"Use ScrH instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"ScreenHeight"
      forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use ScrW instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"ScreenWidth"

-- | Warnings for the table library
tableWarnings :: AParser String
tableWarnings :: AParser String
tableWarnings =
  String -> AParser String -> AParser String
libraryWarnings String
"table" forall a b. (a -> b) -> a -> b
$
    String
"Use ipairs or something instead"
      forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ ( String -> AParser MToken
ident String
"FindNext"
            forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String -> AParser MToken
ident String
"FindPrev"
            forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String -> AParser MToken
ident String
"foreach"
            forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String -> AParser MToken
ident String
"ForEach"
            forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String -> AParser MToken
ident String
"foreachi"
         )
      forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use next instead"
        forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ ( String -> AParser MToken
ident String
"GetFirstKey"
              forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String -> AParser MToken
ident String
"GetFirstValue"
           )
      forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use #tbl instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"GetLastKey"
      forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use tbl[#tbl] instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"GetLastValue"
      forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use #tbl instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"getn"

-- | Warnings for the timer library
timerWarnings :: AParser String
timerWarnings :: AParser String
timerWarnings =
  String -> AParser String -> AParser String
libraryWarnings String
"timer" forall a b. (a -> b) -> a -> b
$
    String
"The function is broken" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"Check"
      forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use timer.Remove instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"Destroy"

-- | Warnings for the umsg library
umsgWarnings :: AParser String
umsgWarnings :: AParser String
umsgWarnings =
  String -> AParser String -> AParser String
libraryWarnings String
"umsg" forall a b. (a -> b) -> a -> b
$
    String
"Use net messages." forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"Start"

-- | Warnings for the util library
utilWarnings :: AParser String
utilWarnings :: AParser String
utilWarnings =
  String -> AParser String -> AParser String
libraryWarnings String
"util" forall a b. (a -> b) -> a -> b
$
    String
"Use tobool, without the util bit" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"tobool"
      forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"The function is broken" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"TraceEntityHull"

-- | Warnings for things to do with self
selfWarnings :: AParser String
selfWarnings :: AParser String
selfWarnings =
  String -> AParser String -> AParser String
libraryWarnings String
"self" forall a b. (a -> b) -> a -> b
$
    String
"Use self:GetOwner() instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"Owner"

-- | Warnings for meta functions
metaFuncWarnings :: AParser String
metaFuncWarnings :: AParser String
metaFuncWarnings = do
  Token -> AParser MToken
pMTok Token
Colon

  -- CLuaLocomotion functions
  String
"Use :IsUsingLadder instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"IsAscendingOrDescendingLadder"
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>
    -- Panel functions
    String
"Use :GetPaintBackground instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"GetDrawBackground"
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use :SetPaintBackground instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"SetDrawBackground"
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"The function is broken" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"AddText"
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Only used by deprecated Derma controls" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"PostMessage"
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Only used in deprecated Derma controls" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"SetActionFunction"
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use :SetKeyboardInputEnabled instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"SetKeyBoardInputEnabled"
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"The function is broken" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"SetPaintFunction"
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use :SetTooltip instead, notice the lowercase fucking t" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"SetToolTip"
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"use :SetTooltipPanel instead, notice the lowercase fucking t" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"SetToolTipPanel"
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use :IsValid instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"Valid"
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>
    -- Entity functions
    String
"Use :GetHitBoxBone instead, note the capital fucking B" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"GetHitboxBone"
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use :GetNWAngle instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"GetNetworkedAngle"
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use :GetNWBool instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"GetNetworkedBool"
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use :GetNWEntity instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"GetNetworkedEntity"
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use :GetNWFloat instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"GetNetworkedFloat"
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use :GetNWInt instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"GetNetworkedInt"
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use :GetNWString instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"GetNetworkedString"
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use :GetNWVarProxy instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"GetNetworkedVarProxy"
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use :GetNWVarTable instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"GetNetworkedVarTable"
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use :GetNWVector instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"GetNetworkedVector"
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"The function is broken" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"GetWorkshopID"
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use :SetNWAngle instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"SetNetworkedAngle"
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use :SetNWBool instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"SetNetworkedBool"
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use :SetNWEntity instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"SetNetworkedEntity"
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use :SetNWFloat instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"SetNetworkedFloat"
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use :SetNWInt instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"SetNetworkedInt"
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use :SetNWString instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"SetNetworkedString"
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use :SetNWVarProxy instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"SetNetworkedVarProxy"
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use :SetNWVector instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"SetNetworkedVector"
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>
    -- Player functions
    String
"Use :GetViewPunchAngles instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"GetPunchAngle"
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>
    -- Material functions
    String
"The function is broken" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"SetShader"
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>
    -- Vector functions
    String
"Use :Dot instead" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"DotProduct"

-- | Parser for all deprecated sequences of tokens
deprecatedSequence :: LintSettings -> AParser Issue
deprecatedSequence :: LintSettings -> AParser Issue
deprecatedSequence LintSettings
opts =
  if Bool -> Bool
not (LintSettings -> Bool
lint_deprecated LintSettings
opts)
    then forall s u (m :: * -> *) a. ParsecT s u m a
parserZero
    else
      String -> Issue
Deprecated
        forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (
              -- Deprecated meta functions
              forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try AParser String
metaFuncWarnings
                -- Library functions
                forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try AParser String
aiWarnings
                forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try AParser String
mathWarnings
                forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try AParser String
spawnmenuWarnings
                forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try AParser String
stringWarnings
                forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try AParser String
surfaceWarnings
                forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try AParser String
tableWarnings
                forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try AParser String
timerWarnings
                forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try AParser String
umsgWarnings
                forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try AParser String
utilWarnings
                forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try AParser String
selfWarnings
                -- Global functions
                forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use collectgarbage(\"count\") instead"
                  forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"gcinfo"
                forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use ConVar objects instead"
                  forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"GetConVarNumber"
                forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use ConVar objects instead"
                  forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"GetConVarString"
                forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use AddCSLuaFile in the file itself instead"
                  forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"IncludeCS"
                forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use ScreenScale instead"
                  forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"SScale"
                forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use IsUselessModel instead"
                  forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"UTIL_IsUselessModel"
                forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use IsValid instead"
                  forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"ValidPanel"
                forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String
"Use net messages."
                  forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> AParser MToken
ident String
"SendUserMessage"
            )

-- | Parser for all beginner mistakes
beginnerMistakeSequence :: LintSettings -> AParser Issue
beginnerMistakeSequence :: LintSettings -> AParser Issue
beginnerMistakeSequence LintSettings
opts =
  if Bool -> Bool
not (LintSettings -> Bool
lint_beginnerMistakes LintSettings
opts)
    then forall s u (m :: * -> *) a. ParsecT s u m a
parserZero
    else
      String -> Issue
BeginnerMistake
        forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ( forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (String
"There's little fucking reason to use ';' in the first place, don't use it twice in a row" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Token -> AParser MToken
pMTok Token
Semicolon forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Token -> AParser MToken
pMTok Token
Semicolon)
                forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try
                  ( String
"The server already knows who sent the net message, use the first parameter of net.Receive" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ do
                      String -> AParser MToken
ident String
"net"
                      Token -> AParser MToken
pMTok Token
Dot
                      String -> AParser MToken
ident String
"WriteEntity"
                      Token -> AParser MToken
pMTok Token
LRound
                      forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m ()
optional AParser MToken
whitespace
                      String -> AParser MToken
ident String
"LocalPlayer"
                      forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m ()
optional AParser MToken
whitespace
                      Token -> AParser MToken
pMTok Token
LRound
                      forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m ()
optional AParser MToken
whitespace
                      Token -> AParser MToken
pMTok Token
RRound
                  )
                forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try
                  ( String
"Jesus christ fuck off already" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ do
                      Token -> AParser MToken
pMTok Token
While
                      AParser MToken
whitespace
                      Token -> AParser MToken
pMTok Token
TTrue
                      AParser MToken
whitespace
                      Token -> AParser MToken
pMTok Token
Do
                      AParser MToken
whitespace
                      Token -> AParser MToken
pMTok Token
End
                  )
            )

whiteSpaceStyleSequence :: LintSettings -> AParser Issue
whiteSpaceStyleSequence :: LintSettings -> AParser Issue
whiteSpaceStyleSequence LintSettings
opts =
  if Bool -> Bool
not (LintSettings -> Bool
lint_whitespaceStyle LintSettings
opts)
    then forall s u (m :: * -> *) a. ParsecT s u m a
parserZero
    else
      String -> Issue
WhitespaceStyle
        forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ( forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (String
"Please put some whitespace after 'if'" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Token -> AParser MToken
pMTok Token
If forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall s (m :: * -> *) t a u.
(Stream s m t, Show a) =>
ParsecT s u m a -> ParsecT s u m ()
notFollowedBy AParser MToken
whitespace)
                forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (String
"Please put some whitespace after 'elseif'" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Token -> AParser MToken
pMTok Token
Elseif forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall s (m :: * -> *) t a u.
(Stream s m t, Show a) =>
ParsecT s u m a -> ParsecT s u m ()
notFollowedBy AParser MToken
whitespace)
                forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (String
"Please put some whitespace after 'while'" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Token -> AParser MToken
pMTok Token
While forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall s (m :: * -> *) t a u.
(Stream s m t, Show a) =>
ParsecT s u m a -> ParsecT s u m ()
notFollowedBy AParser MToken
whitespace)
                forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (String
"Please put some whitespace after 'until'" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Token -> AParser MToken
pMTok Token
Until forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall s (m :: * -> *) t a u.
(Stream s m t, Show a) =>
ParsecT s u m a -> ParsecT s u m ()
notFollowedBy AParser MToken
whitespace)
                forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try
                  ( String
"Please put some whitespace after ')'" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ do
                      Token -> AParser MToken
pMTok Token
RRound
                      (Token -> Bool) -> AParser MToken
pTSatisfy (\Token
t -> Bool -> Bool
not (Token -> Bool
isWhitespace Token
t) Bool -> Bool -> Bool
&& Token
t forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [Token
Colon, Token
RRound, Token
LRound, Token
LSquare, Token
RSquare, Token
LCurly, Token
RCurly, Token
Comma, Token
Dot, Token
Semicolon])
                  )
                forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try
                  ( String
"Please put some whitespace before the operator" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ do
                      AParser MToken
notWhitespace
                      forall s (m :: * -> *) t u a.
Stream s m t =>
[ParsecT s u m a] -> ParsecT s u m a
choice [Token -> AParser MToken
pMTok Token
Plus, Token -> AParser MToken
pMTok Token
Multiply, Token -> AParser MToken
pMTok Token
Divide, Token -> AParser MToken
pMTok Token
Modulus, Token -> AParser MToken
pMTok Token
TEq, Token -> AParser MToken
pMTok Token
TNEq, Token -> AParser MToken
pMTok Token
TCNEq, Token -> AParser MToken
pMTok Token
TLEQ, Token -> AParser MToken
pMTok Token
TGEQ, Token -> AParser MToken
pMTok Token
TLT, Token -> AParser MToken
pMTok Token
TGT, Token -> AParser MToken
pMTok Token
Equals, Token -> AParser MToken
pMTok Token
Concatenate, Token -> AParser MToken
pMTok Token
And, Token -> AParser MToken
pMTok Token
CAnd, Token -> AParser MToken
pMTok Token
Or, Token -> AParser MToken
pMTok Token
COr]
                  )
                forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try
                  ( String
"Please put some whitespace after the operator" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ do
                      forall s (m :: * -> *) t u a.
Stream s m t =>
[ParsecT s u m a] -> ParsecT s u m a
choice [Token -> AParser MToken
pMTok Token
Plus, Token -> AParser MToken
pMTok Token
Multiply, Token -> AParser MToken
pMTok Token
Divide, Token -> AParser MToken
pMTok Token
Modulus, Token -> AParser MToken
pMTok Token
TEq, Token -> AParser MToken
pMTok Token
TNEq, Token -> AParser MToken
pMTok Token
TCNEq, Token -> AParser MToken
pMTok Token
TLEQ, Token -> AParser MToken
pMTok Token
TGEQ, Token -> AParser MToken
pMTok Token
TLT, Token -> AParser MToken
pMTok Token
TGT, Token -> AParser MToken
pMTok Token
Equals, Token -> AParser MToken
pMTok Token
Concatenate, Token -> AParser MToken
pMTok Token
And, Token -> AParser MToken
pMTok Token
CAnd, Token -> AParser MToken
pMTok Token
Or, Token -> AParser MToken
pMTok Token
COr]
                      AParser MToken
notWhitespace
                  )
            )

-- | Matches any token but the given one
pNotTToken :: Token -> AParser MToken
pNotTToken :: Token -> AParser MToken
pNotTToken Token
t = (Token -> Bool) -> AParser MToken
pTSatisfy (Token
t forall a. Eq a => a -> a -> Bool
/=)

-- | Warn about adding or removing spaces after an opening parenthesis. What it actually checks for
-- and wants the user to do depends on the prettyprint_spaceBetweenParens and
-- prettyprint_spaceEmptyParens settings
spaceAfterParenthesis :: LintSettings -> AParser Issue
spaceAfterParenthesis :: LintSettings -> AParser Issue
spaceAfterParenthesis LintSettings
settings
  | Bool -> Bool
not (LintSettings -> Bool
lint_spaceBetweenParens LintSettings
settings) = forall s u (m :: * -> *) a. ParsecT s u m a
parserZero
  | Bool
otherwise =
      case (LintSettings -> Bool
prettyprint_spaceBetweenParens LintSettings
settings, LintSettings -> Bool
prettyprint_spaceEmptyParens LintSettings
settings) of
        (Bool
True, Bool
True) ->
          RemoveOrAddSpace -> Issue
SpaceAfterParenthesis RemoveOrAddSpace
AddSpace forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Token -> AParser MToken
pMTok Token
LRound forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> AParser MToken
notWhitespace)
        (Bool
False, Bool
False) ->
          RemoveOrAddSpace -> Issue
SpaceAfterParenthesis RemoveOrAddSpace
RemoveSpace forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Token -> AParser MToken
pMTok Token
LRound forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> (Token -> Bool) -> AParser MToken
pTSatisfy Token -> Bool
isSpaces)
        (Bool
True, Bool
False) ->
          RemoveOrAddSpace -> Issue
SpaceAfterParenthesis RemoveOrAddSpace
AddSpace forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Token -> AParser MToken
pMTok Token
LRound forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> AParser MToken
notWhitespaceAndNotClose)
            forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> RemoveOrAddSpace -> Issue
SpaceAfterParenthesis RemoveOrAddSpace
RemoveSpace forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Token -> AParser MToken
pMTok Token
LRound forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> (Token -> Bool) -> AParser MToken
pTSatisfy Token -> Bool
isSpaces forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Token -> AParser MToken
pMTok Token
RRound)
        (Bool
False, Bool
True) ->
          RemoveOrAddSpace -> Issue
SpaceAfterParenthesis RemoveOrAddSpace
RemoveSpace forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Token -> AParser MToken
pMTok Token
LRound forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> (Token -> Bool) -> AParser MToken
pTSatisfy Token -> Bool
isSpaces forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Token -> AParser MToken
pNotTToken Token
RRound)
            forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> RemoveOrAddSpace -> Issue
SpaceAfterParenthesis RemoveOrAddSpace
AddSpace forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Token -> AParser MToken
pMTok Token
LRound forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Token -> AParser MToken
pMTok Token
RRound)
  where
    notWhitespaceAndNotClose :: AParser MToken
    notWhitespaceAndNotClose :: AParser MToken
notWhitespaceAndNotClose = (Token -> Bool) -> AParser MToken
pTSatisfy forall a b. (a -> b) -> a -> b
$ \case
      Token
RRound -> Bool
False
      Whitespace String
_ -> Bool
False
      Token
_ -> Bool
True

-- | Warn about adding or removing spaces before a closing parenthesis
spaceBeforeParenthesis :: LintSettings -> AParser Issue
spaceBeforeParenthesis :: LintSettings -> AParser Issue
spaceBeforeParenthesis LintSettings
settings
  | Bool -> Bool
not (LintSettings -> Bool
lint_spaceBetweenParens LintSettings
settings) = forall s u (m :: * -> *) a. ParsecT s u m a
parserZero
  | Bool
otherwise =
      case (LintSettings -> Bool
prettyprint_spaceBetweenParens LintSettings
settings, LintSettings -> Bool
prettyprint_spaceEmptyParens LintSettings
settings) of
        (Bool
True, Bool
True) ->
          RemoveOrAddSpace -> Issue
SpaceBeforeParenthesis RemoveOrAddSpace
AddSpace forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (AParser MToken
notWhitespace forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Token -> AParser MToken
pMTok Token
RRound)
        (Bool
False, Bool
False) ->
          RemoveOrAddSpace -> Issue
SpaceBeforeParenthesis RemoveOrAddSpace
RemoveSpace forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try ((Token -> Bool) -> AParser MToken
pTSatisfy Token -> Bool
isSpaces forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Token -> AParser MToken
pMTok Token
RRound)
        (Bool
True, Bool
False) ->
          RemoveOrAddSpace -> Issue
SpaceBeforeParenthesis RemoveOrAddSpace
AddSpace forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (AParser MToken
notWhitespaceAndNotOpen forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Token -> AParser MToken
pMTok Token
RRound)
        (Bool
False, Bool
True) ->
          RemoveOrAddSpace -> Issue
SpaceBeforeParenthesis RemoveOrAddSpace
RemoveSpace forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Token -> AParser MToken
pNotTToken Token
LRound forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> (Token -> Bool) -> AParser MToken
pTSatisfy Token -> Bool
isSpaces forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Token -> AParser MToken
pMTok Token
RRound)
  where
    notWhitespaceAndNotOpen :: AParser MToken
    notWhitespaceAndNotOpen :: AParser MToken
notWhitespaceAndNotOpen = (Token -> Bool) -> AParser MToken
pTSatisfy forall a b. (a -> b) -> a -> b
$ \case
      Token
LRound -> Bool
False
      Whitespace String
_ -> Bool
False
      Token
_ -> Bool
True

-- | Warn about adding or removing spaces after an opening brace (`}`). What it actually checks for
-- and wants the user to do depends on the prettyprint_spaceBetweenBraces and
-- prettyprint_spaceEmptyBraces settings
spaceAfterBraces :: LintSettings -> AParser Issue
spaceAfterBraces :: LintSettings -> AParser Issue
spaceAfterBraces LintSettings
settings
  | Bool -> Bool
not (LintSettings -> Bool
lint_spaceBetweenBraces LintSettings
settings) = forall s u (m :: * -> *) a. ParsecT s u m a
parserZero
  | Bool
otherwise =
      case (LintSettings -> Bool
prettyprint_spaceBetweenBraces LintSettings
settings, LintSettings -> Bool
prettyprint_spaceEmptyBraces LintSettings
settings) of
        (Bool
True, Bool
True) ->
          RemoveOrAddSpace -> Issue
SpaceAfterBrace RemoveOrAddSpace
AddSpace forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Token -> AParser MToken
pMTok Token
LCurly forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> AParser MToken
notWhitespace)
        (Bool
False, Bool
False) ->
          RemoveOrAddSpace -> Issue
SpaceAfterBrace RemoveOrAddSpace
RemoveSpace forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Token -> AParser MToken
pMTok Token
LCurly forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> (Token -> Bool) -> AParser MToken
pTSatisfy Token -> Bool
isSpaces)
        (Bool
True, Bool
False) ->
          RemoveOrAddSpace -> Issue
SpaceAfterBrace RemoveOrAddSpace
AddSpace forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Token -> AParser MToken
pMTok Token
LCurly forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> AParser MToken
notWhitespaceAndNotClose)
            forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> RemoveOrAddSpace -> Issue
SpaceAfterBrace RemoveOrAddSpace
RemoveSpace forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Token -> AParser MToken
pMTok Token
LCurly forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> (Token -> Bool) -> AParser MToken
pTSatisfy Token -> Bool
isSpaces forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Token -> AParser MToken
pMTok Token
RCurly)
        (Bool
False, Bool
True) ->
          RemoveOrAddSpace -> Issue
SpaceAfterBrace RemoveOrAddSpace
RemoveSpace forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Token -> AParser MToken
pMTok Token
LCurly forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> (Token -> Bool) -> AParser MToken
pTSatisfy Token -> Bool
isSpaces forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Token -> AParser MToken
pNotTToken Token
RCurly)
            forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> RemoveOrAddSpace -> Issue
SpaceAfterBrace RemoveOrAddSpace
AddSpace forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Token -> AParser MToken
pMTok Token
LCurly forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Token -> AParser MToken
pMTok Token
RCurly)
  where
    notWhitespaceAndNotClose :: AParser MToken
    notWhitespaceAndNotClose :: AParser MToken
notWhitespaceAndNotClose = (Token -> Bool) -> AParser MToken
pTSatisfy forall a b. (a -> b) -> a -> b
$ \case
      Token
RCurly -> Bool
False
      Whitespace String
_ -> Bool
False
      Token
_ -> Bool
True

-- | Warn about adding or removing spaces before a closing brace (`}`)
spaceBeforeBraces :: LintSettings -> AParser Issue
spaceBeforeBraces :: LintSettings -> AParser Issue
spaceBeforeBraces LintSettings
settings
  | Bool -> Bool
not (LintSettings -> Bool
lint_spaceBetweenBraces LintSettings
settings) = forall s u (m :: * -> *) a. ParsecT s u m a
parserZero
  | Bool
otherwise =
      case (LintSettings -> Bool
prettyprint_spaceBetweenBraces LintSettings
settings, LintSettings -> Bool
prettyprint_spaceEmptyBraces LintSettings
settings) of
        (Bool
True, Bool
True) ->
          RemoveOrAddSpace -> Issue
SpaceBeforeBrace RemoveOrAddSpace
AddSpace forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (AParser MToken
notWhitespace forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Token -> AParser MToken
pMTok Token
RCurly)
        (Bool
False, Bool
False) ->
          RemoveOrAddSpace -> Issue
SpaceBeforeBrace RemoveOrAddSpace
RemoveSpace forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try ((Token -> Bool) -> AParser MToken
pTSatisfy Token -> Bool
isSpaces forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Token -> AParser MToken
pMTok Token
RCurly)
        (Bool
True, Bool
False) ->
          RemoveOrAddSpace -> Issue
SpaceBeforeBrace RemoveOrAddSpace
AddSpace forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (AParser MToken
notWhitespaceAndNotOpen forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Token -> AParser MToken
pMTok Token
RCurly)
        (Bool
False, Bool
True) ->
          RemoveOrAddSpace -> Issue
SpaceBeforeBrace RemoveOrAddSpace
RemoveSpace forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Token -> AParser MToken
pNotTToken Token
LCurly forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> (Token -> Bool) -> AParser MToken
pTSatisfy Token -> Bool
isSpaces forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Token -> AParser MToken
pMTok Token
RCurly)
  where
    notWhitespaceAndNotOpen :: AParser MToken
    notWhitespaceAndNotOpen :: AParser MToken
notWhitespaceAndNotOpen = (Token -> Bool) -> AParser MToken
pTSatisfy forall a b. (a -> b) -> a -> b
$ \case
      Token
LCurly -> Bool
False
      Whitespace String
_ -> Bool
False
      Token
_ -> Bool
True

-- | Warn about adding or removing spaces after an opening bracket (`[`). What it actually checks
-- for and wants the user to do depends on the prettyprint_spaceBetweenBracket
spaceAfterBrackets :: LintSettings -> AParser Issue
spaceAfterBrackets :: LintSettings -> AParser Issue
spaceAfterBrackets LintSettings
settings
  | Bool -> Bool
not (LintSettings -> Bool
lint_spaceBetweenBrackets LintSettings
settings) = forall s u (m :: * -> *) a. ParsecT s u m a
parserZero
  | LintSettings -> Bool
prettyprint_spaceBetweenBrackets LintSettings
settings =
      RemoveOrAddSpace -> Issue
SpaceAfterBracket RemoveOrAddSpace
AddSpace forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Token -> AParser MToken
pMTok Token
LSquare forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> AParser MToken
notWhitespace)
  | Bool
otherwise =
      RemoveOrAddSpace -> Issue
SpaceAfterBracket RemoveOrAddSpace
RemoveSpace forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Token -> AParser MToken
pMTok Token
LSquare forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> (Token -> Bool) -> AParser MToken
pTSatisfy Token -> Bool
isSpaces)

-- | Warn about adding or removing spaces before a closing bracket (`]`)
spaceBeforeBrackets :: LintSettings -> AParser Issue
spaceBeforeBrackets :: LintSettings -> AParser Issue
spaceBeforeBrackets LintSettings
settings
  | Bool -> Bool
not (LintSettings -> Bool
lint_spaceBetweenBrackets LintSettings
settings) = forall s u (m :: * -> *) a. ParsecT s u m a
parserZero
  | LintSettings -> Bool
prettyprint_spaceBetweenBrackets LintSettings
settings =
      RemoveOrAddSpace -> Issue
SpaceBeforeBracket RemoveOrAddSpace
AddSpace forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (AParser MToken
notWhitespace forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Token -> AParser MToken
pMTok Token
RSquare)
  | Bool
otherwise =
      RemoveOrAddSpace -> Issue
SpaceBeforeBracket RemoveOrAddSpace
RemoveSpace forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try ((Token -> Bool) -> AParser MToken
pTSatisfy Token -> Bool
isSpaces forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Token -> AParser MToken
pMTok Token
RSquare)

-- | Warn about adding or removing spaces after a comma
spaceAfterComma :: LintSettings -> AParser Issue
spaceAfterComma :: LintSettings -> AParser Issue
spaceAfterComma LintSettings
settings
  | Bool -> Bool
not (LintSettings -> Bool
lint_spaceAfterComma LintSettings
settings) = forall s u (m :: * -> *) a. ParsecT s u m a
parserZero
  | LintSettings -> Bool
prettyprint_spaceAfterComma LintSettings
settings =
      RemoveOrAddSpace -> Issue
SpaceAfterComma RemoveOrAddSpace
AddSpace forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Token -> AParser MToken
pMTok Token
Comma forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> AParser MToken
notWhitespace)
  | Bool
otherwise =
      RemoveOrAddSpace -> Issue
SpaceAfterComma RemoveOrAddSpace
RemoveSpace forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Token -> AParser MToken
pMTok Token
Comma forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> (Token -> Bool) -> AParser MToken
pTSatisfy Token -> Bool
isSpaces)

-- | Warn about adding or removing spaces before a comma
spaceBeforeComma :: LintSettings -> AParser Issue
spaceBeforeComma :: LintSettings -> AParser Issue
spaceBeforeComma LintSettings
settings
  | Bool -> Bool
not (LintSettings -> Bool
lint_spaceBeforeComma LintSettings
settings) = forall s u (m :: * -> *) a. ParsecT s u m a
parserZero
  | LintSettings -> Bool
prettyprint_spaceBeforeComma LintSettings
settings =
      RemoveOrAddSpace -> Issue
SpaceBeforeComma RemoveOrAddSpace
AddSpace forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (AParser MToken
notWhitespace forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Token -> AParser MToken
pMTok Token
Comma)
  | Bool
otherwise =
      RemoveOrAddSpace -> Issue
SpaceBeforeComma RemoveOrAddSpace
RemoveSpace forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try ((Token -> Bool) -> AParser MToken
pTSatisfy Token -> Bool
isSpaces forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Token -> AParser MToken
pMTok Token
Comma)

-- | Parser for all profanity
profanitySequence :: LintSettings -> AParser Issue
profanitySequence :: LintSettings -> AParser Issue
profanitySequence LintSettings
opts =
  if Bool -> Bool
not (LintSettings -> Bool
lint_profanity LintSettings
opts)
    then forall s u (m :: * -> *) a. ParsecT s u m a
parserZero
    else
      Issue
Profanity
        forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ ( String -> AParser MToken
ident String
"anus"
              forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String -> AParser MToken
ident String
"bitch"
              forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String -> AParser MToken
ident String
"cock"
              forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String -> AParser MToken
ident String
"cocks"
              forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String -> AParser MToken
ident String
"cunt"
              forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String -> AParser MToken
ident String
"dick"
              forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String -> AParser MToken
ident String
"dicks"
              forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String -> AParser MToken
ident String
"fuck"
              forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String -> AParser MToken
ident String
"fucking"
              forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String -> AParser MToken
ident String
"goddamnit"
              forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String -> AParser MToken
ident String
"knob"
              forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String -> AParser MToken
ident String
"knobs"
              forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String -> AParser MToken
ident String
"motherfucker"
              forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String -> AParser MToken
ident String
"nipple"
              forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String -> AParser MToken
ident String
"shit"
           )

-- | Parses for any bad sequence
badSequence :: LintSettings -> AParser Issue
badSequence :: LintSettings -> AParser Issue
badSequence LintSettings
opts =
  LintSettings -> AParser Issue
deprecatedSequence LintSettings
opts
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> LintSettings -> AParser Issue
profanitySequence LintSettings
opts
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> LintSettings -> AParser Issue
beginnerMistakeSequence LintSettings
opts
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> LintSettings -> AParser Issue
whiteSpaceStyleSequence LintSettings
opts
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> LintSettings -> AParser Issue
spaceAfterParenthesis LintSettings
opts
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> LintSettings -> AParser Issue
spaceBeforeParenthesis LintSettings
opts
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> LintSettings -> AParser Issue
spaceAfterBraces LintSettings
opts
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> LintSettings -> AParser Issue
spaceBeforeBraces LintSettings
opts
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> LintSettings -> AParser Issue
spaceAfterBrackets LintSettings
opts
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> LintSettings -> AParser Issue
spaceBeforeBrackets LintSettings
opts
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> LintSettings -> AParser Issue
spaceAfterComma LintSettings
opts
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> LintSettings -> AParser Issue
spaceBeforeComma LintSettings
opts

-- | Creates a warning for a certain sequence at any position
badSequenceWarning :: Region -> Issue -> [FilePath -> LintMessage] -> [FilePath -> LintMessage]
badSequenceWarning :: Region
-> Issue -> [String -> LintMessage] -> [String -> LintMessage]
badSequenceWarning Region
pos Issue
message = (:) (Severity -> Region -> Issue -> String -> LintMessage
LintMessage Severity
LintWarning Region
pos Issue
message)

-- | Searches for all the bad sequences
badSequenceParser :: LintSettings -> AParser [String -> LintMessage]
badSequenceParser :: LintSettings -> AParser [String -> LintMessage]
badSequenceParser LintSettings
opts =
  -- A bad sequence
  forall a b. (Region -> a -> b) -> AParser a -> AParser b
annotated Region
-> Issue -> [String -> LintMessage] -> [String -> LintMessage]
badSequenceWarning (LintSettings -> AParser Issue
badSequence LintSettings
opts) forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> LintSettings -> AParser [String -> LintMessage]
badSequenceParser LintSettings
opts
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>
    -- Continue searching
    forall s (m :: * -> *) t u.
(Stream s m t, Show t) =>
ParsecT s u m t
anyToken forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> LintSettings -> AParser [String -> LintMessage]
badSequenceParser LintSettings
opts
    forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>
    -- end of input
    forall (m :: * -> *) a. Monad m => a -> m a
return []

-- | Returns all the warnings for a lexicon
sequenceWarnings :: LintSettings -> [MToken] -> [String -> LintMessage]
sequenceWarnings :: LintSettings -> [MToken] -> [String -> LintMessage]
sequenceWarnings LintSettings
opts [MToken]
mts = case forall a. String -> AParser a -> [MToken] -> Either ParseError a
execAParser String
"source.lua" (LintSettings -> AParser [String -> LintMessage]
badSequenceParser LintSettings
opts) [MToken]
mts of
  Left ParseError
_ -> forall a. HasCallStack => String -> a
error String
"[Error] line 1, column 1: Sequence finding error! Report an issue!"
  Right [String -> LintMessage]
warnings -> [String -> LintMessage]
warnings

-- | Helper function: check from string
checkFromString :: AParser a -> String -> Either ParseError a
checkFromString :: forall a. AParser a -> String -> Either ParseError a
checkFromString AParser a
p String
inp = do
  [MToken]
lexed <- String -> Either ParseError [MToken]
Lexer.execParseTokens String
inp
  forall a. String -> AParser a -> [MToken] -> Either ParseError a
execAParser String
"source.lua" AParser a
p [MToken]
lexed