- Loading...
Table of Contents | ||
---|---|---|
|
In this section, we give an overview of the seven query languages that we evaluate in this paper: Java Tools Language,
...
Browse-By-Query,
...
SOUL,
...
JQuery,
...
.QL,
...
Jackpot
...
and
...
PMD.
...
We
...
selected
...
these
...
languages
...
because
...
they
...
provide
...
a
...
variety
...
of
...
design
...
choices
...
and
...
strictly
...
provide
...
a
...
query
...
language.
...
For
...
example,
...
we
...
didn't
...
select
...
Findbugs
...
as
...
it
...
only
...
lets
...
programmers
...
query
...
source
...
by
...
creating
...
new
...
classes
...
based
...
on
...
a
...
Java
...
framework.
...
We
...
also
...
only
...
selected
...
source
...
code
...
query
...
languages
...
that
...
included
...
a
...
guide
...
or
...
a
...
working implementation.
Name | Paradigm | Model | Input | Date |
---|---|---|---|---|
Java Tools Language | Logic | Relational | Bytecode | 2006 |
Browse-By-Query | Declarative (English-like Queries) | Relational | Bytecode | 2005 |
SOUL | Logic | Relational | Source | 2011 |
JQuery | Logic | Relational | Source | 2003 |
.QL | Object-Oriented, SQL-like | Relational | Source | 2007 |
Jackpot | Declarative | Relational | Source | 2009 |
PMD | XPath | Tree | Source | 2004 |
The Java Tools Language (JTL) is a logic-paradigm query language to select Java elements in a code base. The current implementation is based on an analysis of Java bytecode classes. The JTL syntax is inspired by Query-by-Example ideas in order to increase productivity of users. JTL also relies on Datalog-like semantics. For example, one could find all methods taking three int parameters and returning a subclass of Java's Date class using the follow query:
Code Block |
---|
implementation. h4. Java Language Tools h5. The Java Tools Language (JTL) is a logic-paradigm query language to select Java elements in a code base. The current implementation is based on an analysis of Java bytecode classes. The JTL syntax is inspired by Query-by-Example ideas in order to increase productivity of users. For example, one could find all methods taking three int parameters and returning a subclass of Java's Date class using the follow query: {code} public static D method(int, int, int), D extends* /java.util.Date; {code} |
In
...
addition,
...
JTL
...
features
...
variable
...
binding
...
and
...
data
...
flow
...
queries.
...
...
Browse-By-Query
...
(BBQ)
...
reads
...
Java
...
bytecode
...
files
...
and
...
creates
...
a
...
database
...
representing
...
classes,
...
method
...
calls,
...
fields,
...
field
...
references,
...
string
...
constants
...
and
...
string
...
constant
...
references.
...
This
...
database
...
can
...
then
...
be
...
interrogated
...
through
...
English-like
...
queries.
...
The
...
syntax
...
is
...
motivated
...
by
...
the
...
desire
...
to
...
be
...
intuitive.
...
For
...
example,
...
one
...
could
...
find
...
all
...
the
...
methods
...
that
...
call
...
a
...
method
...
whose
...
name
...
matches
...
start
...
by
...
composing
...
the
...
following
...
query:
Code Block |
---|
} methods containing calls to matching "start" methods in all classes {code} |
In
...
addition,
...
BBQ
...
provides
...
filtering
...
mechanisms,
...
set
...
and
...
and
...
relational
...
operators
...
that
...
can
...
be
...
combined
...
to
...
compose
...
more
...
complex
...
queries.
...
SOUL is a logic-paradigm
...
query
...
language.
...
It
...
contains
...
an
...
extensive
...
predicate
...
library
...
called
...
CAVA
...
that
...
matches
...
queries
...
against
...
AST
...
nodes
...
of
...
a
...
Java
...
program
...
generated
...
by
...
the
...
Eclipse
...
JDT.
...
SOUL
...
facilitates
...
the
...
specification
...
of
...
queries
...
by
...
using
...
example-driven
...
matching
...
of
...
templates
...
and
...
structural
...
unification
...
to
...
match
...
a
...
code
...
excerpt
...
with
...
an
...
AST
...
node.
...
In
...
practice,
...
this
...
means
...
a
...
user
...
can
...
create
...
a
...
logic
...
variable
...
to
...
match
...
an
...
AST
...
node
...
and
...
reuse
...
this
...
variable
...
within
...
the
...
query
...
regardless
...
of
...
the
...
execution
...
path
...
where
...
the
...
variable
...
appears.
...
For
...
example,
...
one
...
could
...
specify
...
a
...
query
...
that
...
finds
...
instances
...
of
...
Scanner
...
that
...
is
...
read
...
after
...
it
...
was
...
closed
...
as
...
follows:
Code Block |
---|
{code} if jtMethodDeclaration(?m){ public static void main(String[] args) { ?scanner := [new java.util.Scanner(?argList);] ?scanner.close(); ?scanner.next(); } } {code} h4. JQuery h5. JQuery is a |
JQuery is a logic-paradigm
...
query
...
language
...
built
...
on
...
top
...
of
...
the
...
logic
...
programming
...
language
...
TyRuBa.
...
The
...
implementation
...
of
...
JQuery
...
analyse
...
the
...
AST
...
of
...
a
...
Java
...
program
...
by
...
making
...
calls
...
to
...
the
...
Eclipse
...
JDT.
...
JQuery
...
includes
...
a
...
library
...
of
...
predicates
...
that
...
allows
...
querying
...
Java
...
elements
...
and
...
the
...
relationships
...
between
...
them.
...
For
...
example,
...
the
...
following
...
query
...
finds
...
all
...
method
...
declarations
...
?M
...
that
...
have
...
at
...
least
...
one
...
parameter
...
of
...
type
...
Integer:
Code Block |
---|
} method(?M, paramType, ?PT), match(?PT, /Integer/). {code} h4. .QL h5. .QL is an |
.QL is an object-oriented
...
query
...
language.
...
It
...
enables
...
programmers
...
to
...
query
...
Java
...
source
...
code
...
by
...
composing
...
queries
...
that
...
look
...
like
...
SQL.
...
The
...
motivation
...
for
...
this
...
design
...
choice
...
is
...
to
...
reduce
...
barrier
...
to
...
entry
...
for
...
developers
...
that
...
learn
...
it.
...
In
...
addition,
...
the
...
authors
...
argue
...
that
...
object-orientation
...
provides
...
the
...
structure
...
necessary
...
for
...
building
...
reusable
...
queries.
...
An
...
implementation
...
is
...
available,
...
called
...
SemmleCode,
...
which
...
includes
...
an
...
editor
...
and
...
various
...
optimisations.
...
As
...
an
...
example,
...
the
...
following
...
query
...
describes
...
how
...
to
...
find
...
all
...
classes
...
that
...
declare
...
a
...
method
...
equals,
...
but
...
which
...
do
...
not
...
specify
...
a
...
method
...
hashCode.
Code Block |
---|
} from Class c where c.declaresMethod("equals") and not (c.declaresMethod("hashCode")) and c.fromSource() select c.getPackage(), c {code} h4. Jackpot h5. Jackpot is a module for the NetBeans IDE for querying and transforming Java source files. Jackpot lets user query the AST of a Java program by composing rules under the form of a Java expression. In addition, one can specify variables to bind to a matching AST node. For example, the following query will match any code surrounded by a call to readLock() and readUnlock(): |
Jackpot is a module for the NetBeans IDE for querying and transforming Java source files. Jackpot lets user query the AST of a Java program by composing rules under the form of a Java expression. In addition, one can specify variables to bind to a matching AST node. For example, the following query will match any code surrounded by a call to readLock() and readUnlock():
Code Block |
---|
{code} $document.readLock(); $statementsUnderLock$; $document.readUnlock(); {code} |
PMD is a ruleset based Java source code analyzer that identifies bugs or potential problems including dead code, duplicate code or overcomplicated expressions. PMD has an extensive archive of built-in rules that can be used to identify such problems. One can specify new rules by writing it in Java and making use of the PMD helper classes. Alternatively, one can also compose custom rules via an XPath expression that queries the AST of the program to analyze. For example, the following query finds all method declarations that have at least one parameter of type Integer:
Code Block |
---|
h4. PMD h5. PMD is a ruleset based Java source code analyzer that identifies bugs or potential problems including dead code, duplicate code or overcomplicated expressions. PMD has an extensive archive of built-in rules that can be used to identify such problems. One can specify new rules by writing it in Java and making use of the PMD helper classes. Alternatively, one can also compose custom rules via an XPath expression that queries the AST of the program to analyze. For example, the following query finds all method declarations that have at least one parameter of type Integer: {code} //MethodDeclarator/FormalParameters [FormalParameter/Type/ReferenceType/ClassOrInterfaceType [@Image = 'Integer']] {code} |
In this section, we describe the use cases examined for the evaluation. We selected use cases that are source of language design discussions and make use of a variety of Java features.
Java lets programmers create inner classes, which is a nested class not declared static. There exists three different types of inner classes: non-static member, local and anonymous classes.
Inner classes have a restriction that any local variable, formal parameter, or exception parameter used but not declared in the inner class must be declared final.
However, programmers can circumvent this restriction by declaring a final array with only one element and mutate the element of the array. The following code illustrates this mechanism:
Code Block |
---|
public class OutsideClass { h3. Uses Cases In this section, we describe the use cases examined for the evaluation. We selected use cases that are source of language design discussions and make use of a variety of Java features. h4. Final Array and Anonymous Inner Classes Java lets programmers create inner classes, which is a nested class not declared static. There exists three different types of inner classes: non-static member, local and anonymous classes. Inner classes have a restriction that any local variable, formal parameter, or exception parameter used but not declared in the inner class must be declared final. However, programmers can circumvent this restriction by declaring a final array with only one element and mutate the element of the array. The following code illustrates this mechanism:\\ {code} public class OutsideClass { public void methodA() { final String\[\] s = new String\[1\]; class InnerClass { { public void methodB() { s\[0\ { s[0] = "bypass"; // accepted by compiler } } } } {code}\\ *Use Case 1*: Find occurrence of an anonymous inner class whose code references a final array variable in the enclosing scope and which mutates array elements via that variable. h5. h4. Generic Constructors h5. h5. A constructor can have two sets of type arguments. A constructor can use the type parameters declared in a generic class. One can then specify the types after the class name: \texttt{new Foo<Integer>()}. In addition, a constructor can declare its own type parameters. The types are then specified between the \texttt{new} token and the class name: \texttt{new <Integer> Foo<Number>()}. The code below illustrates a constructor of class \texttt{Foo} which declares its own type parameter \texttt{S} that } } } } |
Use Case 1: Find occurrence of an anonymous inner class whose code references a final array variable in the enclosing scope and which mutates array elements via that variable.
A constructor can have two sets of type arguments. A constructor can use the type parameters declared in a generic class. One can then specify the types after the class name: new Foo<Integer>(). In addition, a constructor can declare its own type parameters. The types are then specified between the new token and the class name: new <Integer> Foo<Number>(). The code below illustrates a constructor of class Foo which declares its own type parameter S that extends the class's own parameters.
Code Block |
---|
extends the class's own parameters.{code}class Foo<T extends Number> { <S extends T> Foo() {}}{code} h5. A constructor can have two sets of type arguments. A constructor can use the type parameters declared in a generic class. One can then specify the types after the class name: new Foo<Integer>(). In addition, a constructor can declare its own type parameters. The types are then specified between the new token and the class name: new <Integer> Foo<Number>(). The code below illustrates a constructor of class Foo which declares its own type parameter S that extends the class's own parameters. h5. {code}class Foo<T extends Number> { h5. <S extends T> Foo() {} h5. }{code} h5. Capture Conversion Idiom h5. Overloaded Methods h5. Covariant Arrays h3. Evaluation || || Final Array & Anonymous Class || Generic Constructors || Capture Conversion Idiom || Overloaded Methods || Covariant Arrays || | +JTL+ | | | X | | | | +BBQ+ | X | X | X | * ?* | | | +SOUL+ | | | | | | | +JQuery+ | X | X | X | *?* | X | | +.QL+ | | | | | | | +Jackpot+ | | | | | | | +PMD+ | | | | | | *{+}JTL{+}* * *{+}BBQ{+}* * {color:#ff0000}doesn't detect local inner classes (local & anonymous). Only inner classes (doesn't differentiate): class in all classes{color} * {color:#ff0000}no access to local variable declared in methods{color} * {color:#ff0000}no support for generics on declaration.{color} * {color:#ff0000}no support for constructors (considered as method init) {color} * {color:#ff0000}no AST structural matching. (e.g loops ...){color} * {color:#ff0000}no variable binding/unification{color} * {color:#008000}set operators (union, intersection){color} * {color:#008000}support for read/write of{color} {color:#008000}{+}fields{+}{color} {color:#008000}references{color} *{+}SOUL{+}* * *{+}Jquery{+}* * [http://jquery.cs.ubc.ca/documentation/toc.html] * [http://jquery.cs.ubc.ca/documentation/appendix2.html] * {color:#008000}variable binding through predicates{color} * {color:#008000}support for read & mutation of fields (write) \[writes(?B,?F,?L) means: "Block ?B writes to field ?F at location ?L"\]{color} * {color:#ff0000}no structural matching (e.g pattern match on a loop or body of a method){color} * {color:#ff0000}no generics support{color} *+.QL{+}* * *{+}Jackpot{+}* * [https://bitbucket.org/jlahoda/jackpot30/wiki/RulesLanguageAdditionalDocs] *{+}PMD{+}* * h3. Time Plan | | *Week 1* | *Week 2* | {color:#00ccff}{*}Week 3{*}{color} | *Week 4* | *Week 5* | | {color:#00ccff}{*}July{*}{color} | {color:#0000ff}{*}Raoul in Cambridge{*}{color} | * {color:#0000ff}Source Code Query Languages Literature Review{color} * {color:#0000ff}{*}paper{*}{color}{color:#0000ff}: Background{color} | * {color:#0000ff}{*}paper{*}{color}{color:#0000ff}: Abstract, Intro, Use Cases{color} * {color:#0000ff}Start evaluation of Source Code QL{color} | * {color:#ff9900}Joel: away Stockholm{color} * {color:#0000ff}Evaluation of Source Code QL{color} * {color:#0000ff}Create Taxonomy{color} * {color:#0000ff}{*}paper{*}{color}{color:#0000ff}: Evaluation/Taxonomy{color} | * {color:#ff9900}Joel: away Stockholm{color} * {color:#0000ff}{*}paper{*}{color}{color:#0000ff}: Related Work/Conclusion & make it top notch{color} * {color:#0000ff}{*}paper{*}{color}{color:#0000ff}: Get reviews & integrate feedback{color} | | *August* | * {color:#0000ff}{*}corpus{*}{color}{color:#0000ff}: Review of existing Java Corpora{color} * {color:#0000ff}{*}corpus{*}{color}{color:#0000ff}: Build Corpus infrastructure (pluggable javac){color} | * {color:#ff0000}PLATEAU paper deadline 10/8{color} * {color:#0000ff}{*}corpus{*}{color}{color:#0000ff}: Prototype of Community Corpus{color} | * {color:#0000ff}{*}corpus{*}{color}: {color:#0000ff}Prototype of Community Corpus{color} | * {color:#ff0000}JavaOne slides deadline 22/8{color} | * {color:#0000ff}Research{color} {color:#0000ff}{+}ranking{+}{color} {color:#0000ff}of source code query results{color} | | *September* | | | | | | | *October* | {color:#ff9900}Joel JavaOne{color} | | {color:#0000ff}{*}Raoul in Cambridge{*}{color} | {color:#0000ff}{*}Raoul in Cambridge{*}{color} | {color:#0000ff}{*}Raoul in Cambridge{*}{color} | +Color scheme:+ * {color:#008000}Alex{color} * {color:#ff9900}Joel{color} * {color:#0000ff}Raoul{color} h2. Relevant Literature \[1\] Brian Goetz. Language designer's notebook: Quantitative language design. [http://www.ibm.com/developerworks/java/library/j-ldn1/| } |
Use Case 2: Find generic constructors whose type parameters extend the enclosing class's own type parameters.
Java 5 introduced wildcards as a variance mechanism for generics. Safety is achieved by restricting accesses to fields and methods based on the position of the type parameter. The unbounded wildcard <?> represents any type and can be used to provide a simple form of bivariance. In practice, this means that List<?> is a supertype of List<T> for any T.
The unbounded wildcard is frequently used as part of the capture conversion idiom. In the code below, the signature of reverse is prefered over rev as it doesn't expose implementation information to the caller. The argument List<?> is passed to rev, which takes a List<T>. However, allowing such a subtype relation would be unsafe. Java provides capture conversion as a solution: the unknown type <?> is captured in a type variable and T is infered to be that type variable within the method rev.
Code Block |
---|
public static void reverse(List<?> list) { rev(list); }
private static <T> void rev(List<T> list) {
List<T> tmp = new ArrayList<T>(list);
for (int i = 0; i < list.size(); i++) {
list.set(i, tmp.get(list.size() - i - 1));
}
}
|
Use Case 3: Find occurrences of the capture conversion idiom.
Overloading methods allows programmers to declare methods with the same name but with different signatures.
For example, one could write an add method that takes a different number of parameters:
Code Block |
---|
public void add(T a) { ... }
public void add(T a, T b) { ... }
public void add(T a, T b, T c) { ... }
|
Often this pattern can be rewritten by using the varargs feature if the overloaded methods' parameters share a single type:
Code Block |
---|
public void add(T a, T ... args) { ... }
|
Related to this use case, recent work has investigated overloading in Java and found that a quarter of overloaded methods are simulating default arguments.
Use Case 4: Find overloaded methods with multiple parameters that share a single type.
In Java and C#, array subtyping is covariant, meaning that type B[] is considered a subtype of A[] whenever B is a subtype of A. However, this relation can cause runtime exceptions. Consider the following Java code where Banana and Apple are subtypes of Fruit:
Code Block |
---|
Banana[] bananas = new Banana[5];
Fruit[] fruit = bananas;
fruits[0] = new Apple(); // ArrayStore Exception
peelBanana(bananas[0]); // Apple???
|
The assignment to the first element of the variable fruit on line 3 will cause an ArrayStore exception. Although statically, the variable fruit has type Fruit[], its runtime type is Banana[] and thus we cannot use it to store an Apple.
Use Case 5: Find occurences of covariant array uses in assignment, method calls, constructor instantiations and return statements.
Java 7 introduced an improved checking for rethrown exceptions. Previously, a rethrown exception was treated as throwing the type of the catch parameter. Now, when a catch parameter is declared final, the type is known to be only the exception types that were thrown in the try block and are a subtype of the catch parameter type.
This new feature introduced two source incompatibilities with respect to Java 6. The code below illustrates the changes. Previously, the statement throw exception would throw a Foo exception. Now, it throws a DaughterOfFoo exception. As a consequence, the catch block catch(SonOfFoo anotherException) is not reachable anymore as the try only throws a DaughterOfFoo exception.
Code Block |
---|
class Foo extends Exception {}
class SonOfFoo extends Foo {}
class DaughterOfFoo extends Foo {}
class Test {
void test() {
try {
throw new DaughterOfFoo();
} catch (final Foo exception) {
try {
throw exception; // first incompatibility
} catch (SonOfFoo anotherException) {
// second incompatibility: is this block reachable?
}
}
}
}
|
Use Case 6: Find occurences of nested try/catch blocks that rethrow an exception.
[This section is work in progress]
X = not supported
✓ = supported
? = not sure
| Final Array & Anonymous Class | Generic Constructors | Capture Conversion Idiom | Overloaded Methods Sharing Single Type | Covariant Arrays | Rethrown Exception |
---|---|---|---|---|---|---|
JTL | X | X | X | ? | X | X |
BBQ | X | X | X | ? | X | X |
SOUL | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
JQuery | X | X | X | X (*1) | X | X |
.QL (*2) | ✓ | ? | ? | ? | ✓ | ? |
Jackpot | X | ✓ | X | X | X | ✓ |
PMD (Xpath) | X | X | X | X | X | X |
*1: can find overloaded methods but not sharing single type: method(?C, ?M1), method(?C, ?M2), likeThis(?M1, ?M2). Tested with operations available in eclipse plugin. Paper describe different operations that don't seem to be supported.
*2: .QL documentation & tool is kept secretive for competitive advantage protection
JTL
Use case 1 not possible because no support for local variable decl. Use case 2 & 3 not possible because no support for generics/wildcards (due to bytecode source). Use 4 not possible because no support for statements & types of expressions. Use case 6 not possible because no control flow support.
BBQ
Similar reasons to JTL.
SOUL
Jquery
Similar reasons to JTL.
.QL
Very expressive. Though sql statements may not scale for control flow matching. (direct ast pattern matching is clearer for some use cases)
Jackpot
PMD
No variable binding support which restricts a lot of the analysis.
[This section is work in progress]
[This section is work in progress]
Relational based query languages not low level enough.
Tree based query languages not expressive enough.
Idea: mix both
Idea: decouple query-by-example from constraints on variables. - two different views-
It seems pure template based languages are not expressive enough and so are pure logic-based queries.
Sweet spot a combination of both mechanisms (which SOUL provides).
Week | Date | Log | Milestones |
---|---|---|---|
1 | 9 July - 13 July |
|
|
2 | 16 July - 20 July |
|
|
3 | 23 July - 27 July |
| Milestone 1
|
4 | 30 July - 3 August |
|
|
5 | 6 August - 10 August |
|
|
6 | 13 August - 17 August |
| Milestone 2
|
7 | 20 August - 24 August |
| Milestone 3
|
8 | 27 August - 31 August |
| Milestone 4
|
9 | 3 September - 7 September |
| Milestone 5
|
10 | 10 September - 14 September |
|
|
11 | 17 September - 21 September |
|
|
12 | 24 September - 28 September |
|
|
13 | 1 October - 5 October |
| DEMO |
14 | 8 October - 12 October |
| DEMO |
Give a live demonstration of the query language for two use cases: Covariant Arrays assignments & Overloaded Methods sharing single type
7th September
Build the minimum vertical implementation to make this possible. This consists of the following milestones:
1) Create a database representation of a Java program, which stores information attributed AST nodes of assignments and method declarations. (deadline: 17/8)
2) Develop backend API that will query the database. (deadline: 23/8)
3) Design query language, different types of queries it will support (deadline: 29/8)
4) Build minimum grammar & parser & compiler to query the two use cases (deadline: 6/9)
5) Output results frontend (deadline: 7/9)
Extra time will be used to expand the infrastructure horizontally:
- Support more AST nodes and relations
- Support more types of queries
- Extend backend
- Test coverage
- Web interface for Demo
[1] Brian Goetz. Language designer's notebook: Quantitative language design. http://www.ibm.com/developerworks/java/library/j-ldn1/
...
.
...
[2
...
]
...
Chris
...
Parnin,
...
Christian
...
Bird,
...
and
...
Emerson
...
Murphy-Hill.
...
2011.
...
Java
...
generics
...
adoption:
...
how
...
new
...
features
...
are
...
introduced,
...
championed,
...
or
...
ignored.
...
In
...
Proceedings
...
of
...
the
...
8th
...
Working
...
Conference
...
on
...
Mining
...
Software
...
Repositories
...
(MSR
...
'11)
...
[3
...
]
...
Ewan
...
Tempero,
...
Craig
...
Anslow,
...
Jens
...
Dietrich,
...
Ted
...
Han,
...
Jing
...
Li,
...
Markus
...
Lumpe,
...
Hayden
...
Melton,
...
and
...
James
...
Noble.
...
2010.
...
The
...
Qualitas
...
Corpus:
...
A
...
Curated
...
Collection
...
of
...
Java
...
Code
...
for
...
Empirical
...
Studies.
...
In
...
Proceedings
...
of
...
the
...
2010
...
Asia
...
Pacific
...
Software
...
Engineering
...
Conference
...
(APSEC
...
'10)
...
[4
...
]
...
Joseph
...
Gil
...
and
...
Keren
...
Lenz.
...
2010.
...
The
...
use
...
of
...
overloading
...
in
...
JAVA
...
programs.
...
In
...
Proceedings
...
of
...
the
...
24th
...
European
...
conference
...
on
...
Object-oriented
...
programming
...
(ECOOP
...
'10)
...
[5
...
]
...
Raoul-Gabriel
...
Urma
...
and
...
Janina
...
Voigt.
...
Using
...
the
...
OpenJDK
...
to
...
Investigate
...
Covariance
...
in
...
Java.
...
Java
...
Magazine
...
May/June
...
2012.
...
...
...
[a
...
]
...
Refactoring
...
NG. http://kenai.com/projects/refactoringng
...
[b
...
]
...
Tal Cohen,
...
Joseph
...
(Yossi)
...
Gil,
...
and
...
Itay
...
Maman.
...
2006.
...
JTL:
...
the
...
Java
...
tools
...
language.
...
In
...
Proceedings
...
of
...
the
...
21st
...
annual
...
ACM
...
SIGPLAN
...
conference
...
on
...
Object-oriented
...
programming
...
systems,
...
languages,
...
and
...
applications
...
(OOPSLA
...
'06)
...
[c
...
]
...
Browse
...
By
...
Query.
...
http://browsebyquery.sourceforge.net/
...