From 71b822ec3af670711077528ff89be8a8d5ef9f35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20K=C3=BChne?= Date: Tue, 17 Dec 2002 23:02:02 +0000 Subject: [PATCH] lots of stuff added --- docs/writingchecks.html | 161 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 146 insertions(+), 15 deletions(-) diff --git a/docs/writingchecks.html b/docs/writingchecks.html index 528a2d0e8..7e60df35e 100644 --- a/docs/writingchecks.html +++ b/docs/writingchecks.html @@ -35,6 +35,8 @@
  • Vistor Pattern
  • Visitor in Action
  • Navigating the AST
  • +
  • Defining Properties +
  • Logging Errors
  • Integrating Checks
  • Limitations
  • @@ -173,13 +175,64 @@

    Understanding the visitor pattern

    - TODO: A brief explanation of the Visitor pattern, xref to - GoF/pattern wiki. + Ready for a bit more theory? OK, here it comes: The last bit + that is missing before you can start writing checks is that you have + to understand the Vistor pattern. +

    + +

    + When working with ASTs, a simple approach to define check operations + on them would be to add a check() method to the Class that defines + the AST nodes. For example, our AST type could have a method + checkNumberOfMethods(). Such an approach would suffer from a few + serious drawbacks. Most importantly, it does not provide an extensible + design, i.e. the checks have to be known at compile time, there is no + way to write plugins. +

    + +

    + Hence Checkstyle's AST classes do not have any methods that implement + checking functionality. Instead, Checkstyle's TreeWalker takes a set + of objects that conform to a Check interface. OK, you're right - + actually it's not an interface but an abstract class to provides + some helper methods. A Check provides + methods that take an AST as an argument and perform the checking + process for that AST, most prominently visitToken(). +

    + +

    + + It is important to understand that the individual Checks do no + drive the AST traversal. Instead, the TreeWalker initiates a recursive + descend from the root of the AST to the leaf nodes and calls the Check + methods. +

    + +

    + Before any visitor method is called, the TreeWalker will call + beginTree() to give the Check a chance to do some + initialization. Then, when performing the recursive descend from the + root to the leaf nodes, the visitToken method is called. Unlike the + basic examples in the pattern book, there is a visitToken counterpart + called leaveToken(). The TreeWalker will call that method to signal + that the subtree below the node has been processed and the TreeWalker + is backtracking from the node. After the root node has been left, the + TreeWalker will call finishTree(). +

    + +

    + If you'd like to learn more about the Visitor pattern you should + grab a copy of the Gof + Design + Patterns book.

    Visitor in action

    + Let's get back to our example and start writing code - that's why + you came here, right? When you fire up the checkstyle GUI and look at a few source files you'll figure out pretty quickly that you are mainly interested in the number of tree nodes of type METHOD_DEF. The @@ -188,23 +241,98 @@

    - Now you have to decide how constructors are treated. Do they - count as a method for the purposes of your Check? Maybe you - should make that configurable, and we have good news for you: - Checkstyle lets you control the token types for which your - visitor methods are called. + Hence we need to register the Check for the token types + CLASS_DEF and INTERFACE_DEF. The TreeWalker will only call + visitToken for these token types. Because the requirements of + our tasks are so simple, there is no need to implement the other + fancy methods, like finishTree(), etc., so here is our first + shot at our check implementation:

    -

    - TODO: Explain how. Explain the visitor methods - (visitToken, leaveToken, beginTree, endTree). -

    +
    +      package com.mycompany.checks;
    +
    +      import com.puppycrawl.tools.checkstyle.api.*;
    +
    +      public class MethodLimitCheck extends Check
    +      {
    +        private int max = 30;
    +
    +        public int[] getDefaultTokens()
    +        {
    +          return new int[]{TokenTypes.CLASS_DEF, TokenTypes.INTERFACE_DEF};
    +        }
    +
    +        public void visitToken(DetailAST ast)
    +        {
    +          int methodDefs = ast.getChildCount(TokenTypes.METHOD_DEF);
    +          if (methodDefs > max) {
    +            log(ast.getLineNo(), "too many methods, only " + max + " are allowed");
    +          }
    +        }
    +      }
    +      

    Navigating the Abstract Syntax Tree (AST)

    - TODO: Explain the navigation methods in DetailAST and how to - use them. + In the example above you already saw that the DetailsAST class + provides utility methods to extract information from the tree, like + getChildCount(). By now you have probably consulted the api + documentation and found that DetailsAST additionally provides methods + for navigating around in the syntax tree, like finding the next + sibling of a node, the childs of a node, the parent of a node, etc. +

    + +

    + These methods provide great power for developing complex + checks. Most of the checks that Checkstyle provides by default + use these methods to analyze the environment of the ASTs that + are visited by the TreeWalker. Don't abuse that feature for + exploring the whole tree, though. Let the TreeWalker drive the + tree traversal and limit the visitor to the neighbours of a + single AST. +

    + + +

    Defining Check Properties

    +

    + + Ok Mr. Checkstyle, that's all very nice but in my company we + have several projects, and each has another number of allowed + methods. I need to control my Check through properties, so where + is the Api to do that? +

    + +

    + Well, the short answer is, there is no Api. It's magic. Really! +

    + +

    + If you need to make something configurable, just add a setter method + to the Check: +

    + +
    +      public class MethodLimitCheck extends Check
    +      {
    +        // code from above omitted for brevity
    +
    +        public void setMax(int limit)
    +        {
    +          max = limit;
    +        }
    +      }
    +      
    +

    + +

    + With this code added, you can set the property max for the MethodLimitCheck module in the + config file. It doesn't get any simpler than that. The secret is + that Checkstyle uses JavaBean introspection to set the JavaBean + properties. That works for all primitive types like boolean, + int, long, etc. plus Strings plus arrays of these types.

    @@ -334,17 +462,20 @@
  • to find duplicate code.
  • to port the TreeWalker solution to check C# instead of Java.
  • +

    -

    Huh? I can't figure it out!

    +

    Huh? I can't figure it out!

    That's probably our fault, it means that we have to provide better docs. Please do not hesitate to ask questions on the user mailing list, this will help us to improve this document. Please make your question as precise as possible, we will not be able to answer questions like "I want to write a check - but I don't know how, can you help me?". + but I don't know how, can you help me?". Be precise, tell us + what you are trying to do (the purpose of the check), what you have + understood so far, and what exactly is the problem that blocks you.