Bug 569345 - duplicate entries in open declaration (F3 and CTRL click)

use a Map (Location->Link) instead of List to filter out duplicate links
that point to the same location

Change-Id: I5a998afde1abdb6826ded1b05b7a264894bfc68a
Signed-off-by: Johan Compagner <jcompagner@gmail.com>
diff --git a/org.eclipse.lsp4e/META-INF/MANIFEST.MF b/org.eclipse.lsp4e/META-INF/MANIFEST.MF
index e1265d1..234f596 100644
--- a/org.eclipse.lsp4e/META-INF/MANIFEST.MF
+++ b/org.eclipse.lsp4e/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: Language Server Protocol client for Eclipse IDE (Incubation)
 Bundle-SymbolicName: org.eclipse.lsp4e;singleton:=true
-Bundle-Version: 0.13.4.qualifier
+Bundle-Version: 0.13.5.qualifier
 Bundle-RequiredExecutionEnvironment: JavaSE-11
 Require-Bundle: org.eclipse.core.runtime;bundle-version="3.12.0",
  org.eclipse.equinox.common;bundle-version="3.8.0",
diff --git a/org.eclipse.lsp4e/pom.xml b/org.eclipse.lsp4e/pom.xml
index b554cc8..c218b51 100644
--- a/org.eclipse.lsp4e/pom.xml
+++ b/org.eclipse.lsp4e/pom.xml
@@ -7,7 +7,7 @@
 	</parent>
 	<artifactId>org.eclipse.lsp4e</artifactId>
 	<packaging>eclipse-plugin</packaging>
-	<version>0.13.4-SNAPSHOT</version>
+	<version>0.13.5-SNAPSHOT</version>
 	
 	<build>
 		<plugins>
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/declaration/OpenDeclarationHyperlinkDetector.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/declaration/OpenDeclarationHyperlinkDetector.java
index d240bbd..f089868 100644
--- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/declaration/OpenDeclarationHyperlinkDetector.java
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/declaration/OpenDeclarationHyperlinkDetector.java
@@ -17,7 +17,9 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
@@ -64,7 +66,7 @@
 		}
 		IRegion r = findWord(textViewer.getDocument(), region.getOffset());
 		final IRegion linkRegion = r != null ? r : region;
-		Collection<LSBasedHyperlink> allLinks = Collections.synchronizedList(new ArrayList<>());
+		Map<Either<Location, LocationLink>,LSBasedHyperlink> allLinks = Collections.synchronizedMap(new LinkedHashMap<>());
 		try {
 			// Collect definitions
 			Collection<CompletableFuture<Either<List<? extends Location>, List<? extends LocationLink>>>> allFutures = Collections.synchronizedCollection(new ArrayList<>());
@@ -84,7 +86,9 @@
 				future.thenAccept(locations -> {
 					Collection<LSBasedHyperlink> links = toHyperlinks(document, linkRegion, locations);
 					synchronized (allLinks) {
-						allLinks.addAll(links);
+						links.forEach(link -> {
+							allLinks.putIfAbsent(link.getLocation(), link);
+						});
 					}
 				})).toArray(CompletableFuture[]::new))
 			).get(500, TimeUnit.MILLISECONDS);
@@ -97,7 +101,7 @@
 		if (allLinks.isEmpty()) {
 			return null;
 		}
-		return allLinks.toArray(new IHyperlink[allLinks.size()]);
+		return allLinks.values().toArray(new IHyperlink[allLinks.size()]);
 	}
 
 	/**