{-# LANGUAGE OverloadedRecordDot #-}

module GLuaFixer.Interface where

import GLua.AG.AST (AST)
import GLua.AG.PrettyPrint (prettyprintConf)
import GLua.AG.Token (MToken, Region)
import qualified GLua.Lexer as UUL
import GLua.LineLimitParser (LineLimit (..), execParseLineLimits)
import qualified GLua.PSLexer as PSL
import qualified GLua.PSParser as PSP
import qualified GLua.Parser as UUP
import GLuaFixer.AG.ASTLint (astWarnings)
import GLuaFixer.AG.LexLint (fixedLexPositions, lintWarnings)
import GLuaFixer.BadSequenceFinder (sequenceWarnings)
import GLuaFixer.LintMessage (Issue (..), LintMessage (..), Severity (..))
import GLuaFixer.LintSettings (LintSettings (..), lint2ppSetting)
import Text.Parsec.Error (errorPos)
import Text.ParserCombinators.UU.BasicInstances (Error, LineColPos)

-- | Run the linters that apply to the source code of a file
sourceLint :: LintSettings -> FilePath -> String -> [LintMessage]
sourceLint :: LintSettings -> FilePath -> FilePath -> [LintMessage]
sourceLint LintSettings
lintSettings FilePath
filepath FilePath
contents =
  FilePath -> LineLimit -> FilePath -> [LintMessage]
execParseLineLimits FilePath
filepath (Int -> LineLimit
LineLimit forall a b. (a -> b) -> a -> b
$ LintSettings -> Int
lint_maxLineLength LintSettings
lintSettings) FilePath
contents

-- | Generate the lexicon of a source file, used as input for the parser
lex :: LintSettings -> FilePath -> String -> Either [LintMessage] [MToken]
lex :: LintSettings
-> FilePath -> FilePath -> Either [LintMessage] [MToken]
lex LintSettings
lintSettings FilePath
filepath FilePath
contents =
  case FilePath -> Either ParseError [MToken]
PSL.execParseTokens FilePath
contents of
    Left ParseError
lexErr ->
      forall a b. a -> Either a b
Left [Severity -> Region -> Issue -> FilePath -> LintMessage
LintMessage Severity
LintError (SourcePos -> Region
PSL.sp2Rg forall a b. (a -> b) -> a -> b
$ ParseError -> SourcePos
errorPos ParseError
lexErr) (ParseError -> Issue
IssueParseError ParseError
lexErr) FilePath
filepath | LintSettings
lintSettings.lint_syntaxErrors]
    Right [MToken]
tokens -> forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$ [MToken] -> [MToken]
fixedLexPositions [MToken]
tokens

-- | Use the (slower, but error-correcting) UU-parsinglib lexer to generate the lexicon
lexUU :: LintSettings -> String -> ([MToken], [Error LineColPos])
lexUU :: LintSettings -> FilePath -> ([MToken], [Error LineColPos])
lexUU LintSettings
lintSettings FilePath
contents = case FilePath -> ([MToken], [Error LineColPos])
UUL.execParseTokens FilePath
contents of
  ([MToken]
tokens, [Error LineColPos]
errors) ->
    ( [MToken] -> [MToken]
fixedLexPositions [MToken]
tokens
    , [Error LineColPos
err | LintSettings
lintSettings.lint_syntaxErrors, Error LineColPos
err <- [Error LineColPos]
errors]
    )

-- | Run the linting functions that inspect the lexicon
lexiconLint :: FilePath -> LintSettings -> [MToken] -> [LintMessage]
lexiconLint :: FilePath -> LintSettings -> [MToken] -> [LintMessage]
lexiconLint FilePath
filepath LintSettings
lintSettings [MToken]
tokens =
  forall a b. (a -> b) -> [a] -> [b]
map (forall a b. (a -> b) -> a -> b
$ FilePath
filepath) forall a b. (a -> b) -> a -> b
$
    LintSettings -> [MToken] -> [FilePath -> LintMessage]
lintWarnings LintSettings
lintSettings [MToken]
tokens forall a. [a] -> [a] -> [a]
++ LintSettings -> [MToken] -> [FilePath -> LintMessage]
sequenceWarnings LintSettings
lintSettings [MToken]
tokens

-- | Parse a lexicon into an Abstract Syntax Tree
parse :: LintSettings -> FilePath -> [MToken] -> Either [LintMessage] AST
parse :: LintSettings -> FilePath -> [MToken] -> Either [LintMessage] AST
parse LintSettings
lintSettings FilePath
filepath [MToken]
tokens =
  case [MToken] -> Either ParseError AST
PSP.parseGLua [MToken]
tokens of
    Left ParseError
err ->
      -- Return syntax errors
      forall a b. a -> Either a b
Left [Severity -> Region -> Issue -> FilePath -> LintMessage
LintMessage Severity
LintError (SourcePos -> Region
PSL.sp2Rg forall a b. (a -> b) -> a -> b
$ ParseError -> SourcePos
errorPos ParseError
err) (ParseError -> Issue
IssueParseError ParseError
err) FilePath
filepath | LintSettings -> Bool
lint_syntaxErrors LintSettings
lintSettings]
    Right AST
ast -> forall a b. b -> Either a b
Right AST
ast

-- | Parse a lexicon into an Abstract Syntax Tree using the slower, but error-correcting
-- uu-parsinglib
parseUU :: [MToken] -> (AST, [Error Region])
parseUU :: [MToken] -> (AST, [Error Region])
parseUU = [MToken] -> (AST, [Error Region])
UUP.parseGLua

-- | Run the linters that inspect the AST
astLint :: FilePath -> LintSettings -> AST -> [LintMessage]
astLint :: FilePath -> LintSettings -> AST -> [LintMessage]
astLint FilePath
filepath LintSettings
lintSettings AST
ast =
  forall a b. (a -> b) -> [a] -> [b]
map (forall a b. (a -> b) -> a -> b
$ FilePath
filepath) forall a b. (a -> b) -> a -> b
$ LintSettings -> AST -> [FilePath -> LintMessage]
astWarnings LintSettings
lintSettings AST
ast

-- | Pretty print code to a string
prettyprint :: LintSettings -> AST -> String
prettyprint :: LintSettings -> AST -> FilePath
prettyprint LintSettings
lintSettings AST
ast =
  PrettyPrintConfig -> AST -> FilePath
prettyprintConf (LintSettings -> PrettyPrintConfig
lint2ppSetting LintSettings
lintSettings) AST
ast