Aspect-oriented (AO) languages are nowadays compiled to the intermediate representation (IR) of an established non-AO language; this usually entails transforming code already provided in that IR, a compilation strategy often called weaving. A typical example is AspectJ which is compiled to Java bytecode. Existing AOP debuggers, like Wicca, AODA, and TOD use only the woven IR of the underlying language. AOP-specific abstractions, such as aspect-precedence declarations, and their locations in the source code are partially or even entirely lost after compilation.
Our debugger for AOP programs is able to support locating all types of dynamic AO-related faults. It is aware of aspect-oriented concepts and presents runtime states in terms of source level abstractions, e.g., pointcuts and advices. It allows programmers to perform various tasks specific to debugging AO constructs, including:
Our debugger is integrated into the Eclipse IDE and we added three new views and extended two existing views. Some views provide visualizations illustrating, e.g., pointcut evaluation, advice composition, and precedence dependencies.
Figure 1 shows the graphical representation of a dispatch. It consists of an AtomicPredicate testing whether the callee object at this call site is an instance of test.Base and two Action nodes with different program compositions according to the evaluation result of the AtomicPredicate. The blue (bold) path indicates the evaluation result of the atomic predicates and the composition of actions to be performed at the current join point. The highlighted Action node firstly performs Azpect.around@line9(). The dashed box surrounding Base.advicedMethod() visualizes the fact that the surrounding action may not execute proceed and thus may leave out the execution of this action. Double-clicking on a label representing an atomic predicate or an action highlights the corresponding source location.
Figure 2 shows the graphical representation of a precedence dependencies. Labels representing actions are numbered and connected by directed lines. The direction of a connection indicates the precedence between two actions.
There are three types of connection representing precedence declared in different ways: Precedence may be declared explicitly by means of the declare precedence statement, visualized by a bold blue connection labeled with ''declared''; it may be defined by the lexical order of advice definitions in the same aspect, visualized by a bold gray connection labeled with ''lexical''; or it may be determined by the kind of action (advice or the join point action), visualized by a thin black connection without label.
The source location of explicitly declared precedence can be highlighted when the connection is double-clicked. The precedence between any two actions without a connection is random, such as action 1 and action 3.
We have provided basic support for setting breakpoint by using pointcuts, but it is not enough. We've found several frequently encountered debugging scenarios, like monitoring values, inspecting history, etc., that cannot be handled neatly and uniformly by existing debugging techniques. Based on the observations, we plan to design a language that models the breakpoint as a first-class object. Using that language, programmers can define breakpoints by using comprehensible source-level abstractions and freely compose breakpoints to higher-level ones.
We have presented a poster about these debuggind scenarios and our envisioned solution approach at the MODULARITY:aosd conference in 2012. Click on the Figure 3 below to view the poster.