Web-разработка, иностранные языки, Eclipse и разные разности

Zygo Profile

Санскрит - словоформы

Verbos Irregulares

7. Поиск исходника.

07.11.2015
Иметь поддержку пошагового прохода и исходного кода - замечательно, но пользователю необходима видимая обратная связь, чтобы понять, где отладчик временно приостановил работу. Исходный код должен быть открыт в редакторе и текущая строка должна быть подсвечена.

Фреймворк отладчика содержит специализированное решение, которое ищет файлы исходика в обозначенных директориях проекта. Первый способ этим воспользоваться - в вашем проекте должна быть возможность настроить поиск директорий с исходниками. Второй вариант - реализовать поиск исходника полностью из временного файла. В нашем случае последний вариант является наиболее простым.

Шаг 1. Развернутая картина.


Когда поток отладчика начинает обработку, он обычно вызывает файлы, методы или функции. Такие элементы составляют стек вызовов. Фреймворк отладчика использует этот стек, чтобы установить текущее место в исходном коде. Каждый элемент стека может быть привязан к определенному месту исходника (содержимое редактора + выделение внутри редактора).



Интерфейс ISourceLocator прикрепляется к расширению запуска как правило посредством использования точки расширения org.eclipse.debug.core.sourceLocators. Локатор превращает IStackFrame в элемент исходника посредством getSourceElement(IStackFrame stackFrame). Этот элемент обычно запрашивает IEditorInput и editorID из отладочной модели. Теперь редактор можно открыть. Выделение строки находится из стекового кадра.

Шаг 2. Добавление стековых кадров (StackFrame).


Используемая нами реализация IStackFrame достаточно проста: мы всего лишь позволяем сохранить текущий номер строку и получить текущий файл исходника. Поскольку нам доступен только один файл исходника, мы сохраняем его непосредственно внутри debug target.

Создайте новый класс TextStackFrame:



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package com.codeandme.textinterpreter.debugger.model;  
  
import org.eclipse.core.resources.IFile;  
import org.eclipse.debug.core.model.IDebugTarget;  
import org.eclipse.debug.core.model.IRegisterGroup;  
import org.eclipse.debug.core.model.IStackFrame;  
import org.eclipse.debug.core.model.IThread;  
import org.eclipse.debug.core.model.IVariable;  
  
public class TextStackFrame extends TextDebugElement implements IStackFrame {  
  
 private final IThread mThread;  
 private int mLineNumber = 1;  
  
 public TextStackFrame(IDebugTarget target, IThread thread) {  
  super(target);  
  mThread = thread;  
 }  
  
 @Override  
 public IThread getThread() {  
  return mThread;  
 }  
  
 @Override  
 public IVariable[] getVariables() {  
  return new IVariable[0];  
 }  
  
 @Override  
 public boolean hasVariables() {  
  return getVariables().length > 0;  
 }  
  
 @Override  
 public int getLineNumber() {  
  return mLineNumber;  
 }  
  
 @Override  
 public int getCharStart() {  
  return -1;  
 }  
  
 @Override  
 public int getCharEnd() {  
  return -1;  
 }  
  
 @Override  
 public String getName() {  
  return getSourceFile().getName() + ", line " + getLineNumber();  
 }  
  
 @Override  
 public IRegisterGroup[] getRegisterGroups() {  
  return new IRegisterGroup[0];  
 }  
  
 @Override  
 public boolean hasRegisterGroups() {  
  return getRegisterGroups().length > 0;  
 }  
  
 public void setLineNumber(int lineNumber) {  
  mLineNumber = lineNumber;  
 }  
  
 public IFile getSourceFile() {  
  return (getDebugTarget()).getFile();  
 }  
}  

Для языка, ориентированного на использование строк, метод getLineNumber() важен, поскольку он используется для работы маркера строки, когда наш код приостановлен. Убедитесь, что getCharStart() и getCharEnd() в этом случае возвращает -1. Если вы хотите выделить участок внутри строки, используйте getCharStart() и getCharEnd().

Поскольку мы не используем несколько файлов с исходниками, мы можем хранить вызовы функций или подобные вещи в одном статическом стековом кадре StackFrame во время всей отладочной сессии. Он регистритуется и обновляется из TextDebugTarget:



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package com.codeandme.textinterpreter.debugger.model;  
  
