Skip to content

Commit 8c612ba

Browse files
thomas-serre-sonarsourceclaude
authored andcommitted
SONARPY-5043 Type adjacent bytes literals like a single bytes literal
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> GitOrigin-RevId: e85ecdf971ccf8dc1b56265eb183b0c44676eaad
1 parent b26b4e8 commit 8c612ba

3 files changed

Lines changed: 13 additions & 2 deletions

File tree

‎python-checks/src/test/resources/checks/incompatibleOperands/arithmetic.py‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,3 +257,12 @@ def __dir__(self) -> tuple:
257257

258258
def custom_directory_operations():
259259
CustomDirectory().__dir__() + ("extra",)
260+
261+
262+
263+
264+
def adjacent_bytes_literals():
265+
# Implicitly concatenated bytes literals form a single bytes literal
266+
bytearray(b"prefix") + b"GET / HTTP/1.1\r\n" b"Host: example.com\r\n"
267+
bytearray(b"prefix") + b"\x00\x01" rb"\x02"
268+
bytearray(b"prefix") + "GET" "/" # Noncompliant

‎python-frontend/src/main/java/org/sonar/python/tree/StringLiteralImpl.java‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ public String trimmedQuotesValue() {
7070
// https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals
7171
@Override
7272
public InferredType type() {
73-
if ((stringElements.size() == 1 && BYTES_PREFIXES.contains(stringElements.get(0).prefix())) ||
74-
stringElements.stream().anyMatch(StringElement::isTemplate)) {
73+
// Adjacent bytes literals (e.g. b"a" b"b") are concatenated into a single bytes literal
74+
if (isBytes() || isTemplate()) {
7575
// Python 3: bytes, Python 2: str
7676
return InferredTypes.anyType();
7777
}

‎python-frontend/src/test/java/org/sonar/python/types/TypeInferenceTest.java‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,8 @@ void string_literals() {
430430

431431
assertThat(lastExpression("b'hello'").type()).isEqualTo(anyType());
432432
assertThat(lastExpression("rb'hello'").type()).isEqualTo(anyType());
433+
assertThat(lastExpression("b'hello' b'world'").type()).isEqualTo(anyType());
434+
assertThat(lastExpression("b'hello' Rb'world'").type()).isEqualTo(anyType());
433435

434436
// this throws a 'SyntaxError: cannot mix bytes and nonbytes literals'
435437
assertThat(lastExpression("b'hello' 'world'").type()).isEqualTo(STR);

0 commit comments

Comments
 (0)