Guest User

Untitled

a guest
Jan 20th, 2018
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.05 KB | None | 0 0
  1. {-# LANGUAGE OverloadedStrings #-}
  2. module Main where
  3.  
  4. import Turtle
  5. import Prelude hiding (FilePath)
  6. import qualified Data.Text as T
  7. import qualified Control.Foldl as Fold
  8. import Data.Maybe
  9. import Control.Monad (filterM)
  10.  
  11. data ViewBindings = ViewBindings { controllerFile :: FilePath
  12. , layoutFile :: FilePath
  13. , bindings :: [Binding]
  14. }
  15. deriving (Eq, Show)
  16.  
  17. -- property name, property type, property layout id
  18. data Binding = Binding { propertyName :: Text
  19. , propertyType :: Text
  20. , propertyLayoutId :: Text
  21. }
  22. deriving (Eq, Show)
  23.  
  24. -- pasted from foldl-1.3.5 to not mess with stack for now
  25. prefilter :: (a -> Bool) -> Fold a r -> Fold a r
  26. prefilter f (Fold step begin done) = Fold step' begin done
  27. where
  28. step' x a = if f a then step x a else x
  29. {-# INLINABLE prefilter #-}
  30.  
  31. snakeToCamel :: T.Text -> T.Text
  32. snakeToCamel t = case T.splitOn "_" t of
  33. [] -> t
  34. (w:ws) -> T.concat (T.toLower w : map T.toTitle ws)
  35.  
  36. kotlinIdPattern :: Pattern Text
  37. kotlinIdPattern = do
  38. rid <- text "R.id."
  39. identifier <- plus (alphaNum <|> char '_')
  40. return $ rid <> (snakeToCamel identifier)
  41.  
  42. bindViewPattern :: Pattern Binding
  43. bindViewPattern = do
  44. text "val"
  45. plus space
  46. propName <- plus alphaNum
  47. char ':'
  48. plus space
  49. propType <- plus alphaNum
  50. plus space
  51. text "by"
  52. plus space
  53. text "BindView(R.id."
  54. propLayoutId <- plus (alphaNum <|> char '_')
  55. char ')'
  56. return $ Binding propName propType propLayoutId
  57.  
  58. -- finds a layout identifier for controller views
  59. viewLayoutPattern :: Pattern Text
  60. viewLayoutPattern = do
  61. text "inflater.inflate(R.layout."
  62. layoutId <- text "content_" <> plus (alphaNum <|> char '_')
  63. char ','
  64. return layoutId
  65.  
  66. -- finds a layout "@id"/"@+id" attributes, returns only name part,
  67. -- i.e. "@+id/some_id" -> "some_id"
  68. idAttrPattern :: Pattern Text
  69. idAttrPattern = do
  70. char '@'
  71. optional (char '+')
  72. text "id/"
  73. propLayoutId <- plus (alphaNum <|> char '_')
  74. return propLayoutId
  75.  
  76. argsParser :: Parser FilePath
  77. argsParser = argPath "SRC_DIR" "A source directory to find file to refactor"
  78.  
  79. nonNullShell :: Shell a -> IO Bool
  80. nonNullShell sh = not <$> fold sh Fold.null
  81.  
  82. findLayoutFileById :: Text -> FilePath -> IO (Maybe FilePath)
  83. findLayoutFileById lid dir = fold (find (suffix layoutFileName) dir) $ prefilter (not . isInBuildDir) Fold.head
  84. where layoutFileName = text (lid <> ".xml")
  85. isInBuildDir fp = any (\p -> p == fromText "build/") $ splitDirectories fp
  86.  
  87. extractLayoutFilePath :: FilePath -> FilePath -> IO (Maybe FilePath)
  88. extractLayoutFilePath dir fp = do
  89. let inputShell = input fp
  90. let grepShell = grep (has viewLayoutPattern) inputShell
  91. let sedShell = sed (has viewLayoutPattern) grepShell
  92. layoutId <- fold sedShell Fold.head
  93. case layoutId of
  94. Just id -> findLayoutFileById (lineToText id) dir
  95. Nothing -> return Nothing
  96.  
  97. extractViewBindings :: FilePath -> IO [Binding]
  98. extractViewBindings fp = do
  99. let inputShell = input fp
  100. let grepShell = lineToText <$> grep (has bindViewPattern) inputShell
  101. let matchFirst p t = head $ match p t
  102. let sedShell = matchFirst (has bindViewPattern) <$> grepShell
  103. fold sedShell Fold.list
  104.  
  105. main :: IO ()
  106. main = do
  107. sourceDir <- options "Refactors BindView delegate to kotlin extensions" argsParser
  108. files <- fold (find (suffix ".kt") sourceDir) Fold.list
  109. let fileShells = map (\filePath -> (filePath, grep (has bindViewPattern) (input filePath))) files
  110. filtered <- filterM (\(_, sh) -> nonNullShell sh) fileShells
  111. let filesWithBinds = map fst filtered
  112. layoutFilesMaybes <- sequence $ map (extractLayoutFilePath sourceDir) filesWithBinds
  113. viewBindings <- sequence $ map extractViewBindings filesWithBinds
  114. let layoutFiles = map fromJust layoutFilesMaybes
  115. let bindings = zipWith3 (\cf lf vb -> ViewBindings cf lf vb) filesWithBinds layoutFiles viewBindings
  116. do if (length filesWithBinds /= length bindings) then error "not all bindings found!" else return ()
  117. putStrLn ("found " ++ (show (length bindings)) ++ " files with bindings")
  118. return ()
Add Comment
Please, Sign In to add comment