Can a compiler plugin operate on the whole AST?

To write a compiler plugin, you have to register a callback which will be invoked whenever your plugin needs to do something. If I'm reading the source code correctly, it seems like there's no way to write a compiler plugin which gets invoked over the whole AST and gets to make any modifications it likes?

The reason that I ask is that I'm trying to write a compiler plugin which selectively disables certain code blocks, and that shouldn't need the user to explicitly mark which blocks need to be disabled - the whole point is to have the plugin figure it out automatically. But as far as I can tell, the only options are to register a syntax extension, which requires a particular keyword to be used, or to register a procedural macro, which requires a named macro to be invoked. Is there something I'm missing, or is this really impossible?

I believe you can make an attribute-based plugin and apply it to the crate root.

Ah, interesting. So you'd still have to do something like #![foobar] in the crate root (in addition to #![plugin(foobar)]), but then you'd get the crate's whole AST?

Yep. I haven't actually tried this, but it seems like it should work?

Well, we'll see :slight_smile:

Ah, no such luck unfortunately. I mocked up a small prototype here which just prints the AST information whenever the function is called, and when I run it on another project, it looks like it's only getting invoked on the #![disable_code] item. I include the plugin like:

#![plugin(disable_code)]
#![disable_code]

And I get the following output when I run cargo build:

MetaItem { name: disable_code(100), node: Word, span: Span { lo: BytePos(1565), hi: BytePos(1581), ctxt: #0 } }

1581 - 1565 = 16, and #![disable_code] is 16 characters long, so I'm pretty sure my function is only getting invoked on that directive.

EDIT: I might have spoken too soon. Printing the Annotatable argument prints what looks like the whole crate's AST. This is promising...