diff --git a/android/module.go b/android/module.go index 196b095dd..126d629ab 100644 --- a/android/module.go +++ b/android/module.go @@ -2812,30 +2812,57 @@ func (m *moduleContext) blueprintModuleContext() blueprint.ModuleContext { return m.bp } -// SrcIsModule decodes module references in the format ":name" into the module name, or empty string if the input -// was not a module reference. +// SrcIsModule decodes module references in the format ":unqualified-name" or "//namespace:name" +// into the module name, or empty string if the input was not a module reference. func SrcIsModule(s string) (module string) { - if len(s) > 1 && s[0] == ':' { - return s[1:] + if len(s) > 1 { + if s[0] == ':' { + module = s[1:] + if !isUnqualifiedModuleName(module) { + // The module name should be unqualified but is not so do not treat it as a module. + module = "" + } + } else if s[0] == '/' && s[1] == '/' { + module = s + } } - return "" + return module } -// SrcIsModule decodes module references in the format ":name{.tag}" into the module name and tag, ":name" into the -// module name and an empty string for the tag, or empty strings if the input was not a module reference. +// SrcIsModule decodes module references in the format ":unqualified-name{.tag}" or +// "//namespace:name{.tag}" into the module name and an empty string for the tag, or empty strings +// if the input was not a module reference. func SrcIsModuleWithTag(s string) (module, tag string) { - if len(s) > 1 && s[0] == ':' { - module = s[1:] - if tagStart := strings.IndexByte(module, '{'); tagStart > 0 { - if module[len(module)-1] == '}' { - tag = module[tagStart+1 : len(module)-1] - module = module[:tagStart] - return module, tag + if len(s) > 1 { + if s[0] == ':' { + module = s[1:] + } else if s[0] == '/' && s[1] == '/' { + module = s + } + + if module != "" { + if tagStart := strings.IndexByte(module, '{'); tagStart > 0 { + if module[len(module)-1] == '}' { + tag = module[tagStart+1 : len(module)-1] + module = module[:tagStart] + } + } + + if s[0] == ':' && !isUnqualifiedModuleName(module) { + // The module name should be unqualified but is not so do not treat it as a module. + module = "" + tag = "" } } - return module, "" } - return "", "" + + return module, tag +} + +// isUnqualifiedModuleName makes sure that the supplied module is an unqualified module name, i.e. +// does not contain any /. +func isUnqualifiedModuleName(module string) bool { + return strings.IndexByte(module, '/') == -1 } type sourceOrOutputDependencyTag struct { diff --git a/android/module_test.go b/android/module_test.go index 9ac929179..9e2b0ca29 100644 --- a/android/module_test.go +++ b/android/module_test.go @@ -55,6 +55,27 @@ func TestSrcIsModule(t *testing.T) { }, wantModule: "foo:bar", }, + { + name: "fully qualified", + args: args{ + s: "//foo:bar", + }, + wantModule: "//foo:bar", + }, + { + name: "fully qualified with tag", + args: args{ + s: "//foo:bar{.tag}", + }, + wantModule: "//foo:bar{.tag}", + }, + { + name: "invalid unqualified name", + args: args{ + s: ":foo/bar", + }, + wantModule: "", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -128,6 +149,35 @@ func TestSrcIsModuleWithTag(t *testing.T) { }, wantModule: "foo.bar}", }, + { + name: "fully qualified", + args: args{ + s: "//foo:bar", + }, + wantModule: "//foo:bar", + }, + { + name: "fully qualified with tag", + args: args{ + s: "//foo:bar{.tag}", + }, + wantModule: "//foo:bar", + wantTag: ".tag", + }, + { + name: "invalid unqualified name", + args: args{ + s: ":foo/bar", + }, + wantModule: "", + }, + { + name: "invalid unqualified name with tag", + args: args{ + s: ":foo/bar{.tag}", + }, + wantModule: "", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/android/paths_test.go b/android/paths_test.go index 4c18cfda0..7675905fc 100644 --- a/android/paths_test.go +++ b/android/paths_test.go @@ -1351,7 +1351,6 @@ func TestPathForModuleSrc(t *testing.T) { { // This test makes sure that an unqualified module name cannot contain characters that make // it appear as a qualified module name. - // TODO(b/193228441): Fix broken test. name: "output file provider, invalid fully qualified name", bp: ` test { @@ -1372,13 +1371,12 @@ func TestPathForModuleSrc(t *testing.T) { outs: ["gen/c"], } `), - errorHandler: FixtureExpectsAllErrorsToMatchAPattern([]string{ - `"foo": missing dependencies: //other:b, is the property annotated with android:"path"`, - `"foo": missing dependency on "//other:c", is the property annotated with android:"path"`, - }), + src: "foo/:/other:b", + rel: ":/other:b", + srcs: []string{"foo/:/other:c"}, + rels: []string{":/other:c"}, }, { - // TODO(b/193228441): Fix broken test. name: "output file provider, missing fully qualified name", bp: ` test { @@ -1386,13 +1384,9 @@ func TestPathForModuleSrc(t *testing.T) { src: "//other:b", srcs: ["//other:c"], }`, - src: "foo", - rel: "foo", - srcs: []string{"foo"}, - rels: []string{"foo"}, errorHandler: FixtureExpectsAllErrorsToMatchAPattern([]string{ - `"foo": Path is outside directory: /other:b`, - `"foo": Path is outside directory: /other:c`, + `"foo" depends on undefined module "//other:b"`, + `"foo" depends on undefined module "//other:c"`, }), }, { @@ -1417,13 +1411,9 @@ func TestPathForModuleSrc(t *testing.T) { outs: ["gen/c"], } `), - src: "foo", - rel: "foo", - srcs: []string{"foo"}, - rels: []string{"foo"}, errorHandler: FixtureExpectsAllErrorsToMatchAPattern([]string{ - `"foo": Path is outside directory: /other:b`, - `"foo": Path is outside directory: /other:c`, + `"foo": missing dependencies: //other:b, is the property annotated with android:"path"`, + `"foo": missing dependency on "//other:c", is the property annotated with android:"path"`, }), }, }