Skip to content

Commit 9a87820

Browse files
author
Alexander Chen
committed
Added diagnostic for deprecated with section and CodeAction to use let
Signed-off-by: Alexander Chen <alchen@redhat.com>
1 parent 3ff7394 commit 9a87820

File tree

7 files changed

+132
-29
lines changed

7 files changed

+132
-29
lines changed

qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/commons/CodeActionFactory.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,16 @@ public static CodeAction replace(String title, Range range, String replaceText,
106106
return replace(title, Collections.singletonList(replace), document, diagnostic);
107107
}
108108

109+
@SuppressWarnings("null")
110+
public static CodeAction replace(String title, List<Range> ranges, String replaceText, TextDocumentItem document,
111+
Diagnostic diagnostic) {
112+
List<TextEdit> edits = null;
113+
for (Range range : ranges) {
114+
edits.add(new TextEdit(range, replaceText));
115+
}
116+
return replace(title, edits, document, diagnostic);
117+
}
118+
109119
public static CodeAction replace(String title, List<TextEdit> replace, TextDocumentItem document,
110120
Diagnostic diagnostic) {
111121

qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/parser/template/sections/WithSection.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,16 @@
1818

1919
/**
2020
* With section AST node.
21-
*
21+
*
2222
* <code>
2323
{#with item.parent}
24-
<h1>{name}</h1>
25-
<p>{description}</p>
24+
<h1>{name}</h1>
25+
<p>{description}</p>
2626
{/with}
2727
* </code>
28-
*
28+
*
2929
* @author Angelo ZERR
30-
*
30+
*
3131
* @see https://quarkus.io/guides/qute-reference#with_section
3232
*
3333
*/

qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/services/QuteCodeActions.java

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050

5151
/**
5252
* Qute code actions support.
53-
*
53+
*
5454
* @author Angelo ZERR
5555
*
5656
*/
@@ -72,6 +72,8 @@ class QuteCodeActions {
7272

7373
private static final String EXCLUDED_VALIDATION_TITLE = "Exclude this file from validation.";
7474

75+
private static final String QUTE_DEPRICATED_WITH_SECTION = "Replace `with` with `let`.";
76+
7577
public CompletableFuture<List<CodeAction>> doCodeActions(Template template, CodeActionContext context, Range range,
7678
SharedSettings sharedSettings) {
7779
List<CodeAction> codeActions = new ArrayList<>();
@@ -109,6 +111,15 @@ public CompletableFuture<List<CodeAction>> doCodeActions(Template template, Code
109111
// Create `undefinedTag`"
110112
doCodeActionsForUndefinedSectionTag(template, diagnostic, codeActions);
111113
break;
114+
case DeprecatedWithSection:
115+
// The following Qute template:
116+
// {#with }
117+
//
118+
// will provide a quickfix like:
119+
//
120+
// Replace `with` with `let`.
121+
doCodeActionsForDeprecatedWithSection(template, diagnostic, codeActions);
122+
break;
112123
default:
113124
break;
114125
}
@@ -186,15 +197,41 @@ private static void doCodeActionToDisableValidation(Template template, List<Diag
186197
codeActions.add(disableValidationForTemplateQuickFix);
187198
}
188199

200+
/**
201+
* Create CodeAction for deprecated `with` Qute syntax.
202+
*
203+
* @param template the Qute template.
204+
* @param diagnostic the diagnostic list that this CodeAction will fix.
205+
* @param codeActions the list of CodeActions to perform.
206+
* @throws BadLocationException
207+
*
208+
*/
209+
private void doCodeActionsForDeprecatedWithSection(Template template, Diagnostic diagnostic,
210+
List<CodeAction> codeActions) {
211+
String title = MessageFormat.format(QUTE_DEPRICATED_WITH_SECTION, "with");
212+
Range withSectionRange = diagnostic.getRange();
213+
try {
214+
int withSectionStart = template.getTextDocument().offsetAt(withSectionRange.getStart());
215+
int withSectionEnd = template.getTextDocument().offsetAt(withSectionRange.getEnd());
216+
String replacement = template.getText(withSectionStart, withSectionEnd).replace("#with", "#let")
217+
.replace("/with", "/let");
218+
CodeAction replaceWithSection = CodeActionFactory.replace(title, diagnostic.getRange(), replacement,
219+
template.getTextDocument(), diagnostic);
220+
codeActions.add(replaceWithSection);
221+
} catch (BadLocationException e) {
222+
return;
223+
}
224+
}
225+
189226
/**
190227
* Create the configuration update (done on client side) quick fix.
191-
*
228+
*
192229
* @param title the displayed name of the QuickFix.
193230
* @param sectionName the section name of the settings to update.
194231
* @param item the section value of the settings to update.
195232
* @param editType the configuration edit type.
196233
* @param diagnostic the diagnostic list that this CodeAction will fix.
197-
*
234+
*
198235
* @return the configuration update (done on client side) quick fix.
199236
*/
200237
private static CodeAction createConfigurationUpdateCodeAction(String title, String scopeUri, String sectionName,

qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/services/QuteDiagnostics.java

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
package com.redhat.qute.services;
1313

1414
import static com.redhat.qute.services.diagnostics.DiagnosticDataFactory.createDiagnostic;
15+
import static com.redhat.qute.services.diagnostics.DiagnosticDataFactory.createDiagnosticWithTags;
1516

1617
import java.nio.file.Files;
1718
import java.nio.file.Path;
@@ -26,6 +27,7 @@
2627

2728
import org.eclipse.lsp4j.Diagnostic;
2829
import org.eclipse.lsp4j.DiagnosticSeverity;
30+
import org.eclipse.lsp4j.DiagnosticTag;
2931
import org.eclipse.lsp4j.Range;
3032
import org.eclipse.lsp4j.jsonrpc.CancelChecker;
3133

@@ -54,6 +56,7 @@
5456
import com.redhat.qute.parser.template.Template;
5557
import com.redhat.qute.parser.template.sections.IncludeSection;
5658
import com.redhat.qute.parser.template.sections.LoopSection;
59+
import com.redhat.qute.parser.template.sections.WithSection;
5760
import com.redhat.qute.project.JavaMemberResult;
5861
import com.redhat.qute.project.QuteProject;
5962
import com.redhat.qute.project.datamodel.JavaDataModelCache;
@@ -246,6 +249,9 @@ private void validateDataModel(Node parent, Template template, ResolvingJavaType
246249
case INCLUDE:
247250
validateIncludeSection((IncludeSection) section, diagnostics);
248251
break;
252+
case WITH:
253+
validateWithSection((WithSection) section, diagnostics);
254+
break;
249255
default:
250256
validateSectionTag(section, template, resolvingJavaTypeContext, diagnostics);
251257
}
@@ -345,6 +351,23 @@ private static void validateIncludeSection(IncludeSection includeSection, List<D
345351
}
346352
}
347353

354+
/**
355+
* Report that `#with` section is deprecated.
356+
*
357+
* @param withSection the with section
358+
* @param diagnostics the diagnostics to fill
359+
*/
360+
private static void validateWithSection(WithSection withSection, List<Diagnostic> diagnostics) {
361+
if (withSection != null) {
362+
List<DiagnosticTag> tags = Collections.singletonList(DiagnosticTag.Deprecated);
363+
// Range range = QutePositionUtility.selectStartTagName(withSection);
364+
Range range = QutePositionUtility.createRange(withSection);
365+
Diagnostic diagnostic = createDiagnosticWithTags(range, DiagnosticSeverity.Warning,
366+
QuteErrorCode.DeprecatedWithSection, tags);
367+
diagnostics.add(diagnostic);
368+
}
369+
}
370+
348371
private ResolvedJavaTypeInfo validateExpression(Expression expression, Section ownerSection, Template template,
349372
ResolutionContext resolutionContext, ResolvingJavaTypeContext resolvingJavaTypeContext,
350373
List<Diagnostic> diagnostics) {
@@ -391,7 +414,7 @@ private ResolvedJavaTypeInfo validateExpressionParts(Parts parts, Section ownerS
391414
ResolvedJavaTypeInfo resolvedJavaType = null;
392415
String namespace = null;
393416
for (int i = 0; i < parts.getChildCount(); i++) {
394-
Part current = ((Part) parts.getChild(i));
417+
Part current = (parts.getChild(i));
395418

396419
if (current.isLast()) {
397420
// It's the last part, check if it is not ended with '.'
@@ -586,7 +609,7 @@ private ResolvedJavaTypeInfo validateObjectPart(ObjectPart objectPart, Section o
586609

587610
/**
588611
* Validate the given property, method part.
589-
*
612+
*
590613
* @param part the property, method part to validate.
591614
* @param ownerSection the owner section and null otherwise.
592615
* @param template the template.
@@ -596,7 +619,7 @@ private ResolvedJavaTypeInfo validateObjectPart(ObjectPart objectPart, Section o
596619
* @param iterableOfType the iterable of type.
597620
* @param diagnostics the diagnostic list to fill.
598621
* @param resolvingJavaTypeContext the resolving Java type context.
599-
*
622+
*
600623
* @return the Java type returned by the member part and null otherwise.
601624
*/
602625
private ResolvedJavaTypeInfo validateMemberPart(Part part, Section ownerSection, Template template,
@@ -617,7 +640,7 @@ private ResolvedJavaTypeInfo validateMemberPart(Part part, Section ownerSection,
617640

618641
/**
619642
* Validate the given property part.
620-
*
643+
*
621644
* @param part the property part to validate.
622645
* @param ownerSection the owner section and null otherwise.
623646
* @param template the template.
@@ -627,7 +650,7 @@ private ResolvedJavaTypeInfo validateMemberPart(Part part, Section ownerSection,
627650
* @param iterableOfType the iterable of type.
628651
* @param diagnostics the diagnostic list to fill.
629652
* @param resolvingJavaTypeContext the resolving Java type context.
630-
*
653+
*
631654
* @return the Java type returned by the member part and null otherwise.
632655
*/
633656
private ResolvedJavaTypeInfo validatePropertyPart(PropertyPart part, Section ownerSection, Template template,
@@ -650,7 +673,7 @@ private ResolvedJavaTypeInfo validatePropertyPart(PropertyPart part, Section own
650673

651674
/**
652675
* Validate the given method part.
653-
*
676+
*
654677
* @param part the method part to validate.
655678
* @param ownerSection the owner section and null otherwise.
656679
* @param template the template.
@@ -660,7 +683,7 @@ private ResolvedJavaTypeInfo validatePropertyPart(PropertyPart part, Section own
660683
* @param iterableOfType the iterable of type.
661684
* @param diagnostics the diagnostic list to fill.
662685
* @param resolvingJavaTypeContext the resolving Java type context.
663-
*
686+
*
664687
* @return the Java type returned by the member part and null otherwise.
665688
*/
666689
private ResolvedJavaTypeInfo validateMethodPart(MethodPart methodPart, Section ownerSection, Template template,

qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/services/diagnostics/DiagnosticDataFactory.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@
1616
import static com.redhat.qute.services.diagnostics.QuteDiagnosticContants.DIAGNOSTIC_DATA_TAG;
1717
import static com.redhat.qute.services.diagnostics.QuteDiagnosticContants.QUTE_SOURCE;
1818

19+
import java.util.List;
20+
1921
import org.eclipse.lsp4j.Diagnostic;
2022
import org.eclipse.lsp4j.DiagnosticSeverity;
23+
import org.eclipse.lsp4j.DiagnosticTag;
2124
import org.eclipse.lsp4j.Range;
2225

2326
import com.google.gson.JsonObject;
@@ -55,4 +58,13 @@ public static Diagnostic createDiagnostic(Range range, String message, Diagnosti
5558
errorCode != null ? errorCode.getCode() : null);
5659
return diagnostic;
5760
}
61+
62+
public static Diagnostic createDiagnosticWithTags(Range range, DiagnosticSeverity severity,
63+
IQuteErrorCode errorCode, List<DiagnosticTag> tags, Object... arguments) {
64+
String message = errorCode.getMessage(arguments);
65+
Diagnostic diagnostic = new Diagnostic(range, message, severity, QUTE_SOURCE,
66+
errorCode != null ? errorCode.getCode() : null);
67+
diagnostic.setTags(tags);
68+
return diagnostic;
69+
}
5870
}

qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/services/diagnostics/QuteErrorCode.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,10 @@ public enum QuteErrorCode implements IQuteErrorCode {
4545

4646
UndefinedSectionTag("No section helper found for `{0}`."), //
4747

48-
SyntaxError("Syntax error: `{0}`.");
48+
SyntaxError("Syntax error: `{0}`."),
49+
50+
// Error code for deprecated #with section
51+
DeprecatedWithSection("`with` is deprecated. Use `let` instead.");
4952

5053
private final String rawMessage;
5154

qute.ls/com.redhat.qute.ls/src/test/java/com/redhat/qute/services/diagnostics/QuteDiagnosticsInExpressionWithWithSectionTest.java

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,16 @@
1717
import static com.redhat.qute.QuteAssert.testCodeActionsFor;
1818
import static com.redhat.qute.QuteAssert.testDiagnosticsFor;
1919

20+
import java.util.Collections;
21+
2022
import org.eclipse.lsp4j.Diagnostic;
2123
import org.eclipse.lsp4j.DiagnosticSeverity;
24+
import org.eclipse.lsp4j.DiagnosticTag;
2225
import org.junit.jupiter.api.Test;
2326

2427
/**
2528
* Test with #with section
26-
*
29+
*
2730
* @author Angelo ZERR
2831
*
2932
*/
@@ -34,23 +37,30 @@ public void undefinedObject() throws Exception {
3437
String template = "{#with item}\r\n" + //
3538
"{/with}";
3639

37-
Diagnostic d = d(0, 7, 0, 11, QuteErrorCode.UndefinedVariable, "`item` cannot be resolved to a variable.",
40+
Diagnostic d1 = d(0, 7, 0, 11, QuteErrorCode.UndefinedVariable, "`item` cannot be resolved to a variable.",
3841
DiagnosticSeverity.Warning);
39-
d.setData(DiagnosticDataFactory.createUndefinedVariableData("item", false));
42+
d1.setData(DiagnosticDataFactory.createUndefinedVariableData("item", false));
4043

41-
testDiagnosticsFor(template, d);
42-
testCodeActionsFor(template, d, //
43-
ca(d, te(0, 0, 0, 0, "{@java.lang.String item}\r\n")));
44+
Diagnostic d2 = d(0, 0, 1, 7, QuteErrorCode.DeprecatedWithSection, "`with` is deprecated. Use `let` instead.",
45+
DiagnosticSeverity.Warning);
46+
d2.setTags(Collections.singletonList(DiagnosticTag.Deprecated));
47+
48+
testDiagnosticsFor(template, d1, d2);
49+
testCodeActionsFor(template, d1, //
50+
ca(d1, te(0, 0, 0, 0, "{@java.lang.String item}\r\n")));
4451
}
4552

4653
@Test
47-
public void noError() throws Exception {
54+
public void singleSection() throws Exception {
4855
String template = "{@org.acme.Item item}\r\n" + //
4956
"{#with item}\r\n" + //
5057
" <h1>{name}</h1> \r\n" + //
5158
" <p>{price}</p> \r\n" + //
5259
"{/with}";
53-
testDiagnosticsFor(template);
60+
Diagnostic d = d(1, 0, 4, 7, QuteErrorCode.DeprecatedWithSection, "`with` is deprecated. Use `let` instead.",
61+
DiagnosticSeverity.Warning);
62+
d.setTags(Collections.singletonList(DiagnosticTag.Deprecated));
63+
testDiagnosticsFor(template, d);
5464
}
5565

5666
@Test
@@ -68,13 +78,21 @@ public void nested() throws Exception {
6878
" {/with}\r\n" + //
6979
"{/with}";
7080

71-
Diagnostic d = d(6, 5, 6, 12, QuteErrorCode.UndefinedVariable, "`average` cannot be resolved to a variable.",
81+
Diagnostic d1 = d(1, 0, 11, 7, QuteErrorCode.DeprecatedWithSection, "`with` is deprecated. Use `let` instead.",
7282
DiagnosticSeverity.Warning);
73-
d.setData(DiagnosticDataFactory.createUndefinedVariableData("average", false));
83+
d1.setTags(Collections.singletonList(DiagnosticTag.Deprecated));
7484

75-
testDiagnosticsFor(template, d);
76-
testCodeActionsFor(template, d, //
77-
ca(d, te(0, 0, 0, 0, "{@java.lang.String average}\r\n")));
85+
Diagnostic d2 = d(4, 2, 10, 9, QuteErrorCode.DeprecatedWithSection, "`with` is deprecated. Use `let` instead.",
86+
DiagnosticSeverity.Warning);
87+
d2.setTags(Collections.singletonList(DiagnosticTag.Deprecated));
88+
89+
Diagnostic d3 = d(6, 5, 6, 12, QuteErrorCode.UndefinedVariable, "`average` cannot be resolved to a variable.",
90+
DiagnosticSeverity.Warning);
91+
d3.setData(DiagnosticDataFactory.createUndefinedVariableData("average", false));
92+
93+
testDiagnosticsFor(template, d1, d2, d3);
94+
testCodeActionsFor(template, d3, //
95+
ca(d3, te(0, 0, 0, 0, "{@java.lang.String average}\r\n")));
7896

7997
}
8098
}

0 commit comments

Comments
 (0)