From 324022b71903ae5a9a61e9e9a3d7eb92d3d9d96c Mon Sep 17 00:00:00 2001
From: Reinier Zwitserloot <reinier@zwitserloot.com>
Date: Mon, 11 Mar 2013 21:01:28 +0100
Subject: work in progress on ProjectSearcher.

---
 src/core/lombok/eclipse/EclipseAST.java            |  29 ++++++
 .../lombok/eclipse/EclipseProjectSearcher.java     | 103 +++++++++++++++++++++
 src/core/lombok/eclipse/handlers/HandleWither.java |  15 +++
 3 files changed, 147 insertions(+)
 create mode 100644 src/core/lombok/eclipse/EclipseProjectSearcher.java

(limited to 'src/core')

diff --git a/src/core/lombok/eclipse/EclipseAST.java b/src/core/lombok/eclipse/EclipseAST.java
index 370b40fc..0f04f749 100644
--- a/src/core/lombok/eclipse/EclipseAST.java
+++ b/src/core/lombok/eclipse/EclipseAST.java
@@ -28,6 +28,8 @@ import org.eclipse.jdt.internal.compiler.CompilationResult;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import lombok.Lombok;
 import lombok.core.AST;
@@ -45,6 +47,9 @@ import org.eclipse.jdt.internal.compiler.ast.Initializer;
 import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.Statement;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.core.BasicCompilationUnit;
+import org.eclipse.jdt.internal.core.JavaElement;
+import org.eclipse.jdt.internal.core.JavaProject;
 
 /**
  * Wraps around Eclipse's internal AST view to add useful features as well as the ability to visit parents from children,
@@ -177,6 +182,30 @@ public class EclipseAST extends AST<EclipseAST, EclipseNode, ASTNode> {
 		return ast.compilationResult.fileName == null ? null : new String(ast.compilationResult.fileName);
 	}
 	
+	private static final Pattern PROJECT_NAME_FROM_FILEPATH = Pattern.compile("^/([^/]+)/(.*)$");
+	/**
+	 * Returns the JavaProject object (eclipse's abstraction of the project) associated with the source file that is represented by this AST.
+	 */
+	public JavaProject getProject() {
+		CompilationUnitDeclaration cud = (CompilationUnitDeclaration) top().get();
+		
+		if (cud.compilationResult().getCompilationUnit() instanceof JavaElement) {
+			JavaElement icu = (JavaElement) cud.compilationResult.compilationUnit;
+			return (JavaProject) icu.getJavaProject();
+		}
+		
+		char[] fn = cud.compilationResult().getFileName();
+		
+		Matcher m = PROJECT_NAME_FROM_FILEPATH.matcher(new String(fn));
+		if (m.matches()) {
+			String projName = m.group(1);
+			String path = m.group(2);
+			return EclipseProjectSearcher.getProject(projName);
+		}
+		
+		return null;
+	}
+	
 	/**
 	 * Call this method to move an EclipseAST generated for a diet parse to rebuild itself for the full parse -
 	 * with filled in method bodies and such. Also propagates problems and errors, which in diet parse
diff --git a/src/core/lombok/eclipse/EclipseProjectSearcher.java b/src/core/lombok/eclipse/EclipseProjectSearcher.java
new file mode 100644
index 00000000..b0a0e131
--- /dev/null
+++ b/src/core/lombok/eclipse/EclipseProjectSearcher.java
@@ -0,0 +1,103 @@
+package lombok.eclipse;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.internal.resources.Project;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.internal.core.ClasspathEntry;
+import org.eclipse.jdt.internal.core.JavaProject;
+
+public class EclipseProjectSearcher {
+	private final JavaProject project;
+	
+	public EclipseProjectSearcher(JavaProject project) {
+		this.project = project;
+	}
+	
+	private static final String[] ENTRY_KINDS = {"", "CPE_LIBRARY", "CPE_PROJECT", "CPE_SOURCE", "CPE_VARIABLE", "CPE_CONTAINER"};
+	
+	
+	public static JavaProject getProject(String projectName) {
+		Project depProjWrapper = (Project) ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
+		if (depProjWrapper == null) return null;
+		if (!JavaProject.hasJavaNature(depProjWrapper)) return null;
+		return (JavaProject) JavaCore.create(depProjWrapper);
+	}
+	
+	public List<String> findAllWithName(String pathSpec) throws Exception {
+		List<IPath> list = new ArrayList<IPath>();
+		findAllWithName0(list, new HashSet<String>(), pathSpec, project, false);
+		System.out.println("-------RESULTS [" + pathSpec + "]:");
+		System.out.println(list);
+		System.out.println("---------------");
+		
+		for (IPath path : list) {
+			try {
+				System.out.println(path + ": " + ResourcesPlugin.getWorkspace().getRoot().getFile(path.append(pathSpec)).getLocationURI());
+			} catch (Exception ignore) {
+				try {
+					System.out.println(path + ": " + ResourcesPlugin.getWorkspace().getRoot().getFolder(path.append(pathSpec)).getLocationURI());
+				} catch (Exception e) {
+				}
+			}
+			
+			// Check if we got through (didn't double-exept out), and then check if the resulting file URI
+			// actually exists.
+			//
+			// Then, check if 'path' itself is a jar, and if so, go root around in there.
+		}
+		
+		System.out.println("---------------");
+		
+		return null;
+	}
+	
+	private void findAllWithName0(List<IPath> list, Set<String> coveredProjectNames, String pathSpec, JavaProject proj, boolean exportedOnly) throws Exception {
+		if (proj == null) return;
+//		if (System.currentTimeMillis() > 0) return;
+		
+		
+		/*
+		 * 
+		 Research conclusions:
+		 
+		  * Eclipse is CRAZY.
+		  * Take a path, for which you don't know if it's project relative or not (nor does eclipse!!! yes, crazy), append the resource you are looking for (whether you know if its a jar or a path),
+		    and ask eclipse if it exists as a file. If yes, you have your answer.
+		  * Then, check if the path is 1 or 0 long, in that case, there is no answer.
+		  * Then, check if the path itself is a file and if yes, try and open it as a zip. Possibly try appending exclamationmark-resource and ask eclipse, maybe it has jar-style handling built in.
+		  * Cache the heck out of this because this code is called after just about every keystroke.
+		  * We should probably do something about duplicate detection and collapse, maybe just grab the textual content of those IPaths (they sure as hell don't contain anything useful beyond that), and
+		    toss em in a set.
+		  
+		 */
+		if (!coveredProjectNames.add(proj.getElementName())) return;
+		
+		for (IClasspathEntry rawEntry : proj.getResolvedClasspath(true)) {
+			ClasspathEntry entry = (ClasspathEntry) rawEntry;
+			if (exportedOnly && !entry.isExported() && entry.entryKind != IClasspathEntry.CPE_SOURCE) continue;
+			
+			switch (entry.entryKind) {
+			case IClasspathEntry.CPE_PROJECT:
+				String projName = entry.path.lastSegment();
+				JavaProject depProj = getProject(projName);
+				findAllWithName0(list, coveredProjectNames, pathSpec, depProj, true);
+				break;
+			case IClasspathEntry.CPE_SOURCE:
+				list.add(entry.path);
+				break;
+			case IClasspathEntry.CPE_LIBRARY:
+				list.add(entry.path);
+				break;
+			default:
+				System.out.println("Wot's this then? " + entry);
+			}
+		}
+	}
+}
diff --git a/src/core/lombok/eclipse/handlers/HandleWither.java b/src/core/lombok/eclipse/handlers/HandleWither.java
index 27fbc635..e114ab19 100644
--- a/src/core/lombok/eclipse/handlers/HandleWither.java
+++ b/src/core/lombok/eclipse/handlers/HandleWither.java
@@ -31,11 +31,13 @@ import java.util.Collections;
 import java.util.List;
 
 import lombok.AccessLevel;
