• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package parser
18 
19 import java.io.File
20 import java.nio.file.Files
21 import java.nio.file.Path
22 import java.nio.file.Paths
23 import kotlin.system.exitProcess
24 
25 const val LOG_NAME = "[hidl-doc]"
26 
27 fun printUsage() {
28     println("""
29 Usage: hidl-doc [-i path]
30  -i=path  Add input HAL file or directory to parse
31  -o=dir   Output directory of generated HTML [${config.outDir}]
32  -x=path  Exclude file or directory from files to parse
33  -v       Verbose mode, print parsing info
34  -h       Print this help and exit
35  Error modes:
36  -w       Warn on errors instead of exiting
37  -l       Lint. Warn-only and do not generate files
38  -e       Error and exit on warnings
39  -s       Skip files that encounter parse errors
40 """.trim())
41 }
42 
43 object config {
44     val files = mutableListOf<File>()
45     var outDir = toPath("~/out/hidl-doc/html")
46     var verbose = false
47     var lintMode = false
48     var warnOnly = false
49     var errorOnly = false
50     var skipError = false
51 
toStringnull52     override fun toString(): String {
53         return """
54 verbose: $verbose
55 warnOnly: $warnOnly
56 errorOnly: $errorOnly
57 skipError: $skipError
58 outDir: $outDir
59 files: $files
60 """
61     }
62 
63     private const val HAL_EXTENSION = ".hal"
64 
parseArgsnull65     fun parseArgs(args: Array<String>) {
66         if (args.isEmpty()) {
67             printUsage()
68             exitProcess(1)
69         }
70 
71         val dirPathArgs = mutableListOf<Path>()
72         val filePathArgs = mutableListOf<Path>()
73         val excludedPathArgs = mutableListOf<Path>()
74 
75         val iter = args.iterator()
76         var arg: String
77 
78         //parse command-line arguments
79         while (iter.hasNext()) {
80             arg = iter.next()
81 
82             when (arg) {
83                 "-i" -> {
84                     val path = toPath(iter.next())
85                     if (Files.isDirectory(path)) dirPathArgs.add(path) else filePathArgs.add(path)
86                 }
87                 "-x" -> excludedPathArgs.add(toPath(iter.next()).toAbsolutePath())
88                 "-o" -> outDir = toPath(iter.next())
89                 "-v" -> verbose = true
90                 "-l" -> { lintMode = true; warnOnly = true }
91                 "-w" -> warnOnly = true
92                 "-e" -> errorOnly = true
93                 "-s" -> skipError = true
94                 "-h" -> {
95                     printUsage()
96                     exitProcess(0)
97                 }
98                 else -> {
99                     System.err.println("Unknown option: $arg")
100                     printUsage()
101                     exitProcess(1)
102                 }
103             }
104         }
105 
106         //collect files (explicitly passed and search directories)
107         val allFiles = mutableListOf<File>()
108 
109         //add individual files
110         filePathArgs.filterNot { excludedPathArgs.contains(it.toAbsolutePath()) }
111                 .map { it.toFile() }.map { fp ->
112             if (!fp.isFile || !fp.canRead() || !fp.absolutePath.toLowerCase().endsWith(HAL_EXTENSION)) {
113                 System.err.println("Error: Invalid $HAL_EXTENSION file: ${fp.path}")
114                 exitProcess(1)
115             }
116             fp
117         }.map { allFiles.add(it) }
118 
119         //check directory args
120         dirPathArgs.map { it.toFile() }
121                 .map { findFiles(it, allFiles, HAL_EXTENSION, excludedPathArgs) }
122 
123         //consolidate duplicates
124         allFiles.distinctBy { it.canonicalPath }
125                 .forEach { files.add(it) }
126 
127         if (files.isEmpty()) {
128             System.err.println("Error: Can't find any $HAL_EXTENSION files")
129             exitProcess(1)
130         }
131     }
132 
133     /**
134      * Recursively search for files in a directory matching an extension and add to files.
135      */
findFilesnull136     private fun findFiles(dir: File, files: MutableList<File>, ext: String, excludedPaths: List<Path>) {
137         if (!dir.isDirectory || !dir.canRead()) {
138             System.err.println("Invalid directory: ${dir.path}, aborting")
139             exitProcess(1)
140         }
141         dir.listFiles()
142                 .filterNot { excludedPaths.contains(it.toPath().toAbsolutePath()) }
143                 .forEach { fp ->
144                     if (fp.isDirectory) {
145                         findFiles(fp, files, ext, excludedPaths)
146                     } else if (fp.absolutePath.toLowerCase().endsWith(ext)) {
147                         files.add(fp)
148                     }
149                 }
150     }
151 
toPathnull152     private fun toPath(string: String): Path {
153         //replace shell expansion for HOME
154         return Paths.get(string.replaceFirst("~", System.getProperty("user.home")))
155     }
156 }