package com.jetbrains.lang.dart.ide.runner; import com.intellij.execution.filters.Filter; import com.intellij.execution.filters.HyperlinkInfo; import com.intellij.execution.filters.OpenFileHyperlinkInfo; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.search.FilenameIndex; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.util.io.URLUtil; import com.jetbrains.lang.dart.ide.runner.server.OpenDartObservatoryUrlAction; import com.jetbrains.lang.dart.sdk.DartSdk; import com.jetbrains.lang.dart.util.DartUrlResolver; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collection; import static com.jetbrains.lang.dart.util.DartUrlResolver.DART_PREFIX; import static com.jetbrains.lang.dart.util.DartUrlResolver.PACKAGE_PREFIX; import static com.jetbrains.lang.dart.util.PubspecYamlUtil.PUBSPEC_YAML; public class DartConsoleFilter implements Filter { private final @NotNull Project myProject; private final @Nullable DartSdk mySdk; private final @Nullable DartUrlResolver myDartUrlResolver; private Collection<VirtualFile> myAllPubspecYamlFiles; public static final String OBSERVATORY_LISTENING_ON = "Observatory listening on "; public DartConsoleFilter(final @NotNull Project project) { this(project, null); } public DartConsoleFilter(final @NotNull Project project, final @Nullable VirtualFile contextFile) { myProject = project; mySdk = DartSdk.getDartSdk(project); myDartUrlResolver = contextFile == null ? null : DartUrlResolver.getInstance(project, contextFile); } @Nullable public Result applyFilter(final String line, final int entireLength) { if (line.startsWith(OBSERVATORY_LISTENING_ON + "http://")) { return getObservatoryUrlResult(line, entireLength - line.length()); } final DartPositionInfo info = DartPositionInfo.parsePositionInfo(line); if (info == null) return null; final VirtualFile file; switch (info.type) { case FILE: String path = URLUtil.unescapePercentSequences(info.path); if (SystemInfo.isWindows) { path = StringUtil.trimLeading(path, '/'); } file = LocalFileSystem.getInstance().findFileByPath(path); break; case DART: file = DartUrlResolver.findFileInDartSdkLibFolder(myProject, mySdk, DART_PREFIX + info.path); break; case PACKAGE: if (myDartUrlResolver != null) { file = myDartUrlResolver.findFileByDartUrl(PACKAGE_PREFIX + info.path); } else { if (myAllPubspecYamlFiles == null) { myAllPubspecYamlFiles = FilenameIndex.getVirtualFilesByName(myProject, PUBSPEC_YAML, GlobalSearchScope.projectScope(myProject)); } VirtualFile inPackage = null; for (VirtualFile yamlFile : myAllPubspecYamlFiles) { inPackage = DartUrlResolver.getInstance(myProject, yamlFile).findFileByDartUrl(PACKAGE_PREFIX + info.path); if (inPackage != null) { break; } } file = inPackage; } break; default: file = null; } if (file != null && !file.isDirectory()) { final int highlightStartOffset = entireLength - line.length() + info.highlightingStartIndex; final int highlightEndOffset = entireLength - line.length() + info.highlightingEndIndex; return new Result(highlightStartOffset, highlightEndOffset, new OpenFileHyperlinkInfo(myProject, file, info.line, info.column)); } return null; } @Nullable private static Result getObservatoryUrlResult(final String line, final int lineStartOffset) { assert line.startsWith(OBSERVATORY_LISTENING_ON + "http://") : line; final String url = line.trim().substring(OBSERVATORY_LISTENING_ON.length()); final int colonIndex = url.indexOf(":", "http://".length()); if (colonIndex <= 0) return null; final String port = url.substring(colonIndex + 1); try { //noinspection ResultOfMethodCallIgnored Integer.parseInt(port); final int startOffset = lineStartOffset + OBSERVATORY_LISTENING_ON.length(); return new Result(startOffset, startOffset + url.length(), new ObservatoryHyperlinkInfo(url)); } catch (NumberFormatException ignore) {/**/} return null; } private static class ObservatoryHyperlinkInfo implements HyperlinkInfo { private final String myUrl; public ObservatoryHyperlinkInfo(@NotNull final String url) { myUrl = StringUtil.replace(url, "http://0.0.0.0:", "http://localhost:"); } @Override public void navigate(final Project project) { OpenDartObservatoryUrlAction.openUrlInChromeFamilyBrowser(myUrl); } } }