diff --git a/eclipse-distribution/org.springframework.boot.ide.branding/about.properties b/eclipse-distribution/org.springframework.boot.ide.branding/about.properties index 80e2eb3eb..a315d00f0 100644 --- a/eclipse-distribution/org.springframework.boot.ide.branding/about.properties +++ b/eclipse-distribution/org.springframework.boot.ide.branding/about.properties @@ -9,7 +9,7 @@ title=Spring Tool Suite 4\n\ Version: @QUALIFIER@\n\ Build Id: @BUILD_ID@\n\ \n\ -Copyright (c) 2007 - 2017 Pivotal Software, Inc.\n\ +Copyright (c) 2007 - 2018 Pivotal Software, Inc.\n\ All rights reserved. Visit http://spring.io/tools/sts\n\ \n\ This product includes software developed by the\n\ diff --git a/eclipse-distribution/org.springframework.boot.ide.branding/plugin.properties b/eclipse-distribution/org.springframework.boot.ide.branding/plugin.properties index d8aefdd87..025ddef0a 100644 --- a/eclipse-distribution/org.springframework.boot.ide.branding/plugin.properties +++ b/eclipse-distribution/org.springframework.boot.ide.branding/plugin.properties @@ -7,7 +7,7 @@ productBlurb=Spring Tool Suite 4 \n\ Version: @QUALIFIER@\n\ Build Id: @BUILD_ID@\n\ \n\ -Copyright (c) 2007 - 2017 Pivotal Software, Inc.\n\ +Copyright (c) 2007 - 2018 Pivotal Software, Inc.\n\ All rights reserved. Visit http://spring.io/tools/sts\n\ \n\ This product includes software developed by the\n\ diff --git a/eclipse-distribution/org.springframework.boot.ide.branding/splash.bmp b/eclipse-distribution/org.springframework.boot.ide.branding/splash.bmp index 69d311df1..dc17ab733 100644 Binary files a/eclipse-distribution/org.springframework.boot.ide.branding/splash.bmp and b/eclipse-distribution/org.springframework.boot.ide.branding/splash.bmp differ diff --git a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/BootJavaLanguageServer.java b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/BootJavaLanguageServer.java index 6779af88e..ac593e3a7 100644 --- a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/BootJavaLanguageServer.java +++ b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/BootJavaLanguageServer.java @@ -254,60 +254,36 @@ public class BootJavaLanguageServer extends SimpleLanguageServer { providers.put(org.springframework.ide.vscode.boot.java.value.Constants.SPRING_VALUE, new ValueHoverProvider()); - providers.put(Annotations.SPRING_REQUEST_MAPPING, - new RequestMappingHoverProvider()); - providers.put(Annotations.SPRING_GET_MAPPING, - new RequestMappingHoverProvider()); - providers.put(Annotations.SPRING_POST_MAPPING, - new RequestMappingHoverProvider()); - providers.put(Annotations.SPRING_PUT_MAPPING, - new RequestMappingHoverProvider()); - providers.put(Annotations.SPRING_DELETE_MAPPING, - new RequestMappingHoverProvider()); - providers.put(Annotations.SPRING_PATCH_MAPPING, - new RequestMappingHoverProvider()); + providers.put(Annotations.SPRING_REQUEST_MAPPING, new RequestMappingHoverProvider()); + providers.put(Annotations.SPRING_GET_MAPPING, new RequestMappingHoverProvider()); + providers.put(Annotations.SPRING_POST_MAPPING, new RequestMappingHoverProvider()); + providers.put(Annotations.SPRING_PUT_MAPPING, new RequestMappingHoverProvider()); + providers.put(Annotations.SPRING_DELETE_MAPPING, new RequestMappingHoverProvider()); + providers.put(Annotations.SPRING_PATCH_MAPPING, new RequestMappingHoverProvider()); providers.put(Annotations.PROFILE, new ActiveProfilesProvider()); providers.put(Annotations.AUTOWIRED, new AutowiredHoverProvider()); providers.put(Annotations.COMPONENT, new ComponentInjectionsHoverProvider()); providers.put(Annotations.BEAN, new BeanInjectedIntoHoverProvider()); - providers.put(Annotations.CONDITIONAL, - new ConditionalsLiveHoverProvider()); - providers.put(Annotations.CONDITIONAL_ON_BEAN, - new ConditionalsLiveHoverProvider()); - providers.put(Annotations.CONDITIONAL_ON_MISSING_BEAN, - new ConditionalsLiveHoverProvider()); - providers.put(Annotations.CONDITIONAL_ON_PROPERTY, - new ConditionalsLiveHoverProvider()); - providers.put(Annotations.CONDITIONAL_ON_RESOURCE, - new ConditionalsLiveHoverProvider()); - providers.put(Annotations.CONDITIONAL_ON_CLASS, - new ConditionalsLiveHoverProvider()); - providers.put(Annotations.CONDITIONAL_ON_MISSING_CLASS, - new ConditionalsLiveHoverProvider()); - providers.put(Annotations.CONDITIONAL_ON_CLOUD_PLATFORM, - new ConditionalsLiveHoverProvider()); - providers.put(Annotations.CONDITIONAL_ON_WEB_APPLICATION, - new ConditionalsLiveHoverProvider()); - providers.put(Annotations.CONDITIONAL_ON_NOT_WEB_APPLICATION, - new ConditionalsLiveHoverProvider()); - providers.put(Annotations.CONDITIONAL_ON_ENABLED_INFO_CONTRIBUTOR, - new ConditionalsLiveHoverProvider()); - providers.put(Annotations.CONDITIONAL_ON_ENABLED_RESOURCE_CHAIN, - new ConditionalsLiveHoverProvider()); - providers.put(Annotations.CONDITIONAL_ON_ENABLED_ENDPOINT, - new ConditionalsLiveHoverProvider()); - providers.put(Annotations.CONDITIONAL_ON_ENABLED_HEALTH_INDICATOR, - new ConditionalsLiveHoverProvider()); - providers.put(Annotations.CONDITIONAL_ON_EXPRESSION, - new ConditionalsLiveHoverProvider()); - providers.put(Annotations.CONDITIONAL_ON_JAVA, - new ConditionalsLiveHoverProvider()); - providers.put(Annotations.CONDITIONAL_ON_JNDI, - new ConditionalsLiveHoverProvider()); - providers.put(Annotations.CONDITIONAL_ON_SINGLE_CANDIDATE, - new ConditionalsLiveHoverProvider()); + providers.put(Annotations.CONDITIONAL, new ConditionalsLiveHoverProvider()); + providers.put(Annotations.CONDITIONAL_ON_BEAN, new ConditionalsLiveHoverProvider()); + providers.put(Annotations.CONDITIONAL_ON_MISSING_BEAN, new ConditionalsLiveHoverProvider()); + providers.put(Annotations.CONDITIONAL_ON_PROPERTY, new ConditionalsLiveHoverProvider()); + providers.put(Annotations.CONDITIONAL_ON_RESOURCE, new ConditionalsLiveHoverProvider()); + providers.put(Annotations.CONDITIONAL_ON_CLASS, new ConditionalsLiveHoverProvider()); + providers.put(Annotations.CONDITIONAL_ON_MISSING_CLASS, new ConditionalsLiveHoverProvider()); + providers.put(Annotations.CONDITIONAL_ON_CLOUD_PLATFORM, new ConditionalsLiveHoverProvider()); + providers.put(Annotations.CONDITIONAL_ON_WEB_APPLICATION, new ConditionalsLiveHoverProvider()); + providers.put(Annotations.CONDITIONAL_ON_NOT_WEB_APPLICATION, new ConditionalsLiveHoverProvider()); + providers.put(Annotations.CONDITIONAL_ON_ENABLED_INFO_CONTRIBUTOR, new ConditionalsLiveHoverProvider()); + providers.put(Annotations.CONDITIONAL_ON_ENABLED_RESOURCE_CHAIN, new ConditionalsLiveHoverProvider()); + providers.put(Annotations.CONDITIONAL_ON_ENABLED_ENDPOINT, new ConditionalsLiveHoverProvider()); + providers.put(Annotations.CONDITIONAL_ON_ENABLED_HEALTH_INDICATOR, new ConditionalsLiveHoverProvider()); + providers.put(Annotations.CONDITIONAL_ON_EXPRESSION, new ConditionalsLiveHoverProvider()); + providers.put(Annotations.CONDITIONAL_ON_JAVA, new ConditionalsLiveHoverProvider()); + providers.put(Annotations.CONDITIONAL_ON_JNDI, new ConditionalsLiveHoverProvider()); + providers.put(Annotations.CONDITIONAL_ON_SINGLE_CANDIDATE, new ConditionalsLiveHoverProvider()); return new BootJavaHoverProvider(this, javaProjectFinder, providers, runningAppProvider); } @@ -315,16 +291,11 @@ public class BootJavaLanguageServer extends SimpleLanguageServer { protected SpringIndexer createAnnotationIndexer(SimpleLanguageServer server, JavaProjectFinder projectFinder) { AnnotationHierarchyAwareLookup providers = new AnnotationHierarchyAwareLookup<>(); providers.put(Annotations.SPRING_REQUEST_MAPPING, new RequestMappingSymbolProvider()); - providers.put(Annotations.SPRING_GET_MAPPING, - new RequestMappingSymbolProvider()); - providers.put(Annotations.SPRING_POST_MAPPING, - new RequestMappingSymbolProvider()); - providers.put(Annotations.SPRING_PUT_MAPPING, - new RequestMappingSymbolProvider()); - providers.put(Annotations.SPRING_DELETE_MAPPING, - new RequestMappingSymbolProvider()); - providers.put(Annotations.SPRING_PATCH_MAPPING, - new RequestMappingSymbolProvider()); + providers.put(Annotations.SPRING_GET_MAPPING, new RequestMappingSymbolProvider()); + providers.put(Annotations.SPRING_POST_MAPPING, new RequestMappingSymbolProvider()); + providers.put(Annotations.SPRING_PUT_MAPPING, new RequestMappingSymbolProvider()); + providers.put(Annotations.SPRING_DELETE_MAPPING, new RequestMappingSymbolProvider()); + providers.put(Annotations.SPRING_PATCH_MAPPING, new RequestMappingSymbolProvider()); providers.put(Annotations.BEAN, new BeansSymbolProvider()); providers.put(Annotations.COMPONENT, new ComponentSymbolProvider()); diff --git a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/annotations/AnnotationHierarchies.java b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/annotations/AnnotationHierarchies.java index 19d9e8274..7de211d63 100644 --- a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/annotations/AnnotationHierarchies.java +++ b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/annotations/AnnotationHierarchies.java @@ -11,22 +11,15 @@ package org.springframework.ide.vscode.boot.java.annotations; import java.util.Collection; -import java.util.HashMap; import java.util.HashSet; -import java.util.List; -import java.util.Map; import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; import java.util.function.Predicate; import java.util.stream.Stream; import org.eclipse.jdt.core.dom.Annotation; import org.eclipse.jdt.core.dom.IAnnotationBinding; import org.eclipse.jdt.core.dom.ITypeBinding; -import org.gradle.internal.io.SkipFirstTextStream; import org.springframework.ide.vscode.commons.util.CollectorUtil; -import org.springframework.ide.vscode.commons.util.Log; import com.google.common.collect.ImmutableList; diff --git a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/annotations/AnnotationHierarchyAwareLookup.java b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/annotations/AnnotationHierarchyAwareLookup.java index 2f7729a86..83e9843d5 100644 --- a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/annotations/AnnotationHierarchyAwareLookup.java +++ b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/annotations/AnnotationHierarchyAwareLookup.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017 Pivotal, Inc. + * Copyright (c) 2017, 2018 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 @@ -18,18 +18,12 @@ import java.util.Map; import java.util.function.Consumer; import org.eclipse.jdt.core.dom.ITypeBinding; -import org.springframework.ide.vscode.boot.java.requestmapping.RequestMappingSymbolProvider; import org.springframework.ide.vscode.commons.util.Assert; -import org.springframework.ide.vscode.commons.util.StringUtil; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; - -import reactor.util.function.Tuple2; -import reactor.util.function.Tuples; /** - * A Map-like utilyt that allows putting and getting values associated with + * A Map-like utilty that allows putting and getting values associated with * annotation types. *

