
org.scalatest.tools.ArgsParser.scala Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2001-2015 Artima, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.scalatest.tools
import java.io.File
import java.net.URL
import java.util.regex.Pattern
import org.scalactic.Requirements._
import org.scalactic.exceptions.NullArgumentException
import org.scalatest.{ConfigMap, Resources}
import scala.collection.mutable.ListBuffer
private[tools] object ArgsParser {
// Returns an Option[String]. Some is an error message. None means no error.
private[scalatest] def checkArgsForValidity(args: Array[String]) = {
if (args == null)
throw new IllegalArgumentException("args was null.")
val lb = new ListBuffer[String]
val it = args.iterator.buffered
while (it.hasNext) {
val s = it.next
if (s.startsWith("-r"))
throw new IllegalArgumentException(
"ERROR: -r has been deprecated for a very long time and is no "+
"longer supported, to prepare for reusing it for a different "+
"purpose in the near future. Please change all uses of -r to -C.")
else if (s.startsWith("-c"))
throw new IllegalArgumentException(
"ERROR: -c has been deprecated for a very long time and is no "+
"longer supported, to prepare for reusing it for a different "+
"purpose in the near future. Please change all uses of -c to -P.")
else if (s.startsWith("-p"))
throw new IllegalArgumentException(
"ERROR: -p has been deprecated for a very long time and is no "+
"longer supported, to prepare for reusing it for a different "+
"purpose in the near future. Please change all uses of -p to -R.")
else if (
s.startsWith("-R") ||
s.startsWith("-f") ||
s.startsWith("-M") ||
s.startsWith("-A") ||
s.startsWith("-u") ||
//s.startsWith("-d") ||
//s.startsWith("-a") ||
s.startsWith("-C") ||
s.startsWith("-n") ||
/* s.startsWith("-x") || */
s.startsWith("-l") ||
s.startsWith("-s") ||
s.startsWith("-S") ||
s.startsWith("-i") ||
s.startsWith("-j") ||
s.startsWith("-m") ||
s.startsWith("-w") ||
s.startsWith("-b") ||
s.startsWith("-y") ||
s.startsWith("-t") ||
s.startsWith("-z") ||
s.startsWith("-q") ||
s.startsWith("-Q") ||
s.startsWith("-F") ||
s.startsWith("-T")
) {
if (it.hasNext)
it.next
}
else if (s.startsWith("-k") || s.startsWith("-K") || s.startsWith("-W")) {
if (it.hasNext)
it.next
if (it.hasNext)
it.next
}
else if (s.startsWith("-h")) {
if (it.hasNext)
it.next
if (it.hasNext && it.head == "-Y") {
it.next
it.next
}
}
else if (!s.startsWith("-D") && !s.startsWith("-g") && !s.startsWith("-o") && !s.startsWith("-e") && !s.startsWith("-P")) {
lb += s
}
}
val argsList = lb.toList
if (argsList.length != 0) {
val argWord = "Argument" + (if (argsList.size == 1) "" else "s")
Some(argWord + " unrecognized by ScalaTest's Runner: " + argsList.mkString("", ", ", "."))
}
else
None
}
//
// Generates a Pattern based on suffixes passed in by user. Pattern
// matches class names that end with one of the specified suffixes.
//
def genSuffixesPattern(suffixesList: List[String]): Option[Pattern] = {
if (suffixesList.isEmpty)
None
else
Some(Pattern.compile(".*(" + suffixesList.mkString("|") + ")$"))
}
private[scalatest] def parseArgs(args: Array[String]): ParsedArgs = {
val reporters = new ListBuffer[String]()
val suites = new ListBuffer[String]()
val includes = new ListBuffer[String]()
val excludes = new ListBuffer[String]()
val membersOnly = new ListBuffer[String]()
val wildcard = new ListBuffer[String]()
val suffixes = new ListBuffer[String]()
val seeds = ListBuffer[String]()
val it = args.iterator.buffered
while (it.hasNext) {
val s = it.next
if (s.startsWith("-D")) {
throw new IllegalArgumentException("Argument not supported by ScalaTest-js: " + s)
}
else if (s.startsWith("-R")) {
throw new IllegalArgumentException("Argument not supported by ScalaTest-js: " + s)
}
else if (s.startsWith("-g")) {
throw new IllegalArgumentException("Argument not supported by ScalaTest-js: " + s)
}
else if (s.startsWith("-o")) {
reporters += s
}
else if (s.startsWith("-e")) {
throw new IllegalArgumentException("Argument not supported by ScalaTest-js: " + s)
}
else if (s.startsWith("-f")) {
throw new IllegalArgumentException("Argument not supported by ScalaTest-js: " + s)
}
else if (s == "-M") {
throw new IllegalArgumentException("Argument not supported by ScalaTest-js: " + s)
}
else if (s == "-u") {
throw new IllegalArgumentException("Argument not supported by ScalaTest-js: " + s)
}
/*else if (s.startsWith("-d")) {
reporters += s
if (it.hasNext)
reporters += it.next
}
else if (s.startsWith("-a")) {
reporters += s
if (it.hasNext)
reporters += it.next
}
else if (s.startsWith("-x")) {
reporters += s
if (it.hasNext)
reporters += it.next
}*/
else if (s.startsWith("-h")) {
throw new IllegalArgumentException("Argument not supported by ScalaTest-js: " + s)
}
else if (s == "-n") {
includes += s
if (it.hasNext)
includes += it.next
}
else if (s == "-l") {
excludes += s
if (it.hasNext)
excludes += it.next
}
else if (s.startsWith("-C")) {
throw new IllegalArgumentException("Argument not supported by ScalaTest-js: " + s)
}
else if (s == "-s") {
suites += s
if (it.hasNext)
suites += it.next
}
else if (s == "-A") {
throw new IllegalArgumentException("Argument not supported by ScalaTest-js: " + s)
}
else if (s == "-i") {
suites += s
if (it.hasNext)
suites += it.next
}
else if (s == "-t") {
suites += s
if (it.hasNext)
suites += it.next
}
else if (s == "-z") {
suites += s
if (it.hasNext)
suites += it.next
}
else if (s == "-j") {
throw new IllegalArgumentException("Argument not supported by ScalaTest-js: " + s)
}
else if (s == "-m") {
membersOnly += s
if (it.hasNext)
membersOnly += it.next
}
else if (s == "-w") {
wildcard += s
if (it.hasNext)
wildcard += it.next
}
else if (s.startsWith("-P")) {
throw new IllegalArgumentException("Argument not supported by ScalaTest-js: " + s)
}
else if (s == "-b") {
throw new IllegalArgumentException("Argument not supported by ScalaTest-js: " + s)
}
else if (s == "-q") {
if (it.hasNext)
suffixes += it.next()
}
else if (s == "-Q") {
suffixes += "Spec|Suite"
}
else if (s == "-k") {
throw new IllegalArgumentException("Argument not supported by ScalaTest-js: " + s)
}
else if (s == "-K") {
throw new IllegalArgumentException("Argument not supported by ScalaTest-js: " + s)
}
else if (s == "-y") {
throw new IllegalArgumentException("Argument not supported by ScalaTest-js: " + s)
}
else if (s == "-F") {
throw new IllegalArgumentException("Argument not supported by ScalaTest-js: " + s)
}
else if (s == "-S") {
seeds += s
if (it.hasNext)
seeds += it.next()
}
else if (s == "-T") {
throw new IllegalArgumentException("Argument not supported by ScalaTest-js: " + s)
}
else if (s == "-W") {
throw new IllegalArgumentException("Argument not supported by ScalaTest-js: " + s)
}
else {
throw new IllegalArgumentException("Argument unrecognized by ScalaTest's Runner: " + s)
}
}
ParsedArgs(
reporters.toList,
suites.toList,
includes.toList,
excludes.toList,
membersOnly.toList,
wildcard.toList,
seeds.toList
)
}
// Used to parse -j, -m, and -w args, one of which will be passed as a String as dashArg
def parseSuiteArgsIntoNameStrings(args: List[String], dashArg: String) = {
requireNonNull(args)
if (args.exists(_ == null))
throw new NullArgumentException("an arg String was null")
if (dashArg != "-j" && dashArg != "-w" && dashArg != "-m" && dashArg != "-b")
throw new IllegalArgumentException("dashArg invalid: " + dashArg)
/*
<<<<<<< .working TODOCS: Is the above the correct way to merge these?
if (dashArg != "-j" && dashArg != "-w" && dashArg != "-m" && dashArg != "-b")
throw new IllegalArgumentException("dashArg invalid: " + dashArg)
=======
if (dashArg != "-j" && dashArg != "-s" && dashArg != "-w" && dashArg != "-m" && dashArg != "-b")
throw new NullPointerException("dashArg invalid: " + dashArg)
>>>>>>> .merge-right.r3653
*/
val lb = new ListBuffer[String]
val it = args.iterator
while (it.hasNext) {
val dashS = it.next
if (dashS != dashArg)
throw new IllegalArgumentException("Every other element, starting with the first, must be " + dashArg)
if (it.hasNext) {
val suiteName = it.next
if (!suiteName.startsWith("-"))
lb += suiteName
else
throw new IllegalArgumentException("Expecting a Suite class name or package name to follow " + dashArg + ", but got: " + suiteName)
}
else
throw new IllegalArgumentException("Last element must be a Suite class name or package name, not a " + dashArg + ".")
}
lb.toList
}
/**
* Returns a possibly empty ConfigSet containing configuration
* objects specified in the passed reporterArg. Configuration
* options are specified immediately following
* the reporter option, as in:
*
* -oFA
*
* If no configuration options are specified, this method returns an
* empty ConfigSet. This method never returns null.
*/
def parseConfigSet(reporterArg: String): Set[ReporterConfigParam] = {
requireNonNull(reporterArg)
if (reporterArg.length < 2)
throw new IllegalArgumentException("reporterArg < 2")
// The reporterArg passed includes the initial -, as in "-oFI",
// so the first config param will be at index 2
val configString = reporterArg.substring(2)
val it = configString.iterator
var set = Set[ReporterConfigParam]()
while (it.hasNext)
it.next match {
case 'Y' => throw new IllegalArgumentException("Use of Y was deprecated in ScalaTest 1.0 and removed in 1.5. Please check the Scaladoc documentation of org.scalatest.Runner for information on valid Reporter config parameters.")
case 'Z' => throw new IllegalArgumentException("Use of Z was deprecated in ScalaTest 1.0 and removed in 1.5. Please check the Scaladoc documentation of org.scalatest.Runner for information on valid Reporter config parameters.")
//case 'P' =>throw new IllegalArgumentException("Use of P was deprecated in ScalaTest 1.0 and removed in 1.5. Please check the Scaladoc documentation of org.scalatest.Runner for information on valid Reporter config parameters.")
case 'B' =>throw new IllegalArgumentException("Use of B was deprecated in ScalaTest 1.0 and removed in 1.5. Please check the Scaladoc documentation of org.scalatest.Runner for information on valid Reporter config parameters.")
// case 'S' => // Use for Short Stack Traces
case 'A' =>throw new IllegalArgumentException("Use of A was deprecated in ScalaTest 1.0 and removed in 1.5. Please check the Scaladoc documentation of org.scalatest.Runner for information on valid Reporter config parameters.")
//case 'R' =>throw new IllegalArgumentException("Use of R was deprecated in ScalaTest 1.0 and removed in 1.5. Please check the Scaladoc documentation of org.scalatest.Runner for information on valid Reporter config parameters.")
case 'I' => set += PresentReminderWithoutStackTraces
case 'T' => set += PresentReminderWithShortStackTraces
case 'G' => set += PresentReminderWithFullStackTraces
case 'K' => set += PresentReminderWithoutCanceledTests
case 'N' => set += FilterTestStarting
case 'C' => set += FilterTestSucceeded
case 'X' => set += FilterTestIgnored
case 'E' => set += FilterTestPending
case 'H' => set += FilterSuiteStarting
case 'L' => set += FilterSuiteCompleted
case 'O' => set += FilterInfoProvided
case 'P' => set += FilterScopeOpened
case 'Q' => set += FilterScopeClosed
case 'R' => set += FilterScopePending
case 'M' => set += FilterMarkupProvided
case 'W' => set += PresentWithoutColor
case 'F' => set += PresentFullStackTraces
case 'S' => set += PresentShortStackTraces
case 'D' => set += PresentAllDurations
case 'U' => set += PresentUnformatted
case 'V' => set += PresentFilePathname
case 'J' => set += PresentJson
case c: Char => {
// this should be moved to the checker, and just throw an exception here with a debug message. Or allow a MatchError.
val msg1 = Resources.invalidConfigOption(String.valueOf(c)) + '\n'
val msg2 = Resources.probarg(reporterArg) + '\n'
throw new IllegalArgumentException(msg1 + msg2)
}
}
set
}
//
// Determines whether specified token is complete or partial.
//
// Tokens are considered partial if they end with a backslash, since
// backslash is used to escape spaces that would otherwise be
// treated as delimiters within the path string.
//
// Exceptions are cases where the token ends in a backslash
// but is still considered a complete token because it constitutes
// a valid representation of a root directory on a windows system,
// e.g. "c:\" or just "\".
//
private val ROOT_DIR_PATTERN = Pattern.compile("""(?i)\\|[a-z]:\\""")
private def isCompleteToken(token: String): Boolean = {
val matcher = ROOT_DIR_PATTERN.matcher(token)
matcher.matches() || (token(token.length - 1) != '\\')
}
//
// Splits a space-delimited path into its component parts.
//
// Spaces within path elements may be escaped with backslashes, e.g.
// "c:\Documents\ And\ Settings c:\Program\ Files"
//
// See comments for isCompleteToken() below for exceptions.
//
private val START_TOKEN_PATTERN = Pattern.compile("""^\s*(.*?)(\s|$)""")
private val FULL_TOKEN_PATTERN = Pattern.compile("""^\s*(.+?[^\\])(\s|$)""")
private def splitPath(pathArg: String): List[String] = {
val path = pathArg.trim
if (path.isEmpty) Nil
else {
val startMatcher = START_TOKEN_PATTERN.matcher(path)
if (!startMatcher.find())
throw new RuntimeException("unexpected startMatcher path [" +
path + "]")
val token = startMatcher.group(1)
if (isCompleteToken(token)) {
token :: splitPath(path.substring(startMatcher.end))
}
else {
val fullMatcher = FULL_TOKEN_PATTERN.matcher(path)
if (!fullMatcher.find())
throw new RuntimeException("unexpected fullMatcher path [" +
path + "]")
val fullToken = fullMatcher.group(1).replaceAll("""\\(\s)""", "$1")
fullToken :: splitPath(path.substring(fullMatcher.end))
}
}
}
def parseCompoundArgIntoSet(args: List[String], expectedDashArg: String): Set[String] =
Set() ++ parseCompoundArgIntoList(args, expectedDashArg)
def parseRunpathArgIntoList(args: List[String]): List[String] = parseCompoundArgIntoList(args, "-R")
def parseCompoundArgIntoList(args: List[String], expectedDashArg: String): List[String] = {
requireNonNull(args)
if (args.exists(_ == null))
throw new NullArgumentException("an arg String was null")
if (args.length == 0) {
List()
}
else if (args.length % 2 == 0) {
def parsePair(dashArg: String, compoundArg: String) = {
if (dashArg != expectedDashArg)
throw new IllegalArgumentException("First arg must be " + expectedDashArg + ", but was: " + dashArg)
if (compoundArg.trim.isEmpty)
throw new IllegalArgumentException("The argument string must actually include some non-whitespace characters.")
splitPath(compoundArg)
}
args.grouped(2).flatMap(p => parsePair(p(0), p(1))).toList
}
else {
throw new IllegalArgumentException("Compound arg must be either zero-length or have even number of args: " + args)
}
}
def parseChosenStylesIntoChosenStyleSet(args: List[String], dashArg: String) = {
val it = args.iterator
val lb = new ListBuffer[String]()
while (it.hasNext) {
val dash = it.next
if (dash != dashArg)
throw new IllegalArgumentException("Every other element, starting with the first, must be " + dashArg)
if (it.hasNext) {
lb += it.next
}
else
throw new IllegalArgumentException("Last element must be a style name, not a " + dashArg + ".")
}
lb.toSet
}
def parseDoubleArgument(args: List[String], dashArg: String, defaultValue: Double): Double = {
val it = args.iterator
val lb = new ListBuffer[Double]()
while (it.hasNext) {
val dash = it.next
if (dash != dashArg)
throw new IllegalArgumentException("Every other element, starting with the first, must be " + dashArg)
if (it.hasNext) {
val spanString = it.next
try {
lb += spanString.toDouble
}
catch {
case e: NumberFormatException =>
throw new IllegalArgumentException(dashArg + " must be followed by a number, but '" + spanString + "' is not a number.")
}
}
else
throw new IllegalArgumentException("Last element must be a number, not a " + dashArg + ".")
}
if (lb.size == 0)
defaultValue
else if (lb.size == 1)
lb(0)
else
throw new IllegalArgumentException("Only one " + dashArg + " can be specified.")
}
def parseLongArgument(args: List[String], dashArg: String): Option[Long] = {
val it = args.iterator
val lb = new ListBuffer[Long]()
while (it.hasNext) {
val dash = it.next
if (dash != dashArg)
throw new IllegalArgumentException("Every other element, starting with the first, must be " + dashArg)
if (it.hasNext) {
val spanString = it.next
try {
lb += spanString.toLong
}
catch {
case e: NumberFormatException =>
throw new IllegalArgumentException(dashArg + " must be followed by a number, but '" + spanString + "' is not a number.")
}
}
else
throw new IllegalArgumentException("Last element must be a number, not a " + dashArg + ".")
}
if (lb.size == 0)
None
else if (lb.size == 1)
Some(lb(0))
else
throw new IllegalArgumentException("Only one " + dashArg + " can be specified.")
}
def parsePropertiesArgsIntoMap(args: List[String]): ConfigMap = {
requireNonNull(args)
if (args.exists(_ == null))
throw new NullArgumentException("an arg String was null")
if (args.exists(_.indexOf('=') == -1))
throw new IllegalArgumentException("A -D arg does not contain an equals sign.")
if (args.exists(!_.startsWith("-D")))
throw new IllegalArgumentException("A spice arg does not start with -D.")
if (args.exists(_.indexOf('=') == 2))
throw new IllegalArgumentException("A spice arg does not have a key to the left of the equals sign.")
if (args.exists(arg => arg.indexOf('=') == arg.length - 1))
throw new IllegalArgumentException("A spice arg does not have a value to the right of the equals sign.")
val tuples = for (arg <- args) yield {
val keyValue = arg.substring(2) // Cut off the -D at the beginning
val equalsPos = keyValue.indexOf('=')
val key = keyValue.substring(0, equalsPos)
val value = keyValue.substring(equalsPos + 1)
(key, value)
}
new ConfigMap(Map(tuples: _*))
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy