package com.jetbrains.lang.dart.ide.runner;
import com.intellij.execution.filters.Filter;
import com.intellij.execution.filters.OpenFileHyperlinkInfo;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Couple;
import com.intellij.openapi.util.Trinity;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
// resolves paths relative to working dir that are reported by package:test or 'pub build'
public class DartRelativePathsConsoleFilter implements Filter {
@NotNull private final Project myProject;
@NotNull private final String myBaseDirPath;
public DartRelativePathsConsoleFilter(@NotNull final Project project, @NotNull final String baseDirPath) {
myProject = project;
myBaseDirPath = baseDirPath;
}
@Nullable
public Result applyFilter(final String text, final int entireLength) {
final String trimmedText = StringUtil.trimLeading(text);
final Trinity<String, Integer, Integer> fileRelPathLineAndColumn = getFileRelPathLineAndColumn(trimmedText);
if (fileRelPathLineAndColumn == null) return null;
final String fileRelPath = fileRelPathLineAndColumn.first;
final int line = fileRelPathLineAndColumn.second;
final int column = fileRelPathLineAndColumn.third;
final VirtualFile file =
LocalFileSystem.getInstance().findFileByPath(myBaseDirPath + "/" + trimmedText.substring(0, fileRelPath.length()));
if (file == null || file.isDirectory()) return null;
return new Result(entireLength - trimmedText.length(),
entireLength - trimmedText.length() + fileRelPath.length(),
new OpenFileHyperlinkInfo(myProject, file, line, column));
}
@Nullable
public static Trinity<String, Integer, Integer> getFileRelPathLineAndColumn(@NotNull final String text) {
// "web\anagram.dart:23:8:"
// " ../subdir/someFile.dart 73:29 main.<fn>"
if (text.isEmpty()) return null;
if (text.charAt(0) != '.' && !Character.isJavaIdentifierStart(text.charAt(0))) return null;
int index = 0;
while (text.length() > ++index) {
final char ch = text.charAt(index);
if (ch != '/' && ch != '\\' && ch != '.' && !Character.isJavaIdentifierPart(ch)) break;
}
if (text.length() <= index + 3) return null; // at least 4 symbols more: " 1:1" or ":1:1"
final String relPath = text.substring(0, index);
if (!relPath.endsWith(".dart") || (text.charAt(index) != ' ' && text.charAt(index) != ':')) return null;
final Couple<Integer> lineAndColumn = DartPositionInfo.parseLineAndColumn(text.substring(index + 1));
final int line = lineAndColumn == null ? -1 : lineAndColumn.first >= 0 ? lineAndColumn.first - 1 : lineAndColumn.first;
final int column = lineAndColumn == null ? -1 : lineAndColumn.second >= 0 ? lineAndColumn.second - 1 : lineAndColumn.second;
if (line < 0 || column < 0) return null;
return Trinity.create(relPath, line, column);
}
}