Skip to content

Commit

Permalink
Allow unquoted canonical repository names with query
Browse files Browse the repository at this point in the history
  • Loading branch information
fmeum committed Sep 11, 2024
1 parent 1e481ab commit cf90523
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 5 deletions.
4 changes: 3 additions & 1 deletion site/en/query/language.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,9 @@ tokens:
hyphen, underscore, colon, dollar sign, tilde, left square brace, right square
brace). However, unquoted words may not start with a hyphen `-` or asterisk `*`
even though relative [target names](/concepts/labels#target-names) may start
with those characters.
with those characters. As a special rule meant to simplify the handling of
labels referring to external repositories, unquoted words that start with
`@@` may contain `+` characters.

Unquoted words also may not include the characters plus sign `+` or equals
sign `=`, even though those characters are permitted in target names. When
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,10 @@ private TokenKind getTokenKindForWord(String word) {
return kind == null ? TokenKind.WORD : kind;
}

private String scanWord() {
private String scanWord(char firstChar) {
int oldPos = pos - 1;
boolean startsWithDoubleAt =
firstChar == '@' && pos < input.length() && input.charAt(pos) == '@';
while (pos < input.length()) {
switch (input.charAt(pos)) {
case 'a',
Expand Down Expand Up @@ -245,6 +247,17 @@ private String scanWord() {
'[',
']' ->
pos++;
case '+' -> {
if (startsWithDoubleAt) {
// Allow unquoted canonical labels such as
// @@rules_jvm_external++maven+maven//:bar, but still parse @foo+@bar as two separate
// labels (here @foo refers to the @foo//:foo target).
// If @@foo+bar is intended to mean @@foo + bar, it can be written as such with spaces.
pos++;
} else {
return bufferSlice(oldPos, pos);
}
}
default -> {
return bufferSlice(oldPos, pos);
}
Expand All @@ -261,8 +274,8 @@ private String scanWord() {
*
* @return the word or keyword token.
*/
private Token wordOrKeyword() {
String word = scanWord();
private Token wordOrKeyword(char firstChar) {
String word = scanWord(firstChar);
TokenKind kind = getTokenKindForWord(word);
return kind == TokenKind.WORD ? new Token(word) : new Token(kind);
}
Expand All @@ -284,7 +297,7 @@ private void tokenize() throws QuerySyntaxException {
/* ignore */
}
case '\'', '\"' -> addToken(quotedWord(c));
default -> addToken(wordOrKeyword());
default -> addToken(wordOrKeyword(c));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,4 +141,27 @@ public void testOperatorWithUnquotedExprWithSpecialCharacters() throws QuerySynt
assertThat(tokens[6].kind).isEqualTo(Lexer.TokenKind.WORD);
assertThat(tokens[7].kind).isEqualTo(Lexer.TokenKind.RPAREN);
}

@Test
public void testUnquotedCanonicalLabels() throws QuerySyntaxException {
Lexer.Token[] tokens =
scan("somepath(@foo+@bar+//baz+@@foo +bar, @@rules_jvm_external++maven+maven//:bar)");
assertThat(asString(tokens))
.isEqualTo(
"somepath ( @foo + @bar + //baz + @@foo + bar , @@rules_jvm_external++maven+maven//:bar ) EOF");
assertThat(tokens[0].kind).isEqualTo(Lexer.TokenKind.WORD);
assertThat(tokens[1].kind).isEqualTo(Lexer.TokenKind.LPAREN);
assertThat(tokens[2].kind).isEqualTo(Lexer.TokenKind.WORD);
assertThat(tokens[3].kind).isEqualTo(Lexer.TokenKind.PLUS);
assertThat(tokens[4].kind).isEqualTo(Lexer.TokenKind.WORD);
assertThat(tokens[5].kind).isEqualTo(Lexer.TokenKind.PLUS);
assertThat(tokens[6].kind).isEqualTo(Lexer.TokenKind.WORD);
assertThat(tokens[7].kind).isEqualTo(Lexer.TokenKind.PLUS);
assertThat(tokens[8].kind).isEqualTo(Lexer.TokenKind.WORD);
assertThat(tokens[9].kind).isEqualTo(Lexer.TokenKind.PLUS);
assertThat(tokens[10].kind).isEqualTo(Lexer.TokenKind.WORD);
assertThat(tokens[11].kind).isEqualTo(Lexer.TokenKind.COMMA);
assertThat(tokens[12].kind).isEqualTo(Lexer.TokenKind.WORD);
assertThat(tokens[13].kind).isEqualTo(Lexer.TokenKind.RPAREN);
}
}

0 comments on commit cf90523

Please sign in to comment.