• Aucun résultat trouvé

Java code that is not within a JML annotation uses the usual access control rules for determining visibility (or accessibility) of Java [Arnold-Gosling-Holmes00] [Gosling-etal00].

That is, a name declared in packageP and typeP.T may be referenced from outsideP only if it is declared aspublic, or if it is declared asprotected and the reference occurs within a subclass ofP.T. This name may be referenced from withinP but outside ofP.T only if it is declared aspublic, default access, orprotected. Such a name may always be referenced from within P.T, even if it is declared as private. See the Java language specification [Gosling-etal00] for details on visibility rules applied to nested and inner classes.

Within annotations, JML imposes some extra rules in addition to the usual Java visibility rules [Leavens-Baker-Ruby06] [Leavens-Mueller07]. These rules depend not just on the declaration of the name but also on the visibility level of the context that is referring to the name in question. For purposes of this section, the annotation context of a reference to a name is the smallest grammatical unit with an attached (or implicit) visibility. For example, this annotation context could be a method specification case, an invariant, a history constraint, or a field declaration. The visibility level of such an annotation context can bepublic,protected,private, or default (package) visibility.

JML has two rules governing visibility that differ from Java. The first is that an annota-tion context cannot refer to names that are more hidden than the context’s own visibility.

That is, for a reference to a name x to be legal, the visibility of the annotation context that contains the reference tox must be at least as permissive as the declaration ofx itself.

The reason for this restriction is that the people who are allowed to see the annotation should be able to see each of the names used in that annotation [Meyer97], otherwise they might not understand it. For example, public clients should be able to see all the

declara-Chapter 2: Fundamental Concepts 13

tions of names in publicly visible annotations, hence public annotations should not contain protected, default access, or private names.

In more detail, supposex is a name declared in package P and type P.T.

• An expression in a public annotation context (e.g., in a public method specification case) can refer to x only if x is declared aspublic(or spec_public).

• An expression in a protected annotation context (e.g., in a protected method specifi-cation) can refer to x only if x is declared as public orprotected, and x must also be visible according to Java’s rules (so ifx isprotected, orspec_protected, then the reference must either be from within P or, if it is from outside P, then the reference must occur in a subclass of P.T).

• An expression in a default (package) visibility annotation context (e.g., in a default visibility method specification) can refer toxonly ifxis declared aspublic,protected, or with default visibility, and x must also be visible according to Java’s rules (so if x has default visibility, then the reference must be from within P).

• An expression in a private visibility annotation context (e.g., in a private method specification) can refer to x only if x is visible according to Java’s rules (so if x has private visibility, then the reference must be from within P.T).

In the following example, the comments on the right show which uses of the various privacy level names are legal and illegal. Similar examples could be given for method specifications, history constraints, and so on.

public class PrivacyDemoLegalAndIllegal { public int pub;

protected int prot;

int def;

private int priv;

//@ public invariant pub > 0; // legal //@ public invariant prot > 0; // illegal!

//@ public invariant def > 0; // illegal!

//@ public invariant priv < 0; // illegal!

//@ protected invariant prot > 1; // legal //@ protected invariant def > 1; // illegal!

//@ protected invariant priv < 1; // illegal!

//@ invariant def > 1; // legal //@ invariant priv < 1; // illegal!

//@ private invariant priv < 1; // legal }

Note that in a lightweight method specification, the privacy level is assumed to be the same privacy level as the method itself. That is, for example, a protected method with a lightweight method specification is considered to be a protected annotation context for purposes of checking proper visibility usage [Leavens-Baker-Ruby06] [Mueller02]. See

Chapter 2: Fundamental Concepts 14

Section 2.3 [Lightweight and Heavyweight Specifications], page 12, for more about the differences between lightweight and heavyweight specification cases.

(The ESC/Java2 system has the same visibility rules as described above. However, this was not true of the old version of ESC/Java [Leino-Nelson-Saxe00].)

The JML keywordsspec_publicandspec_protectedprovide a way to make a declara-tion that has different visibilities for Java and JML. For example, the following declaradeclara-tion declares an integer field that Java regards as private but JML regards as public.

private /*@ spec_public @*/ int length;

Thus, for example, length in the above declaration could be used in a public method specification or invariant.

However, spec_public is more than just a way to change the visibility of a name for specification purposes. When applied to fields it can be considered to be shorthand for the declaration of a model field with a similar name. That is, the declaration oflengthabove can be thought of as equivalent to the following declarations, together with a rewrite of the Java code that useslengthto use_lengthinstead (where we assume_lengthis fresh, i.e., not used elsewhere in the class).

//@ public model int length;

private int _length; //@ in length;

//@ private represents length = _length;

The above desugaring allows one to change the underlying field without affecting the readers of the specification.

The desugaring of spec_protected is the same as for spec_public, except that one uses protectedinstead of publicin the desugared form.

The second rule for visibility prohibits an annotation context from writing specifications in an annotation context that constrain fields that are visible to more clients than the specifications (see section 3 of [Leavens-Mueller07]). In particular, this applies to invariants and history constraints. Thus, for example, a private invariant cannot mention a public field, since clients could see the public field without seeing the invariant, and thus would not know when they might violate the private invariant by assigning to the public field. Thus, for example, the invariants in the following example are all illegal, since they constrain fields that are more visible than the invariant itself.

public class PrivacyDemoIllegal { public int pub;

protected int prot;

int def;

private int priv;

//@ protected invariant pub > 1; // illegal!

//@ invariant pub > 1; // illegal!

//@ invariant prot > 1; // illegal!

//@ private invariant pub > 1; // illegal!

//@ private invariant prot > 1; // illegal!

//@ private invariant def > 1; // illegal!

Chapter 2: Fundamental Concepts 15

}