JavaDeclarativeHintsDescriptionSketch

Contents

Repeating Variables

The same variable can appear multiple times in the pattern. The pattern will match if and only if all parts of the subject tree that correspond to the variable occurrences are "the same". Two trees are "the same", if they have the same structure and each of the two corresponding tree node refers to the same element. Exceptions:

  • single statement and a block with single statement are equivalent provided the statements are equivalent
  • implicit "this." may be omitted

So, for example, the following pattern will match all assignments that read and write to the same variable:

$var = $var

So for example:

public class Test {
    private int i;

    public void t(Test other) {
        i = i; //will match the pattern
        this.i = i; //will match the pattern
        i = this.i; //will match the pattern
        i = other.i; //will NOT match the pattern
    }
}

Multi Variables

Expressions

$<name>$ will match any number of expressions, e.g.

new java.lang.String($args$)

will match any of the String's constructor. Can be be mixed with the single-expression variables, e.g.:

new java.lang.String($charArray, $rest) :: $charArray instanceof char[]

will match both the String(char[]) and String(char[], int, int) constructors.

Statements and Members

$<name>$; will match any number of statements or class members. The semicolon is needed so that the pattern is not ambiguous. The pattern parser might sometimes recover from the missing semicolon, but omitting it is strongly discouraged for statement/members.

Caveats

In general, a given code may match pattern with multi variables multiple times with different assignments of subtrees to the multi variables. For example, consider pattern:

$preceding$;
$lock.lock();
$intervening$;
$lock.unlock();
$trailing$;

and code:

lock.lock();
System.err.println("1");
lock.unlock();
lock.lock();
System.err.println("2");
lock.unlock();

There are two possible matches, one with empty $preceding$; and one with empty $trailing$; multi variables. But the current engine cannot currently report both of these matches, only the first one (jlahoda: not 100% sure, should verify).

Modifiers

A special form to express any modifiers is $mods$. Annotations generally belong into the modifiers. E.g.:

$mods$ $type $name;

will match any of:

private int I;
private static int I;
@Deprecated private static int I;

There are many caveats to the modifiers, one cannot currently express that the modifiers must contain a specific annotation, specific modifier, etc. Only "any modifiers" is specified. Also, multi statement pattern involving modifiers variable do not currently work properly. For example:

$mods$ $type $name;
$name = $init;

does not work.

Patterns with Multiple Statements

It is possible to express a pattern that consists of several consecutive statements, e.g.:

   java.lang.System.err.print($whatever$);
   java.lang.System.err.println();
=> java.lang.System.err.println($whatever$);
;;

will convert:

private void t() {
    System.err.println("This is an example:");
    System.err.print("Hello, world!");
    System.err.println();
    System.err.println("All done.");
}

to

private void t() {
    System.err.println("This is an example:");
    System.err.println("Hello, world!");
    System.err.println("All done.");
}

Note that if intervening statements are allowed, they need to be specified explicitly using $<name>. For example, the above pattern won't match this:

private void t() {
    System.err.println("This is an example:");
    System.err.print("Hello, world!");
    printHelp();
    System.err.println();
    System.err.println("All done.");
}

To allow intervening statements:

$document.readLock();
$statementsUnderLock$;
$document.readUnlock(); :: $document instanceof javax.swing.text.AbstractDocument
=>
$document.readLock();
try {
    $statementsUnderLock$;
} finally {
    $document.readUnlock();
}
;;

which will match and rewrite:

private void t(AbstractDocument doc) {
    doc.readLock();
    System.err.println("Under the lock!");
    doc.readUnlock();
}

Zero-or-one

If some part of the tree is optional, the multi-expression or multi statement variable can be used to express that the pattern should match whether or not that optional part is present. For example:

if ($cond) $then
else $else$;

will match both:

if (true) {
    System.err.println("foo bar");
}

and

if (true) {
    System.err.println("foo bar");
} else {
    System.err.println("bar foo");
}

XXX: there is a bug that this:

if (!$cond) $then
else $else$;

does not work properly.

Can be also used to express an optional variable initializer:

