The "One Laptop Per Child" project has a great device ready to ship, but there's no Java on there. Let's think about working together to put Java on OLPC!
Eclipse 3.2 M5 brings the addition of a new supported
SuppressWarnings
annotation parameter: 'restriction'.
This new annotation allows you to tell the Eclipse JDT compiler to stop nagging you about something naughty you are doing
in your code, such as referencing an 'internal' package in your Eclipse plug-in, or perhaps your project has access rules
defined,
as I described previously here
.
These access rules and definitions exist for a reason; to warn you if you are breaking rules. That being said, sometimes
breaking rules is neccessary; and in those cases it's nice to be able to tell Eclipse to keep it's mouth shut .
The Eclipse JDT compiler will happily process this annotation at any level - at a type, a field, a method, a method parameter,
a constructor, or even a local variable or statement - something which the Javac compiler doesn't
currently support for any annotations as far as I know.
As an example, say we are trying to avoid any AWT usage whatsoever in our application due to some valid reason, or perhaps
just due to an extreme distaste for the long-toothed windowing toolkit. Maybe we want to ensure we use Swing instead,
so we have some simple rules set up, such as this one:
Now, we all know that in some cases it might be beneficial to reference AWT code even when coding in Swing - so when those
cases arise we can use this new annotation to keep the compiler happy. We could use the annotation in this way:
package com.javalobby.tnt.misc;
import java.awt.*;
publicclass RestrictedWarningTest {
publicstaticvoid main(String[] args) {
@SuppressWarnings("restriction")
Frame f = new Frame();
}
}
In this case, even though we are referencing the AWT frame class, Eclipse won't mark the frame usage as bad because
we are suppressing that warning with the annotation. Now, let's say that we had more lines that were breaking rules.
package com.javalobby.tnt.misc;
import java.awt.*;
publicclass RestrictedWarningTest {
publicstaticvoid main(String[] args) {
@SuppressWarnings("restriction")
Frame f = new Frame();
f.setVisible(true);
}
}
What happens? Well, long story short, the first line that instantiates the frame is quietly accepted, but the
line that sets the visibility is flagged as being a no-no. One way to ensure that Eclipse accepts all of these lines
as a neccessary evil is to naturally group them in a method, and assign the annotation to the method rather than the statement:
This parameter is something that the Eclipse JDT compiler exclusively will recognize; the Java compiler will not
at this time, even in Mustang (aka Java 6). Java 5 (Tiger) won't even process the
SuppressWarnings
annotation at all.
That's not to say that it's a problem; the
SuppressWarnings
annotation explicitly states that compilers
must accept parameters they don't recognize, and compile accordingly. It does leave the option for the compiler
to throw a warning (How ironic, the compiler can emit a warning when we are trying to suppress them).
Here is more from the annotation documentation:
The set of warnings that are to be suppressed by the compiler in the annotated element. Duplicate names are permitted. The second and successive occurrences of a name are ignored. The presence of unrecognized warning names is not an error: Compilers must ignore any warning names they do not recognize. They are, however, free to emit a warning if an annotation contains an unrecognized warning name.
Compiler vendors should document the warning names they support in conjunction with this annotation type. They are encouraged to cooperate to ensure that the same names work across multiple compilers.
Re: Clean Up Warnings with the 'restriction' Suppression Flag
When playing with @SuppressWarnings, in case you did not notice, the Eclipse JDT compiler has 2 useful options in this area, see under:
Preferences>Java>Compiler>Errors/Warnings>Annotations
- Unhandled warning token in '@SuppressWarnings' : this addresses using exotic parameters in @SuppressWarnings which are not recognized at present time.
- Not enable '@SuppressWarnings' annotations: in case you want to revisit the warnings you silenced at some point in time.
The list of supported warning tokens as of 3.2M5 is:
"all" - for everything
"deprecation" - for usage of deprecated code
"finally" - for finally blocks not completing normally
"hiding" - for variable/type hiding issues
"nls" - for string literal externalization issues
"unused" - for unused constructs
"static-access" - for unoptimal access to statics
"synthetic-access" - for visibility issues in innerclasses
"unqualified-field-access" - for unqualified field access
"unchecked" - for unchecked conversion in generics
"serial" - for missing serial UID
"boxing" - for autoboxing diagnosis
"incomplete-switch" - for incomplete enum switch
"dep-ann" - for missing @Deprecated annotation
"restriction" - for usage of restricted types
"null" - for possible null pointer issues
"fallthrough" - for switch case fall-through
On easy way to find out the list, it to use the quickfix (light bulb icon) associated to a particular warning; it will offer a specific annotation for suppressing this very warning.
Last, we made a little trick to @SuppressWarnings to make it more useful in import statements. The language spec doesn't allow import to carry annotations. Thus one cannot silence warnings in imports (unused, restriction, deprecation). What we did is that if you specify a @SuppressWarnings onto the first type in a Java file, it will also apply to leading imports.
Re: Clean Up Warnings with the 'restriction' Suppression Flag
is it possible to export access rules into a jar file?
Because that would be cool, i am a developer of wicket and we have some protected or public method on classes that we use internally but shouldn't be used by the outside world because we can't guarentee that it will exist in another version.
So if i can define that export in in the jar file and then everybody that uses eclipse (or maybe an other ide that also embraces this) will see our access rules.
Re: Clean Up Warnings with the 'restriction' Suppression Flag
It would be nice if packages/classes/methods with default access could simply declare which other packages/classes/methods can see them. Even without fancy features like package signatures and so forth on top of this, it would be a wonderful feature. Like this:
@VisibleTo("wicket.request.**")
class Whatever
{
}
or
public class Whatever
{
@VisibleTo("package.Class1, package.Class2, package2.*")
void whatever()
If this is not a security feature but rather a way of helping programmers specify API contracts better, only JavaC would need to be changed. If it were a security feature (probably better), I assume the VM would be involved as well as crypto and sealing stuff.
Re: Clean Up Warnings with the 'restriction' Suppression Flag
I agree, we are willing to consider expressing finer granularity rules near access rights, such as the ones you mentionned. Other things would be to indicate whether a abstract type can be implemented outside the defining API etc...
Likely this would use annotations, or separate specification files which could be associated to existing libraries (possibly included along with them).
Re: Clean Up Warnings with the 'restriction' Suppression Flag
I've wanted this feature ever since I first heard Tom Ball complaining about it back in 1997. There is no need to get complex with this. You can't implement an abstract type if you can't see it. I've thought a lot about this over the past 9 years and I think it would be smart to keep this really simple because you can get very carried away if you start considering all the possible requirements of complex, secure systems.
The @VisibleTo() annotation seems quite nice to me. If the Java Package object was more consistent (which I think is a separate bug!) and annotations were extended to include Packages as well as Classes (and I think you SHOULD be able to say MyClass.class.package and get the class' Package object or wicket.request.package and get the package itself directly), the whole thing could just about fall out. You could say this: @VisibleTo(wicket.request.package, MySpecialClass.class, MyOtherSpecialClassThatMightMove.class.package)
It doesn't solve the problem of visibility to subpackages, but you could just add another annotation for that oddball case like @VisibleToSubPackagesOf(wicket.request.package, wicket.markup.package).
If we cleaned up the nature of Package objects (which is a hassle requiring a workaround in Wicket) and make them consistent and accessible through the language, the whole thing becomes Java simple again.
Re: Clean Up Warnings with the 'restriction' Suppression Flag
I have submitted an RFE with incident #659185 to Sun. Would love to see Packages made accessible to the language and annotations. Some effort here could go a really long way in solving API problems! I'm dying to use something like @VisibleTo() in Wicket.
Clean Up Warnings with the 'restriction' Suppression Flag
At 12:04 AM on Feb 20, 2006, R.J. Lorimer
wrote:
Eclipse 3.2 M5 brings the addition of a new supported
.
SuppressWarningsannotation parameter: 'restriction'. This new annotation allows you to tell the Eclipse JDT compiler to stop nagging you about something naughty you are doing in your code, such as referencing an 'internal' package in your Eclipse plug-in, or perhaps your project has access rules defined, as I described previously here . These access rules and definitions exist for a reason; to warn you if you are breaking rules. That being said, sometimes breaking rules is neccessary; and in those cases it's nice to be able to tell Eclipse to keep it's mouth shutThe Eclipse JDT compiler will happily process this annotation at any level - at a type, a field, a method, a method parameter, a constructor, or even a local variable or statement - something which the Javac compiler doesn't currently support for any annotations as far as I know.
As an example, say we are trying to avoid any AWT usage whatsoever in our application due to some valid reason, or perhaps just due to an extreme distaste for the long-toothed windowing toolkit. Maybe we want to ensure we use Swing instead, so we have some simple rules set up, such as this one:
(Follow the instructions in the tip referenced above to try this out).
Now, we all know that in some cases it might be beneficial to reference AWT code even when coding in Swing - so when those cases arise we can use this new annotation to keep the compiler happy. We could use the annotation in this way:
package com.javalobby.tnt.misc; import java.awt.*; public class RestrictedWarningTest { public static void main(String[] args) { @SuppressWarnings("restriction") Frame f = new Frame(); } }In this case, even though we are referencing the AWT frame class, Eclipse won't mark the frame usage as bad because we are suppressing that warning with the annotation. Now, let's say that we had more lines that were breaking rules.
package com.javalobby.tnt.misc; import java.awt.*; public class RestrictedWarningTest { public static void main(String[] args) { @SuppressWarnings("restriction") Frame f = new Frame(); f.setVisible(true); } }What happens? Well, long story short, the first line that instantiates the frame is quietly accepted, but the line that sets the visibility is flagged as being a no-no. One way to ensure that Eclipse accepts all of these lines as a neccessary evil is to naturally group them in a method, and assign the annotation to the method rather than the statement:
public class RestrictedWarningTest { public static void main(String[] args) { doNaughtyAWTStuff(); } @SuppressWarnings("restriction") private static void doNaughtyAWTStuff() { Frame f = new Frame(); f.setVisible(true); } }This parameter is something that the Eclipse JDT compiler exclusively will recognize; the Java compiler will not at this time, even in Mustang (aka Java 6). Java 5 (Tiger) won't even process the
SuppressWarningsannotation at all.That's not to say that it's a problem; the
SuppressWarningsannotation explicitly states that compilers must accept parameters they don't recognize, and compile accordingly. It does leave the option for the compiler to throw a warning (How ironic, the compiler can emit a warning when we are trying to suppress them).Here is more from the annotation documentation:
Until next time,
R.J. Lorimer
Contributing Editor -rj -at- javalobby.orgAuthor -http://www.coffee-bytes.comSoftware Consultant -http://www.numbersix.com8 replies so far (
Post your own)
Re: Clean Up Warnings with the 'restriction' Suppression Flag
When playing with @SuppressWarnings, in case you did not notice, the Eclipse JDT compiler has 2 useful options in this area, see under:Preferences>Java>Compiler>Errors/Warnings>Annotations
- Unhandled warning token in '@SuppressWarnings' : this addresses using exotic parameters in @SuppressWarnings which are not recognized at present time.
- Not enable '@SuppressWarnings' annotations: in case you want to revisit the warnings you silenced at some point in time.
The list of supported warning tokens as of 3.2M5 is:
"all" - for everything
"deprecation" - for usage of deprecated code
"finally" - for finally blocks not completing normally
"hiding" - for variable/type hiding issues
"nls" - for string literal externalization issues
"unused" - for unused constructs
"static-access" - for unoptimal access to statics
"synthetic-access" - for visibility issues in innerclasses
"unqualified-field-access" - for unqualified field access
"unchecked" - for unchecked conversion in generics
"serial" - for missing serial UID
"boxing" - for autoboxing diagnosis
"incomplete-switch" - for incomplete enum switch
"dep-ann" - for missing @Deprecated annotation
"restriction" - for usage of restricted types
"null" - for possible null pointer issues
"fallthrough" - for switch case fall-through
On easy way to find out the list, it to use the quickfix (light bulb icon) associated to a particular warning; it will offer a specific annotation for suppressing this very warning.
Last, we made a little trick to @SuppressWarnings to make it more useful in import statements. The language spec doesn't allow import to carry annotations. Thus one cannot silence warnings in imports (unused, restriction, deprecation). What we did is that if you specify a @SuppressWarnings onto the first type in a Java file, it will also apply to leading imports.
The Eclipse JDT team
Re: Clean Up Warnings with the 'restriction' Suppression Flag
Philippe,As usual, very thorough and concise. Thanks so much for chiming in!
Re: Clean Up Warnings with the 'restriction' Suppression Flag
is it possible to export access rules into a jar file?Because that would be cool, i am a developer of wicket and we have some protected or public method on classes that we use internally but shouldn't be used by the outside world because we can't guarentee that it will exist in another version.
So if i can define that export in in the jar file and then everybody that uses eclipse (or maybe an other ide that also embraces this) will see our access rules.
Re: Clean Up Warnings with the 'restriction' Suppression Flag
It would be nice if packages/classes/methods with default access could simply declare which other packages/classes/methods can see them. Even without fancy features like package signatures and so forth on top of this, it would be a wonderful feature. Like this:@VisibleTo("wicket.request.**")
class Whatever
{
}
or
public class Whatever
{
@VisibleTo("package.Class1, package.Class2, package2.*")
void whatever()
If this is not a security feature but rather a way of helping programmers specify API contracts better, only JavaC would need to be changed. If it were a security feature (probably better), I assume the VM would be involved as well as crypto and sealing stuff.
Re: Clean Up Warnings with the 'restriction' Suppression Flag
It does feel sometimes that the existing access modifiers just aren't expressive enough.Re: Clean Up Warnings with the 'restriction' Suppression Flag
I agree, we are willing to consider expressing finer granularity rules near access rights, such as the ones you mentionned. Other things would be to indicate whether a abstract type can be implemented outside the defining API etc...Likely this would use annotations, or separate specification files which could be associated to existing libraries (possibly included along with them).
Re: Clean Up Warnings with the 'restriction' Suppression Flag
I've wanted this feature ever since I first heard Tom Ball complaining about it back in 1997. There is no need to get complex with this. You can't implement an abstract type if you can't see it. I've thought a lot about this over the past 9 years and I think it would be smart to keep this really simple because you can get very carried away if you start considering all the possible requirements of complex, secure systems.The @VisibleTo() annotation seems quite nice to me. If the Java Package object was more consistent (which I think is a separate bug!) and annotations were extended to include Packages as well as Classes (and I think you SHOULD be able to say MyClass.class.package and get the class' Package object or wicket.request.package and get the package itself directly), the whole thing could just about fall out. You could say this: @VisibleTo(wicket.request.package, MySpecialClass.class, MyOtherSpecialClassThatMightMove.class.package)
It doesn't solve the problem of visibility to subpackages, but you could just add another annotation for that oddball case like @VisibleToSubPackagesOf(wicket.request.package, wicket.markup.package).
If we cleaned up the nature of Package objects (which is a hassle requiring a workaround in Wicket) and make them consistent and accessible through the language, the whole thing becomes Java simple again.
No?
Re: Clean Up Warnings with the 'restriction' Suppression Flag
I have submitted an RFE with incident #659185 to Sun. Would love to see Packages made accessible to the language and annotations. Some effort here could go a really long way in solving API problems! I'm dying to use something like @VisibleTo() in Wicket.