diff options
-rw-r--r-- | src/core/lombok/core/configuration/FileSystemSourceCache.java | 47 | ||||
-rw-r--r-- | src/core/lombok/eclipse/EclipseAST.java | 71 |
2 files changed, 110 insertions, 8 deletions
diff --git a/src/core/lombok/core/configuration/FileSystemSourceCache.java b/src/core/lombok/core/configuration/FileSystemSourceCache.java index d502a56b..12516557 100644 --- a/src/core/lombok/core/configuration/FileSystemSourceCache.java +++ b/src/core/lombok/core/configuration/FileSystemSourceCache.java @@ -24,6 +24,7 @@ package lombok.core.configuration; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; +import java.io.InputStream; import java.net.URI; import java.util.Collections; import java.util.Iterator; @@ -34,6 +35,10 @@ import java.util.concurrent.TimeUnit; import lombok.ConfigurationKeys; import lombok.core.configuration.ConfigurationSource.Result; +import lombok.eclipse.handlers.EclipseHandlerUtil; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.ResourcesPlugin; public class FileSystemSourceCache { private static String LOMBOK_CONFIG_FILENAME = "lombok.config"; @@ -47,9 +52,47 @@ public class FileSystemSourceCache { URI uri = javaFile.normalize(); if (!uri.isAbsolute()) { uri = new File(".").toURI().resolve(uri); + reporter.report(javaFile.toString(), "Somehow ended up with a relative path. This is a bug that the lombok authors cannot reproduce, so please help us out! Is this path: \"" + uri.toString() + "\" the correct absolute path for resource \"" + javaFile + "\"? If yes, or no, please report back to: https://code.google.com/p/projectlombok/issues/detail?id=683 and let us know. Thanks!", 0, ""); + } + try { + return sourcesForDirectory(new File(uri).getParentFile(), reporter); + } catch (Exception e) { + // possibly eclipse knows how to open this thing. Let's try! + int filesOpenedWithEclipse = 0; + String specialEclipseMessage = null; + try { + IFile[] files = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(uri); + if (files == null) specialEclipseMessage = ".findFilesForLocationURI returned 'null'"; + for (IFile file : files) { + InputStream in = file.getContents(true); + if (in != null) { + filesOpenedWithEclipse++; + in.close(); + } + } + if (filesOpenedWithEclipse == 0) specialEclipseMessage = ".findFilesForLocationURI did work and returned " + files.length + " entries, but none of those resulted in readable contents."; + } catch (Throwable t) { + // That's unfortunate. + } + + StringBuilder sb = new StringBuilder(); + sb.append("Lombok is trying to find the directory on disk where source file \"").append(javaFile.toString()); + sb.append("\" is located. We're trying to turn this URL into a file: \"").append(uri.toString()); + sb.append("\" but that isn't working. Please help us out by going to "); + sb.append("https://code.google.com/p/projectlombok/issues/detail?id=683 and reporting this error. Thanks!\n\n"); + sb.append("Exception thrown: ").append(e.getClass().getName()).append("\nException msg: ").append(e.getMessage()); + if (specialEclipseMessage == null && filesOpenedWithEclipse > 0) { + sb.append("\n\n Alternate strategy to read this resource via eclipse DID WORK however!! files read: " + filesOpenedWithEclipse); + } else if (specialEclipseMessage != null) { + sb.append("\n\n Alternate strategy to read this resource via eclipse produced a noteworthy result: ").append(specialEclipseMessage).append(" files read: ").append(filesOpenedWithEclipse); + } + + reporter.report(javaFile.toString(), sb.toString(), 0, ""); + try { + EclipseHandlerUtil.warning(sb.toString(), null); + } catch (Throwable ignore) {} + return Collections.emptyList(); } - - return sourcesForDirectory(new File(uri).getParentFile(), reporter); } public Iterable<ConfigurationSource> sourcesForDirectory(URI directory, ConfigurationProblemReporter reporter) { diff --git a/src/core/lombok/eclipse/EclipseAST.java b/src/core/lombok/eclipse/EclipseAST.java index 62a01e59..6e3f1847 100644 --- a/src/core/lombok/eclipse/EclipseAST.java +++ b/src/core/lombok/eclipse/EclipseAST.java @@ -22,6 +22,7 @@ package lombok.eclipse; import java.io.File; +import java.io.InputStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.URI; @@ -33,6 +34,7 @@ import java.util.List; import lombok.Lombok; import lombok.core.AST; import lombok.core.LombokImmutableList; +import lombok.eclipse.handlers.EclipseHandlerUtil; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.Path; @@ -49,6 +51,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.compiler.env.ICompilationUnit; +import org.eclipse.jdt.internal.core.Openable; +import org.eclipse.jdt.internal.core.builder.SourceFile; /** * Wraps around Eclipse's internal AST view to add useful features as well as the ability to visit parents from children, @@ -72,17 +77,31 @@ public class EclipseAST extends AST<EclipseAST, EclipseNode, ASTNode> { public URI getAbsoluteFileLocation() { String fileName = getFileName(); + + // state of the research in this: + // * We need an abstraction of a 'directory level'. This abstraction needs 'read()' which returns a string (content of lombok.config) and 'getParent()'. + // * sometimes, cud.compilationResult.compilationUnit is an 'openable', you can chase this down to end up with a path, you can jigger this into being the sibling 'lombok.config', and then use: + // InputStream in = ResourcesPlugin.getWorkspace().getRoot().getFile(ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(x)).getFullPath()).getContents(true); + // to read out this data. Our theory is that this will work even with very crazy virtual filesystems such as sourcecontrol://jazz/blabla. + // * With jazz and other creative file backed systems, is there even a 'project root' concept? Surely there won't be a 'workspace root' concept so how do we abstract the idea that, from jazz://whatever/projectroot, the parent is c:\myWorkspace? + // * Check the .getAlternateAbsolutePath() impl which has the research done so far. + // * VIRTUAL FILES: Sometimes virtual files are created; their location tends to be /FileName.java which cannot be resolved. Optimally speaking we should find the 'source' of the virtual code and use IT for determining lombok.config, but that may not be feasible. If not, can we get at project or at least workspace? + // * Either way there are sufficiently many WTF situations, that in case of error, as painful as this is, we should just carry on and not apply lombok.config, though at least if we don't recognize the scenario we should write a log file imploring the user to send us a bunch of feedback on the situation. + // Relevant issues: Comment 2 on #683, all of #682 if (!skipEclipseWorkspaceBasedFileResolver) { +// if (Boolean.FALSE) throw new IllegalArgumentException("Here's the alt strat result: " + getAlternativeAbsolutePathDEBUG()); try { /*if (fileName.startsWith("/") && fileName.indexOf('/', 1) > -1) */ try { return EclipseWorkspaceBasedFileResolver.resolve(fileName); } catch (IllegalArgumentException e) { - String msg = e.getMessage(); - if (msg != null && msg.startsWith("Path must include project and resource name")) { - // go with the fallthrough, but log that this happened. - addProblem(new ParseProblem(true, "Path resolution for lombok.config failed. Path: " + fileName + " -- falling back to: " + new File(fileName).getAbsoluteFile(), 0, 1)); - } else throw e; + EclipseHandlerUtil.warning("Finding 'lombok.config' file failed for '" + fileName + "'", e); +// String msg = e.getMessage(); +// if (msg != null && msg.startsWith("Path must include project and resource name")) { +// // We shouldn't throw an exception at all, but we can't reproduce this so we need help from our users to figure this out. +// // Let's bother them with an error that slows their eclipse down to a crawl and makes it unusable. +// throw new IllegalArgumentException("Path resolution for lombok.config failed. Path: " + fileName + " -- package of this class: " + this.getPackageDeclaration()); +// } else throw e; } } catch (NoClassDefFoundError e) { skipEclipseWorkspaceBasedFileResolver = true; @@ -91,7 +110,47 @@ public class EclipseAST extends AST<EclipseAST, EclipseNode, ASTNode> { // Our fancy workspace based source file to absolute disk location algorithm only works in a fully fledged eclipse. // This fallback works when using 'ecj', which has a much simpler project/path system. For example, no 'linked' resources. - return new File(fileName).getAbsoluteFile().toURI(); + + try { + return new File(fileName).getAbsoluteFile().toURI(); + } catch (Exception e) { + // This is a temporary workaround while we try and gather all the various exotic shenanigans where lombok.config resolution is not going to work! + return null; + } + } + + /** This is ongoing research for issues with lombok.config resolution. */ + @SuppressWarnings("unused") private String getAlternativeAbsolutePathDEBUG() { + try { + ICompilationUnit cu = this.compilationUnitDeclaration.compilationResult.compilationUnit; + + if (cu instanceof Openable) { + String x = ((Openable) cu).getResource().getFullPath().makeAbsolute().toString(); + int lastLoc = x.lastIndexOf('/'); + x = x.substring(0, lastLoc + 1) + "lombok.config"; + URI lombokConfigLoc = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(x)).getLocationURI(); + InputStream in = ResourcesPlugin.getWorkspace().getRoot().getFile(ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(x)).getFullPath()).getContents(true); + byte[] b = new byte[100000]; + int p = 0; + while (true) { + int r = in.read(b, p, b.length - p); + if (r == -1) break; + p += r; + } + in.close(); + return "(Contents of lombok.config: " + new String(b, 0, p, "UTF-8"); + +// return "(alt strategy result C: '" + ((Openable) cu).getResource().getFullPath().makeAbsolute().toString() + "'): resolved: " + EclipseWorkspaceBasedFileResolver.resolve(((Openable) cu).getResource().getFullPath().makeAbsolute().toString()); + } + if (cu instanceof SourceFile) { + String cuFileName = new String(((SourceFile) cu).getFileName()); + String cuIFilePath = ((SourceFile) cu).resource.getFullPath().toString(); + return "(alt strategy result A: \"" + cuFileName + "\" B: \"" + cuIFilePath + "\")"; + } + return "(alt strategy failed: cu isn't a SourceFile or Openable but a " + cu.getClass() + ")"; + } catch (Exception e) { + return "(alt strategy failed: " + e + ")"; + } } private static class EclipseWorkspaceBasedFileResolver { |