Skip to content

Commit

Permalink
Navigation / Historical Behaviors have changed / Round 2 eclipse#405
Browse files Browse the repository at this point in the history
  • Loading branch information
vrubezhny committed Jul 5, 2023
1 parent ef1969b commit 4d49474
Show file tree
Hide file tree
Showing 9 changed files with 443 additions and 52 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2020-2023 Red Hat Inc. and others.
* Copyright (c) 2020, 2023 Red Hat Inc. and others.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
Expand All @@ -25,6 +25,7 @@

import org.apache.maven.Maven;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.InputLocation;
import org.apache.maven.project.MavenProject;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.lemminx.dom.DOMDocument;
Expand Down Expand Up @@ -92,15 +93,23 @@ public void findDefinition(IDefinitionRequest request, List<LocationLink> locati
// Find in workspace
if (ParticipantUtils.isWellDefinedDependency(dependency)) {
cancelChecker.checkCanceled();
Artifact artifact = ParticipantUtils.findWorkspaceArtifact(plugin, request, dependency);
if (artifact != null && artifact.getFile() != null) {
LocationLink location = toLocationNoRange(artifact.getFile(), element);
if (location != null) {
cancelChecker.checkCanceled();
locations.add(location);
return;

LocationLink location = null;
Optional<Dependency> managed = ParticipantUtils.findManagedDependency(p, dependency);
if (managed.isPresent()) {
location = toLocation(managed.get().getLocation("artifactId"),
XMLPositionUtility.createRange(element));
} else {
Artifact artifact = ParticipantUtils.findWorkspaceArtifact(plugin, request, dependency);
if (artifact != null && artifact.getFile() != null) {
location = toLocationNoRange(artifact.getFile(), element);
}
}
if (location != null) {
cancelChecker.checkCanceled();
locations.add(location);
return;
}
}

cancelChecker.checkCanceled();
Expand Down Expand Up @@ -139,10 +148,21 @@ public void findDefinition(IDefinitionRequest request, List<LocationLink> locati
cancelChecker.checkCanceled();
// Find in workspace
if (ParticipantUtils.isWellDefinedDependency(dependency)) {
Artifact artifact = ParticipantUtils.findWorkspaceArtifact(plugin, request, dependency);
if (artifact != null && artifact.getFile() != null) {
LocationLink location = null;
Optional<Dependency> managed = ParticipantUtils.isManagedDependency(element) ?
Optional.empty() : ParticipantUtils.findManagedDependency(p, dependency);
if (managed.isPresent()) {
location = toLocation(managed.get().getLocation("artifactId"),
XMLPositionUtility.createRange(element));
} else {
Artifact artifact = ParticipantUtils.findWorkspaceArtifact(plugin, request, dependency);
if (artifact != null && artifact.getFile() != null) {
location = toLocationNoRange(artifact.getFile(), element);
}
}
if (location != null) {
cancelChecker.checkCanceled();
locations.add(toLocationNoRange(artifact.getFile(), element));
locations.add(location);
return;
}
}
Expand Down Expand Up @@ -229,4 +249,14 @@ private static LocationLink toLocation(File target, DOMNode targetNode, Range or
Range targetRange = XMLPositionUtility.createRange(targetNode);
return new LocationLink(target.toURI().toString(), targetRange, targetRange, originRange);
}

private static LocationLink toLocation(InputLocation target, Range originRange) {
if (target == null || target.getSource() == null || target.getSource().getLocation() == null) {
return null;
}
Position position = new Position(target.getLineNumber(), target.getColumnNumber());
Range targetRange = new Range(position, position);
File file = new File(target.getSource().getLocation());
return new LocationLink(file.toURI().toString(), targetRange, targetRange, originRange);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2020-2023 Red Hat Inc. and others.
* Copyright (c) 2020, 2023 Red Hat Inc. and others.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
Expand Down Expand Up @@ -68,6 +68,7 @@
import org.eclipse.lsp4j.Hover;
import org.eclipse.lsp4j.MarkupContent;
import org.eclipse.lsp4j.MarkupKind;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.jsonrpc.CancelChecker;

Expand Down Expand Up @@ -292,18 +293,30 @@ private static File getParentPomFile (MavenProject project, DOMDocument documen
private static String createVersionMessage(boolean supportsMarkdown, String version, InputLocation location) {
String sourceModelId = null;
String uri = null;
Range range = null;
if (location != null) {
InputSource source = location.getSource();
if (source != null) {
sourceModelId = source.getModelId();
uri = source.getLocation();
}

int lineNumber = location.getLineNumber();
if (lineNumber != -1) {
int columnNumber = location.getColumnNumber();
Position position = new Position(lineNumber, columnNumber != -1 ? columnNumber : 0);
range = new Range(position, position);
}
}

return createVersionMessage(supportsMarkdown, version, sourceModelId, uri);
return createVersionMessage(supportsMarkdown, version, sourceModelId, uri, range);
}

private static String createVersionMessage(boolean supportsMarkdown, String version, String sourceModelId, String uri) {
return createVersionMessage(supportsMarkdown, version, sourceModelId, uri, null);
}

private static String createVersionMessage(boolean supportsMarkdown, String version, String sourceModelId, String uri, Range range) {
UnaryOperator<String> toBold = supportsMarkdown ? MarkdownUtils::toBold : UnaryOperator.identity();

String message = (version != null)
Expand All @@ -312,7 +325,7 @@ private static String createVersionMessage(boolean supportsMarkdown, String vers

if (sourceModelId != null) {
message += ' ' + toBold.apply(MessageFormat.format(PomTextHover_managed_location,
supportsMarkdown ? MarkdownUtils.toLink(uri, sourceModelId, null) : sourceModelId));
supportsMarkdown ? MarkdownUtils.toLink(uri, range, sourceModelId, sourceModelId) : sourceModelId));
} else {
message += ' ' + toBold.apply(PomTextHover_managed_location_missing);
}
Expand Down Expand Up @@ -361,14 +374,29 @@ private Hover collectArtifactDescription(IHoverRequest request, CancelChecker ca
boolean wellDefined = ParticipantUtils.isWellDefinedDependency(dependency);
DOMElement element = ParticipantUtils.findInterestingElement(request.getNode());
dependency = ParticipantUtils.resolveDependency(p, dependency, element, plugin);

Optional<Dependency> managed = ParticipantUtils.isManagedDependency(element) ?
Optional.empty() : ParticipantUtils.findManagedDependency(p, dependency);

Dependency originalDependency = dependency; // To get the scope
cancelChecker.checkCanceled();
try {
ModelBuilder builder = plugin.getProjectCache().getPlexusContainer().lookup(ModelBuilder.class);
// Find in local repository
File localArtifactLocation = plugin.getLocalRepositorySearcher().findLocalFile(dependency);
File localArtifactLocation = null;
if (managed.isPresent()) {
// Use managed dependency
dependency = managed.get();
InputLocation inputLocation = dependency.getLocation(ARTIFACT_ID_ELT);
if (inputLocation != null && inputLocation.getSource() != null) {
String url = inputLocation.getSource().getLocation();
localArtifactLocation = new File(url);
}
} else {
localArtifactLocation = plugin.getLocalRepositorySearcher().findLocalFile(dependency);
}

if (localArtifactLocation != null && localArtifactLocation.isFile()) {
cancelChecker.checkCanceled();
ModelBuilder builder = plugin.getProjectCache().getPlexusContainer().lookup(ModelBuilder.class);
Model model = builder.buildRawModel(localArtifactLocation, ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL, true).get();
if (model != null) {
UnaryOperator<String> toBold = supportsMarkdown ? MarkdownUtils::toBold
Expand All @@ -385,7 +413,9 @@ private Hover collectArtifactDescription(IHoverRequest request, CancelChecker ca
}

if (!wellDefined) {
String managedVersion = getManagedVersionText(request, cancelChecker);
String managedVersion = managed.isPresent() ?
createVersionMessage(request.canSupportMarkupKind(MarkupKind.MARKDOWN), dependency.getVersion(), dependency.getLocation(ARTIFACT_ID_ELT))
: getManagedVersionText(request, cancelChecker);
if (managedVersion == null) {
managedVersion = getActualVersionText(supportsMarkdown, model);
}
Expand All @@ -394,9 +424,13 @@ private Hover collectArtifactDescription(IHoverRequest request, CancelChecker ca
}
}

// Add dependency scope info
if (dependency.getScope() != null) {
message += lineBreak + toBold.apply(MessageFormat.format(PomTextHover_managed_scope, dependency.getScope()));
// Dependency scope info from original dependency has higher priority
String scope = dependency.getScope();
if (originalDependency.getScope() != null) {
scope = originalDependency.getScope();
}
if (scope != null) {
message += lineBreak + toBold.apply(MessageFormat.format(PomTextHover_managed_scope, scope));
}

if (message.length() > 2) {
Expand Down Expand Up @@ -549,7 +583,7 @@ private Hover collectProperty(IHoverRequest request, Map.Entry<Range, String> pr

if (propertyDeclaration != null) {
cancelChecker.checkCanceled();
String uri = childProj.getFile().toURI().toString();
String uri = childProj.getFile().getAbsolutePath();
Range targetRange = XMLPositionUtility.createRange(propertyDeclaration);
String sourceModelId = childProj.getGroupId() + ':' + childProj.getArtifactId() + ':' + childProj.getVersion();
message.append(toBold.apply(MessageFormat.format(PomTextHover_property_location,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
*******************************************************************************/
package org.eclipse.lemminx.extensions.maven.utils;

import java.io.File;
import java.util.Arrays;
import java.util.Objects;

Expand Down Expand Up @@ -62,7 +63,7 @@ public static String toLink(String uri, Range range, String message, String titl
// [Message](http://example.com/ "Title")
link.append('[').append(message != null ? message : "This link").append(']');
if (uri != null) {
link.append('(').append(uri);
link.append('(').append(new File(uri).toURI().toString());
if(range != null && (range.getStart() != null || range.getEnd() != null)) {
// #L34,1-L35,3
StringBuilder selection = new StringBuilder();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
package org.eclipse.lemminx.extensions.maven.utils;

import static org.eclipse.lemminx.extensions.maven.DOMConstants.ARTIFACT_ID_ELT;
import static org.eclipse.lemminx.extensions.maven.DOMConstants.DEPENDENCIES_ELT;
import static org.eclipse.lemminx.extensions.maven.DOMConstants.DEPENDENCY_ELT;
import static org.eclipse.lemminx.extensions.maven.DOMConstants.DEPENDENCY_MANAGEMENT_ELT;
import static org.eclipse.lemminx.extensions.maven.DOMConstants.GROUP_ID_ELT;
import static org.eclipse.lemminx.extensions.maven.DOMConstants.MODULE_ELT;
import static org.eclipse.lemminx.extensions.maven.DOMConstants.PARENT_ELT;
Expand All @@ -23,16 +25,20 @@

import java.net.URI;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.commons.lang3.Validate;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.DependencyManagement;
import org.apache.maven.plugin.InvalidPluginDescriptorException;
import org.apache.maven.plugin.PluginDescriptorParsingException;
import org.apache.maven.plugin.PluginResolutionException;
Expand Down Expand Up @@ -194,6 +200,24 @@ public static boolean isDependency(DOMElement element) {
(element.getParentElement() != null && DEPENDENCY_ELT.equals(element.getParentElement().getLocalName()));
}

public static boolean isManagedDependency(DOMElement element) {
DOMElement parent = element;
// Find dependency element
while (parent != null && !DEPENDENCY_ELT.equals(parent.getLocalName())) {
parent = parent.getParentElement();
}
if (parent == null) {
return false;
}
// Check if parent is dependencies element
parent = parent.getParentElement();
if (parent == null || !DEPENDENCIES_ELT.equals(parent.getLocalName())) {
return false;
}
// Check if parent is dependencyManagement element
parent = parent.getParentElement();
return (parent != null && DEPENDENCY_MANAGEMENT_ELT.equals(parent.getLocalName()));
}

public static boolean isPlugin(DOMElement element) {
return PLUGIN_ELT.equals(element.getLocalName()) ||
Expand Down Expand Up @@ -356,4 +380,35 @@ public static String getDocumentLineSeparator(DOMDocument document) {
return (lineDelimiter == null || lineDelimiter.isEmpty())
? System.lineSeparator() : lineDelimiter;
}

public static Optional<Dependency> findManagedDependency(MavenProject project, Dependency dependency) {
// Search in Managed Demendencies
// collect the managed dep ids
List<Dependency> managed = new ArrayList<>();
DependencyManagement dm = project.getDependencyManagement();
if (dm != null) {
List<Dependency> deps = dm.getDependencies();
if (deps != null) {
// #335366
// 355882 use dep.getManagementKey() to prevent false positives
// when type or classifier doesn't match
deps.stream()
.filter(dep -> dep.getLocation("artifactId") != null)
.filter(dep -> dependency.getGroupId() != null && dependency.getGroupId().equals(dep.getGroupId()))
.filter(dep -> dependency.getArtifactId() != null && dependency.getArtifactId().equals(dep.getArtifactId()))
.filter(dep -> dependency.getVersion() != null && dependency.getVersion().equals(dep.getVersion()))
.forEach(managed::add);
}
}

return managed.stream()
.sorted(new Comparator<Dependency>() {
// Backward order
@Override
public int compare(Dependency o1, Dependency o2) {
return new DefaultArtifactVersion(o2.getVersion())
.compareTo(new DefaultArtifactVersion(o1.getVersion()));
}
}).findFirst();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2019-2022 Red Hat Inc. and others.
* Copyright (c) 2019, 2023 Red Hat Inc. and others.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
Expand Down Expand Up @@ -71,6 +71,7 @@ public void testDoNotCompleteNonExistingArtifact()
@Test
public void testDefinitionManagedDependency() throws IOException, URISyntaxException {
assertTrue(languageService.findDefinition(createDOMDocument("/pom-dependencyManagement-child.xml", languageService), new Position(17, 6), () -> {})
.stream().map(LocationLink::getTargetUri).anyMatch(uri -> uri.endsWith("maven-surefire-plugin-2.22.2.pom")));
.stream().map(LocationLink::getTargetUri)
.anyMatch(uri -> uri.endsWith("/pom-dependencyManagement-parent.xml")));
}
}
Loading

0 comments on commit 4d49474

Please sign in to comment.