From 2863e4535eb65e15f955dc8ed48fa99b1d2a1db5 Mon Sep 17 00:00:00 2001 From: Anton Hansson Date: Fri, 22 Sep 2023 07:17:37 +0000 Subject: [PATCH] Make package parsing code consume annotations The code previously assumed an annotation meant there was no package declaration, but package declarations can be annotated. Update the code to consume any leading annotations. Bug: 151360309 Test: jar_test.go (& manual verification on full bootclasspath srcs) Change-Id: I3de5a2a675363fc3627a278103dd2cabe80a2d80 --- jar/jar.go | 22 ++++++++++++++++------ jar/jar_test.go | 10 ++++++++++ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/jar/jar.go b/jar/jar.go index f164ee1ee..54eded93a 100644 --- a/jar/jar.go +++ b/jar/jar.go @@ -166,10 +166,23 @@ func JavaPackage(r io.Reader, src string) (string, error) { } s.IsIdentRune = javaIdentRune - tok := s.Scan() - if sErr != nil { - return "", sErr + var tok rune + for { + tok = s.Scan() + if sErr != nil { + return "", sErr + } + // If the first token is an annotation, it could be annotating a package declaration, so consume them. + // Note that this does not support "complex" annotations with attributes, e.g. @Foo(x=y). + if tok != '@' { + break + } + tok = s.Scan() + if tok != scanner.Ident || sErr != nil { + return "", fmt.Errorf("expected annotation identifier, got @%v", tok) + } } + if tok == scanner.Ident { switch s.TokenText() { case "package": @@ -189,9 +202,6 @@ func JavaPackage(r io.Reader, src string) (string, error) { default: return "", fmt.Errorf(`expected first token of java file to be "package", got %q`, s.TokenText()) } - } else if tok == '@' { - // File has no package statement, first token is an annotation - return "", nil } else if tok == scanner.EOF { // File no package statement, it has no non-whitespace non-comment tokens return "", nil diff --git a/jar/jar_test.go b/jar/jar_test.go index c92011e12..61da9bb6f 100644 --- a/jar/jar_test.go +++ b/jar/jar_test.go @@ -61,6 +61,16 @@ func TestGetJavaPackage(t *testing.T) { in: "package 0foo.bar;", wantErr: true, }, + { + name: "annotations", + in: "@NonNullApi\n@X\npackage foo.bar;", + want: "foo.bar", + }, + { + name: "complex annotation", + in: "@Foo(x=y)\n@package foo.bar;", + wantErr: true, // Complex annotation not supported yet. + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) {