go.tools/go/loader: simplify command-line syntax.

Previously, each word could be a package import path or a
comma-separated list of *.go file names.  Now, if the
first word ends with ".go", all words are assumed to be
Go source files.  This makes it impossible to specify
two ad-hoc packages from source files, but no-one needs that.

FromArgs also takes a boolean indicating whether tests
are wanted or not.

Also: ssadump: add -test flag to set that boolean.
For the oracle it's always true.

LGTM=gri
R=gri
CC=golang-codereviews
https://golang.org/cl/61470047
diff --git a/go/loader/importer_test.go b/go/loader/importer_test.go
index be6a470..54aec5b 100644
--- a/go/loader/importer_test.go
+++ b/go/loader/importer_test.go
@@ -14,7 +14,7 @@
 
 func loadFromArgs(args []string) (prog *loader.Program, rest []string, err error) {
 	conf := &loader.Config{}
-	rest, err = conf.FromArgs(args)
+	rest, err = conf.FromArgs(args, true)
 	if err == nil {
 		prog, err = conf.Load()
 	}
@@ -39,11 +39,10 @@
 	}
 
 	// Successful load.
-	args = []string{"fmt", "errors", "testdata/a.go,testdata/b.go", "--", "surplus"}
+	args = []string{"fmt", "errors", "--", "surplus"}
 	prog, rest, err := loadFromArgs(args)
 	if err != nil {
-		t.Errorf("loadFromArgs(%q) failed: %s", args, err)
-		return
+		t.Fatalf("loadFromArgs(%q) failed: %s", args, err)
 	}
 	if got, want := fmt.Sprint(rest), "[surplus]"; got != want {
 		t.Errorf("loadFromArgs(%q) rest: got %s, want %s", args, got, want)
@@ -54,7 +53,7 @@
 		pkgnames = append(pkgnames, info.Pkg.Path())
 	}
 	// Only the first import path (currently) contributes tests.
-	if got, want := fmt.Sprint(pkgnames), "[fmt_test P]"; got != want {
+	if got, want := fmt.Sprint(pkgnames), "[fmt_test]"; got != want {
 		t.Errorf("Created: got %s, want %s", got, want)
 	}
 
@@ -82,3 +81,25 @@
 		}
 	}
 }
+
+func TestLoadFromArgsSource(t *testing.T) {
+	// mixture of *.go/non-go.
+	args := []string{"testdata/a.go", "fmt"}
+	prog, _, err := loadFromArgs(args)
+	if err == nil {
+		t.Errorf("loadFromArgs(%q) succeeded, want failure", args)
+	} else {
+		// "named files must be .go files: fmt": ok
+	}
+
+	// successful load
+	args = []string{"testdata/a.go", "testdata/b.go"}
+	prog, _, err = loadFromArgs(args)
+	if err != nil {
+		t.Errorf("loadFromArgs(%q) failed: %s", args, err)
+		return
+	}
+	if len(prog.Created) != 1 || prog.Created[0].Pkg.Path() != "P" {
+		t.Errorf("loadFromArgs(%q): got %v, want [P]", prog.Created)
+	}
+}
diff --git a/go/loader/loader.go b/go/loader/loader.go
index 06c2603..3fcd7f8 100644
--- a/go/loader/loader.go
+++ b/go/loader/loader.go
@@ -23,7 +23,7 @@
 //      // Use the command-line arguments to specify
 //      // a set of initial packages to load from source.
 //      // See FromArgsUsage for help.
-//      rest, err := conf.FromArgs(os.Args[1:])
+//      rest, err := conf.FromArgs(os.Args[1:], wantTests)
 //
 //      // Parse the specified files and create an ad-hoc package with path "foo".
 //      // All files must have the same 'package' declaration.
