From 3cbce5e81ad9f95fa0f23272326f6ae76f92ec89 Mon Sep 17 00:00:00 2001 From: Martin Lippert Date: Sun, 27 Aug 2017 18:48:00 +0200 Subject: [PATCH] started to implement infrastructure to parse java projects completely --- .../BootJavaWorkspaceSymbolHandler.java | 124 +++++++++++++++++- .../completions/test/ScopeCompletionTest.java | 17 ++- .../completions/test/ValueCompletionTest.java | 55 +++++--- .../harness/AbstractPropsEditorTest.java | 17 ++- .../gradle/GradleProjectFinderStrategy.java | 30 ++--- .../java/DefaultJavaProjectFinder.java | 46 ++++++- .../java/IJavaProjectFinderStrategy.java | 10 +- .../java/JavaProjectFinder.java | 8 +- ...rojectWithClasspathFileFinderStrategy.java | 37 ++---- .../maven/MavenProjectFinderStrategy.java | 33 ++--- .../ide/vscode/commons/util/FileUtils.java | 14 +- 11 files changed, 285 insertions(+), 106 deletions(-) diff --git a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/symbols/BootJavaWorkspaceSymbolHandler.java b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/symbols/BootJavaWorkspaceSymbolHandler.java index 49bbb2d76..1ee07e364 100644 --- a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/symbols/BootJavaWorkspaceSymbolHandler.java +++ b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/symbols/BootJavaWorkspaceSymbolHandler.java @@ -1,10 +1,25 @@ package org.springframework.ide.vscode.boot.java.symbols; +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.List; +import java.util.Map; +import java.util.stream.Stream; +import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.core.dom.AST; +import org.eclipse.jdt.core.dom.ASTParser; +import org.eclipse.jdt.core.dom.ASTVisitor; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jdt.core.dom.MarkerAnnotation; +import org.eclipse.jdt.core.dom.NormalAnnotation; +import org.eclipse.jdt.core.dom.SingleMemberAnnotation; import org.eclipse.lsp4j.SymbolInformation; import org.eclipse.lsp4j.WorkspaceSymbolParams; import org.springframework.ide.vscode.boot.java.BootJavaLanguageServer; +import org.springframework.ide.vscode.commons.java.IClasspath; +import org.springframework.ide.vscode.commons.java.IJavaProject; import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder; import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer; import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService; @@ -15,14 +30,121 @@ public class BootJavaWorkspaceSymbolHandler implements WorkspaceSymbolHandler { private SimpleLanguageServer server; private JavaProjectFinder projectFinder; - public BootJavaWorkspaceSymbolHandler(BootJavaLanguageServer bootJavaLanguageServer, JavaProjectFinder javaProjectFinder) { + public BootJavaWorkspaceSymbolHandler(BootJavaLanguageServer server, JavaProjectFinder projectFinder) { this.server = server; this.projectFinder = projectFinder; } @Override public List handle(WorkspaceSymbolParams params) { + Path root = this.server.getWorkspaceRoot(); + + scanFiles(root.toFile()); + return collectSymbols(); + } + + private List collectSymbols() { return SimpleTextDocumentService.NO_SYMBOLS; } + private void scanFiles(File directory) { + if (this.projectFinder.isProjectRoot(directory)) { + IJavaProject project = this.projectFinder.find(directory); + if (project != null) { + scanProject(project, directory); + } + } + else if (directory.isDirectory() && directory.exists()) { + File[] files = directory.listFiles(); + for (File file : files) { + scanFiles(file); + } + } + } + + private void scanProject(IJavaProject project, File directory) { + try { + ASTParser parser = ASTParser.newParser(AST.JLS8); + Map options = JavaCore.getOptions(); + JavaCore.setComplianceOptions(JavaCore.VERSION_1_8, options); + parser.setCompilerOptions(options); + parser.setKind(ASTParser.K_COMPILATION_UNIT); + parser.setStatementsRecovery(true); + parser.setBindingsRecovery(true); + parser.setResolveBindings(true); + + String[] classpathEntries = getClasspathEntries(project); + String[] sourceEntries = new String[] {}; + parser.setEnvironment(classpathEntries, sourceEntries, null, true); + + scanFiles(parser, directory); + + } + catch (Exception e) { + e.printStackTrace(); + } + } + + private void scanFiles(ASTParser parser, File directory) throws Exception { + File[] javaFiles = directory.listFiles((file) -> file.getName().endsWith(".java")); + for (File javaFile : javaFiles) { + if (javaFile.isFile() && javaFile.exists()) { + scanFile(parser, javaFile); + } + } + + File[] directories = directory.listFiles((file) -> file.isDirectory() && file.exists()); + for (File dir : directories) { + scanFiles(parser, dir); + } + } + + private void scanFile(ASTParser parser, File javaFile) throws Exception { + + Path path = javaFile.toPath(); + + String unitName = path.getFileName().toString(); + parser.setUnitName(unitName); + + String content = new String(Files.readAllBytes(path)); + parser.setSource(content.toCharArray()); + + CompilationUnit cu = (CompilationUnit) parser.createAST(null); + if (cu != null) { + System.out.println("AST node found: " + cu.getClass().getName()); + scanAST(cu); + } + } + + private void scanAST(CompilationUnit cu) { + cu.accept(new ASTVisitor() { + + @Override + public boolean visit(SingleMemberAnnotation node) { + System.out.println("annotation found: " + node.toString()); + return super.visit(node); + } + + @Override + public boolean visit(NormalAnnotation node) { + System.out.println("annotation found: " + node.toString()); + return super.visit(node); + } + + @Override + public boolean visit(MarkerAnnotation node) { + System.out.println("annotation found: " + node.toString()); + return super.visit(node); + } + }); + } + + private String[] getClasspathEntries(IJavaProject project) throws Exception { + IClasspath classpath = project.getClasspath(); + Stream classpathEntries = classpath.getClasspathEntries(); + return classpathEntries + .filter(path -> path.toFile().exists()) + .map(path -> path.toAbsolutePath().toString()).toArray(String[]::new); + } + } diff --git a/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/completions/test/ScopeCompletionTest.java b/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/completions/test/ScopeCompletionTest.java index 7324295c7..6f83c9acf 100644 --- a/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/completions/test/ScopeCompletionTest.java +++ b/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/completions/test/ScopeCompletionTest.java @@ -13,6 +13,7 @@ package org.springframework.ide.vscode.boot.java.completions.test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import java.io.File; import java.io.InputStream; import java.util.List; import java.util.concurrent.Callable; @@ -24,6 +25,7 @@ import org.junit.Test; import org.springframework.ide.vscode.boot.java.BootJavaLanguageServer; import org.springframework.ide.vscode.commons.java.IJavaProject; import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder; +import org.springframework.ide.vscode.commons.util.text.IDocument; import org.springframework.ide.vscode.commons.util.text.LanguageId; import org.springframework.ide.vscode.languageserver.testharness.Editor; import org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness; @@ -35,7 +37,20 @@ import org.springframework.ide.vscode.project.harness.PropertyIndexHarness; */ public class ScopeCompletionTest { - private final JavaProjectFinder javaProjectFinder = (doc) -> getTestProject(); + protected final JavaProjectFinder javaProjectFinder = new JavaProjectFinder() { + @Override + public boolean isProjectRoot(File file) { + return false; + } + @Override + public IJavaProject find(File file) { + return null; + } + @Override + public IJavaProject find(IDocument doc) { + return getTestProject(); + } + }; private LanguageServerHarness harness; private PropertyIndexHarness indexHarness; diff --git a/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/completions/test/ValueCompletionTest.java b/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/completions/test/ValueCompletionTest.java index f4089a12b..a0102890f 100644 --- a/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/completions/test/ValueCompletionTest.java +++ b/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/completions/test/ValueCompletionTest.java @@ -13,6 +13,7 @@ package org.springframework.ide.vscode.boot.java.completions.test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import java.io.File; import java.io.InputStream; import java.util.List; import java.util.concurrent.Callable; @@ -25,6 +26,7 @@ import org.springframework.ide.vscode.boot.java.BootJavaLanguageServer; import org.springframework.ide.vscode.boot.java.completions.ValueCompletionProcessor; import org.springframework.ide.vscode.commons.java.IJavaProject; import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder; +import org.springframework.ide.vscode.commons.util.text.IDocument; import org.springframework.ide.vscode.commons.util.text.LanguageId; import org.springframework.ide.vscode.languageserver.testharness.Editor; import org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness; @@ -35,8 +37,21 @@ import org.springframework.ide.vscode.project.harness.PropertyIndexHarness; * @author Martin Lippert */ public class ValueCompletionTest { - - private final JavaProjectFinder javaProjectFinder = (doc) -> getTestProject(); + + protected final JavaProjectFinder javaProjectFinder = new JavaProjectFinder() { + @Override + public boolean isProjectRoot(File file) { + return false; + } + @Override + public IJavaProject find(File file) { + return null; + } + @Override + public IJavaProject find(IDocument doc) { + return getTestProject(); + } + }; private LanguageServerHarness harness; private IJavaProject testProject; @@ -49,7 +64,7 @@ public class ValueCompletionTest { public void setup() throws Exception { testProject = ProjectsHarness.INSTANCE.mavenProject("test-annotations"); indexHarness = new PropertyIndexHarness(); - + harness = new LanguageServerHarness(new Callable() { @Override public BootJavaLanguageServer call() throws Exception { @@ -64,15 +79,15 @@ public class ValueCompletionTest { }; harness.intialize(null); } - + private IJavaProject getTestProject() { return testProject; } - + @Test public void testPrefixIdentification() { ValueCompletionProcessor processor = new ValueCompletionProcessor(null); - + assertEquals("pre", processor.identifyPropertyPrefix("pre", 3)); assertEquals("pre", processor.identifyPropertyPrefix("prefix", 3)); assertEquals("", processor.identifyPropertyPrefix("", 0)); @@ -195,20 +210,20 @@ public class ValueCompletionTest { public void testPlainPrefixCompletion() throws Exception { prepareCase("@Value(\"onField\")", "@Value(spri<*>)"); prepareDefaultIndexData(); - + assertAnnotationCompletions( "@Value(\"${spring.prop1}\"<*>)"); } - + @Test public void testQoutedPrefixCompletion() throws Exception { prepareCase("@Value(\"onField\")", "@Value(\"spri<*>\")"); prepareDefaultIndexData(); - + assertAnnotationCompletions( "@Value(\"${spring.prop1}<*>\")"); } - + @Test public void testRandomSpelExpressionNoCompletion() throws Exception { prepareCase("@Value(\"onField\")", "@Value(\"#{<*>}\")"); @@ -219,7 +234,7 @@ public class ValueCompletionTest { "@Value(\"#{${else.prop3}<*>}\")", "@Value(\"#{${spring.prop1}<*>}\")"); } - + @Test public void testRandomSpelExpressionWithPropertyDollar() throws Exception { prepareCase("@Value(\"onField\")", "@Value(\"#{345$<*>}\")"); @@ -230,7 +245,7 @@ public class ValueCompletionTest { "@Value(\"#{345${else.prop3}<*>}\")", "@Value(\"#{345${spring.prop1}<*>}\")"); } - + @Test public void testRandomSpelExpressionWithPropertyDollerWithoutClosindBracket() throws Exception { prepareCase("@Value(\"onField\")", "@Value(\"#{345${<*>}\")"); @@ -241,7 +256,7 @@ public class ValueCompletionTest { "@Value(\"#{345${else.prop3}<*>}\")", "@Value(\"#{345${spring.prop1}<*>}\")"); } - + @Test public void testRandomSpelExpressionWithPropertyDollerWithClosingBracket() throws Exception { prepareCase("@Value(\"onField\")", "@Value(\"#{345${<*>}}\")"); @@ -252,7 +267,7 @@ public class ValueCompletionTest { "@Value(\"#{345${else.prop3<*>}}\")", "@Value(\"#{345${spring.prop1<*>}}\")"); } - + @Test public void testRandomSpelExpressionWithPropertyPrefixWithoutClosingBracket() throws Exception { prepareCase("@Value(\"onField\")", "@Value(\"#{345${spri<*>}\")"); @@ -261,7 +276,7 @@ public class ValueCompletionTest { assertAnnotationCompletions( "@Value(\"#{345${spring.prop1}<*>}\")"); } - + @Test public void testRandomSpelExpressionWithPropertyPrefixWithClosingBracket() throws Exception { prepareCase("@Value(\"onField\")", "@Value(\"#{345${spri<*>}}\")"); @@ -270,21 +285,21 @@ public class ValueCompletionTest { assertAnnotationCompletions( "@Value(\"#{345${spring.prop1<*>}}\")"); } - + private void prepareDefaultIndexData() { indexHarness.data("spring.prop1", "java.lang.String", null, null); indexHarness.data("data.prop2", "java.lang.String", null, null); indexHarness.data("else.prop3", "java.lang.String", null, null); } - + private void prepareCase(String selectedAnnotation, String annotationStatementBeforeTest) throws Exception { InputStream resource = this.getClass().getResourceAsStream("/test-projects/test-annotations/src/main/java/org/test/TestValueCompletion.java"); String content = IOUtils.toString(resource); - + content = content.replace(selectedAnnotation, annotationStatementBeforeTest); editor = new Editor(harness, content, LanguageId.JAVA); } - + private void assertAnnotationCompletions(String... completedAnnotations) throws Exception { List completions = editor.getCompletions(); int i = 0; @@ -293,7 +308,7 @@ public class ValueCompletionTest { clonedEditor.apply(completions.get(i++)); assertTrue(clonedEditor.getText().contains(expectedCompleted)); } - + assertEquals(i, completions.size()); } diff --git a/headless-services/boot-properties-language-server/src/test/java/org/springframework/ide/vscode/boot/editor/harness/AbstractPropsEditorTest.java b/headless-services/boot-properties-language-server/src/test/java/org/springframework/ide/vscode/boot/editor/harness/AbstractPropsEditorTest.java index 3b66fee60..8395cc90e 100644 --- a/headless-services/boot-properties-language-server/src/test/java/org/springframework/ide/vscode/boot/editor/harness/AbstractPropsEditorTest.java +++ b/headless-services/boot-properties-language-server/src/test/java/org/springframework/ide/vscode/boot/editor/harness/AbstractPropsEditorTest.java @@ -14,6 +14,7 @@ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; +import java.io.File; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; @@ -42,8 +43,22 @@ public abstract class AbstractPropsEditorTest { public static final String STRING = String.class.getName(); private ProjectsHarness projects = ProjectsHarness.INSTANCE; + protected PropertyIndexHarness md; - protected final JavaProjectFinder javaProjectFinder = (doc) -> getTestProject(); + protected final JavaProjectFinder javaProjectFinder = new JavaProjectFinder() { + @Override + public boolean isProjectRoot(File file) { + return false; + } + @Override + public IJavaProject find(File file) { + return null; + } + @Override + public IJavaProject find(IDocument doc) { + return getTestProject(); + } + }; private LanguageServerHarness harness; private IJavaProject testProject; diff --git a/headless-services/commons/commons-gradle/src/main/java/org/springframework/ide/vscode/commons/gradle/GradleProjectFinderStrategy.java b/headless-services/commons/commons-gradle/src/main/java/org/springframework/ide/vscode/commons/gradle/GradleProjectFinderStrategy.java index f46142d8f..1addc54e0 100644 --- a/headless-services/commons/commons-gradle/src/main/java/org/springframework/ide/vscode/commons/gradle/GradleProjectFinderStrategy.java +++ b/headless-services/commons/commons-gradle/src/main/java/org/springframework/ide/vscode/commons/gradle/GradleProjectFinderStrategy.java @@ -11,14 +11,10 @@ package org.springframework.ide.vscode.commons.gradle; import java.io.File; -import java.net.URI; -import java.net.URISyntaxException; import java.util.concurrent.ExecutionException; import org.springframework.ide.vscode.commons.languageserver.java.IJavaProjectFinderStrategy; import org.springframework.ide.vscode.commons.util.FileUtils; -import org.springframework.ide.vscode.commons.util.StringUtil; -import org.springframework.ide.vscode.commons.util.text.IDocument; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; @@ -40,23 +36,19 @@ public class GradleProjectFinderStrategy implements IJavaProjectFinderStrategy { } @Override - public GradleJavaProject find(IDocument d) throws ExecutionException, URISyntaxException { - String uriStr = d.getUri(); - if (StringUtil.hasText(uriStr)) { - URI uri = new URI(uriStr); - // TODO: This only work with File uri. Should it work with others - // too? - if (uri.getScheme().equalsIgnoreCase("file")) { - File file = new File(uri).getAbsoluteFile(); - File gradlebuild = FileUtils.findFile(file, GradleCore.GRADLE_BUILD_FILE); - if (gradlebuild != null) { - return cache.get(gradlebuild.getParentFile(), () -> { - return new GradleJavaProject(gradle, gradlebuild.getParentFile()); - }); - } - } + public GradleJavaProject find(File file) throws ExecutionException { + File gradlebuild = FileUtils.findFile(file, GradleCore.GRADLE_BUILD_FILE); + if (gradlebuild != null) { + return cache.get(gradlebuild.getParentFile(), () -> { + return new GradleJavaProject(gradle, gradlebuild.getParentFile()); + }); } return null; } + @Override + public boolean isProjectRoot(File file) { + return FileUtils.findFile(file, GradleCore.GRADLE_BUILD_FILE, false) != null; + } + } diff --git a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/DefaultJavaProjectFinder.java b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/DefaultJavaProjectFinder.java index d31efc816..ae8705c1d 100644 --- a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/DefaultJavaProjectFinder.java +++ b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/DefaultJavaProjectFinder.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016-2017 Pivotal, Inc. + * Copyright (c) 2016, 2017 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 @@ -8,11 +8,15 @@ * Contributors: * Pivotal, Inc. - initial API and implementation *******************************************************************************/ - package org.springframework.ide.vscode.commons.languageserver.java; +import java.io.File; +import java.net.URI; +import java.net.URISyntaxException; + import org.springframework.ide.vscode.commons.java.IJavaProject; import org.springframework.ide.vscode.commons.util.Log; +import org.springframework.ide.vscode.commons.util.StringUtil; import org.springframework.ide.vscode.commons.util.text.IDocument; public class DefaultJavaProjectFinder implements JavaProjectFinder { @@ -24,10 +28,30 @@ public class DefaultJavaProjectFinder implements JavaProjectFinder { } @Override - public IJavaProject find(IDocument d) { + public IJavaProject find(IDocument doc) { + try { + String uriStr = doc.getUri(); + if (StringUtil.hasText(uriStr)) { + URI uri = new URI(uriStr); + // TODO: This only work with File uri. Should it work with others + // too? + if (uri.getScheme().equalsIgnoreCase("file")) { + File file = new File(uri).getAbsoluteFile(); + return find(file); + } + } + } + catch (URISyntaxException e) { + Log.log(e); + } + return null; + } + + @Override + public IJavaProject find(File file) { for (IJavaProjectFinderStrategy strategy : strategies) { try { - IJavaProject project = strategy.find(d); + IJavaProject project = strategy.find(file); if (project != null) { return project; } @@ -37,5 +61,19 @@ public class DefaultJavaProjectFinder implements JavaProjectFinder { } return null; } + + @Override + public boolean isProjectRoot(File file) { + for (IJavaProjectFinderStrategy strategy : strategies) { + try { + if (strategy.isProjectRoot(file)) { + return true; + } + } catch (Exception e) { + Log.log(e); + } + } + return false; + } } diff --git a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/IJavaProjectFinderStrategy.java b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/IJavaProjectFinderStrategy.java index e8b8021f1..65453a589 100644 --- a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/IJavaProjectFinderStrategy.java +++ b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/IJavaProjectFinderStrategy.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016 Pivotal, Inc. + * Copyright (c) 2016, 2017 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 @@ -10,18 +10,18 @@ *******************************************************************************/ package org.springframework.ide.vscode.commons.languageserver.java; +import java.io.File; + import org.springframework.ide.vscode.commons.java.IJavaProject; -import org.springframework.ide.vscode.commons.util.text.IDocument; /** * Strategy foe finding Java project for a document * * @author Alex Boyko - * */ -@FunctionalInterface public interface IJavaProjectFinderStrategy { - IJavaProject find(IDocument document) throws Exception; + IJavaProject find(File file) throws Exception; + boolean isProjectRoot(File file); } diff --git a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/JavaProjectFinder.java b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/JavaProjectFinder.java index a305995c0..1c18b5196 100644 --- a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/JavaProjectFinder.java +++ b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/JavaProjectFinder.java @@ -8,13 +8,17 @@ * Contributors: * Pivotal, Inc. - initial API and implementation *******************************************************************************/ - package org.springframework.ide.vscode.commons.languageserver.java; +import java.io.File; + import org.springframework.ide.vscode.commons.java.IJavaProject; import org.springframework.ide.vscode.commons.util.text.IDocument; -@FunctionalInterface public interface JavaProjectFinder { + IJavaProject find(IDocument doc); + IJavaProject find(File file); + boolean isProjectRoot(File file); + } diff --git a/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/JavaProjectWithClasspathFileFinderStrategy.java b/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/JavaProjectWithClasspathFileFinderStrategy.java index 9c6712bec..dbcb67108 100644 --- a/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/JavaProjectWithClasspathFileFinderStrategy.java +++ b/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/JavaProjectWithClasspathFileFinderStrategy.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016 Pivotal, Inc. + * Copyright (c) 2016, 2017 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,15 +11,11 @@ package org.springframework.ide.vscode.commons.maven; import java.io.File; -import java.net.URI; -import java.net.URISyntaxException; import java.util.concurrent.ExecutionException; import org.springframework.ide.vscode.commons.languageserver.java.IJavaProjectFinderStrategy; import org.springframework.ide.vscode.commons.maven.java.classpathfile.JavaProjectWithClasspathFile; import org.springframework.ide.vscode.commons.util.FileUtils; -import org.springframework.ide.vscode.commons.util.StringUtil; -import org.springframework.ide.vscode.commons.util.text.IDocument; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; @@ -29,32 +25,19 @@ public class JavaProjectWithClasspathFileFinderStrategy implements IJavaProjectF public Cache cache = CacheBuilder.newBuilder().build(); @Override - public JavaProjectWithClasspathFile find(IDocument d) throws ExecutionException, URISyntaxException { - String uriStr = d.getUri(); - if (StringUtil.hasText(uriStr)) { - URI uri = new URI(uriStr); - // TODO: This only work with File uri. Should it work with others - // too? - if (uri.getScheme().equalsIgnoreCase("file")) { - File file = toFile(uri); - File cpFile = FileUtils.findFile(file, MavenCore.CLASSPATH_TXT); - if (cpFile != null) { - return cache.get(cpFile, () -> { - return new JavaProjectWithClasspathFile(cpFile); - }); - } - } + public JavaProjectWithClasspathFile find(File file) throws ExecutionException { + File cpFile = FileUtils.findFile(file, MavenCore.CLASSPATH_TXT); + if (cpFile != null) { + return cache.get(cpFile, () -> { + return new JavaProjectWithClasspathFile(cpFile); + }); } return null; } - protected File toFile(URI uri) { -// try { - return new File(uri).getAbsoluteFile(); -// } catch (Exception e) { -// Log.log("Ignored Uri '"+uri+"'. Not a file?", e); -// return null; -// } + @Override + public boolean isProjectRoot(File file) { + return FileUtils.findFile(file, MavenCore.CLASSPATH_TXT, false) != null; } } diff --git a/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/MavenProjectFinderStrategy.java b/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/MavenProjectFinderStrategy.java index c925015dd..3088714f1 100644 --- a/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/MavenProjectFinderStrategy.java +++ b/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/MavenProjectFinderStrategy.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016 Pivotal, Inc. + * Copyright (c) 2016, 2017 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,15 +11,11 @@ package org.springframework.ide.vscode.commons.maven; import java.io.File; -import java.net.URI; -import java.net.URISyntaxException; import java.util.concurrent.ExecutionException; import org.springframework.ide.vscode.commons.languageserver.java.IJavaProjectFinderStrategy; import org.springframework.ide.vscode.commons.maven.java.MavenJavaProject; import org.springframework.ide.vscode.commons.util.FileUtils; -import org.springframework.ide.vscode.commons.util.StringUtil; -import org.springframework.ide.vscode.commons.util.text.IDocument; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; @@ -28,7 +24,6 @@ import com.google.common.cache.CacheBuilder; * Finds Maven Project based * * @author Alex Boyko - * */ public class MavenProjectFinderStrategy implements IJavaProjectFinderStrategy { @@ -41,23 +36,19 @@ public class MavenProjectFinderStrategy implements IJavaProjectFinderStrategy { } @Override - public MavenJavaProject find(IDocument d) throws ExecutionException, URISyntaxException { - String uriStr = d.getUri(); - if (StringUtil.hasText(uriStr)) { - URI uri = new URI(uriStr); - // TODO: This only work with File uri. Should it work with others - // too? - if (uri.getScheme().equalsIgnoreCase("file")) { - File file = new File(uri).getAbsoluteFile(); - File pomFile = FileUtils.findFile(file, MavenCore.POM_XML); - if (pomFile != null) { - return cache.get(pomFile, () -> { - return new MavenJavaProject(maven, pomFile); - }); - } - } + public MavenJavaProject find(File file) throws ExecutionException { + File pomFile = FileUtils.findFile(file, MavenCore.POM_XML); + if (pomFile != null) { + return cache.get(pomFile, () -> { + return new MavenJavaProject(maven, pomFile); + }); } return null; } + @Override + public boolean isProjectRoot(File file) { + return FileUtils.findFile(file, MavenCore.POM_XML, false) != null; + } + } diff --git a/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/FileUtils.java b/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/FileUtils.java index d968c80b5..b4329bd51 100644 --- a/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/FileUtils.java +++ b/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/FileUtils.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016 Pivotal, Inc. + * Copyright (c) 2016, 2017 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 @@ -13,26 +13,30 @@ package org.springframework.ide.vscode.commons.util; import java.io.File; /** - * Utilitity methods for working with files + * Utilitity methods for working with files * * @authro Kris De Volder * @author Alex Boyko - * */ public class FileUtils { /** * Find file given its fil name in the given folder or its parent folders + * * @param folder Starting folder * @param fileNameToFind Name of the file to find * @return Found File */ public static File findFile(File folder, String fileNameToFind) { - if (folder!=null && folder.exists()) { + return findFile(folder, fileNameToFind, true); + } + + public static File findFile(File folder, String fileNameToFind, boolean recursiveUp) { + if (folder != null && folder.exists()) { File file = new File(folder, fileNameToFind); if (file.isFile()) { return file; - } else { + } else if (recursiveUp) { return findFile(folder.getParentFile(), fileNameToFind); } }