Skip to content

Commit

Permalink
Added diagnostic and CodeAction to use let to replace with
Browse files Browse the repository at this point in the history
Signed-off-by: Alexander Chen <[email protected]>
  • Loading branch information
Alexander Chen committed Feb 25, 2022
1 parent 3ff7394 commit 037a9fa
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,16 @@ public static CodeAction replace(String title, Range range, String replaceText,
return replace(title, Collections.singletonList(replace), document, diagnostic);
}

@SuppressWarnings("null")
public static CodeAction replace(String title, List<Range> ranges, String replaceText, TextDocumentItem document,
Diagnostic diagnostic) {
List<TextEdit> edits = null;
for (Range range : ranges) {
edits.add(new TextEdit(range, replaceText));
}
return replace(title, edits, document, diagnostic);
}

public static CodeAction replace(String title, List<TextEdit> replace, TextDocumentItem document,
Diagnostic diagnostic) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@

/**
* Qute code actions support.
*
*
* @author Angelo ZERR
*
*/
Expand All @@ -72,6 +72,8 @@ class QuteCodeActions {

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

private static final String QUTE_DEPRICATED_WITH_SECTION = "Replace `with` with `let`.";

public CompletableFuture<List<CodeAction>> doCodeActions(Template template, CodeActionContext context, Range range,
SharedSettings sharedSettings) {
List<CodeAction> codeActions = new ArrayList<>();
Expand Down Expand Up @@ -109,6 +111,15 @@ public CompletableFuture<List<CodeAction>> doCodeActions(Template template, Code
// Create `undefinedTag`"
doCodeActionsForUndefinedSectionTag(template, diagnostic, codeActions);
break;
case NotRecommendedWithSection:
// The following Qute template:
// {#with }
//
// will provide a quickfix like:
//
// Replace `with` with `let`.
doCodeActionsForDeprecatedWithSection(template, diagnostic, codeActions);
break;
default:
break;
}
Expand Down Expand Up @@ -186,15 +197,42 @@ private static void doCodeActionToDisableValidation(Template template, List<Diag
codeActions.add(disableValidationForTemplateQuickFix);
}

/**
* Create CodeAction for deprecated `with` Qute syntax.
*
* @param template the Qute template.
* @param diagnostic the diagnostic list that this CodeAction will fix.
* @param codeActions the list of CodeActions to perform.
* @throws BadLocationException
*
*/
private void doCodeActionsForDeprecatedWithSection(Template template, Diagnostic diagnostic,
List<CodeAction> codeActions) {
Range withSectionRange = diagnostic.getRange();
try {
int withSectionStart = template.offsetAt(withSectionRange.getStart());
int withSectionEnd = template.offsetAt(withSectionRange.getEnd());
String withSectionText = template.getText(withSectionStart, withSectionEnd);
int withClosingSectionIndex = withSectionText.lastIndexOf("/with");
String replacement = withSectionText.replaceFirst("#with", "#let").substring(0, withClosingSectionIndex)
+ "/let";
CodeAction replaceWithSection = CodeActionFactory.replace(QUTE_DEPRICATED_WITH_SECTION,
diagnostic.getRange(), replacement, template.getTextDocument(), diagnostic);
codeActions.add(replaceWithSection);
} catch (BadLocationException e) {
return;
}
}

/**
* Create the configuration update (done on client side) quick fix.
*
*
* @param title the displayed name of the QuickFix.
* @param sectionName the section name of the settings to update.
* @param item the section value of the settings to update.
* @param editType the configuration edit type.
* @param diagnostic the diagnostic list that this CodeAction will fix.
*
*
* @return the configuration update (done on client side) quick fix.
*/
private static CodeAction createConfigurationUpdateCodeAction(String title, String scopeUri, String sectionName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
import com.redhat.qute.parser.template.Template;
import com.redhat.qute.parser.template.sections.IncludeSection;
import com.redhat.qute.parser.template.sections.LoopSection;
import com.redhat.qute.parser.template.sections.WithSection;
import com.redhat.qute.project.JavaMemberResult;
import com.redhat.qute.project.QuteProject;
import com.redhat.qute.project.datamodel.JavaDataModelCache;
Expand Down Expand Up @@ -246,6 +247,9 @@ private void validateDataModel(Node parent, Template template, ResolvingJavaType
case INCLUDE:
validateIncludeSection((IncludeSection) section, diagnostics);
break;
case WITH:
validateWithSection((WithSection) section, diagnostics);
break;
default:
validateSectionTag(section, template, resolvingJavaTypeContext, diagnostics);
}
Expand Down Expand Up @@ -345,6 +349,22 @@ private static void validateIncludeSection(IncludeSection includeSection, List<D
}
}

/**
* Report that `#with` section is deprecated.
*
* @param withSection the with section
* @param diagnostics the diagnostics to fill
*/
private static void validateWithSection(WithSection withSection, List<Diagnostic> diagnostics) {
// List<DiagnosticTag> tags = Collections.singletonList(DiagnosticTag.Deprecated);
Range range = QutePositionUtility.createRange(withSection);
// Diagnostic diagnostic = createDiagnosticWithTags(range, DiagnosticSeverity.Warning,
// QuteErrorCode.DeprecatedWithSection, tags);
Diagnostic diagnostic = createDiagnostic(range, DiagnosticSeverity.Warning,
QuteErrorCode.NotRecommendedWithSection);
diagnostics.add(diagnostic);
}

private ResolvedJavaTypeInfo validateExpression(Expression expression, Section ownerSection, Template template,
ResolutionContext resolutionContext, ResolvingJavaTypeContext resolvingJavaTypeContext,
List<Diagnostic> diagnostics) {
Expand Down Expand Up @@ -391,7 +411,7 @@ private ResolvedJavaTypeInfo validateExpressionParts(Parts parts, Section ownerS
ResolvedJavaTypeInfo resolvedJavaType = null;
String namespace = null;
for (int i = 0; i < parts.getChildCount(); i++) {
Part current = ((Part) parts.getChild(i));
Part current = (parts.getChild(i));

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

/**
* Validate the given property, method part.
*
*
* @param part the property, method part to validate.
* @param ownerSection the owner section and null otherwise.
* @param template the template.
Expand All @@ -596,7 +616,7 @@ private ResolvedJavaTypeInfo validateObjectPart(ObjectPart objectPart, Section o
* @param iterableOfType the iterable of type.
* @param diagnostics the diagnostic list to fill.
* @param resolvingJavaTypeContext the resolving Java type context.
*
*
* @return the Java type returned by the member part and null otherwise.
*/
private ResolvedJavaTypeInfo validateMemberPart(Part part, Section ownerSection, Template template,
Expand All @@ -617,7 +637,7 @@ private ResolvedJavaTypeInfo validateMemberPart(Part part, Section ownerSection,

/**
* Validate the given property part.
*
*
* @param part the property part to validate.
* @param ownerSection the owner section and null otherwise.
* @param template the template.
Expand All @@ -627,7 +647,7 @@ private ResolvedJavaTypeInfo validateMemberPart(Part part, Section ownerSection,
* @param iterableOfType the iterable of type.
* @param diagnostics the diagnostic list to fill.
* @param resolvingJavaTypeContext the resolving Java type context.
*
*
* @return the Java type returned by the member part and null otherwise.
*/
private ResolvedJavaTypeInfo validatePropertyPart(PropertyPart part, Section ownerSection, Template template,
Expand All @@ -650,7 +670,7 @@ private ResolvedJavaTypeInfo validatePropertyPart(PropertyPart part, Section own

/**
* Validate the given method part.
*
*
* @param part the method part to validate.
* @param ownerSection the owner section and null otherwise.
* @param template the template.
Expand All @@ -660,7 +680,7 @@ private ResolvedJavaTypeInfo validatePropertyPart(PropertyPart part, Section own
* @param iterableOfType the iterable of type.
* @param diagnostics the diagnostic list to fill.
* @param resolvingJavaTypeContext the resolving Java type context.
*
*
* @return the Java type returned by the member part and null otherwise.
*/
private ResolvedJavaTypeInfo validateMethodPart(MethodPart methodPart, Section ownerSection, Template template,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@
import static com.redhat.qute.services.diagnostics.QuteDiagnosticContants.DIAGNOSTIC_DATA_TAG;
import static com.redhat.qute.services.diagnostics.QuteDiagnosticContants.QUTE_SOURCE;

import java.util.List;

import org.eclipse.lsp4j.Diagnostic;
import org.eclipse.lsp4j.DiagnosticSeverity;
import org.eclipse.lsp4j.DiagnosticTag;
import org.eclipse.lsp4j.Range;

import com.google.gson.JsonObject;
Expand Down Expand Up @@ -55,4 +58,13 @@ public static Diagnostic createDiagnostic(Range range, String message, Diagnosti
errorCode != null ? errorCode.getCode() : null);
return diagnostic;
}

public static Diagnostic createDiagnosticWithTags(Range range, DiagnosticSeverity severity,
IQuteErrorCode errorCode, List<DiagnosticTag> tags, Object... arguments) {
String message = errorCode.getMessage(arguments);
Diagnostic diagnostic = new Diagnostic(range, message, severity, QUTE_SOURCE,
errorCode != null ? errorCode.getCode() : null);
diagnostic.setTags(tags);
return diagnostic;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@ public enum QuteErrorCode implements IQuteErrorCode {

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

SyntaxError("Syntax error: `{0}`.");
SyntaxError("Syntax error: `{0}`."),

// Error code for deprecated #with section
NotRecommendedWithSection("`with` is not recommended. Use `let` instead.");

private final String rawMessage;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

/**
* Test with #with section
*
*
* @author Angelo ZERR
*
*/
Expand All @@ -34,23 +34,28 @@ public void undefinedObject() throws Exception {
String template = "{#with item}\r\n" + //
"{/with}";

Diagnostic d = d(0, 7, 0, 11, QuteErrorCode.UndefinedVariable, "`item` cannot be resolved to a variable.",
Diagnostic d1 = d(0, 7, 0, 11, QuteErrorCode.UndefinedVariable, "`item` cannot be resolved to a variable.",
DiagnosticSeverity.Warning);
d.setData(DiagnosticDataFactory.createUndefinedVariableData("item", false));
d1.setData(DiagnosticDataFactory.createUndefinedVariableData("item", false));

testDiagnosticsFor(template, d);
testCodeActionsFor(template, d, //
ca(d, te(0, 0, 0, 0, "{@java.lang.String item}\r\n")));
Diagnostic d2 = d(0, 0, 1, 7, QuteErrorCode.NotRecommendedWithSection,
"`with` is not recommended. Use `let` instead.", DiagnosticSeverity.Warning);

testDiagnosticsFor(template, d1, d2);
testCodeActionsFor(template, d1, //
ca(d1, te(0, 0, 0, 0, "{@java.lang.String item}\r\n")));
}

@Test
public void noError() throws Exception {
public void singleSection() throws Exception {
String template = "{@org.acme.Item item}\r\n" + //
"{#with item}\r\n" + //
" <h1>{name}</h1> \r\n" + //
" <p>{price}</p> \r\n" + //
"{/with}";
testDiagnosticsFor(template);
Diagnostic d = d(1, 0, 4, 7, QuteErrorCode.NotRecommendedWithSection,
"`with` is not recommended. Use `let` instead.", DiagnosticSeverity.Warning);
testDiagnosticsFor(template, d);
}

@Test
Expand All @@ -68,13 +73,19 @@ public void nested() throws Exception {
" {/with}\r\n" + //
"{/with}";

Diagnostic d = d(6, 5, 6, 12, QuteErrorCode.UndefinedVariable, "`average` cannot be resolved to a variable.",
Diagnostic d1 = d(1, 0, 11, 7, QuteErrorCode.NotRecommendedWithSection,
"`with` is not recommended. Use `let` instead.", DiagnosticSeverity.Warning);

Diagnostic d2 = d(4, 2, 10, 9, QuteErrorCode.NotRecommendedWithSection,
"`with` is not recommended. Use `let` instead.", DiagnosticSeverity.Warning);

Diagnostic d3 = d(6, 5, 6, 12, QuteErrorCode.UndefinedVariable, "`average` cannot be resolved to a variable.",
DiagnosticSeverity.Warning);
d.setData(DiagnosticDataFactory.createUndefinedVariableData("average", false));
d3.setData(DiagnosticDataFactory.createUndefinedVariableData("average", false));

testDiagnosticsFor(template, d);
testCodeActionsFor(template, d, //
ca(d, te(0, 0, 0, 0, "{@java.lang.String average}\r\n")));
testDiagnosticsFor(template, d1, d2, d3);
testCodeActionsFor(template, d3, //
ca(d3, te(0, 0, 0, 0, "{@java.lang.String average}\r\n")));

}
}

0 comments on commit 037a9fa

Please sign in to comment.