| 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; |
| } |
| } |