public class TextDebugTarget extends TextDebugElement implements IDebugTarget, IEventProcessor {  
  
 private final IFile mFile;  
  
 @Override  
 public void handleEvent(final IDebugEvent event) {  
  
  if (!isDisconnected()) {  
   System.out.println("Target.handleEvent() " + event);  
  
   if (event instanceof DebuggerStartedEvent) {  
    // create debug thread  
    TextThread thread = new TextThread(this);  
    mThreads.add(thread);  
    thread.fireCreationEvent();  
  
    // create stack frame  
    TextStackFrame stackFrame = new TextStackFrame(this, thread);  
    thread.addStackFrame(stackFrame);  
    stackFrame.fireCreationEvent();  
  
    // add breakpoint listener  
    DebugPlugin.getDefault().getBreakpointManager().addBreakpointListener(this);  
  
    // attach deferred breakpoints to debugger  
    IBreakpoint[] breakpoints = DebugPlugin.getDefault().getBreakpointManager().getBreakpoints(getModelIdentifier());  
    for (IBreakpoint breakpoint : breakpoints)  
     breakpointAdded(breakpoint);  
  
    // resume execution after setting breakpoints  
    resume();  
  
   } else if (event instanceof SuspendedEvent) {  
    // breakpoint hit  
    setState(State.SUSPENDED);  
  
    getThreads()[0].getTopStackFrame().setLineNumber(((SuspendedEvent) event).getLineNumber());  
    getThreads()[0].getTopStackFrame().fireChangeEvent(DebugEvent.CONTENT);  
  
    // inform eclipse of suspended state  
    fireSuspendEvent(DebugEvent.CLIENT_REQUEST);  
   }  
  }  
 }  
}  

Важно, чтобы StackFrame был зарегистрирован до того, как UI отладчика приостановил работу в первый раз. В противном случае Debug view не сможет полностью развернуть все узлы и по этой причине не отобразит в первую очередь приостановленный StackFrame и соответствующий файл с исходником. Пользователю придется вручную развернуть и выбрать стековый кадр.

Шаг 3. Определение файлов исходника.


Нахождение файлов исходника обычно обрабатывается SourceLocator. Нам нужно зарегистрировать новый SourceLocator в com.codeandme.textinterpreter.debugger/plugin.xml:



Реализация класса TextSourceLocator довольно проста, нам только необходимо разобраться с getSourceElement():


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
package com.codeandme.textinterpreter.debugger.model;  
  
public class TextSourceLocator implements IPersistableSourceLocator {  
  
 @Override  
 public Object getSourceElement(IStackFrame stackFrame) {  
  if (stackFrame instanceof TextStackFrame)  
   return ((TextStackFrame) stackFrame).getSourceFile();  
  
  return null;  
 }  
}  

Теперь при наличии локатора исходника мы можем зарегистрировать в его в конфигурации запуска. Откройте com.codeandme.textinterpreter.ui/plugin.xml, перейдите к Text Interpreter launchConfigurationType и задайте значение для sourceLocatorId равным com.codeandme.textinterpreter.debugger.sourceLocator.

Шаг 4. Добавляем поддержку редактора.


Последняя ступень - определить редактор, который будет использоваться. Это обрабатывается в классе TextDebugModelPresentation:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
package com.codeandme.textinterpreter.debugger.model;  
  
public class TextDebugModelPresentation implements IDebugModelPresentation {  
  
 @Override  
 public IEditorInput getEditorInput(Object element) {  
  if (element instanceof IFile)  
   return new FileEditorInput((IFile) element);  
  
  return null;  
 }  
  
 @Override  
 public String getEditorId(IEditorInput input, Object element) {  
  if (element instanceof IFile)  
   return PlatformUI.getWorkbench().getEditorRegistry().getDefaultEditor(((IFile) element).getName()).getId();  
  
  return null;  
 }  
}  


Использование редактора по умолчанию для файла исходника - хороший выбор, поскольку в данном случае выбор определенного редактора зависит от пользователя. Мы можем добавить код, открывающий текстовый редактор по умолчанию вместо возвращения null в случае возникновения ошибки.

Сейчас поиск кода должен работать. Попробуйте с ним поработать и осуществите пошаговый проход по некоторым простым скриптам.

Облако тегов
Меню
Архив
© Psytronica.ru. Блог существа SherZa. 2015-2017 Наверх