diff --git a/headless-services/spring-boot-language-server/.classpath b/headless-services/spring-boot-language-server/.classpath
index cb7220e87..5a94da1a3 100644
--- a/headless-services/spring-boot-language-server/.classpath
+++ b/headless-services/spring-boot-language-server/.classpath
@@ -34,19 +34,16 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/headless-services/spring-boot-language-server/pom.xml b/headless-services/spring-boot-language-server/pom.xml
index 5a42bf130..4595a2f50 100644
--- a/headless-services/spring-boot-language-server/pom.xml
+++ b/headless-services/spring-boot-language-server/pom.xml
@@ -22,6 +22,17 @@
${project.name}-repo
file://${project.basedir}/repo
+
+
+ oss-jfrog-snapshots
+ https://oss.jfrog.org/artifactory/libs-snapshot
+
+
+ true
+
+
@@ -78,12 +89,24 @@
commons-io
${commons-io-version}
-
-
+
+ org.lsp4xml
+ org.eclipse.lsp4xml
+ 0.3.0-SNAPSHOT
+
+
+ org.eclipse.lsp4j
+ org.eclipse.lsp4j
+
+
+ org.eclipse.lsp4j
+ org.eclipse.lsp4j.jsonrpc
+
+
+
+
+
org.springframework.boot
diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/DocumentUtils.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/DocumentUtils.java
new file mode 100644
index 000000000..dbd822582
--- /dev/null
+++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/DocumentUtils.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2019 Pivotal, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springframework.ide.vscode.boot.java.utils;
+
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.springframework.ide.vscode.commons.util.text.LanguageId;
+import org.springframework.ide.vscode.commons.util.text.TextDocument;
+
+public class DocumentUtils {
+
+ public static TextDocument getTempTextDocument(String docURI, AtomicReference docRef, String content) throws Exception {
+ TextDocument doc = docRef.get();
+ if (doc == null) {
+ doc = createTempTextDocument(docURI, content);
+ docRef.set(doc);
+ }
+ return doc;
+ }
+
+ private static TextDocument createTempTextDocument(String docURI, String content) throws Exception {
+ if (content == null) {
+ Path path = Paths.get(new URI(docURI));
+ content = new String(Files.readAllBytes(path));
+ }
+
+ TextDocument doc = new TextDocument(docURI, LanguageId.PLAINTEXT, 0, content);
+ return doc;
+ }
+
+}
diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexerJava.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexerJava.java
index 8a0d76076..a66b44820 100644
--- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexerJava.java
+++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexerJava.java
@@ -11,9 +11,7 @@
package org.springframework.ide.vscode.boot.java.utils;
import java.io.File;
-import java.net.URI;
import java.nio.file.Files;
-import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.List;
@@ -46,7 +44,6 @@ import org.springframework.ide.vscode.commons.java.IClasspath;
import org.springframework.ide.vscode.commons.java.IClasspathUtil;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.util.UriUtil;
-import org.springframework.ide.vscode.commons.util.text.LanguageId;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
/**
@@ -222,7 +219,7 @@ public class SpringIndexerJava implements SpringIndexer {
private void extractSymbolInformation(IJavaProject project, TypeDeclaration typeDeclaration, String docURI, AtomicReference docRef, String content) throws Exception {
Collection providers = symbolProviders.getAll();
if (!providers.isEmpty()) {
- TextDocument doc = getTempTextDocument(docURI, docRef, content);
+ TextDocument doc = DocumentUtils.getTempTextDocument(docURI, docRef, content);
for (SymbolProvider provider : providers) {
Collection sbls = provider.getSymbols(typeDeclaration, doc);
if (sbls != null) {
@@ -237,7 +234,7 @@ public class SpringIndexerJava implements SpringIndexer {
private void extractSymbolInformation(IJavaProject project, MethodDeclaration methodDeclaration, String docURI, AtomicReference docRef, String content) throws Exception {
Collection providers = symbolProviders.getAll();
if (!providers.isEmpty()) {
- TextDocument doc = getTempTextDocument(docURI, docRef, content);
+ TextDocument doc = DocumentUtils.getTempTextDocument(docURI, docRef, content);
for (SymbolProvider provider : providers) {
Collection sbls = provider.getSymbols(methodDeclaration, doc);
if (sbls != null) {
@@ -256,7 +253,7 @@ public class SpringIndexerJava implements SpringIndexer {
Collection providers = symbolProviders.get(typeBinding);
Collection metaAnnotations = AnnotationHierarchies.getMetaAnnotations(typeBinding, symbolProviders::containsKey);
if (!providers.isEmpty()) {
- TextDocument doc = getTempTextDocument(docURI, docRef, content);
+ TextDocument doc = DocumentUtils.getTempTextDocument(docURI, docRef, content);
for (SymbolProvider provider : providers) {
Collection sbls = provider.getSymbols(node, typeBinding, metaAnnotations, doc);
if (sbls != null) {
@@ -280,7 +277,7 @@ public class SpringIndexerJava implements SpringIndexer {
if (type != null) {
String qualifiedName = type.getQualifiedName();
if (qualifiedName != null && qualifiedName.startsWith("org.springframework")) {
- TextDocument doc = getTempTextDocument(docURI, docRef, content);
+ TextDocument doc = DocumentUtils.getTempTextDocument(docURI, docRef, content);
return DefaultSymbolProvider.provideDefaultSymbol(node, doc);
}
}
@@ -301,23 +298,4 @@ public class SpringIndexerJava implements SpringIndexer {
.toArray(String[]::new);
}
- private TextDocument getTempTextDocument(String docURI, AtomicReference docRef, String content) throws Exception {
- TextDocument doc = docRef.get();
- if (doc == null) {
- doc = createTempTextDocument(docURI, content);
- docRef.set(doc);
- }
- return doc;
- }
-
- private TextDocument createTempTextDocument(String docURI, String content) throws Exception {
- if (content == null) {
- Path path = Paths.get(new URI(docURI));
- content = new String(Files.readAllBytes(path));
- }
-
- TextDocument doc = new TextDocument(docURI, LanguageId.PLAINTEXT, 0, content);
- return doc;
- }
-
}
diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexerXML.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexerXML.java
index 116cddb8f..34e786e47 100644
--- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexerXML.java
+++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexerXML.java
@@ -10,27 +10,23 @@
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.utils;
-import java.io.ByteArrayInputStream;
import java.io.File;
-import java.io.FileInputStream;
-import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
-import javax.xml.stream.XMLEventReader;
-import javax.xml.stream.XMLInputFactory;
-import javax.xml.stream.events.Characters;
-import javax.xml.stream.events.EndElement;
-import javax.xml.stream.events.StartElement;
-import javax.xml.stream.events.XMLEvent;
-
+import org.apache.commons.io.FileUtils;
+import org.eclipse.lsp4xml.dom.DOMDocument;
+import org.eclipse.lsp4xml.dom.DOMNode;
+import org.eclipse.lsp4xml.dom.DOMParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.util.UriUtil;
+import org.springframework.ide.vscode.commons.util.text.TextDocument;
/**
* @author Martin Lippert
@@ -39,11 +35,11 @@ public class SpringIndexerXML implements SpringIndexer {
private static final Logger log = LoggerFactory.getLogger(SpringIndexerJava.class);
- private final SymbolHandler handler;
+ private final SymbolHandler symbolHandler;
private final Map namespaceHandler;
public SpringIndexerXML(SymbolHandler handler, Map namespaceHandler) {
- this.handler = handler;
+ this.symbolHandler = handler;
this.namespaceHandler = namespaceHandler;
}
@@ -70,7 +66,7 @@ public class SpringIndexerXML implements SpringIndexer {
@Override
public void updateFile(IJavaProject project, String docURI, String content) throws Exception {
- scanFile(project, new ByteArrayInputStream(content.getBytes()), docURI);
+ scanFile(project, content, docURI);
}
private void scanProject(IJavaProject project, String[] files) {
@@ -79,52 +75,55 @@ public class SpringIndexerXML implements SpringIndexer {
}
}
- private void scanFile(IJavaProject project, String file) {
- log.debug("starting to parse XML file for Spring symbol indexing: ", file);
+ private void scanFile(IJavaProject project, String fileName) {
+ log.debug("starting to parse XML file for Spring symbol indexing: ", fileName);
try {
- String docURI = UriUtil.toUri(new File(file)).toString();
+ File file = new File(fileName);
- InputStream xmlInputStream = new FileInputStream(file);
- scanFile(project, xmlInputStream, docURI);
+ String docURI = UriUtil.toUri(file).toString();
+ String fileContent = FileUtils.readFileToString(file);
+
+ scanFile(project, fileContent, docURI);
}
catch (Exception e) {
log.error("error parsing XML file: ", e);
}
}
- private void scanFile(IJavaProject project, InputStream xmlInput, String docURI) throws Exception {
- XMLInputFactory inputFactory = XMLInputFactory.newInstance();
- XMLEventReader eventReader = inputFactory.createXMLEventReader(xmlInput);
+ private void scanFile(IJavaProject project, String fileContent, String docURI) throws Exception {
+ DOMParser parser = DOMParser.getInstance();
+ DOMDocument document = parser.parse(fileContent, "", null);
- while (eventReader.hasNext()) {
- XMLEvent event = eventReader.nextEvent();
- switch (event.getEventType()) {
-
- case XMLEvent.START_ELEMENT:
- StartElement startElement = event.asStartElement();
-
- String namespaceURI = startElement.getName().getNamespaceURI();
- if (namespaceURI != null && this.namespaceHandler.containsKey(namespaceURI)) {
- SpringIndexerXMLNamespaceHandler namespaceHandler = this.namespaceHandler.get(namespaceURI);
- namespaceHandler.processStartElement(project, docURI, startElement, this.handler);
- }
-
- break;
-
- case XMLEvent.CHARACTERS:
- Characters characters = event.asCharacters();
- log.debug(characters.getData());
- break;
- case XMLEvent.END_ELEMENT:
- EndElement endElement = event.asEndElement();
- log.debug("" + endElement.getName().toString() + ">");
- break;
- default:
- // do nothing
- break;
- }
- }
+ AtomicReference docRef = new AtomicReference<>();
+ scanNode(document, project, docURI, docRef, fileContent);
}
+ private void scanNode(DOMNode node, IJavaProject project, String docURI, AtomicReference docRef, String content) throws Exception {
+ String namespaceURI = node.getNamespaceURI();
+
+ if (namespaceURI != null && this.namespaceHandler.containsKey(namespaceURI)) {
+ SpringIndexerXMLNamespaceHandler namespaceHandler = this.namespaceHandler.get(namespaceURI);
+
+ TextDocument document = DocumentUtils.getTempTextDocument(docURI, docRef, content);
+ namespaceHandler.processNode(node, project, docURI, document, this.symbolHandler);
+ }
+
+
+// if ("http://www.springframework.org/schema/beans".equals(namespaceURI)) {
+// List attributeNodes = node.getAttributeNodes();
+// if (attributeNodes != null) {
+// for (DOMAttr attribute : attributeNodes) {
+// System.out.println(attribute.getName() + " - " + attribute.getValue());
+// }
+// }
+// }
+
+ List children = node.getChildren();
+ for (DOMNode child : children) {
+ scanNode(child, project, docURI, docRef, content);
+ }
+
+
+ }
}
diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexerXMLNamespaceHandler.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexerXMLNamespaceHandler.java
index de06859a9..cd020a079 100644
--- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexerXMLNamespaceHandler.java
+++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexerXMLNamespaceHandler.java
@@ -10,15 +10,15 @@
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.utils;
-import javax.xml.stream.events.StartElement;
-
+import org.eclipse.lsp4xml.dom.DOMNode;
import org.springframework.ide.vscode.commons.java.IJavaProject;
+import org.springframework.ide.vscode.commons.util.text.TextDocument;
/**
* @author Martin Lippert
*/
public interface SpringIndexerXMLNamespaceHandler {
- void processStartElement(IJavaProject project, String docURI, StartElement startElement, SymbolHandler handler);
+ void processNode(DOMNode node, IJavaProject project, String docURI, TextDocument document, SymbolHandler symbolHandler) throws Exception;
}
diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexerXMLNamespaceHandlerBeans.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexerXMLNamespaceHandlerBeans.java
index 2a356b62d..e92851c0b 100644
--- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexerXMLNamespaceHandlerBeans.java
+++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexerXMLNamespaceHandlerBeans.java
@@ -10,18 +10,18 @@
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.utils;
-import java.util.Iterator;
-
-import javax.xml.stream.events.Attribute;
-import javax.xml.stream.events.StartElement;
+import java.util.List;
import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.SymbolInformation;
import org.eclipse.lsp4j.SymbolKind;
+import org.eclipse.lsp4xml.dom.DOMAttr;
+import org.eclipse.lsp4xml.dom.DOMNode;
import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformation;
import org.springframework.ide.vscode.commons.java.IJavaProject;
+import org.springframework.ide.vscode.commons.util.text.TextDocument;
/**
* @author Martin Lippert
@@ -29,24 +29,28 @@ import org.springframework.ide.vscode.commons.java.IJavaProject;
public class SpringIndexerXMLNamespaceHandlerBeans implements SpringIndexerXMLNamespaceHandler {
@Override
- public void processStartElement(IJavaProject project, String docURI, StartElement startElement, SymbolHandler handler) {
- String localPart = startElement.getName().getLocalPart();
- if (localPart != null && "bean".equals(localPart)) {
- createBeanSymbol(project, docURI, startElement, handler);
+ public void processNode(DOMNode node, IJavaProject project, String docURI, TextDocument document, SymbolHandler symbolHandler) throws Exception {
+ String localName = node.getLocalName();
+ if (localName != null && "bean".equals(localName)) {
+ createBeanSymbol(node, project, docURI, document, symbolHandler);
}
}
- private void createBeanSymbol(IJavaProject project, String docURI, StartElement startElement, SymbolHandler handler) {
+ private void createBeanSymbol(DOMNode node, IJavaProject project, String docURI, TextDocument document, SymbolHandler symbolHandler) throws Exception {
String beanID = null;
+ int beanIDStart = 0;
+ int beanIDEnd = 0;
+
String beanClass = null;
- Iterator> attributes = startElement.getAttributes();
- while (attributes.hasNext()) {
- Attribute attribute = (Attribute) attributes.next();
+ List attributes = node.getAttributeNodes();
+ for (DOMAttr attribute : attributes) {
- String name = attribute.getName().getLocalPart();
+ String name = attribute.getName();
if (name != null && name.equals("id")) {
beanID = attribute.getValue();
+ beanIDStart = attribute.getStart();
+ beanIDEnd = attribute.getEnd();
}
else if (name != null && name.equals("class")) {
String value = attribute.getValue();
@@ -55,9 +59,15 @@ public class SpringIndexerXMLNamespaceHandlerBeans implements SpringIndexerXMLNa
}
if (beanID != null && beanClass != null) {
+ int lineStart = document.getLineOfOffset(beanIDStart);
+ int lineEnd = document.getLineOfOffset(beanIDEnd);
+
+ int startInLine = beanIDStart - document.getLineOffset(lineStart);
+ int endInLine = beanIDEnd - document.getLineOffset(lineEnd);
+
Range range = new Range();
- range.setStart(new Position(startElement.getLocation().getLineNumber(), startElement.getLocation().getColumnNumber()));
- range.setEnd(new Position(startElement.getLocation().getLineNumber(), startElement.getLocation().getColumnNumber() + 1));
+ range.setStart(new Position(lineStart + 1, startInLine));
+ range.setEnd(new Position(lineEnd + 1, endInLine));
Location location = new Location();
location.setUri(docURI);
@@ -66,7 +76,7 @@ public class SpringIndexerXMLNamespaceHandlerBeans implements SpringIndexerXMLNa
SymbolInformation symbol = new SymbolInformation("@+ '" + beanID + "' " + beanClass, SymbolKind.Interface, new Location(docURI, range));
EnhancedSymbolInformation fullSymbol = new EnhancedSymbolInformation(symbol, null);
- handler.addSymbol(project, docURI, fullSymbol);
+ symbolHandler.addSymbol(project, docURI, fullSymbol);
}
}
diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/utils/test/SpringIndexerXMLProjectTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/utils/test/SpringIndexerXMLProjectTest.java
index 5cc57a32f..e4d3f918b 100644
--- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/utils/test/SpringIndexerXMLProjectTest.java
+++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/utils/test/SpringIndexerXMLProjectTest.java
@@ -73,9 +73,9 @@ public class SpringIndexerXMLProjectTest {
assertEquals(3, allSymbols.size());
String docUri = directory.toPath().resolve("config/simple-spring-config.xml").toUri().toString();
- assertTrue(containsSymbol(allSymbols, "@+ 'transactionManager' DataSourceTransactionManager", docUri, 7, 143, 7, 144));
- assertTrue(containsSymbol(allSymbols, "@+ 'jdbcTemplate' JdbcTemplate", docUri, 9, 84, 9, 85));
- assertTrue(containsSymbol(allSymbols, "@+ 'namedParameterJdbcTemplate' NamedParameterJdbcTemplate", docUri, 14, 91, 14, 92));
+ assertTrue(containsSymbol(allSymbols, "@+ 'transactionManager' DataSourceTransactionManager", docUri, 7, 14, 7, 37));
+ assertTrue(containsSymbol(allSymbols, "@+ 'jdbcTemplate' JdbcTemplate", docUri, 9, 14, 9, 31));
+ assertTrue(containsSymbol(allSymbols, "@+ 'namedParameterJdbcTemplate' NamedParameterJdbcTemplate", docUri, 13, 14, 13, 45));
}
private boolean containsSymbol(List extends SymbolInformation> symbols, String name, String uri, int startLine, int startCHaracter, int endLine, int endCharacter) {