Skip to content

Commit 5009808

Browse files
committed
Support string constants for embedded languages
1 parent f0524b4 commit 5009808

File tree

3 files changed

+173
-2
lines changed

3 files changed

+173
-2
lines changed

headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/embedded/lang/EmbeddedLangAstUtils.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2024 Broadcom, Inc.
2+
* Copyright (c) 2024, 2025 Broadcom, Inc.
33
* All rights reserved. This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License v1.0
55
* which accompanies this distribution, and is available at
@@ -14,7 +14,10 @@
1414
import java.util.List;
1515

1616
import org.eclipse.jdt.core.dom.Expression;
17+
import org.eclipse.jdt.core.dom.FieldAccess;
1718
import org.eclipse.jdt.core.dom.InfixExpression;
19+
import org.eclipse.jdt.core.dom.QualifiedName;
20+
import org.eclipse.jdt.core.dom.SimpleName;
1821
import org.eclipse.jdt.core.dom.StringLiteral;
1922
import org.eclipse.jdt.core.dom.TextBlock;
2023

@@ -50,6 +53,15 @@ public static EmbeddedLanguageSnippet extractEmbeddedExpression(Expression value
5053
}
5154
}
5255
return new CompositeEmbeddedLanguageSnippet(snippets);
56+
} else if (valueExp instanceof SimpleName se) {
57+
Object o = se.resolveConstantExpressionValue();
58+
if (o instanceof String v) {
59+
return new StringConstantLanguageSnippet(valueExp.getStartPosition(), v);
60+
}
61+
} else if (valueExp instanceof FieldAccess fa) {
62+
return extractEmbeddedExpression(fa.getName());
63+
} else if (valueExp instanceof QualifiedName qn) {
64+
return extractEmbeddedExpression(qn.getName());
5365
}
5466
return null;
5567
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 Broadcom, Inc.
3+
* All rights reserved. This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License v1.0
5+
* which accompanies this distribution, and is available at
6+
* https://www.eclipse.org/legal/epl-v10.html
7+
*
8+
* Contributors:
9+
* Broadcom, Inc. - initial API and implementation
10+
*******************************************************************************/
11+
package org.springframework.ide.vscode.boot.java.embedded.lang;
12+
13+
import java.util.Collections;
14+
import java.util.List;
15+
16+
import org.springframework.ide.vscode.commons.util.text.IRegion;
17+
18+
public class StringConstantLanguageSnippet implements EmbeddedLanguageSnippet {
19+
20+
final private int offset;
21+
final private String value;
22+
23+
public StringConstantLanguageSnippet(int offset, String value) {
24+
this.offset = offset;
25+
this.value = value;
26+
}
27+
28+
@Override
29+
public List<IRegion> toJavaRanges(IRegion range) {
30+
return Collections.emptyList();
31+
}
32+
33+
@Override
34+
public int toJavaOffset(int offset) {
35+
return this.offset;
36+
}
37+
38+
@Override
39+
public String getText() {
40+
return value;
41+
}
42+
43+
}

headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/JdtDataQuerySemanticTokensProviderTest.java

Lines changed: 117 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2024 Broadcom, Inc.
2+
* Copyright (c) 2024, 2025 Broadcom, Inc.
33
* All rights reserved. This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License v1.0
55
* which accompanies this distribution, and is available at
@@ -536,5 +536,121 @@ public interface OwnerRepository {
536536

537537
}
538538

