Skip to content

Commit

Permalink
validate element in plugin <configuration> and plugin goals
Browse files Browse the repository at this point in the history
Fix #9

Signed-off-by: Andrew Obuchowicz <aobuchow@redhat.com>
  • Loading branch information
AObuchow committed Apr 27, 2020
1 parent be74d58 commit 98b44e0
Show file tree
Hide file tree
Showing 11 changed files with 222 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,18 @@ public static DOMNode findClosestParentNode(final IPositionRequest request, fina
return null;
}
DOMNode pluginNode = request.getNode();
return internalFindClosestParentNode(localName, pluginNode);
}

public static DOMNode findClosestParentNode(final DiagnosticRequest request, final String localName) {
if (localName == null || request == null) {
return null;
}
DOMNode pluginNode = request.getNode();
return internalFindClosestParentNode(localName, pluginNode);
}

private static DOMNode internalFindClosestParentNode(final String localName, DOMNode pluginNode) {
try {
while (!localName.equals(pluginNode.getLocalName())) {
pluginNode = pluginNode.getParentNode();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@ public class DiagnosticRequest {

public DiagnosticRequest(DOMNode node, DOMDocument xmlDocument, List<Diagnostic> diagnostics) {
this.setNode(node);
this.setDOMDocument(xmlDocument);
this.setXMLDocument(xmlDocument);
this.setDiagnostics(diagnostics);
}

public DOMDocument getDOMDocument() {
public DOMDocument getXMLDocument() {
return xmlDocument;
}

public void setDOMDocument(DOMDocument xmlDocument) {
public void setXMLDocument(DOMDocument xmlDocument) {
this.xmlDocument = xmlDocument;
}

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

import org.apache.maven.model.building.ModelProblem;
import org.apache.maven.model.building.ModelProblem.Severity;
import org.apache.maven.plugin.MavenPluginManager;
import org.eclipse.lemminx.dom.DOMDocument;
import org.eclipse.lemminx.dom.DOMElement;
import org.eclipse.lemminx.dom.DOMNode;
Expand All @@ -31,9 +32,11 @@
public class MavenDiagnosticParticipant implements IDiagnosticsParticipant {

private MavenProjectCache projectCache;
MavenPluginManager pluginManager;

public MavenDiagnosticParticipant(MavenProjectCache projectCache) {
public MavenDiagnosticParticipant(MavenProjectCache projectCache, MavenPluginManager pluginManager) {
this.projectCache = projectCache;
this.pluginManager = pluginManager;
}

@Override
Expand Down Expand Up @@ -79,24 +82,13 @@ public void doDiagnostics(DOMDocument xmlDocument, List<Diagnostic> diagnostics,

private HashMap<String, Function<DiagnosticRequest, Diagnostic>> configureDiagnosticFunctions(
DOMDocument xmlDocument) {
// SubModuleValidator subModuleValidator= new SubModuleValidator();
// try {
// subModuleValidator.setPomFile(new File(xmlDocument.getDocumentURI().substring(5)));
// } catch (IOException | XmlPullParserException e) {
// // TODO: Use plug-in error logger
// e.printStackTrace();
// }
//Function<DiagnosticRequest, Diagnostic> versionFunc = VersionValidator::validateVersion;
//Function<DiagnosticRequest, Diagnostic> submoduleExistenceFunc = subModuleValidator::validateSubModuleExistence;
// Below is a mock Diagnostic function which creates a warning between inside
// <configuration> tags
//Function<DiagnosticRequest, Diagnostic> configFunc = diagnosticReq -> new Diagnostic(diagnosticReq.getRange(),
// "Configuration Error", DiagnosticSeverity.Warning, xmlDocument.getDocumentURI(), "XML");
PluginValidator pluginValidator = new PluginValidator(projectCache, pluginManager);
Function<DiagnosticRequest, Diagnostic> validatePluginConfiguration = pluginValidator::validateConfiguration;
Function<DiagnosticRequest, Diagnostic> validatePluginGoal = pluginValidator::validateGoal;

HashMap<String, Function<DiagnosticRequest, Diagnostic>> tagDiagnostics = new HashMap<>();
//tagDiagnostics.put("version", versionFunc);
//tagDiagnostics.put("configuration", configFunc);
//tagDiagnostics.put("module", submoduleExistenceFunc);
tagDiagnostics.put("configuration", validatePluginConfiguration);
tagDiagnostics.put("goal", validatePluginGoal);
return tagDiagnostics;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,11 @@ public void start(InitializeParams params, XMLExtensionsRegistry registry) {
e.printStackTrace();
}
registry.registerCompletionParticipant(completionParticipant);
diagnosticParticipant = new MavenDiagnosticParticipant(cache);
try {
diagnosticParticipant = new MavenDiagnosticParticipant(cache, container.lookup(MavenPluginManager.class));
} catch (ComponentLookupException e) {
e.printStackTrace();
}
registry.registerDiagnosticsParticipant(diagnosticParticipant);
try {
hoverParticipant = new MavenHoverParticipant(cache, indexSearcher, (MavenPluginManager) container.lookup(MavenPluginManager.class));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,30 @@ public static List<Parameter> collectPluginConfigurationParameters(IPositionRequ
if (pluginDescriptor == null) {
return Collections.emptyList();
}
List<MojoDescriptor> mojosToConsiderList = pluginDescriptor.getMojos();
DOMNode executionElementDomNode = DOMUtils.findClosestParentNode(request, "execution");
return getPluginParametersWithGoals(pluginDescriptor, executionElementDomNode);
}

public static List<Parameter> collectPluginConfigurationParameters(DiagnosticRequest request,
MavenProjectCache cache, MavenPluginManager pluginManager) {
PluginDescriptor pluginDescriptor = MavenPluginUtils.getContainingPluginDescriptor(request, cache,
pluginManager);
if (pluginDescriptor == null) {
return Collections.emptyList();
}

DOMNode executionElementDomNode = DOMUtils.findClosestParentNode(request, "execution");
return getPluginParametersWithGoals(pluginDescriptor, executionElementDomNode);
}

/**
* @param pluginDescriptor
* @param executionElementDomNode Can be null if not available
* @return {@code List<Parameter>} The plugin's parameters
*/
private static List<Parameter> getPluginParametersWithGoals(PluginDescriptor pluginDescriptor,
DOMNode executionElementDomNode) {
List<MojoDescriptor> mojosToConsiderList = pluginDescriptor.getMojos();
if (executionElementDomNode != null) {
Set<String> interestingMojos = executionElementDomNode.getChildren().stream()
.filter(node -> "goals".equals(node.getLocalName())).flatMap(node -> node.getChildren().stream())
Expand All @@ -62,9 +84,8 @@ public static List<Parameter> collectPluginConfigurationParameters(IPositionRequ
mojosToConsiderList = mojosToConsiderList.stream().filter(mojo -> interestingMojos.contains(mojo.getGoal()))
.collect(Collectors.toList());
}
List<Parameter> parameters = mojosToConsiderList.stream().flatMap(mojo -> mojo.getParameters().stream())
return mojosToConsiderList.stream().flatMap(mojo -> mojo.getParameters().stream())
.collect(Collectors.toList());
return parameters;
}

public static RemoteRepository toRemoteRepo(Repository modelRepo) {
Expand All @@ -82,6 +103,24 @@ public static PluginDescriptor getContainingPluginDescriptor(IPositionRequest re
if (pluginNode == null) {
return null;
}
return getNodePluginDescriptor(cache, pluginManager, project, pluginNode);
}

public static PluginDescriptor getContainingPluginDescriptor(DiagnosticRequest request, MavenProjectCache cache,
MavenPluginManager pluginManager) {
MavenProject project = cache.getLastSuccessfulMavenProject(request.getXMLDocument());
if (project == null) {
return null;
}
DOMNode pluginNode = DOMUtils.findClosestParentNode(request, "plugin");
if (pluginNode == null) {
return null;
}
return getNodePluginDescriptor(cache, pluginManager, project, pluginNode);
}

private static PluginDescriptor getNodePluginDescriptor(MavenProjectCache cache, MavenPluginManager pluginManager,
MavenProject project, DOMNode pluginNode) {
Optional<String> groupId = DOMUtils.findChildElementText(pluginNode, "groupId");
Optional<String> artifactId = DOMUtils.findChildElementText(pluginNode, "artifactId");
String pluginKey = "";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package org.eclipse.lemminx.maven;

import java.util.List;

import org.apache.maven.plugin.MavenPluginManager;
import org.apache.maven.plugin.descriptor.Parameter;
import org.eclipse.lemminx.dom.DOMNode;
import org.eclipse.lsp4j.Diagnostic;
import org.eclipse.lsp4j.DiagnosticSeverity;

public class PluginValidator {
private final MavenProjectCache cache;
private final MavenPluginManager pluginManager;

public PluginValidator(MavenProjectCache cache, MavenPluginManager pluginManager) {
this.cache = cache;
this.pluginManager = pluginManager;
}

public Diagnostic validateConfiguration(DiagnosticRequest diagnosticRequest) {
DOMNode node = diagnosticRequest.getNode();
if (node == null) {
return null;
}
if (node.isElement() && node.hasChildNodes()) {
List<Parameter> parameters = MavenPluginUtils.collectPluginConfigurationParameters(diagnosticRequest, cache,
pluginManager);
for (DOMNode childNode : node.getChildren()) {
DiagnosticRequest childDiagnosticReq = new DiagnosticRequest(childNode,
diagnosticRequest.getXMLDocument(), diagnosticRequest.getDiagnostics());
Diagnostic diag = internalValidateConfiguration(childDiagnosticReq, parameters);
if (diag != null) {
diagnosticRequest.getDiagnostics().add(diag);
}
}
}
return null;
}

public Diagnostic validateGoal(DiagnosticRequest diagnosticRequest) {
DOMNode node = diagnosticRequest.getNode();
if (node == null) {
return null;
}
if (node.isElement() && node.hasChildNodes()) {
List<Parameter> parameters = MavenPluginUtils.collectPluginConfigurationParameters(diagnosticRequest, cache,
pluginManager);
Diagnostic diag = internalValidateGoal(diagnosticRequest, parameters);
if (diag != null) {
diagnosticRequest.getDiagnostics().add(diag);
}
}
return null;
}

private static Diagnostic internalValidateGoal(DiagnosticRequest diagnosticReq, List<Parameter> parameters) {
DOMNode node = diagnosticReq.getNode();
if (!node.hasChildNodes()) {
return null;
}
for (Parameter parameter : parameters) {
if (node.getChild(0).getNodeValue().equals(parameter.getName())) {
return null;
}
}
return new Diagnostic(diagnosticReq.getRange(), "Invalid goal for this plugin", DiagnosticSeverity.Warning,
diagnosticReq.getXMLDocument().getDocumentURI(), "XML");

}

private static Diagnostic internalValidateConfiguration(DiagnosticRequest diagnosticReq,
List<Parameter> parameters) {
DOMNode node = diagnosticReq.getNode();
if (node.getLocalName() == null) {
return null;
}
for (Parameter parameter : parameters) {
if (node.getLocalName().equals(parameter.getName())) {
return null;
}
}
return new Diagnostic(diagnosticReq.getRange(), "Invalid plugin configuration", DiagnosticSeverity.Warning,
diagnosticReq.getXMLDocument().getDocumentURI(), "XML");

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public void setPomFile(File pomFile) throws FileNotFoundException, IOException,

public Diagnostic validateSubModuleExistence(DiagnosticRequest diagnosticRequest) {
DOMNode node = diagnosticRequest.getNode();
DOMDocument xmlDocument = diagnosticRequest.getDOMDocument();
DOMDocument xmlDocument = diagnosticRequest.getXMLDocument();
Diagnostic diagnostic = null;
Range range = diagnosticRequest.getRange();
String tagContent = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class VersionValidator {

public static Diagnostic validateVersion(DiagnosticRequest diagnosticRequest) {
DOMNode node = diagnosticRequest.getNode();
DOMDocument xmlDocument = diagnosticRequest.getDOMDocument();
DOMDocument xmlDocument = diagnosticRequest.getXMLDocument();
Dependency model = MavenParseUtils.parseArtifact(node);
Artifact artifact = null;
Range range = diagnosticRequest.getRange();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;

import org.eclipse.lemminx.dom.DOMDocument;
import org.eclipse.lemminx.extensions.contentmodel.settings.XMLValidationSettings;
import org.eclipse.lemminx.services.XMLLanguageService;
import org.eclipse.lemminx.settings.SharedSettings;
import org.eclipse.lemminx.settings.XMLHoverSettings;
import org.eclipse.lsp4j.CompletionItem;
import org.eclipse.lsp4j.Diagnostic;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.TextEdit;
import org.junit.After;
Expand Down Expand Up @@ -86,4 +89,24 @@ public void testPluginArtifactHover() throws IOException, InterruptedException,
assertTrue(languageService.doHover(createDOMDocument("/pom-plugin-artifact-hover.xml", languageService),
new Position(14, 18), new XMLHoverSettings()).getContents().getRight().getValue().contains("Maven Surefire MOJO in maven-surefire-plugin"));
}

// Diagnostic related tests

@Test(timeout=30000)
public void testPluginConfigurationDiagnostics() throws IOException, InterruptedException, ExecutionException, URISyntaxException {
DOMDocument document = createDOMDocument("/pom-plugin-configuration-hover.xml", languageService);
assertTrue(languageService.doDiagnostics(document, () -> {}, new XMLValidationSettings()).stream().map(Diagnostic::getMessage)
.anyMatch(message -> message.contains("Invalid plugin configuration")));

assertTrue(languageService.doDiagnostics(document, () -> {}, new XMLValidationSettings()).size() == 2);
}

@Test
public void testPluginGoalDiagnostics() throws IOException, InterruptedException, ExecutionException, URISyntaxException {
DOMDocument document = createDOMDocument("/pom-plugin-goal-diagnostic.xml", languageService);
assertTrue(languageService.doDiagnostics(document, () -> {}, new XMLValidationSettings()).stream().map(Diagnostic::getMessage)
.anyMatch(message -> message.contains("Invalid goal for this plugin")));
//languageService.doDiagnostics(document, () -> {}, new XMLValidationSettings()).forEach(diag -> System.out.println(diag.toString()));
assertTrue(languageService.doDiagnostics(document, () -> {}, new XMLValidationSettings()).size() == 2);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
<version>3.8.0</version>
<configuration>
<source>true</source>
<notValidConfig><!-- This tag should cause a warning --></notValidConfig>
<anotherNotValidConfig><!-- This tag should cause a warning --></anotherNotValidConfig>
</configuration>
</plugin>
</plugins>
Expand Down
37 changes: 37 additions & 0 deletions lemminx-maven/src/test/resources/pom-plugin-goal-diagnostic.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>

<groupId>org.test</groupId>
<artifactId>test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version> <!-- Need to be same as in lemminx-maven pom so we're sure version in in local repo -->
<executions>
<execution>
<id>execution1</id>
<goals><goal>test</goal></goals>
</execution>
<execution>
<id>execution2</id>
<goals><goal>invalid-goal</goal></goals>
<configuration>

</configuration>
</execution>
<execution>
<id>execution3</id>
<goals><goal>another-invalid-goal</goal></goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

0 comments on commit 98b44e0

Please sign in to comment.