Skip to content

Commit

Permalink
Resolve path relative to file opened in editor.
Browse files Browse the repository at this point in the history
Closes #59
  • Loading branch information
basti1302 committed Sep 15, 2014
1 parent d8dda9d commit ec0c578
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public void testNullPath() throws Exception
{
try
{
this.validator.checkPath(null, ResourceType.BOTH);
this.validator.checkPath(null, ResourceType.BOTH, null);
fail("IllegalArgumentException expected");
}
catch (IllegalArgumentException e)
Expand All @@ -67,7 +67,7 @@ public void testNullResourceType() throws Exception
{
try
{
this.validator.checkPath("/path/to/resource", null);
this.validator.checkPath("/path/to/resource", null, null);
fail("IllegalArgumentException expected");
}
catch (IllegalArgumentException e)
Expand All @@ -86,7 +86,7 @@ public void testResourceDoesNotExistNoParentAvailable() throws Exception
{
String pathString = "doesnotexist";
Validator.MaybeFile checkedFile = this.validator.checkPath(pathString,
ResourceType.BOTH);
ResourceType.BOTH, null);
assertNull(checkedFile.file);
assertEquals(Validator.Reason.RESOURCE_DOES_NOT_EXIST, checkedFile.reason);
this.validator.showMessageFor(checkedFile.reason, pathString,
Expand All @@ -110,7 +110,7 @@ public void testResourceDoesNotExistNorDoesParent() throws Exception
{
String pathString = "test-resources/does/not/exist";
Validator.MaybeFile checkedFile = this.validator.checkPath(pathString,
ResourceType.BOTH);
ResourceType.BOTH, null);
assertNull(checkedFile.file);
assertEquals(Validator.Reason.RESOURCE_DOES_NOT_EXIST, checkedFile.reason);
this.validator.showMessageFor(checkedFile.reason, pathString,
Expand All @@ -132,7 +132,7 @@ public void testDirectoryInsteadOfFile() throws Exception
{
String pathString = "test-resources/path/to/resource";
Validator.MaybeFile checkedFile = this.validator.checkPath(pathString,
ResourceType.FILE);
ResourceType.FILE, null);
assertNull(checkedFile.file);
assertEquals(Validator.Reason.NOT_A_FILE, checkedFile.reason);
this.validator.showMessageFor(checkedFile.reason, pathString,
Expand All @@ -153,7 +153,7 @@ public void testFileInsteadOfDirectoryReturnParentDirectory()
{
String pathString = "test-resources/path/to/resource/file.txt";
Validator.MaybeFile checkedFile = this.validator.checkPath(pathString,
ResourceType.DIRECTORY);
ResourceType.DIRECTORY, null);
assertEquals(new File(pathString).getParentFile(), checkedFile.file);
assertNull(checkedFile.reason);
}
Expand All @@ -168,7 +168,7 @@ public void testFile() throws Exception
{
String pathString = "test-resources/path/to/resource/file.txt";
Validator.MaybeFile checkedFile = this.validator.checkPath(pathString,
ResourceType.FILE);
ResourceType.FILE, null);
assertEquals(new File(pathString), checkedFile.file);
assertNull(checkedFile.reason);
}
Expand All @@ -183,7 +183,7 @@ public void testDirectoryNoTrailingSlash() throws Exception
{
String pathString = "test-resources/path/to/resource";
Validator.MaybeFile checkedFile = this.validator.checkPath(pathString,
ResourceType.DIRECTORY);
ResourceType.DIRECTORY, null);
assertEquals(new File(pathString), checkedFile.file);
assertNull(checkedFile.reason);
}
Expand All @@ -198,7 +198,7 @@ public void testDirectoryTrailingSlash() throws Exception
{
String pathString = "test-resources/path/to/resource/";
Validator.MaybeFile checkedFile = this.validator.checkPath(pathString,
ResourceType.DIRECTORY);
ResourceType.DIRECTORY, null);
assertEquals(new File(pathString), checkedFile.file);
assertNull(checkedFile.reason);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,17 @@ public Object executeForSelection(ExecutionEvent event, ISelection selection,
getLogFacility().logWarning("Current selection's text is null.");
return null;
}
else if (selectedText.equals("") || this.alwaysUseFileOpenedInEditor())

File fileOpenedInEditor = this
.prefetchFileOpenedInEditor(event, appContext);
if (selectedText.equals("") || this.alwaysUseFileOpenedInEditor())
{
this.executeForFileOpenedInEditor(event, appContext);
this.executeForFileOpenedInEditor(fileOpenedInEditor, event, appContext);
return null;
}
else if (this.shouldInterpretTextSelectionAsFileName())
{
this.executeForSelectedText(event, selectedText);
this.executeForSelectedText(event, selectedText, fileOpenedInEditor);
return null;
}
else
Expand All @@ -118,19 +121,14 @@ else if (this.shouldInterpretTextSelectionAsFileName())
return null;
}

private void executeForFileOpenedInEditor(ExecutionEvent event,
private File prefetchFileOpenedInEditor(ExecutionEvent event,
IEvaluationContext appContext) throws ExecutionException
{
Object editorInputObject = appContext.getParent().getVariable(
"activeEditorInput");
if (editorInputObject == null)
{
getPluginContext()
.getLogFacility()
.logWarning(
"The current selection is an empty text selection, so the command was invoked for the resource opened in the editor. "
+ "But the object fetched by event.getApplicationContext().getParent().getVariable(\"activeEditorInput\") is null.");
return;
return null;
}

File file = null;
Expand All @@ -141,7 +139,7 @@ private void executeForFileOpenedInEditor(ExecutionEvent event,
IResource fileInEditor = ResourceUtil.getResource(editorInput);
if (fileInEditor != null)
{
file = this.resourceToFile(fileInEditor, this.getResourceType(), event);
file = this.resourceToFile(fileInEditor, ResourceType.FILE, event);
}
}
// case 2: a file that is not part of the workspace
Expand All @@ -161,30 +159,52 @@ private void executeForFileOpenedInEditor(ExecutionEvent event,
{
file = uglyHackForFilesFromJars(editorInputObject, event);
}
// neither of the above, giving up
if (file == null)
// if neither of the above, then give up and return null

return file;
}

private void executeForFileOpenedInEditor(File fileInEditor,
ExecutionEvent event, IEvaluationContext appContext)
throws ExecutionException
{
if (fileInEditor == null)
{
getPluginContext()
.getLogFacility()
.logWarning(
"The current selection is an empty text selection, so the command was invoked for the resource opened in the editor. "
+ "But the object fetched by event.getApplicationContext().getParent().getVariable(\"activeEditorInput\") is not of expected type IFileEditorInput, but of type "
+ editorInputObject.getClass().getName());
MessageDialog
.openError(
HandlerUtil.getActiveShellChecked(event),
"This is not a normal file, is it?",
"The current selection is an empty text selection, so the command was invoked for the resource opened in the editor. "
+ "Unfortunately, the resource opened in the editor does not directly map to a file.");
return;
Object editorInputObject = appContext.getParent().getVariable(
"activeEditorInput");
if (editorInputObject == null)
{
getPluginContext()
.getLogFacility()
.logWarning(
"The current selection is an empty text selection, so the command was invoked for the resource opened in the editor. "
+ "But the object fetched by event.getApplicationContext().getParent().getVariable(\"activeEditorInput\") is null.");
return;
}
else
{
getPluginContext()
.getLogFacility()
.logWarning(
"The current selection is an empty text selection, so the command was invoked for the resource opened in the editor. "
+ "But the object fetched by event.getApplicationContext().getParent().getVariable(\"activeEditorInput\") is neither of the expected types (IEditorInput, IURIEditorInput or IClassFileEditorInput) but of type "
+ editorInputObject.getClass().getName());
MessageDialog
.openError(
HandlerUtil.getActiveShellChecked(event),
"This is not a normal file, is it?",
"The current selection is an empty text selection, so the command was invoked for the resource opened in the editor. "
+ "Unfortunately, the resource opened in the editor does not directly map to a file.");
return;
}
}

AbstractStartFromResourceHandlerDelegate startFromResourceHandlerDelegate = this
.getAppropriateStartFromResourceHandlerDelegate();
if (startFromResourceHandlerDelegate != null)
{
startFromResourceHandlerDelegate.doActionForFileList(Collections
.singletonList(file));
.singletonList(fileInEditor));
return;
}
else
Expand All @@ -200,7 +220,7 @@ private void executeForFileOpenedInEditor(ExecutionEvent event,

private File uglyHackForFilesFromJars(Object editorInput, ExecutionEvent event)
{
// I think I've never dirty hack as ugly as this.
// I think I've never written a dirty hack as ugly as this.
// I solemnly swear to never do it again. BK.
// Oh, btw, it's done via reflection to avoid a dependency to JDT for
// StartExplorer but still work for the class file editor for a class from
Expand Down Expand Up @@ -238,12 +258,13 @@ private File uglyHackForFilesFromJars(Object editorInput, ExecutionEvent event)
return null;
}

private void executeForSelectedText(ExecutionEvent event, String selectedText)
private void executeForSelectedText(ExecutionEvent event,
String selectedText, File fileOpenedInEditor)
throws ExecutionException
{
selectedText = selectedText.trim();
Validator.MaybeFile maybeFile = this.getValidator().checkPath(selectedText,
this.getResourceType());
this.getResourceType(), fileOpenedInEditor);
if (maybeFile.file != null)
{
this.doActionForFile(maybeFile.file);
Expand Down
43 changes: 41 additions & 2 deletions plugin/src/de/bastiankrol/startexplorer/util/Validator.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static de.bastiankrol.startexplorer.Activator.getPluginContext;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

Expand Down Expand Up @@ -72,7 +73,7 @@ public File checkPathAndShowMessage(String pathString,
ResourceType resourceType, ExecutionEvent event)
throws ExecutionException
{
MaybeFile maybeFile = this.checkPath(pathString, resourceType);
MaybeFile maybeFile = this.checkPath(pathString, resourceType, null);
if (maybeFile.file != null)
{
return maybeFile.file;
Expand All @@ -91,11 +92,14 @@ public File checkPathAndShowMessage(String pathString,
* @param resourceType either ResourceType.FILE or ResourceType.DIRECTORY,
* depending on which resource type is expected or ResourceType.BOTH,
* if both resource types are acceptable
* @param fileOpenedInEditor the file that is currently open in the editor, if
* any - used to resolve relative paths
* @return the absolute path of the file specified by <code>pathString</code>
* or a {@link Reason}, if <code>pathString</code> does not point to a
* valid file/directory.
*/
public MaybeFile checkPath(String pathString, ResourceType resourceType)
public MaybeFile checkPath(String pathString, ResourceType resourceType,
File fileOpenedInEditor)
{
if (pathString == null)
{
Expand All @@ -106,6 +110,25 @@ public MaybeFile checkPath(String pathString, ResourceType resourceType)
throw new IllegalArgumentException("resourceType is null");
}
File file = new File(pathString);
if (!file.isAbsolute() && fileOpenedInEditor != null)
{
try
{
file = absolutize(fileOpenedInEditor.getParentFile(), file);
}
catch (IOException e)
{
// That should not happen under normal circumstances. If it does, ignore
// it and work with the non-absolute path
getPluginContext()
.getLogFacility()
.logException(
"Could not resolve "
+ file.getPath()
+ " to an absolute path relative to the file that is currently opened in the editor ("
+ fileOpenedInEditor.getPath() + ").", e);
}
}
if (!file.exists())
{
File parentFile = file.getParentFile();
Expand Down Expand Up @@ -139,6 +162,22 @@ else if (!parentFile.exists())
return new MaybeFile(file);
}

private File absolutize(File base, File relativePath) throws IOException
{
if (base == null){
throw new NullPointerException(
"Can't create absolute path because base is null.");
}
if (relativePath == null)
{
throw new NullPointerException(
"Can't create absolute path because relativePath is null.");
}
String relative = relativePath.getPath();
relative = relative.replace("\\", "/");
return new File(base, relative).getCanonicalFile();
}

/**
* Shows a message dialog for the given reason.
*
Expand Down

1 comment on commit ec0c578

@paulvi
Copy link
Contributor

@paulvi paulvi commented on ec0c578 Sep 16, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a small change however.

Please sign in to comment.