blob: cf1cd73050fa3baba0fb93352fad72cf58eadd1c [file] [log] [blame]
package org.eclipse.ui.internal.ide.application;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileInfo;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.runtime.Path;
/**
* @since 3.3
*
*/
/**
* Decode paths with line and column location information. Formats supported
* include:
* <ul>
* <li>filepath:line</li>
* <li>filepath:line:col</li>
* <li>filepath:line+col</li>
* <li>filepath+line</li>
* <li>filepath+line:col</li>
* <li>filepath+line+col</li>
* </ul>
* Certain OS/WS interpret colons differently (see bug 496845)
*
* @see #resolve(String)
*/
public class FileLocationDetails {
// vars are package protected for access from DelayedEventsProcessor
Path path;
IFileStore fileStore;
IFileInfo fileInfo;
int line = -1;
int column = -1;
/**
* Check if path exists with optional encoded line and/or column
* specification
*
* @param path
* the possibly-encoded file path with optional line/column
* details
* @return the location details or {@code null} if the file doesn't exist
*/
public static FileLocationDetails resolve(String path) {
FileLocationDetails details = checkLocation(path, -1, -1);
if (details != null) {
return details;
}
// Ideally we'd use a regex, except that we need to be greedy
// in matching. For example, we're trying to open /tmp/foo:3:3
// and there is an actual file named /tmp/foo:3
Pattern lPattern = Pattern.compile("^(?<path>.*?)[+:](?<line>\\d+)$"); //$NON-NLS-1$
Pattern lcPattern = Pattern.compile("^(?<path>.*?)[+:](?<line>\\d+)[:+](?<column>\\d+)$"); //$NON-NLS-1$
Matcher m = lPattern.matcher(path);
if (m.matches()) {
try {
details = checkLocation(m.group("path"), Integer.parseInt(m.group("line")), -1); //$NON-NLS-1$//$NON-NLS-2$
if (details != null) {
return details;
}
} catch (NumberFormatException e) {
// shouldn't happen
}
}
m = lcPattern.matcher(path);
if (m.matches()) {
try {
details = checkLocation(m.group("path"), Integer.parseInt(m.group("line")), //$NON-NLS-1$//$NON-NLS-2$
m.group("column") != null ? Integer.parseInt(m.group("column")) : -1); //$NON-NLS-1$ //$NON-NLS-2$
if (details != null) {
return details;
}
} catch (NumberFormatException e) {
// shouldn't happen invalid line or column
}
}
// no matches on line or line+column
return null;
}
/** Return details if {@code path} exists */
private static FileLocationDetails checkLocation(String path, int line, int column) {
FileLocationDetails spec = new FileLocationDetails();
spec.path = new Path(path);
spec.fileStore = EFS.getLocalFileSystem().getStore(spec.path);
spec.fileInfo = spec.fileStore.fetchInfo();
spec.line = line;
spec.column = column;
return spec.fileInfo.exists() ? spec : null;
}
}