+import lombok.Lombok;
 import lombok.core.AST.Kind;
 import lombok.core.AnnotationValues;
 import lombok.core.TransformationsUtil;
 import lombok.eclipse.EclipseAnnotationHandler;
 import lombok.eclipse.EclipseNode;
+import lombok.eclipse.EclipseProjectSearcher;
 import lombok.eclipse.handlers.EclipseHandlerUtil.FieldAccess;
 import lombok.experimental.Wither;
 
@@ -56,6 +58,7 @@ import org.eclipse.jdt.internal.compiler.ast.ThisReference;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.TypeReference;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.core.JavaProject;
 import org.mangosdk.spi.ProviderFor;
 
 @ProviderFor(EclipseAnnotationHandler.class)
@@ -124,6 +127,18 @@ public class HandleWither extends EclipseAnnotationHandler<Wither> {
 		AccessLevel level = annotation.getInstance().value();
 		if (level == AccessLevel.NONE || node == null) return;
 		
+		/** hackery */ {
+			JavaProject project = annotationNode.getAst().getProject();
+			if (project != null) try {
+				new EclipseProjectSearcher(project).findAllWithName("/java/lang/String.class");
+			} catch (Exception e) {
+				throw Lombok.sneakyThrow(e);
+			} else {
+				Thread.dumpStack();
+				System.err.println("****!!!!*!*!*!*!*!*!!*!********!!!! PROJECT IS NULL!!!!");
+			}
+		}
+		
 		List<Annotation> onMethod = unboxAndRemoveAnnotationParameter(ast, "onMethod", "@Setter(onMethod=", annotationNode);
 		List<Annotation> onParam = unboxAndRemoveAnnotationParameter(ast, "onParam", "@Setter(onParam=", annotationNode);
 		
-- 
cgit