$modifiers$ $variableType $name = $init$;

Conditions

Conditions are specified after ::, their result can be negated using ! and result of multiple conditions can be and-ed using &&. There is no "or" currently. Specifying multiple fixes or multiple rules works as an implicit "or".

Language Conditions

The conditions defined directly by the language are:

  • instanceof: which allows to specify a type of an expression variable. Only expressions assignable to the given type will be bound to the specified variable.
  • otherwise: valid only on the "fixes". Will evaluate to true if no fix above was used (XXX: cannot be negated currently). E.g. (note the constant matching - will match only if the string literal in the subject code will match the literal given in the pattern):
   $str.equals("")
=> $str.isEmpty() :: sourceVersionGE(SourceVersion.RELEASE_6)
=> $str.length() == 0 :: otherwise
;;

will rewrite var.equals("") to var.isEmpty() for source levels >= 1.6, but to var.length() == 0 in all other cases.

Standard Conditions

Other standard conditions are defined in DefaultRuleUtilities. Special variable $_ represents the whole matching region. The notable ones are:

  • matchesAny(variable, one-or-more-patterns) true if and only if at least one of the given patterns matches the tree bound to the given variable
  • containsAny(variable, one-or-more-patterns) true if and only if at least one of the given patterns matches the tree bound to the given variable, or any of its subtrees
  • matchesWithBind(variable, one-patterns) similar to matchesAny, but if the pattern matches, any free variables inside it will be bound as if it was specified as a normal pattern/rule.
  • matches(one-patterns) do not use - semi-deprecated. Use matchesAny($_, the-pattern) instead.

Custom Conditions

TBD

Catch Pattern

This:

try {
    $statements$;
} catch $catches$
  finally {
  $finally$;
}

will match any resource-less try statement with finally block, with or without catch clauses. To find a specific catch clause:

try {
    $statements$;
} catch $precedingCatches$
  catch (NullPointerException ex) {
  $code$;
} catch $trailingCatches$
  finally {
  $finally$;
}

There is currently no form to express optional finally section (i.e. two patterns are required, one with and one without finally).

Full Variable

$modifiers$ $type $name = $init$;

Full Method

For methods without type parameters and with body:

$modifiers$ $returnType $name($args$) throws $thrown$ {
    $bodyStatements$;
}

For methods without type parameters and without body and without default value:

$modifiers$ $returnType $name($args$) throws $thrown$;

Note 1: after this fix, the following works for methods with and without type parameters, with body:

$modifiers$ <$typeParams$> $returnType $name($args) throws $thrown$ {
    $bodyStatements$;
}

Note 2: this should work for annotation attribute methods with and without default value, but it does not work currently: $modifiers$ $returnType $name() default $def$;

Full Class

For classes without type parameters:

$modifiers$ class $name extends $superClass$ implements $superInterfaces$ {
    $members$;
}

Options

Various options can be specified inside <! > block. The currently recognized options are:

  • error (on fixes): report the given error through the standard refactoring means to the user (in I&T). Example:
   System.err.println("Hello, world!");
=> <!error='Cannot convert'>
;;
  • warning (on fixes): as error but produced refactoring's warning instead of an error
  • hint (on hints): define a explicit ID for the hint. If missing, an ID will be inferred from the file name
  • description (on hints): a longer description of the hint. Will appear in the Tools/Options.
  • hint-category (on hints): the hint category into which the hint should be assigned in Tools/Options and Inspect&Transform. Most hints should not specify this.
  • suppress-warnings (on hints): keys for @SuppressWarnings, which will automatically suppress the given hint. Can specify more keys, separated with ','. An empty key has a special meaning: the keys before the empty key will be offered to the user for inclusion in the source code, while the after the empty key will not. All the keys (except the empty one) will suppress the warning.
  • ensure-dependency (on hints or files): will ensure that the current module/project will have the specified dependency. Format for specifying the dependency is currently not specified. Do not use unless you know what you are doing.

Display Names

TBD

Not logged in. Log in, Register

By use of this website, you agree to the NetBeans Policies and Terms of Use. © 2012, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo