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 }