Basic Queries

From AtlasWiki
Revision as of 20:20, 2 February 2015 by BenHolland (Talk | contribs) (forward)

Jump to: navigation, search

This tutorial assumes you have the HelloWorld Java project in your workspace and have just completed the Learning Atlas Setup tutorials.

If you haven't already enter the following queries in the Atlas Shell. Don't worry what they mean right now, by the end of this tutorial you will!

var declaresEdges = universe.edgesTaggedWithAny(Edge.DECLARES).retainEdges()
var app = declaresEdges.forward(universe.project("HelloWorld"))
var methods = app.nodesTaggedWithAny(Node.METHOD)
var initializers = app.methods("<init>") union app.methods("<clinit>")
var constructors = app.nodesTaggedWithAny(Node.IS_CONSTRUCTOR)
var callEdges = universe.edgesTaggedWithAny(Edge.CALL).retainEdges()
var graph = (methods difference (initializers union constructors)).induce(callEdges)
show(graph)

Your Eclipse should now look something like the following screenshot.

Hello-world-queries.png

Note: You can drag and drop Eclipse views around and rearrange them by pinning views to different areas in Eclipse.

Let's take a look at the graph that Atlas computed for us in response to our queries. We see a graph with 7 methods (A, B, ... G). We also see that all of these methods are public (green dot icon) static (S icon) methods. We see that all methods are declared inside the class MyClass. MyClass is declared by the package com.example which is declared in the project HelloWorld. Most importantly, we see that many of the methods have a directed call relationship to other methods. Atlas has recorded and abstracted the relationships in the MyClass.java source code file. You can see in the source that method A calls method B in its body. In the graph this is represented by a call edge from the A method node to the B method node.

As a developer if I wanted to know what methods method A calls it would be pretty easy to open up the MyClass.java source code file, find the method and read its source. However if I wanted to know what methods called method A I would have to search all source files in my project since method A could be called from anywhere. With Atlas you can use the graph abstraction to easily answer this question. First we start at method A on the graph and follow all call edges backwards to find the methods that call method A. In this case no methods call method A. If we look at the graph node for method B we quickly learn that method B is called by methods A and C. This graph with call edges is typically called a "call graph". A graph that starts at a set of method nodes and expands backwards along call edges is called a "reverse call graph". Call graphs show a rough granularity of program control flow at the method level. Atlas tracks many relationships between program artifacts, which we will explore more at a later time.

Query Language

Atlas indexes Eclipse projects in the workspace, and produces an index, which is essentially a graph data structure containing all the necessary program artifacts and relationships needed to perform program analysis. The entire graph is usually referred to as the "universe". The universe graph may be accessed directly via Common.universe(). Note that on the Atlas Shell we can just type universe instead of Common.universe(), because we have automatically imported the class Common and the ., (, and ) characters are implicit.

The Atlas query language is an internal DSL embedded within Java. The primary interface used to build queries is Q. Queries written using Q are evaluated, yielding a Graph, which is a subset of the "universe". One may write queries entirely in terms of Graph, but most routine queries are easier to write using Q. This tutorial focuses on the common uses of Q (query) objects.

Queries are methods of a Q object that tend to follow the form graph.operation(orgin). Here "graph" is the universe or a subgraph of the universe that the graph traversal will operate in. The "operation" is the Q method to perform in the context of the subgraph. The "origin" is Q that defines where the operation (typically a graph traversal) will begin. Note that Q’s can be chained together to form more complex queries.

In the sections below we are going to explore some of the most common Q operations in detail. To follow along you should declare a few variables to represent different methods in our example graph. Declare these variables by running the following queries in the Atlas Shell.

var A = app.methods("A")
var B = app.methods("B")
var C = app.methods("C")
var D = app.methods("D")
var E = app.methods("E")
var F = app.methods("F")
var G = app.methods("G")

forward

Selects the subgraph reachable from the given nodes using a forward transitive traversal. This query includes the origin in the resulting graph.

graph.forward(D) will output the graph D->E and D->G.

graph.forward(C) will output the graph C->B->C, C->D->E and C->D->G.

forwardStep

successors

reverse

reverseStep

predecessors