539+
@Test
540+
void ConcatenatedStringWithConstantQuery() throws Exception {
541+
String source = """
542+
package my.package
543+
544+
import org.springframework.data.jpa.repository.Query;
545+
546+
public interface OwnerRepository {
547+
548+
static final String Q = " test FROM Te";
549+
550+
@Query(value = "SELECT" +
551+
" DIS" +
552+
"TINCT" +
553+
Q +
554+
"st", nativeQuery = true)
555+
void findByLastName();
556+
}
557+
""";
558+
559+
String uri = Paths.get(jp.getLocationUri()).resolve("src/main/resource/my/package/OwnerRepository.java").toUri()
560+
.toASCIIString();
561+
CompilationUnit cu = CompilationUnitCache.parse2(source.toCharArray(), uri, "OwnerRepository.java", jp);
539562

563+
assertThat(cu).isNotNull();
564+
565+
List<SemanticTokenData> tokens = computeTokens(cu);
566+
567+
SemanticTokenData token = tokens.get(0);
568+
assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("SELECT");
569+
assertThat(token).isEqualTo(new SemanticTokenData(171, 177, "keyword", new String[0]));
570+
571+
token = tokens.get(1);
572+
assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("DIS");
573+
assertThat(token).isEqualTo(new SemanticTokenData(185, 188, "keyword", new String[0]));
574+
575+
token = tokens.get(2);
576+
assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("TINCT");
577+
assertThat(token).isEqualTo(new SemanticTokenData(195, 200, "keyword", new String[0]));
578+
579+
// token = tokens.get(3);
580+
// assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("test");
581+
// assertThat(token).isEqualTo(new SemanticTokenData(165, 169, "variable", new String[0]));
582+
//
583+
// token = tokens.get(4);
584+
// assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("FROM");
585+
// assertThat(token).isEqualTo(new SemanticTokenData(170, 174, "keyword", new String[0]));
586+
//
587+
// token = tokens.get(5);
588+
// assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("Te");
589+
// assertThat(token).isEqualTo(new SemanticTokenData(175, 177, "variable", new String[0]));
590+
591+
token = tokens.get(3);
592+
assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("st");
593+
assertThat(token).isEqualTo(new SemanticTokenData(213, 215, "variable", new String[0]));
594+
595+
}
596+
597+
@Test
598+
void ConcatenatedStringWithFieldAccessConstantQuery() throws Exception {
599+
String source = """
600+
package my.package
601+
602+
import org.springframework.data.jpa.repository.Query;
603+
604+
public interface OwnerRepository {
605+
606+
static class P {
607+
static final String Q = " test FROM Te";
608+
}
609+
610+
@Query(value = "SELECT" +
611+
" DIS" +
612+
"TINCT" +
613+
P.Q +
614+
"st", nativeQuery = true)
615+
void findByLastName();
616+
}
617+
""";
618+
619+
String uri = Paths.get(jp.getLocationUri()).resolve("src/main/resource/my/package/OwnerRepository.java").toUri()
620+
.toASCIIString();
621+
CompilationUnit cu = CompilationUnitCache.parse2(source.toCharArray(), uri, "OwnerRepository.java", jp);
622+
623+
assertThat(cu).isNotNull();
624+
625+
List<SemanticTokenData> tokens = computeTokens(cu);
626+
627+
SemanticTokenData token = tokens.get(0);
628+
assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("SELECT");
629+
assertThat(token).isEqualTo(new SemanticTokenData(194, 200, "keyword", new String[0]));
630+
631+
token = tokens.get(1);
632+
assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("DIS");
633+
assertThat(token).isEqualTo(new SemanticTokenData(208, 211, "keyword", new String[0]));
634+
635+
token = tokens.get(2);
636+
assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("TINCT");
637+
assertThat(token).isEqualTo(new SemanticTokenData(218, 223, "keyword", new String[0]));
638+
639+
// token = tokens.get(3);
640+
// assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("test");
641+
// assertThat(token).isEqualTo(new SemanticTokenData(165, 169, "variable", new String[0]));
642+
//
643+
// token = tokens.get(4);
644+
// assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("FROM");
645+
// assertThat(token).isEqualTo(new SemanticTokenData(170, 174, "keyword", new String[0]));
646+
//
647+
// token = tokens.get(5);
648+
// assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("Te");
649+
// assertThat(token).isEqualTo(new SemanticTokenData(175, 177, "variable", new String[0]));
650+
651+
token = tokens.get(3);
652+
assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("st");
653+
assertThat(token).isEqualTo(new SemanticTokenData(238, 240, "variable", new String[0]));
654+
655+
}
540656
}

0 commit comments

Comments
 (0)