Commit ec99ecae authored by Felix Blaumer's avatar Felix Blaumer
Browse files

Adds final code version for the extern PackageAnalysis project as well as the version in Masala

parent 3fd510e4
......@@ -15,7 +15,9 @@ import Database.CDBI.Connection
import qualified CPM.Package as CPM
import IO
import List
import Analysis.Pathing
import PackageAnalysis.Logic
import PackageAnalysis.Filemanagement
import PackageAnalysis.Types
--- Choose the controller for a Package entity according to the URL parameter.
mainPackageController :: Controller
......@@ -118,12 +120,13 @@ showPackagePV package version versions = do
let path = "packages/" ++ pack ++ "/" ++ ver ++ "/"
json <- getFileContent (path ++ "package.json")
let epackage = CPM.readPackageSpec json
analysisText <- getAnalysisText package version
-- analysisText <- getAnalysisText package version
case epackage of
(Left error) -> fail ("Invalid package.json\n" ++ error)
(Right packagejson) -> do
readme <- getFileContent (path ++ "README.md")
return $ showPackage package version versions packagejson readme analysisText
return $ showPackage package version versions packagejson readme [[]]
--analysisText
showPackageByNameLatestController :: String -> Controller
showPackageByNameLatestController pack = do
......@@ -153,7 +156,9 @@ showPackageByNameController pack ver = do
--- if not [] is returned
getAnalysisText :: Package -> Version -> IO [String]
getAnalysisText package version = do
filepaths <- getAnalysisFilepaths package version
-- make analysis first (instead of analysis at upload/explicit analysis)
analyzePackage package version allAnalysisTypes
filepaths <- getAnalysisFolderContent package version
getFileContents filepaths
where
getFileContents (file:restFiles) = do
......
module PackageAnalysis.Analysis where
import PackageAnalysis.FileCreation
--- Contains analysis result as string and the type of the analysis made
data AnalysisData = AnalysisData String AnalysisType
--- Contains everything that defines an analysis
data AnalysisType = AnalysisType ConcreteAnalysisType AnalysisFunc
--- the explicit types of Analyses possible
data ConcreteAnalysisType = LinesOfCode | NumberOfFileLines
deriving (Eq)
--- Signature of Analysis functions
type AnalysisFunc = (String -> IO String)
--- returns file suffix of given Analysistype
getAnalysisTypeSuffix :: AnalysisType -> String
getAnalysisTypeSuffix (AnalysisType LinesOfCode _) = "aloc"
getAnalysisTypeSuffix (AnalysisType NumberOfFileLines _) = "anof"
getAnalysisTypeSuffix _ = "txt"
--- returns all analysisTypes that should be used for package analysis
allAnalysisTypes :: [AnalysisType]
allAnalysisTypes = [ (AnalysisType LinesOfCode loc)
, (AnalysisType NumberOfFileLines nol)
]
{-
data Test = Test Int TestType
data ConcreteData = Data1 | Data2
type TestType = (Int -> Int)
main = testing (Test 1 testFunc)
testing :: Test -> Int
testing (Test x theTestFunc) = theTestFunc x
getTest :: Int -> Test
getTest x = Test x testFunc
testFunc :: Int -> Int
testFunc x = x + 1
-}
--- Takes a path to a package and a list of AnalysisTypes.
--- Creates a folder for all AnalysisData (as Files) and copies the hierachy of
--- the original packageData.
analyzePackage :: Package -> [AnalysisType] -> IO [AnalysisData]
analyzePackage package analyzations = do
makeAnalysisStructure package
files <- getCurryFiles package
makeFiles files
where
makeFiles _@(curr:rest) = do
content <- readFile curr
result <- analyzeFile content
createAnalysisFile curr result
return $ (result : (makeFiles rest))
--- Analyzes a file's content given as a single string
analyzeFile :: String -> [AnalysisType] -> [AnalysisData]
analyzeFile fileContent _@((AnalysisType concType aFunc):restTypes) =
((AnalysisData (aFunc fileContent) concType) : (analyzeFile fileContent restTypes))
analyzeFile _ [] = []
--- Analysisfunction for countCodeLines
loc :: AnalysisFunc
loc filecontent = return "Lines of Code:\n" ++ countCodeLines filecontent
--- Analysisfunction for numberOfFileLines
nol :: AnalysisFunc
nol filecontent = return "Number of lines in the file:\n" ++ numberOfFileLines filecontent
--- counts lines of code of a given strign which should represent a curry file
countCodeLines :: String -> String
countCodeLines filecontent = show $ analyzing $ lines fileContent
where
analyzing contentLines@(x:xs) =
(isLoc x) + (analyzing xs)
where
isLoc line@(c:cs)
| c == '\n' = 0
| c == '-' = 0
| otherwise = 1
isLoc [] = 0
analyzing [] = 0
--- counts number of lines of a given string which should represent a curry file
numberOfFileLines :: String -> String
numberOfFileLines content = show $ length $ lines content
module PackageAnalysis.Filemanagement where
import PacakgeAnalysis.Analysis
import Masala
import System
import FilePath
import List
import CPM.FileUtil
import IOExts
import IO
import Directory
import FileGoodies
import FilePath
import Directory
import IO
import IOExts
import List
import Masala
import PackageAnalysis.Types
import System
--- the name of the folder that contains the data for analyses. Every version of
--- a package should have its own folder.
......@@ -21,38 +20,29 @@ analysisPath = "AnalysisData/"
analysisNameSuffix :: String
analysisNameSuffix = "_analysis."
--- Takes a path to a curryfile and AnalysisTypes and writes the analysis result
--- into the corresponding analysisdata files
createAnalysisFile :: String -> package -> version -> [AnalysisType] -> IO [String]
createAnalysisFile filepath package version _@(aType : rest) = do
analysispath <- getAnalysisFilePath filepath package version aType
content <- readFile filepath
let result = analyzeFile content [aType]
writeFile analysispath (head result)
return (analysispath : createAnalysisFile filepath package version rest)
createAnalysisFile _ _ _ [] = return []
--- gets the path to an analysisdata-file of a curry file given as filepath
--- w.r.t. to the packageversion and analysistype. It does not check, if
--- the file exists. Filepath must be absolute.
getAnalysisFilePath :: String -> Package -> Version -> AnalysisType -> IO String
getAnalysisFilePath filepath package version aType = do
let analysisPackagePath = getAnalysisFolderPath package version
let packageStructure = getHierarchyInSrcFolder
let filename = takeBaseName filepath ++ analysisNameSuffix
analysisPackagePath <- getAnalysisFolderPath package version
let packageStructure = getHierarchyInSrcFolder analysisPackagePath
let filename = takeBaseName filepath ++ analysisNameSuffix
++ getAnalysisTypeSuffix aType
dirs <- getSrcDirectories package version
return $ analysisPackagePath ++ packageStructure ++ filename
where
getHierarchyInSrcFolder =
getHierarchyInSrcFolder analysisPackagePath =
(remakePath
-- analysisPackagePath has the same directories as filepath, but
-- filepath has some additional ones.
rmfirst (length $ splitDirectories analysisPackagePath)
(init $ splitDirectories filepath)
(rmfirst
(length (splitDirectories analysisPackagePath))
(init (splitDirectories filepath))
)
) ++ "/"
rmfirst count subject@(_:rest) | count > 0 = rmfirst count-1 rest
rmfirst count subject@(_:rest) | count > 0 = rmfirst (count-1) rest
| otherwise = subject
rmfirst _ [] = []
--- calls getAnalysisFilePath with every available AnalysisType and returns
--- the results as a list
......@@ -60,16 +50,19 @@ getAnalysisFilepaths :: String -> Package -> Version -> IO [String]
getAnalysisFilepaths filepath package version = do
getPaths allAnalysisTypes
where
getPaths _@(curr:rest) = (
(getAnalysisFilePath package version curr)
: (getPaths rest)
)
getPaths paths@(curr:rest) = do
firstPath <- getAnalysisFilePath filepath package version curr
restPaths <- getPaths rest
return (firstPath : restPaths)
getPaths [] = return [""]
--- tries to get all analysisdata-files for a specific packageversion
getAnalysisFolderContent :: Package -> Version -> IO [String]
getAnalysisFolderContent package version = do
catch (checkAndGetVisibleDirectoryContents (getAnalysisFolderPath package version))
(\_ -> return [])
folderPath <- getAnalysisFolderPath package version
handle <- connectToCommand ("find '" ++ folderPath ++ "' -type f")
result <- hGetContents handle
return $ lines result
--- gets the absolute path to the folder containing the analyses data
getAnalysisFolderPath :: Package -> Version -> IO String
......@@ -81,7 +74,15 @@ getAnalysisFolderPath package version = do
--- strings.
getCurryFiles :: String -> IO [String]
getCurryFiles directory = do
hGetcontents $ execCmd "find '" ++ directory ++ "' -name '*.curry'"
handle <- connectToCommand ("find '" ++ directory ++ "' -name '*.curry'")
result <- hGetContents handle
return $ lines result
getCurryFilesOfPackage :: Package -> Version -> IO [String]
getCurryFilesOfPackage package version = do
dirs <- getSrcDirectories package version
files <- sequenceIO $ map getCurryFiles dirs
return $ concat files
--- gets the absolute path of a Package according to the given version.
getPackageDirectory :: Package -> Version -> IO String
......@@ -89,62 +90,29 @@ getPackageDirectory package version = do
let result = "./packages/" ++ packageName package ++ "/" ++ versionVersion version ++ "/"
getAbsolutePath result
--- goes one level up in the pathh ierarchy
--- goes one level up in the path ierarchy
getParentDirectory :: String -> String
getParentDirectory filepath =
(remakePath $ init $ splitDirectories filepath) ++ "/"
---TODO: just a mock up right now
getSources :: String -> IO [String]
getSources packageDirectory = do
return [packageDirectory ++ "src/"]
--TODO: get srcDirectories of package.json file
--- Takes a Package and returns the src directories that are listed in its
--- package.json file.
getSrcDirectories :: Package -> Version -> IO [String]
getSrcDirectories package version = do
packageDirectory <- getPackageDirectory package version
-- get package.json file in packagefolder
jsonfile <- hGetContents $ execCmd "find '" ++ packageDirectory
++ "' -name \"package.json\" -type f"
handle <- connectToCommand ("find '" ++ packageDirectory ++ "' -name \"package.json\" -type f")
jsonfile <- hGetContents handle
content <- readFile jsonfile
return getSources
where
--TODO: just a mock up right now
getSources = [packageDirectory ++ "src/"]
--TODO: get srcDirectories of package.json file
getSources packageDirectory
--- Takes a string which should represent the folderpath of a package.
--- Creates an analysis folder if not existent and copies the folder structure
--- of given source folders of the package. Returns the paths of the analyzed
--- curry-files.
makeAnalysisStructure :: Package -> Version -> IO [String]
makeAnalysisStructure package version = do
-- let packageFolder = getAnalysisFolderPath package version
sources <- getSrcDirectories --TODO
copyStructure
where
copyStructure = do
filepaths <- map getCurryFiles sources
copyFileStructure filepaths
-- give read + write rights to the analysisfolder
system "chmod u+rw '" ++ (getAnalysisFolderPath package version) ++ "' -R" -- maybe u+rwx instead
return filepaths
copyFileStructure _@(curr:rest) = do
dir <- getParentDirectory curr
analysisFilepaths <- getAnalysisFilepaths curr package version
system "mkdir -p '" ++ dir ++ "'"
map (\path -> system "touch '" ++ path ++ "'") analysisFilepaths
return $ copyFileStructure rest
copyFileStructure [] = return ()
--- Creates all analysis files (with analysis results) for each curry files in
--- the source directories of the specified packageversion. Returns the filepath
--- to the analysis filepaths.
makePackageAnalysis :: Package -> Version -> IO [String]
makePackageAnalysis package version = do
filepaths <- makeAnalysisStructure package version
createAnalysis filepaths
where
createAnalysis _@(curr:rest) = do
((createAnalysisFile curr package version allAnalysisTypes)
: (createAnalysis rest))
createAnalysis [] = return []
remakePath :: [String] -> String
remakePath directoriesList = concat $ map ("/" ++) directoriesList
remakePath directoriesList = concat ((head directoriesList) :
(map ("/" ++) (tail directoriesList)))
module PackageAnalysis.Functions where
--- counts lines of code of a given strign which should represent a curry file
countCodeLines :: String -> String
countCodeLines fileContent = show $ analyzing $ lines fileContent
where
analyzing contentLines@(x:xs) =
(isLoc x) + (analyzing xs)
where
isLoc line@(c:cs)
| c == '\n' = 0
| c == '-' = 0
| otherwise = 1
isLoc [] = 0
analyzing [] = 0
--- counts number of lines of a given string which should represent a curry file
numberOfFileLines :: String -> String
numberOfFileLines content = show $ length $ lines content
module PackageAnalysis.Logic where
import Masala
import PackageAnalysis.Functions
import PackageAnalysis.Filemanagement
import PackageAnalysis.Types
import System
--- Analyzes a file's content given as a single string
analyzeFile :: String -> [AnalysisType] -> IO [AnalysisData]
analyzeFile fileContent aTypes@((AnalysisType concType aFunc):restTypes) = do
aResult <- aFunc fileContent
rest <- analyzeFile fileContent restTypes
return ((AnalysisData aResult (AnalysisType concType aFunc)) : rest)
analyzeFile _ [] = return []
--- Takes a path to a package and a list of AnalysisTypes.
--- Creates a folder for all AnalysisData (as Files) and copies the hierachy of
--- the original packageData.
analyzePackage :: Package -> Version -> [AnalysisType] -> IO [[AnalysisData]]
analyzePackage package version aTypes = do
makeAnalysisStructure package version
files <- getCurryFilesOfPackage package version
makeFiles files
where
makeFiles files@(curr:rest) = do
aDatas <- createAnalysisFile curr package version aTypes
restDatas <- makeFiles rest
return (aDatas : restDatas)
makeFiles [] = return []
--- Takes a path to a curryfile and AnalysisTypes and writes the analysis result
--- into the corresponding analysisdata files
createAnalysisFile :: String -> Package -> Version -> [AnalysisType] ->
IO [AnalysisData]
createAnalysisFile filepath package version aTypes = do
content <- readFile filepath
aData <- analyzeFile content aTypes
let result = map getAnalysisDataContent aData
writeAnalysisFiles aTypes result
return aData
where
writeAnalysisFiles aTypes@(currType : restTypes)
contents@(currContent : restContent) = do
analysispath <- getAnalysisFilePath filepath package version currType
writeFile analysispath currContent
writeAnalysisFiles aTypes@(_:_) [] = return ()
writeAnalysisFiles [] content@(_:_) = return ()
writeAnalysisFiles [] [] = return ()
--- Takes a string which should represent the folderpath of a package.
--- Creates an analysis folder if not existent and copies the folder structure
--- of given source folders of the package. Returns the paths of the analyzed
--- curry-files.
makeAnalysisStructure :: Package -> Version -> IO [String]
makeAnalysisStructure package version = do
-- let packageFolder = getAnalysisFolderPath package version
curryFiles <- getCurryFilesOfPackage package version
folderPath <- getAnalysisFolderPath package version
copyFileStructure curryFiles
-- give read + write rights to the analysisfolder
system ("chmod u+rw \'" ++ folderPath ++ "\' -R") -- maybe u+rwx instead
return curryFiles
where
copyFileStructure paths@(curr:rest) = do
let dir = getParentDirectory curr
analysisFilepaths <- getAnalysisFilepaths curr package version
system ("mkdir -p \'" ++ dir ++ "\'")
touchPaths analysisFilepaths
-- map (\path -> system ("touch \'" ++ path ++ "\'")) analysisFilepaths
copyFileStructure rest
copyFileStructure [] = return ()
touchPaths files@(curr:rest) = do
system ("touch \'" ++ curr ++ "\'")
touchPaths rest
touchPaths [] = return ()
--- Creates all analysis files (with analysis results) for each curry files in
--- the source directories of the specified packageversion. Returns the results
--- as lists of a list of AnalysisDatas.
makePackageAnalysis :: Package -> Version -> IO [[AnalysisData]]
makePackageAnalysis package version = do
filepaths <- makeAnalysisStructure package version
createAnalysis filepaths
where
createAnalysis paths@(curr:rest) = do
result <- createAnalysisFile curr package version allAnalysisTypes
restAnalyses <- createAnalysis rest
return (result : restAnalyses)
createAnalysis [] = return []
module PackageAnalysis.Types where
import PackageAnalysis.Functions
--- Contains analysis result as string and the type of the analysis made
data AnalysisData = AnalysisData String AnalysisType
--- Contains everything that defines an analysis
data AnalysisType = AnalysisType ConcreteAnalysisType AnalysisFunc
--- the explicit types of Analyses possible
data ConcreteAnalysisType = LinesOfCode | NumberOfFileLines
deriving (Eq)
--- Signature of Analysis functions
type AnalysisFunc = (String -> IO String)
--- returns all analysisTypes that should be used for package analysis
allAnalysisTypes :: [AnalysisType]
allAnalysisTypes = [ (AnalysisType LinesOfCode loc)
, (AnalysisType NumberOfFileLines nol)
]
getAnalysisDataContent :: AnalysisData -> String
getAnalysisDataContent (AnalysisData content _) = content
getAnalysisType :: AnalysisData -> AnalysisType
getAnalysisType (AnalysisData _ analysisType) = analysisType
--- returns file suffix of given Analysistype
getAnalysisTypeSuffix :: AnalysisType -> String
getAnalysisTypeSuffix (AnalysisType aType _)
| aType == LinesOfCode = "aloc"
| aType == NumberOfFileLines = "anof"
| otherwise = "txt"
--- Analysisfunction for countCodeLines
loc :: AnalysisFunc
loc filecontent = return $ "Lines of Code:\n" ++ countCodeLines filecontent
--- Analysisfunction for numberOfFileLines
nol :: AnalysisFunc
nol filecontent = return $ "Number of lines in the file:\n" ++ numberOfFileLines filecontent
......@@ -213,16 +213,6 @@ analysis :: Package -> [String] -> HtmlExp -- multiple files for each package
analysis package analysisText@(_:_) = HtmlStruct "li" [("class", "list-group-item")]
[h4 [htxt "analysis"], htxt (unlines analysisText)]
analysis _ [] = htxt ""
{-
--TODO: delete:
where
checkForID = fileInPath filePath
getPackageanalysis = do
fileContent <- readFile filePath
return $ htxt fileContent
filePath = "./analysisData/" ++ fileName package
fileName (Package packageID name _ _) = name ++ "_" ++ (\(PackageID key) -> show key) packageID
-}
-- From CPM source. Not exported
......
......@@ -27,9 +27,8 @@ getAnalysisFilePath :: String -> Package -> Version -> AnalysisType -> IO String
getAnalysisFilePath filepath package version aType = do
analysisPackagePath <- getAnalysisFolderPath package version
let packageStructure = getHierarchyInSrcFolder analysisPackagePath
let filename = takeBaseName filepath ++ analysisNameSuffix
let filename = takeBaseName filepath ++ analysisNameSuffix
++ getAnalysisTypeSuffix aType
dirs <- getSrcDirectories package version
return $ analysisPackagePath ++ packageStructure ++ filename
where
getHierarchyInSrcFolder analysisPackagePath =
......@@ -41,9 +40,9 @@ getAnalysisFilePath filepath package version aType = do
(init (splitDirectories filepath))
)
) ++ "/"
rmfirst count subject@(first:rest) | count > 0 = rmfirst (count-1) rest
rmfirst count subject@(_:rest) | count > 0 = rmfirst (count-1) rest
| otherwise = subject
rmfirst _ [] = []
--- calls getAnalysisFilePath with every available AnalysisType and returns
--- the results as a list
getAnalysisFilepaths :: String -> Package -> Version -> IO [String]
......
......@@ -44,8 +44,9 @@ createAnalysisFile filepath package version aTypes = do
contents@(currContent : restContent) = do
analysispath <- getAnalysisFilePath filepath package version currType
writeFile analysispath currContent
writeAnalysisFiles _ [] = return ()
writeAnalysisFiles [] _ = return ()
writeAnalysisFiles aTypes@(_:_) [] = return ()
writeAnalysisFiles [] content@(_:_) = return ()
writeAnalysisFiles [] [] = return ()
--- Takes a string which should represent the folderpath of a package.
--- Creates an analysis folder if not existent and copies the folder structure
......@@ -72,7 +73,7 @@ makeAnalysisStructure package version = do
touchPaths files@(curr:rest) = do
system ("touch \'" ++ curr ++ "\'")
touchPaths rest
touchPathhs [] = return ()
touchPaths [] = return ()
--- Creates all analysis files (with analysis results) for each curry files in
--- the source directories of the specified packageversion. Returns the results
......
......@@ -29,9 +29,10 @@ getAnalysisType (AnalysisData _ analysisType) = analysisType
--- returns file suffix of given Analysistype
getAnalysisTypeSuffix :: AnalysisType -> String
getAnalysisTypeSuffix (AnalysisType LinesOfCode _) = "aloc"
getAnalysisTypeSuffix (AnalysisType NumberOfFileLines _) = "anof"
getAnalysisTypeSuffix _ = "txt"
getAnalysisTypeSuffix (AnalysisType aType _)
| aType == LinesOfCode = "aloc"
| aType == NumberOfFileLines = "anof"
| otherwise = "txt"
--- Analysisfunction for countCodeLines
loc :: AnalysisFunc
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment