/* * Copyright 2012 Dart project authors. * * Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.eclipse.org/legal/epl-v10.html * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package com.google.dart.tools.debug.core.util; import com.google.common.io.CharStreams; import com.google.common.io.Closeables; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.model.IStackFrame; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.util.Arrays; import java.util.List; /** * This class contains static utility methods for use by the debugger. */ public class DebuggerUtils { /** * Returns whether the given frame needs some additional disambiguating information from its two * surrounding frames. * * @param frame * @return * @throws DebugException */ public static boolean areSiblingNamesUnique(IExceptionStackFrame frame) throws DebugException { List<IStackFrame> frames = Arrays.asList(frame.getThread().getStackFrames()); int index = frames.indexOf(frame); if (index == -1) { return true; } if (index > 0) { IExceptionStackFrame other = (IExceptionStackFrame) frames.get(index - 1); if (needsDisambiguating(other, frame)) { return false; } } if ((index + 1) < frames.size()) { IExceptionStackFrame other = (IExceptionStackFrame) frames.get(index + 1); if (needsDisambiguating(frame, other)) { return false; } } return true; } /** * The names of private fields are mangled by the VM. * <p> * _foo@652376 ==> _foo * <p> * Also, remove "set:" and "get:", as these are artifacts of the VM implementation. * <p> * e.x., Cat.get:color() ==> Cat.color() * * @param name * @return */ public static String demangleVmName(String name) { if (name == null) { return null; } int atIndex = name.indexOf('@'); while (atIndex != -1) { // check for _foo@76876.bar (or _Process@14117cc4._reportError@14117cc4) int endIndex = name.indexOf('.', atIndex); if (endIndex == -1) { name = name.substring(0, atIndex); } else { name = name.substring(0, atIndex) + name.substring(endIndex); } atIndex = name.indexOf('@'); } // Also remove the trailing '.' for default constructors. if (name.endsWith(".")) { name = name.substring(0, name.length() - 1); } // remove "set:" and "get:" // Cat.get:color() ==> Cat.color() if (name.indexOf(".set:") != -1) { int index = name.indexOf(".set:"); name = name.substring(0, index + 1) + name.substring(index + 5); } if (name.indexOf(".get:") != -1) { int index = name.indexOf(".get:"); name = name.substring(0, index + 1) + name.substring(index + 5); } return name; } public static String extractFileLine(IFile file, int lineNumber) { if (file == null) { return null; } try { return extractFileLine(file.getContents(), file.getCharset(), lineNumber); } catch (CoreException ce) { } return null; } public static String extractFileLine(InputStream contents, String charset, int lineNumber) { if (contents == null) { return null; } try { Reader r = charset != null ? new InputStreamReader(contents, charset) : new InputStreamReader(contents); List<String> lines = CharStreams.readLines(r); Closeables.close(r, true); if (lineNumber >= 0 && lineNumber < lines.size()) { String lineStr = lines.get(lineNumber).trim(); return lineStr.length() == 0 ? null : lineStr; } } catch (IOException ioe) { } return null; } public static boolean isInternalMethodName(String methodName) { return methodName.startsWith("Object._noSuchMethod@"); } /** * @return whether the given debugger symbol name represents a private symbol */ public static boolean isPrivateName(String name) { // These are special names generated by dart2js. if (name.startsWith("$.") || name.startsWith("$$.")) { return false; } // A private top-level method (_foo()). if (name.startsWith("_")) { return true; } // A private static or instance method (i.e Foo._bar()). return name.indexOf("._") != -1; } public static String printString(String str) { if (str == null) { return null; } if (str.indexOf('\n') != -1) { str = str.replace("\n", "\\n"); } if (str.indexOf('\r') != -1) { str = str.replace("\r", "\\r"); } if (str.indexOf('\t') != -1) { str = str.replace("\t", "\\t"); } // Don't re-quote already quoted strings. if (str.length() > 1 && str.startsWith("\"") && str.endsWith("\"")) { return str; } else { return "\"" + str + "\""; } } private static boolean needsDisambiguating(IExceptionStackFrame frame1, IExceptionStackFrame frame2) { if (frame1.getShortName().equals(frame2.getShortName())) { // These will need disambiguating if the long names are different. return !frame1.getLongName().equals(frame2.getLongName()); } return false; } private DebuggerUtils() { } }