Wednesday, January 2, 2013

Built-in Dart Annotations: @deprecated

‹prev | My Chain | next›

In the comments to yesterday's post on Dart annotations, Ladislav Thon pointed out that there is already a package in the Dart Pub using them: meta. I cannot resist the temptation to kick the tires, so I update my pubspec.yaml to include any version of meta:
name: classes
dependencies:
  unittest: any
  meta: any
And install the newly specified dependency:
➜  classes git:(master) ✗ pub install
Resolving dependencies...
Downloading meta 0.2.9+7...
Dependencies installed!
Next, in my awesome Cookie class, I decide that cookie should not be responsible for mixing its own ingredients. I factor that functionality out into a Mixer class and deprecate the mix_it() method. Rather than raising an error or printing a warning that I will be sure to ignore, I use meta's @deprecated annotation:
import 'package:meta/meta.dart';

class Cookie {
  int number_of_chips;
  Cookie({this.number_of_chips:42});

  @deprecated
  void mix_it() {
    print("Mixing ingredients and ${number_of_chips} chips.");
  }
}
Since that is an annotation, it has no effect whatsoever on the ability to exercise that code. Given the following main() entry point:
main() {
  var cookie = new Cookie();
  print("cookie has ${cookie.number_of_chips} chips");

  // Whoa! Calling a deprecated method:
  cookie.mix_it();
}
Dart produces the same output as it would were that annotation not in place:
➜  classes git:(master) ✗ dart annotations.dart         
cookie has 42 chips
Mixing ingredients and 42 chips.
But, when I run the code through dart_analyzer, I get a warning:
➜  classes git:(master) ✗ dart_analyzer annotations.dart
file:/Code/classes/annotations.dart:23:10: Method 'mix_it' is deprecated
    22: 
    23:   cookie.mix_it();
                 ~~~~~~
That is pretty cool. This even works if I trace it through subclasses. Consider the amazing thin mint cookie:
class ThinMint extends Cookie {
  ThinMint(): super(number_of_chips: 0);
}
When I try to mix it as well:
main() {
  @FixMe("Moar better code")
  var cookie = new Cookie();
  print("cookie has ${cookie.number_of_chips} chips");

  cookie.mix_it();

  print("\n*** Thin Mint time!");
  var thin_mint = new ThinMint();
  thin_mint.mix_it();
}
The code still runs just fine:
➜  classes git:(master) ✗ dart annotations.dart         
cookie has 42 chips
Mixing ingredients and 42 chips.

*** Thin Mint time!
Mixing ingredients and 0 chips
Only now I get two dart_analyzer warning instead of one:
➜  classes git:(master) ✗ dart_analyzer annotations.dart
file:/Code/classes/annotations.dart:27:10: Method 'mix_it' is deprecated
    26: 
    27:   cookie.mix_it();
                 ~~~~~~
file:/Code/classes/annotations.dart:31:13: Method 'mix_it' is deprecated
    30:   var thin_mint = new ThinMint();
    31:   thin_mint.mix_it();
                    ~~~~~~
That is amazing.

I would very much like to adapt this kind of annotation for my own internal annotations. Specifically, I would like to make my @IntentionalError annotation suppress normal warnings from dart_analyzer. This is very specific to examples from Dart for Hipsters so I would not expect dart_analyzer to support it natively. But if I could adapt what the meta package does to influence dart_analyzer, I would be very happy.

Unfortunately, the meta package does nothing. It only includes a few constant constructor definitions. Internal code in dart_analyzer must look for these annotations in order to do its thing. Ah well, maybe someday.

Until then, I can be secure in the knowledge that dart_analyzer (and Dart Editor) are hard at work warning other developers of the danger of telling a cookie to mix itself.


Day #618

No comments:

Post a Comment