Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CodeAction for missing root end tag #595

Merged
merged 1 commit into from
Nov 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,9 @@ public List<DOMNode> getRoots() {
return super.getChildren();
}

public Position positionAt(int position) throws BadLocationException {
public Position positionAt(int offset) throws BadLocationException {
checkCanceled();
return textDocument.positionAt(position);
return textDocument.positionAt(offset);
}

public int offsetAt(Position position) throws BadLocationException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4xml.dom.DOMDocument;
import org.eclipse.lsp4xml.dom.DOMDocumentType;
import org.eclipse.lsp4xml.extensions.contentmodel.participants.codeactions.ETagRequiredCodeAction;
import org.eclipse.lsp4xml.extensions.contentmodel.participants.codeactions.ElementUnterminatedCodeAction;
import org.eclipse.lsp4xml.extensions.contentmodel.participants.codeactions.EqRequiredInAttributeCodeAction;
import org.eclipse.lsp4xml.extensions.contentmodel.participants.codeactions.MarkupEntityMismatchCodeAction;
import org.eclipse.lsp4xml.extensions.contentmodel.participants.codeactions.OpenQuoteExpectedCodeAction;
import org.eclipse.lsp4xml.services.extensions.ICodeActionParticipant;
import org.eclipse.lsp4xml.services.extensions.diagnostics.IXMLErrorCode;
Expand Down Expand Up @@ -211,5 +213,7 @@ public static void registerCodeActionParticipants(Map<String, ICodeActionPartici
codeActions.put(ElementUnterminated.getCode(), new ElementUnterminatedCodeAction());
codeActions.put(EqRequiredInAttribute.getCode(), new EqRequiredInAttributeCodeAction());
codeActions.put(OpenQuoteExpected.getCode(), new OpenQuoteExpectedCodeAction());
codeActions.put(MarkupEntityMismatch.getCode(), new MarkupEntityMismatchCodeAction());
codeActions.put(ETagRequired.getCode(), new ETagRequiredCodeAction());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*******************************************************************************
* Copyright (c) 2019 Red Hat Inc. and others.
* All rights reserved. This program and the accompanying materials
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/

package org.eclipse.lsp4xml.extensions.contentmodel.participants.codeactions;
NikolasKomonen marked this conversation as resolved.
Show resolved Hide resolved

import java.util.List;

import org.eclipse.lsp4j.CodeAction;
import org.eclipse.lsp4j.Diagnostic;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4xml.dom.DOMDocument;
import org.eclipse.lsp4xml.services.extensions.ICodeActionParticipant;
import org.eclipse.lsp4xml.services.extensions.IComponentProvider;
import org.eclipse.lsp4xml.settings.XMLFormattingOptions;

/**
* ETagRequiredCodeAction
*/
public class ETagRequiredCodeAction implements ICodeActionParticipant {

@Override
public void doCodeAction(Diagnostic diagnostic, Range range, DOMDocument document, List<CodeAction> codeActions,
XMLFormattingOptions formattingSettings, IComponentProvider componentProvider) {
MarkupEntityMismatchCodeAction.createEndTagInsertCodeAction(diagnostic, range, document, codeActions, formattingSettings, componentProvider);
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*******************************************************************************
* Copyright (c) 2019 Red Hat Inc. and others.
* All rights reserved. This program and the accompanying materials
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/el-v20.html
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/

package org.eclipse.lsp4xml.extensions.contentmodel.participants.codeactions;
NikolasKomonen marked this conversation as resolved.
Show resolved Hide resolved

import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.eclipse.lsp4j.CodeAction;
import org.eclipse.lsp4j.Diagnostic;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4xml.commons.BadLocationException;
import org.eclipse.lsp4xml.commons.CodeActionFactory;
import org.eclipse.lsp4xml.dom.DOMDocument;
import org.eclipse.lsp4xml.dom.DOMElement;
import org.eclipse.lsp4xml.dom.DOMNode;
import org.eclipse.lsp4xml.extensions.contentmodel.participants.XMLSyntaxErrorCode;
import org.eclipse.lsp4xml.services.extensions.ICodeActionParticipant;
import org.eclipse.lsp4xml.services.extensions.IComponentProvider;
import org.eclipse.lsp4xml.settings.XMLFormattingOptions;

/**
* MarkupEntityMismatchCodeAction is a code action that triggers when the end tag of the
* root element is missing. This will provide a codeaction that inserts that missing
* end tag.
*/
public class MarkupEntityMismatchCodeAction implements ICodeActionParticipant {
private static final Logger LOGGER = Logger.getLogger(MarkupEntityMismatchCodeAction.class.getName());


@Override
public void doCodeAction(Diagnostic diagnostic, Range range, DOMDocument document, List<CodeAction> codeActions,
XMLFormattingOptions formattingSettings, IComponentProvider componentProvider) {
createEndTagInsertCodeAction(diagnostic, range, document, codeActions, formattingSettings, componentProvider);
}

public static void createEndTagInsertCodeAction(Diagnostic diagnostic, Range range, DOMDocument document, List<CodeAction> codeActions,
XMLFormattingOptions formattingSettings, IComponentProvider componentProvider) {
try {
int offset = document.offsetAt(diagnostic.getRange().getStart());
DOMNode node = document.findNodeAt(offset);
if(!node.isElement()) {
return;
}

DOMElement element = (DOMElement) node;
int startOffset = element.getStartTagOpenOffset();
Position startPosition = document.positionAt(startOffset);
Position endPosition;

XMLSyntaxErrorCode code = XMLSyntaxErrorCode.get(diagnostic.getCode());
switch (code) {
case MarkupEntityMismatch:
endPosition = document.positionAt(document.getEnd());
if (endPosition.getLine() > startPosition.getLine()) {
endPosition.setCharacter(startPosition.getCharacter());
}
break;
case ETagRequired:
endPosition = document.positionAt(element.getStartTagCloseOffset() + 1);
break;
default:
return;
}

String elementName = element.getTagName();
CodeAction action = CodeActionFactory.insert("Close with '</" + elementName + ">'", endPosition, "</" + elementName + ">", document.getTextDocument(), diagnostic);
codeActions.add(action);
} catch (BadLocationException e) {
LOGGER.log(Level.WARNING, "Exception while resolving the code action for " + diagnostic.getCode() + ":", e);
}
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,9 @@ public void testETagRequired() throws Exception {
" <Nm>Name\r\n" + //
" </UltmtDbtr> \r\n" + //
" </Nm> ";
testDiagnosticsFor(xml, d(1, 5, 1, 7, XMLSyntaxErrorCode.ETagRequired));
Diagnostic d = d(1, 5, 1, 7, XMLSyntaxErrorCode.ETagRequired);
testDiagnosticsFor(xml, d);
testCodeActionsFor(xml, d, ca(d, te(1, 8, 1, 8, "</Nm>")));
}

@Test
Expand All @@ -200,7 +202,9 @@ public void testETagRequired3() throws Exception {
" <Ad>\r\n" +
" <Ph>\r\n" +
"</UltmtDbtr>";
testDiagnosticsFor(xml, d(3, 5, 3, 7, XMLSyntaxErrorCode.ETagRequired));
Diagnostic d = d(3, 5, 3, 7, XMLSyntaxErrorCode.ETagRequired);
testDiagnosticsFor(xml, d);
testCodeActionsFor(xml, d, ca(d, te(3, 8, 3, 8, "</Ph>")));
}

/**
Expand Down Expand Up @@ -255,9 +259,21 @@ public void testLessThanAttValue() throws Exception {
public void testMarkupEntityMismatch() throws Exception {
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
+ "<Document xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"urn:iso:std:iso:20022:tech:xsd:pain.001.001.03\">\r\n"
+ "<CstmrCdtTrfInitn>\r\n" + //
"</CstmrCdtTrfInitn>";
testDiagnosticsFor(xml, d(1, 1, 1, 9, XMLSyntaxErrorCode.MarkupEntityMismatch));
+ "<CstmrCdtTrfInitn>\r\n"
+ "</CstmrCdtTrfInitn>";

Diagnostic d = d(1, 1, 1, 9, XMLSyntaxErrorCode.MarkupEntityMismatch);
testDiagnosticsFor(xml, d);
testCodeActionsFor(xml, d, ca(d, te(3, 0, 3, 0, "</Document>")));
}

@Test
public void testMarkupEntityMismatch2() throws Exception {
String xml = "<ABC>";

Diagnostic d = d(0, 1, 0, 4, XMLSyntaxErrorCode.MarkupEntityMismatch);
testDiagnosticsFor(xml, d);
testCodeActionsFor(xml, d, ca(d, te(0, 5, 0, 5, "</ABC>")));
}

@Test
Expand Down