diff options
author | Siva Velusamy <vsiva@google.com> | 2011-08-16 17:33:17 -0700 |
---|---|---|
committer | Siva Velusamy <vsiva@google.com> | 2011-08-17 11:20:12 -0700 |
commit | 50192fe103eacf358a399358f9945944fc142e44 (patch) | |
tree | 269fbdb36dfa362201570682a3c77eb51eeed11c /ddms | |
parent | 4106ac0477c4bfe2bed77e4709afe2f611bf1916 (diff) | |
download | sdk-50192fe103eacf358a399358f9945944fc142e44.zip sdk-50192fe103eacf358a399358f9945944fc142e44.tar.gz sdk-50192fe103eacf358a399358f9945944fc142e44.tar.bz2 |
Goto source when user double clicks on stack trace.
Change-Id: Ia2693424f0106fb3aa1724c211a8e1273f3a0c28
Diffstat (limited to 'ddms')
4 files changed, 188 insertions, 0 deletions
diff --git a/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/ILogCatMessageSelectionListener.java b/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/ILogCatMessageSelectionListener.java new file mode 100644 index 0000000..6e814b0 --- /dev/null +++ b/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/ILogCatMessageSelectionListener.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 + * + * 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.android.ddmuilib.logcat; + +/** + * Classes interested in listening to user selection of logcat + * messages should implement this interface. + */ +public interface ILogCatMessageSelectionListener { + void messageDoubleClicked(LogCatMessage m); +} diff --git a/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatPanel.java b/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatPanel.java index 9a598c0..83a0e2f 100644 --- a/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatPanel.java +++ b/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatPanel.java @@ -548,6 +548,8 @@ public final class LogCatPanel extends SelectionDependentPanel mViewer.setLabelProvider(mLogCatMessageLabelProvider); mViewer.setContentProvider(new LogCatMessageContentProvider()); mViewer.setInput(mReceiver.getMessages()); + + initDoubleClickListener(); } private String getColPreferenceKey(String field) { @@ -660,6 +662,9 @@ public final class LogCatPanel extends SelectionDependentPanel private void refreshFiltersTable() { Display.getDefault().asyncExec(new Runnable() { public void run() { + if (mFiltersTableViewer.getTable().isDisposed()) { + return; + } mFiltersTableViewer.refresh(); } }); @@ -704,4 +709,28 @@ public final class LogCatPanel extends SelectionDependentPanel return sb.getSelection() + sb.getThumb() == sb.getMaximum(); } + + private List<ILogCatMessageSelectionListener> mMessageSelectionListeners; + + private void initDoubleClickListener() { + mMessageSelectionListeners = new ArrayList<ILogCatMessageSelectionListener>(1); + + mViewer.getTable().addSelectionListener(new SelectionAdapter() { + @Override + public void widgetDefaultSelected(SelectionEvent arg0) { + List<LogCatMessage> selectedMessages = getSelectedLogCatMessages(); + if (selectedMessages.size() == 0) { + return; + } + + for (ILogCatMessageSelectionListener l : mMessageSelectionListeners) { + l.messageDoubleClicked(selectedMessages.get(0)); + } + } + }); + } + + public void addLogCatMessageSelectionListener(ILogCatMessageSelectionListener l) { + mMessageSelectionListeners.add(l); + } } diff --git a/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatStackTraceParser.java b/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatStackTraceParser.java new file mode 100644 index 0000000..3da9fd0 --- /dev/null +++ b/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatStackTraceParser.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 + * + * 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.android.ddmuilib.logcat; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Helper class that can determine if a string matches the exception + * stack trace pattern, and if so, can provide the java source file + * and line where the exception occured. + */ +public final class LogCatStackTraceParser { + /** Regex to match a stack trace line. E.g.: + * at com.foo.Class.method(FileName.extension:10) + * extension is typically java, but can be anything (java/groovy/scala/..). + */ + private static final String EXCEPTION_LINE_REGEX = + "\\s*at\\ (.*)\\((.*)\\..*\\:(\\d+)\\)"; //$NON-NLS-1$ + + private static final Pattern EXCEPTION_LINE_PATTERN = + Pattern.compile(EXCEPTION_LINE_REGEX); + + /** + * Identify if a input line matches the expected pattern + * for a stack trace from an exception. + */ + public boolean isValidExceptionTrace(String line) { + return EXCEPTION_LINE_PATTERN.matcher(line).find(); + } + + /** + * Get fully qualified method name that threw the exception. + * @param line line from the stack trace, must have been validated with + * {@link LogCatStackTraceParser#isValidExceptionTrace(String)} before calling this method. + * @return fully qualified method name + */ + public String getMethodName(String line) { + Matcher m = EXCEPTION_LINE_PATTERN.matcher(line); + m.find(); + return m.group(1); + } + + /** + * Get source file name where exception was generated. Input line must be first validated with + * {@link LogCatStackTraceParser#isValidExceptionTrace(String)}. + */ + public String getFileName(String line) { + Matcher m = EXCEPTION_LINE_PATTERN.matcher(line); + m.find(); + return m.group(2); + } + + /** + * Get line number where exception was generated. Input line must be first validated with + * {@link LogCatStackTraceParser#isValidExceptionTrace(String)}. + */ + public int getLineNumber(String line) { + Matcher m = EXCEPTION_LINE_PATTERN.matcher(line); + m.find(); + try { + return Integer.parseInt(m.group(3)); + } catch (NumberFormatException e) { + return 0; + } + } + +} diff --git a/ddms/libs/ddmuilib/tests/src/com/android/ddmuilib/logcat/LogCatStackTraceParserTest.java b/ddms/libs/ddmuilib/tests/src/com/android/ddmuilib/logcat/LogCatStackTraceParserTest.java new file mode 100644 index 0000000..7d9869a --- /dev/null +++ b/ddms/libs/ddmuilib/tests/src/com/android/ddmuilib/logcat/LogCatStackTraceParserTest.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 + * + * 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.android.ddmuilib.logcat; + +import junit.framework.TestCase; + +public class LogCatStackTraceParserTest extends TestCase { + private LogCatStackTraceParser mTranslator; + + private static final String SAMPLE_METHOD = "com.foo.Class.method"; //$NON-NLS-1$ + private static final String SAMPLE_FNAME = "FileName"; //$NON-NLS-1$ + private static final int SAMPLE_LINENUM = 20; + private static final String SAMPLE_TRACE = + String.format(" at %s(%s.groovy:%d)", //$NON-NLS-1$ + SAMPLE_METHOD, SAMPLE_FNAME, SAMPLE_LINENUM); + + @Override + protected void setUp() throws Exception { + mTranslator = new LogCatStackTraceParser(); + } + + public void testIsValidExceptionTrace() { + assertTrue(mTranslator.isValidExceptionTrace(SAMPLE_TRACE)); + assertFalse(mTranslator.isValidExceptionTrace( + "java.lang.RuntimeException: message")); //$NON-NLS-1$ + assertFalse(mTranslator.isValidExceptionTrace( + "at com.foo.test(Ins.java:unknown)")); //$NON-NLS-1$ + } + + public void testGetMethodName() { + assertEquals(SAMPLE_METHOD, mTranslator.getMethodName(SAMPLE_TRACE)); + } + + public void testGetFileName() { + assertEquals(SAMPLE_FNAME, mTranslator.getFileName(SAMPLE_TRACE)); + } + + public void testGetLineNumber() { + assertEquals(SAMPLE_LINENUM, mTranslator.getLineNumber(SAMPLE_TRACE)); + } +} |