@@ -228,15 +228,14 @@
 // FromArgs may wish to include in their -help output.
 const FromArgsUsage = `
 <args> is a list of arguments denoting a set of initial packages.
-Each argument may take one of two forms:
+It may take one of two forms:
 
-1. A comma-separated list of *.go source files.
+1. A list of *.go source files.
 
    All of the specified files are loaded, parsed and type-checked
-   as a single package.
-   All the files must belong to the same directory.
+   as a single package.  All the files must belong to the same directory.
 
-2. An import path.
+2. A list of import paths, each denoting a package.
 
    The package's directory is found relative to the $GOROOT and
    $GOPATH using similar logic to 'go build', and the *.go files in
@@ -248,9 +247,8 @@
    the non-*_test.go files are included in the primary package.  Test
    files whose package declaration ends with "_test" are type-checked
    as another package, the 'external' test package, so that a single
-   import path may denote two packages.  This behaviour may be
-   disabled by prefixing the import path with "notest:",
-   e.g. "notest:fmt".
+   import path may denote two packages.  (Whether this behaviour is
+   enabled is tool-specific, and may depend on additional flags.)
 
    Due to current limitations in the type-checker, only the first
    import path of the command line will contribute any tests.
@@ -266,33 +264,40 @@
 // set of initial packages to be specified; see FromArgsUsage message
 // for details.
 //
-func (conf *Config) FromArgs(args []string) (rest []string, err error) {
-	for len(args) > 0 {
-		arg := args[0]
-		args = args[1:]
+func (conf *Config) FromArgs(args []string, xtest bool) (rest []string, err error) {
+	for i, arg := range args {
 		if arg == "--" {
+			rest = args[i+1:]
+			args = args[:i]
 			break // consume "--" and return the remaining args
 		}
+	}
 
-		if strings.HasSuffix(arg, ".go") {
-			// Assume arg is a comma-separated list of *.go files
-			// denoting a single ad-hoc package.
-			err = conf.CreateFromFilenames("", strings.Split(arg, ",")...)
-		} else {
-			// Assume arg is a directory name denoting a
-			// package, perhaps plus an external test
-			// package unless prefixed by "notest:".
-			if path := strings.TrimPrefix(arg, "notest:"); path != arg {
-				conf.Import(path)
-			} else {
-				err = conf.ImportWithTests(path)
+	if len(args) > 0 && strings.HasSuffix(args[0], ".go") {
+		// Assume args is a list of a *.go files
+		// denoting a single ad-hoc package.
+		for _, arg := range args {
+			if !strings.HasSuffix(arg, ".go") {
+				return nil, fmt.Errorf("named files must be .go files: %s", arg)
 			}
 		}
-		if err != nil {
-			return nil, err
+		err = conf.CreateFromFilenames("", args...)
+	} else {
+		// Assume args are directories each denoting a
+		// package and (perhaps) an external test, iff xtest.
+		for _, arg := range args {
+			if xtest {
+				err = conf.ImportWithTests(arg)
+				if err != nil {
+					break
+				}
+			} else {
+				conf.Import(arg)
+			}
 		}
 	}
-	return args, nil
+
+	return
 }
 
 // CreateFromFilenames is a convenience function that parses the
@@ -371,7 +376,8 @@
 	if conf.ImportPkgs == nil {
 		conf.ImportPkgs = make(map[string]bool)
 	}
-	conf.ImportPkgs[path] = false // unaugmented source package
+	// Subtle: adds value 'false' unless value is already true.
+	conf.ImportPkgs[path] = conf.ImportPkgs[path] // unaugmented source package
 }
 
 // PathEnclosingInterval returns the PackageInfo and ast.Node that
diff --git a/go/ssa/stdlib_test.go b/go/ssa/stdlib_test.go
index e3ae81c..b09be7e 100644
--- a/go/ssa/stdlib_test.go
+++ b/go/ssa/stdlib_test.go
@@ -53,7 +53,7 @@
 	t0 := time.Now()
 
 	var conf loader.Config
-	if _, err := conf.FromArgs(allPackages()); err != nil {
+	if _, err := conf.FromArgs(allPackages(), true); err != nil {
 		t.Errorf("FromArgs failed: %v", err)
 		return
 	}