* The lookup is 'hierarchy aware' which means that is able to associate values @@ -99,6 +93,13 @@ public class AnnotationHierarchyAwareLookup { return found.build(); } + public Collection getAll() { + ImmutableList.Builder found = ImmutableList.builder(); + Collection> values = bindings.values(); + values.forEach(binding -> found.add(binding.value)); + return found.build(); + } + private void findElements(ITypeBinding typeBinding, HashSet seen, Consumer requestor) { String qname = typeBinding.getQualifiedName(); if (seen.add(qname)) { diff --git a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/BeansSymbolProvider.java b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/BeansSymbolProvider.java index b60159be4..23170d694 100644 --- a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/BeansSymbolProvider.java +++ b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/BeansSymbolProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017 Pivotal, Inc. + * Copyright (c) 2017, 2018 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 @@ -22,6 +22,7 @@ import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.ParameterizedType; import org.eclipse.jdt.core.dom.StringLiteral; import org.eclipse.jdt.core.dom.Type; +import org.eclipse.jdt.core.dom.TypeDeclaration; import org.eclipse.lsp4j.Location; import org.eclipse.lsp4j.SymbolInformation; import org.eclipse.lsp4j.SymbolKind; @@ -35,6 +36,7 @@ import org.springframework.ide.vscode.commons.util.text.TextDocument; import com.google.common.collect.ImmutableList; import reactor.util.function.Tuple2; +import reactor.util.function.Tuple3; import reactor.util.function.Tuples; /** @@ -46,8 +48,163 @@ public class BeansSymbolProvider implements SymbolProvider { private static final String FUNCTION_FUNCTION_TYPE = Function.class.getName(); private static final String FUNCTION_CONSUMER_TYPE = Consumer.class.getName(); private static final String FUNCTION_SUPPLIER_TYPE = Supplier.class.getName(); + private static final String[] NAME_ATTRIBUTES = {"value", "name"}; + @Override + public Collection getSymbols(Annotation node, ITypeBinding annotationType, Collection metaAnnotations, TextDocument doc) { + boolean isFunction = isFunctionBean(node); + + ImmutableList.Builder symbols = ImmutableList.builder(); + String beanType = getBeanType(node); + for (Tuple2 nameAndRegion : getBeanNames(node, doc)) { + try { + symbols.add(new SymbolInformation( + beanLabel(isFunction, nameAndRegion.getT1(), beanType, "@Bean"), + SymbolKind.Interface, + new Location(doc.getUri(), doc.toRange(nameAndRegion.getT2())) + )); + } catch (BadLocationException e) { + Log.log(e); + } + } + return symbols.build(); + } + + @Override + public Collection getSymbols(TypeDeclaration typeDeclaration, TextDocument doc) { + // this checks function beans that are defined as implementations of Function interfaces + Tuple3 functionBean = getFunctionBean(typeDeclaration, doc); + if (functionBean != null) { + try { + SymbolInformation symbol = new SymbolInformation( + beanLabel(true, functionBean.getT1(), functionBean.getT2(), null), + SymbolKind.Interface, + new Location(doc.getUri(), doc.toRange(functionBean.getT3()))); + return ImmutableList.of(symbol); + } catch (BadLocationException e) { + Log.log(e); + } + } + return ImmutableList.of(); + } + + protected Tuple3 getFunctionBean(TypeDeclaration typeDeclaration, TextDocument doc) { + ITypeBinding resolvedType = typeDeclaration.resolveBinding(); + if (resolvedType != null) { + return getFunctionBean(typeDeclaration, doc, resolvedType); + } + else { + return null; + } + } + + private Tuple3 getFunctionBean(TypeDeclaration typeDeclaration, TextDocument doc, + ITypeBinding resolvedType) { + + ITypeBinding[] interfaces = resolvedType.getInterfaces(); + for (ITypeBinding resolvedInterface : interfaces) { + String simplifiedType = null; + if (resolvedInterface.isParameterizedType()) { + simplifiedType = resolvedInterface.getBinaryName(); + } + else { + simplifiedType = resolvedType.getQualifiedName(); + } + + if (FUNCTION_FUNCTION_TYPE.equals(simplifiedType) || FUNCTION_CONSUMER_TYPE.equals(simplifiedType) + || FUNCTION_SUPPLIER_TYPE.equals(simplifiedType)) { + String beanName = getBeanName(typeDeclaration); + String beanType = resolvedInterface.getName(); + DocumentRegion region = ASTUtils.nodeRegion(doc, typeDeclaration.getName()); + + return Tuples.of(beanName, beanType, region); + } + else { + Tuple3 result = getFunctionBean(typeDeclaration, doc, resolvedInterface); + if (result != null) { + return result; + } + } + } + + ITypeBinding superclass = resolvedType.getSuperclass(); + if (superclass != null) { + return getFunctionBean(typeDeclaration, doc, superclass); + } + else { + return null; + } + } + + protected Collection> getBeanNames(Annotation node, TextDocument doc) { + Collection beanNameNodes = getBeanNameLiterals(node); + + if (beanNameNodes != null && !beanNameNodes.isEmpty()) { + ImmutableList.Builder> namesAndRegions = ImmutableList.builder(); + for (StringLiteral nameNode : beanNameNodes) { + String name = ASTUtils.getLiteralValue(nameNode); + namesAndRegions.add(Tuples.of(name, ASTUtils.stringRegion(doc, nameNode))); + } + return namesAndRegions.build(); + } + else { + ASTNode parent = node.getParent(); + if (parent instanceof MethodDeclaration) { + MethodDeclaration method = (MethodDeclaration) parent; + return ImmutableList.of(Tuples.of( + method.getName().toString(), + ASTUtils.nameRegion(doc, node) + )); + } + return ImmutableList.of(); + } + } + + protected String beanLabel(boolean isFunctionBean, String beanName, String beanType, String markerString) { + StringBuilder symbolLabel = new StringBuilder(); + symbolLabel.append('@'); + symbolLabel.append(isFunctionBean ? '>' : '+'); + symbolLabel.append(' '); + symbolLabel.append('\''); + symbolLabel.append(beanName); + symbolLabel.append('\''); + + markerString = markerString != null && markerString.length() > 0 ? " (" + markerString + ") " : " "; + symbolLabel.append(markerString); + + symbolLabel.append(beanType); + return symbolLabel.toString(); + } + + protected Collection getBeanNameLiterals(Annotation node) { + ImmutableList.Builder literals = ImmutableList.builder(); + for (String attrib : NAME_ATTRIBUTES) { + ASTUtils.getAttribute(node, attrib).ifPresent((valueExp) -> { + literals.addAll(ASTUtils.getExpressionValueAsListOfLiterals(valueExp)); + }); + } + return literals.build(); + } + + protected String getBeanType(Annotation node) { + ASTNode parent = node.getParent(); + if (parent instanceof MethodDeclaration) { + MethodDeclaration method = (MethodDeclaration) parent; + String returnType = method.getReturnType2().resolveBinding().getName(); + return returnType; + } + return null; + } + + protected String getBeanName(TypeDeclaration typeDeclaration) { + String beanName = typeDeclaration.getName().toString(); + if (beanName.length() > 0 && Character.isUpperCase(beanName.charAt(0))) { + beanName = Character.toLowerCase(beanName.charAt(0)) + beanName.substring(1); + } + return beanName; + } + private boolean isFunctionBean(Annotation node) { ASTNode parent = node.getParent(); if (parent instanceof MethodDeclaration) { @@ -70,94 +227,5 @@ public class BeansSymbolProvider implements SymbolProvider { return false; } -// private SymbolInformation createFunctionSymbol(Annotation node, TextDocument doc) throws BadLocationException { -// StringBuilder symbolLabel = new StringBuilder(); -// symbolLabel.append("@> "); -// -// String beanName = getBeanName(node); -// String beanType = getBeanType(node); -// -// symbolLabel.append('\''); -// symbolLabel.append(beanName); -// symbolLabel.append('\''); -// symbolLabel.append(" (@Bean) "); -// symbolLabel.append(beanType); -// -// SymbolInformation symbol = new SymbolInformation(symbolLabel.toString(), SymbolKind.Interface, -// new Location(doc.getUri(), doc.toRange(node.getStartPosition(), node.getLength()))); -// return symbol; -// } - @Override - public Collection getSymbols(Annotation node, ITypeBinding annotationType, Collection metaAnnotations, TextDocument doc) { - boolean isFunction = isFunctionBean(node); - ImmutableList.Builder symbols = ImmutableList.builder(); - String beanType = getBeanType(node); - for (Tuple2 nameAndRegion : getBeanNames(node, doc)) { - try { - symbols.add(new SymbolInformation( - beanLabel(isFunction, nameAndRegion.getT1(), beanType), - SymbolKind.Interface, - new Location(doc.getUri(), doc.toRange(nameAndRegion.getT2())) - )); - } catch (BadLocationException e) { - Log.log(e); - } - } - return symbols.build(); - } - - Collection> getBeanNames(Annotation node, TextDocument doc) { - Collection beanNameNodes = getBeanNameLiterals(node); - if (beanNameNodes!=null && !beanNameNodes.isEmpty()) { - ImmutableList.Builder> namesAndRegions = ImmutableList.builder(); - for (StringLiteral nameNode : beanNameNodes) { - String name = ASTUtils.getLiteralValue(nameNode); - namesAndRegions.add(Tuples.of(name, ASTUtils.stringRegion(doc, nameNode))); - } - return namesAndRegions.build(); - } else { - ASTNode parent = node.getParent(); - if (parent instanceof MethodDeclaration) { - MethodDeclaration method = (MethodDeclaration) parent; - return ImmutableList.of(Tuples.of( - method.getName().toString(), - ASTUtils.nameRegion(doc, node) - )); - } - return ImmutableList.of(); - } - } - - protected String beanLabel(boolean isFunctionBean, String beanName, String beanType) { - StringBuilder symbolLabel = new StringBuilder(); - symbolLabel.append('@'); - symbolLabel.append(isFunctionBean ? '>' : '+'); - symbolLabel.append(' '); - symbolLabel.append('\''); - symbolLabel.append(beanName); - symbolLabel.append('\''); - symbolLabel.append(" (@Bean) "); - symbolLabel.append(beanType); - return symbolLabel.toString(); - } - protected Collection getBeanNameLiterals(Annotation node) { - ImmutableList.Builder literals = ImmutableList.builder(); - for (String attrib : NAME_ATTRIBUTES) { - ASTUtils.getAttribute(node, attrib).ifPresent((valueExp) -> { - literals.addAll(ASTUtils.getExpressionValueAsListOfLiterals(valueExp)); - }); - } - return literals.build(); - } - - protected String getBeanType(Annotation node) { - ASTNode parent = node.getParent(); - if (parent instanceof MethodDeclaration) { - MethodDeclaration method = (MethodDeclaration) parent; - String returnType = method.getReturnType2().resolveBinding().getName(); - return returnType; - } - return null; - } } diff --git a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/ComponentSymbolProvider.java b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/ComponentSymbolProvider.java index 92ed764c1..aa745f103 100644 --- a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/ComponentSymbolProvider.java +++ b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/ComponentSymbolProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017 Pivotal, Inc. + * Copyright (c) 2017, 2018 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 @@ -23,7 +23,6 @@ import org.eclipse.lsp4j.SymbolKind; import org.springframework.ide.vscode.boot.java.handlers.SymbolProvider; import org.springframework.ide.vscode.commons.util.BadLocationException; import org.springframework.ide.vscode.commons.util.Log; -import org.springframework.ide.vscode.commons.util.StringUtil; import org.springframework.ide.vscode.commons.util.text.TextDocument; import com.google.common.collect.ImmutableList; @@ -112,4 +111,10 @@ public class ComponentSymbolProvider implements SymbolProvider { return null; } + @Override + public Collection getSymbols(TypeDeclaration typeDeclaration, TextDocument doc) { + // TODO Auto-generated method stub + return null; + } + } diff --git a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaCompletionEngine.java b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaCompletionEngine.java index 50e436435..7a2b37bc2 100644 --- a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaCompletionEngine.java +++ b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaCompletionEngine.java @@ -51,7 +51,7 @@ public class BootJavaCompletionEngine implements ICompletionEngine { @Override public Collection getCompletions(IDocument document, int offset) throws Exception { - ASTParser parser = ASTParser.newParser(AST.JLS8); + ASTParser parser = ASTParser.newParser(AST.JLS9); Map options = JavaCore.getOptions(); JavaCore.setComplianceOptions(JavaCore.VERSION_1_8, options); parser.setCompilerOptions(options); diff --git a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaHoverProvider.java b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaHoverProvider.java index 3cf3416dd..4e8740734 100644 --- a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaHoverProvider.java +++ b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaHoverProvider.java @@ -10,18 +10,14 @@ *******************************************************************************/ package org.springframework.ide.vscode.boot.java.handlers; -import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; -import java.util.List; -import java.util.Map; import java.util.Optional; import java.util.concurrent.CompletableFuture; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.ASTVisitor; import org.eclipse.jdt.core.dom.Annotation; -import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.MarkerAnnotation; import org.eclipse.jdt.core.dom.NodeFinder; diff --git a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaReferencesHandler.java b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaReferencesHandler.java index 2e032aa7e..b6c81415c 100644 --- a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaReferencesHandler.java +++ b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaReferencesHandler.java @@ -71,7 +71,7 @@ public class BootJavaReferencesHandler implements ReferencesHandler { } private CompletableFuture> provideReferences(TextDocument document, int offset) throws Exception { - ASTParser parser = ASTParser.newParser(AST.JLS8); + ASTParser parser = ASTParser.newParser(AST.JLS9); Map options = JavaCore.getOptions(); JavaCore.setComplianceOptions(JavaCore.VERSION_1_8, options); parser.setCompilerOptions(options); diff --git a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/SymbolProvider.java b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/SymbolProvider.java index 3c0ca62cf..ff4802e26 100644 --- a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/SymbolProvider.java +++ b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/SymbolProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017 Pivotal, Inc. + * Copyright (c) 2017, 2018 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 @@ -14,6 +14,7 @@ import java.util.Collection; import org.eclipse.jdt.core.dom.Annotation; import org.eclipse.jdt.core.dom.ITypeBinding; +import org.eclipse.jdt.core.dom.TypeDeclaration; import org.eclipse.lsp4j.SymbolInformation; import org.springframework.ide.vscode.commons.util.text.TextDocument; @@ -24,5 +25,6 @@ import org.springframework.ide.vscode.commons.util.text.TextDocument; public interface SymbolProvider { Collection getSymbols(Annotation node, ITypeBinding typeBinding, Collection metaAnnotations, TextDocument doc); + Collection getSymbols(TypeDeclaration typeDeclaration, TextDocument doc); } diff --git a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingSymbolProvider.java b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingSymbolProvider.java index f7ca9ae55..ec9d4d7a0 100644 --- a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingSymbolProvider.java +++ b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingSymbolProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017 Pivotal, Inc. + * Copyright (c) 2017, 2018 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 @@ -176,4 +176,9 @@ public class RequestMappingSymbolProvider implements SymbolProvider { return null; } + @Override + public Collection getSymbols(TypeDeclaration typeDeclaration, TextDocument doc) { + return null; + } + } diff --git a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/CompilationUnitCache.java b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/CompilationUnitCache.java index a35a14572..3a9af0836 100644 --- a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/CompilationUnitCache.java +++ b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/CompilationUnitCache.java @@ -126,7 +126,7 @@ public final class CompilationUnitCache { } public static CompilationUnit parse(TextDocument document, IJavaProject project) throws Exception { - ASTParser parser = ASTParser.newParser(AST.JLS8); + ASTParser parser = ASTParser.newParser(AST.JLS9); Map options = JavaCore.getOptions(); JavaCore.setComplianceOptions(JavaCore.VERSION_1_8, options); parser.setCompilerOptions(options); diff --git a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexer.java b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexer.java index eedc19440..8d4bc1038 100644 --- a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexer.java +++ b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017 Pivotal, Inc. + * Copyright (c) 2017, 2018 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 @@ -43,6 +43,7 @@ import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.MarkerAnnotation; import org.eclipse.jdt.core.dom.NormalAnnotation; import org.eclipse.jdt.core.dom.SingleMemberAnnotation; +import org.eclipse.jdt.core.dom.TypeDeclaration; import org.eclipse.lsp4j.Location; import org.eclipse.lsp4j.SymbolInformation; import org.eclipse.lsp4j.SymbolKind; @@ -273,7 +274,7 @@ public class SpringIndexer { private void scanProject(IJavaProject project, String[] files) { try { - ASTParser parser = ASTParser.newParser(AST.JLS8); + ASTParser parser = ASTParser.newParser(AST.JLS9); String[] classpathEntries = getClasspathEntries(project); scanFiles(parser, files, classpathEntries); @@ -284,7 +285,7 @@ public class SpringIndexer { } private void scanFile(String docURI, String content, String[] classpathEntries) throws Exception { - ASTParser parser = ASTParser.newParser(AST.JLS8); + ASTParser parser = ASTParser.newParser(AST.JLS9); Map options = JavaCore.getOptions(); JavaCore.setComplianceOptions(JavaCore.VERSION_1_8, options); parser.setCompilerOptions(options); @@ -342,6 +343,17 @@ public class SpringIndexer { private void scanAST(final CompilationUnit cu, final String docURI, AtomicReference docRef, final String content) { cu.accept(new ASTVisitor() { + @Override + public boolean visit(TypeDeclaration node) { + try { + extractSymbolInformation(node, docURI, docRef, content); + } + catch (Exception e) { + e.printStackTrace(); + } + return super.visit(node); + } + @Override public boolean visit(SingleMemberAnnotation node) { try { @@ -380,6 +392,22 @@ public class SpringIndexer { }); } + private void extractSymbolInformation(TypeDeclaration typeDeclaration, String docURI, AtomicReference docRef, String content) throws Exception { + Collection providers = symbolProviders.getAll(); + if (!providers.isEmpty()) { + TextDocument doc = getTempTextDocument(docURI, docRef, content); + for (SymbolProvider provider : providers) { + Collection sbls = provider.getSymbols(typeDeclaration, doc); + if (sbls != null) { + sbls.forEach(symbol -> { + symbols.add(symbol); + symbolsByDoc.computeIfAbsent(docURI, s -> new ArrayList()).add(symbol); + }); + } + } + } + } + private void extractSymbolInformation(Annotation node, String docURI, AtomicReference docRef, String content) throws Exception { ITypeBinding typeBinding = node.resolveTypeBinding(); diff --git a/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/beans/test/SpringIndexerBeansTest.java b/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/beans/test/SpringIndexerBeansTest.java index 48ab22d89..2e5268eb3 100644 --- a/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/beans/test/SpringIndexerBeansTest.java +++ b/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/beans/test/SpringIndexerBeansTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017 Pivotal, Inc. + * Copyright (c) 2017, 2018 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 @@ -11,10 +11,7 @@ package org.springframework.ide.vscode.boot.java.beans.test; import java.io.File; -import java.util.Iterator; -import java.util.List; -import org.eclipse.lsp4j.SymbolInformation; import org.junit.Before; import org.junit.Test; import org.springframework.ide.vscode.boot.java.Annotations; @@ -89,19 +86,6 @@ public class SpringIndexerBeansTest { ); } - @Test - public void testScanSimpleFunctionBean() throws Exception { - SpringIndexerHarness indexer = new SpringIndexerHarness(harness.getServer(), projectFinder, symbolProviders); - File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-beans/").toURI()); - indexer.initialize(indexer.wsFolder(directory)); - - String uriPrefix = "file://" + directory.getAbsolutePath(); - indexer.assertDocumentSymbols(uriPrefix + "/src/main/java/org/test/FunctionClass.java", - symbol("@Configuration", "@+ 'functionClass' (@Configuration <: @Component) FunctionClass"), - symbol("@Bean", "@> 'uppercase' (@Bean) Function") - ); - } - @Test public void testScanSimpleComponentClass() throws Exception { SpringIndexerHarness indexer = new SpringIndexerHarness(harness.getServer(), projectFinder, symbolProviders); @@ -112,9 +96,6 @@ public class SpringIndexerBeansTest { indexer.assertDocumentSymbols(uriPrefix + "/src/main/java/org/test/SimpleComponent.java", symbol("@Component", "@+ 'simpleComponent' (@Component) SimpleComponent") ); -// List symbols = indexer.getSymbols(uriPrefix + "/src/main/java/org/test/SimpleComponent.java"); -// assertEquals(1, symbols.size()); -// assertTrue(containsSymbol(symbols, "@+ 'simpleComponent' (@Component) SimpleComponent", uriPrefix + "/src/main/java/org/test/SimpleComponent.java", 4, 0, 4, 10)); } @Test public void testScanSimpleControllerClass() throws Exception { @@ -145,23 +126,6 @@ public class SpringIndexerBeansTest { //////////////////////////////// // harness code - private boolean containsSymbol(List symbols, String name, String uri, int startLine, int startCHaracter, int endLine, int endCharacter) { - for (Iterator iterator = symbols.iterator(); iterator.hasNext();) { - SymbolInformation symbol = iterator.next(); - - if (symbol.getName().equals(name) - && symbol.getLocation().getUri().equals(uri) - && symbol.getLocation().getRange().getStart().getLine() == startLine - && symbol.getLocation().getRange().getStart().getCharacter() == startCHaracter - && symbol.getLocation().getRange().getEnd().getLine() == endLine - && symbol.getLocation().getRange().getEnd().getCharacter() == endCharacter) { - return true; - } - } - - return false; - } - private TestSymbolInfo symbol(String coveredText, String label) { return new TestSymbolInfo(coveredText, label); } diff --git a/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/beans/test/SpringIndexerFunctionBeansTest.java b/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/beans/test/SpringIndexerFunctionBeansTest.java new file mode 100644 index 000000000..03d038c66 --- /dev/null +++ b/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/beans/test/SpringIndexerFunctionBeansTest.java @@ -0,0 +1,112 @@ +/******************************************************************************* + * Copyright (c) 2017, 2018 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.beans.test; + +import java.io.File; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.ide.vscode.boot.java.Annotations; +import org.springframework.ide.vscode.boot.java.annotations.AnnotationHierarchyAwareLookup; +import org.springframework.ide.vscode.boot.java.beans.BeansSymbolProvider; +import org.springframework.ide.vscode.boot.java.beans.ComponentSymbolProvider; +import org.springframework.ide.vscode.boot.java.beans.test.SpringIndexerHarness.TestSymbolInfo; +import org.springframework.ide.vscode.boot.java.handlers.SymbolProvider; +import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder; +import org.springframework.ide.vscode.project.harness.BootLanguageServerHarness; +import org.springframework.ide.vscode.project.harness.ProjectsHarness; + +/** + * @author Martin Lippert + */ +public class SpringIndexerFunctionBeansTest { + + private AnnotationHierarchyAwareLookup symbolProviders; + private BootLanguageServerHarness harness; + private JavaProjectFinder projectFinder; + + @Before + public void setup() throws Exception { + symbolProviders = new AnnotationHierarchyAwareLookup<>(); + symbolProviders.put(Annotations.BEAN, new BeansSymbolProvider()); + symbolProviders.put(Annotations.COMPONENT, new ComponentSymbolProvider()); + + harness = BootLanguageServerHarness.builder().build(); + projectFinder = harness.getProjectFinder(); + harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-beans/").toURI())); + } + + @Test + public void testScanSimpleFunctionBean() throws Exception { + SpringIndexerHarness indexer = new SpringIndexerHarness(harness.getServer(), projectFinder, symbolProviders); + File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-beans/").toURI()); + indexer.initialize(indexer.wsFolder(directory)); + + String uriPrefix = "file://" + directory.getAbsolutePath(); + indexer.assertDocumentSymbols(uriPrefix + "/src/main/java/org/test/FunctionClass.java", + symbol("@Configuration", "@+ 'functionClass' (@Configuration <: @Component) FunctionClass"), + symbol("@Bean", "@> 'uppercase' (@Bean) Function") + ); + } + + @Test + public void testScanSimpleFunctionClass() throws Exception { + SpringIndexerHarness indexer = new SpringIndexerHarness(harness.getServer(), projectFinder, symbolProviders); + File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-beans/").toURI()); + indexer.initialize(indexer.wsFolder(directory)); + + String uriPrefix = "file://" + directory.getAbsolutePath(); + indexer.assertDocumentSymbols(uriPrefix + "/src/main/java/org/test/ScannedFunctionClass.java", + symbol("ScannedFunctionClass", "@> 'scannedFunctionClass' Function") + ); + } + + @Test + public void testScanSpecializedFunctionClass() throws Exception { + SpringIndexerHarness indexer = new SpringIndexerHarness(harness.getServer(), projectFinder, symbolProviders); + File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-beans/").toURI()); + indexer.initialize(indexer.wsFolder(directory)); + + String uriPrefix = "file://" + directory.getAbsolutePath(); + indexer.assertDocumentSymbols(uriPrefix + "/src/main/java/org/test/FunctionFromSpecializedClass.java", + symbol("FunctionFromSpecializedClass", "@> 'functionFromSpecializedClass' Function") + ); + } + + @Test + public void testScanSpecializedFunctionInterface() throws Exception { + SpringIndexerHarness indexer = new SpringIndexerHarness(harness.getServer(), projectFinder, symbolProviders); + File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-beans/").toURI()); + indexer.initialize(indexer.wsFolder(directory)); + + String uriPrefix = "file://" + directory.getAbsolutePath(); + indexer.assertDocumentSymbols(uriPrefix + "/src/main/java/org/test/FunctionFromSpecializedInterface.java", + symbol("FunctionFromSpecializedInterface", "@> 'functionFromSpecializedInterface' Function") + ); + } + + @Test + public void testScanInconsistentInterfaceHierarchy() throws Exception { + SpringIndexerHarness indexer = new SpringIndexerHarness(harness.getServer(), projectFinder, symbolProviders); + File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-beans/").toURI()); + indexer.initialize(indexer.wsFolder(directory)); + + String uriPrefix = "file://" + directory.getAbsolutePath(); + indexer.assertDocumentSymbols(uriPrefix + "/src/main/java/org/test/LoopedFunctionClass.java"); + } + + //////////////////////////////// + // harness code + + private TestSymbolInfo symbol(String coveredText, String label) { + return new TestSymbolInfo(coveredText, label); + } +} diff --git a/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/references/test/PropertyReferenceFinderTest.java b/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/references/test/PropertyReferenceFinderTest.java index 4ac7509e2..50c9d71b2 100644 --- a/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/references/test/PropertyReferenceFinderTest.java +++ b/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/references/test/PropertyReferenceFinderTest.java @@ -13,7 +13,6 @@ package org.springframework.ide.vscode.boot.java.references.test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import java.io.File; import java.net.URI; import java.nio.file.Path; import java.nio.file.Paths; diff --git a/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/scope/test/ScopeCompletionTest.java b/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/scope/test/ScopeCompletionTest.java index f3ad70632..60ccde49e 100644 --- a/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/scope/test/ScopeCompletionTest.java +++ b/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/scope/test/ScopeCompletionTest.java @@ -11,7 +11,6 @@ package org.springframework.ide.vscode.boot.java.scope.test; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; import java.io.InputStream; import java.util.List; diff --git a/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/FunctionFromSpecializedClass.java b/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/FunctionFromSpecializedClass.java new file mode 100644 index 000000000..b2d69778d --- /dev/null +++ b/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/FunctionFromSpecializedClass.java @@ -0,0 +1,10 @@ +package org.test; + +public class FunctionFromSpecializedClass extends SpecializedFunctionClass { + + @Override + public String apply(String t) { + return null; + } + +} diff --git a/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/FunctionFromSpecializedInterface.java b/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/FunctionFromSpecializedInterface.java new file mode 100644 index 000000000..079fcc143 --- /dev/null +++ b/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/FunctionFromSpecializedInterface.java @@ -0,0 +1,10 @@ +package org.test; + +public class FunctionFromSpecializedInterface implements SpecializedFunctionInterface { + + @Override + public String apply(String t) { + return null; + } + +} diff --git a/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/LoopedFunctionClass.java b/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/LoopedFunctionClass.java new file mode 100644 index 000000000..dc1dceb93 --- /dev/null +++ b/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/LoopedFunctionClass.java @@ -0,0 +1,4 @@ +package org.test; + +public class LoopedFunctionClass implements LoopedInterface1 { +} diff --git a/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/LoopedInterface1.java b/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/LoopedInterface1.java new file mode 100644 index 000000000..d08a23aaf --- /dev/null +++ b/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/LoopedInterface1.java @@ -0,0 +1,6 @@ +package org.test; + +import java.util.function.Function; + +public interface LoopedInterface1 extends LoopedInterface2 { +} diff --git a/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/LoopedInterface2.java b/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/LoopedInterface2.java new file mode 100644 index 000000000..490a4fecf --- /dev/null +++ b/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/LoopedInterface2.java @@ -0,0 +1,4 @@ +package org.test; + +public interface LoopedInterface2 extends LoopedInterface1 { +} diff --git a/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/ScannedFunctionClass.java b/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/ScannedFunctionClass.java new file mode 100644 index 000000000..838951e0f --- /dev/null +++ b/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/ScannedFunctionClass.java @@ -0,0 +1,12 @@ +package org.test; + +import java.util.function.Function; + +public class ScannedFunctionClass implements Function { + + @Override + public String apply(String t) { + return t.toUpperCase(); + } + +} diff --git a/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/SpecializedFunctionClass.java b/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/SpecializedFunctionClass.java new file mode 100644 index 000000000..021211a65 --- /dev/null +++ b/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/SpecializedFunctionClass.java @@ -0,0 +1,6 @@ +package org.test; + +import java.util.function.Function; + +public abstract class SpecializedFunctionClass implements Function { +} diff --git a/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/SpecializedFunctionInterface.java b/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/SpecializedFunctionInterface.java new file mode 100644 index 000000000..3388dba99 --- /dev/null +++ b/headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotation-indexing-beans/src/main/java/org/test/SpecializedFunctionInterface.java @@ -0,0 +1,6 @@ +package org.test; + +import java.util.function.Function; + +public interface SpecializedFunctionInterface extends Function { +} diff --git a/vscode-extensions/commons-vscode/src/launch-util.ts b/vscode-extensions/commons-vscode/src/launch-util.ts index f2a895637..5fc5bd85b 100644 --- a/vscode-extensions/commons-vscode/src/launch-util.ts +++ b/vscode-extensions/commons-vscode/src/launch-util.ts @@ -33,7 +33,7 @@ export interface ActivatorOptions { clientOptions: LanguageClientOptions; launcher: (context: VSCode.ExtensionContext) => string; jvmHeap?: string; - classpath?: (context: VSCode.ExtensionContext) => string[]; + classpath?: (context: VSCode.ExtensionContext, javaVersion: number) => string[]; } export function activate(options: ActivatorOptions, context: VSCode.ExtensionContext): Promise { @@ -98,7 +98,7 @@ export function activate(options: ActivatorOptions, context: VSCode.ExtensionCon '-Dorg.slf4j.simpleLogger.logFile=' + logfile ]; if (options.classpath) { - const classpath = options.classpath(context); + const classpath = options.classpath(context, version); if (classpath) { args.push('-cp'); args.push(classpath.join(Path.delimiter)); diff --git a/vscode-extensions/vscode-boot-java/lib/Main.ts b/vscode-extensions/vscode-boot-java/lib/Main.ts index d94520247..2b6e1225a 100644 --- a/vscode-extensions/vscode-boot-java/lib/Main.ts +++ b/vscode-extensions/vscode-boot-java/lib/Main.ts @@ -22,16 +22,20 @@ export function activate(context: VSCode.ExtensionContext) { CONNECT_TO_LS: false, extensionId: 'boot-java', launcher: (context: VSCode.ExtensionContext) => 'org.springframework.boot.loader.JarLauncher', - classpath: (context: VSCode.ExtensionContext) => { + classpath: (context: VSCode.ExtensionContext, javaVersion: number) => { const classpath = [ Path.resolve(context.extensionPath, 'jars/language-server.jar') ]; - const toolsJar = commons.findJvmFile('lib', 'tools.jar'); - if (toolsJar) { - classpath.push(toolsJar); - } else { - VSCode.window.showWarningMessage('JAVA_HOME environment variable points either to JRE or JDK missing "lib/tools.jar" hence Boot Hints are unavailable'); + + if (javaVersion < 9) { + const toolsJar = commons.findJvmFile('lib', 'tools.jar'); + if (toolsJar) { + classpath.push(toolsJar); + } else { + VSCode.window.showWarningMessage('JAVA_HOME environment variable points either to JRE or JDK missing "lib/tools.jar" hence Boot Hints are unavailable'); + } } + return classpath; }, clientOptions: {