001    /*
002     * Sonar, open source software quality management tool.
003     * Copyright (C) 2009 SonarSource SA
004     * mailto:contact AT sonarsource DOT com
005     *
006     * Sonar is free software; you can redistribute it and/or
007     * modify it under the terms of the GNU Lesser General Public
008     * License as published by the Free Software Foundation; either
009     * version 3 of the License, or (at your option) any later version.
010     *
011     * Sonar is distributed in the hope that it will be useful,
012     * but WITHOUT ANY WARRANTY; without even the implied warranty of
013     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014     * Lesser General Public License for more details.
015     *
016     * You should have received a copy of the GNU Lesser General Public
017     * License along with Sonar; if not, write to the Free Software
018     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
019     */
020    package org.sonar.squid.ast;
021    
022    import java.util.ArrayList;
023    import java.util.Collection;
024    import java.util.List;
025    import java.util.SortedSet;
026    import java.util.TreeSet;
027    
028    import org.slf4j.Logger;
029    import org.slf4j.LoggerFactory;
030    import org.sonar.squid.api.SquidConfiguration;
031    import org.sonar.squid.ast.visitor.AstVisitor;
032    import org.sonar.squid.recognizer.CodeRecognizer;
033    import org.sonar.squid.recognizer.JavaFootprint;
034    import org.sonar.squid.text.Source;
035    
036    import com.puppycrawl.tools.checkstyle.api.Check;
037    import com.puppycrawl.tools.checkstyle.api.DetailAST;
038    import com.puppycrawl.tools.checkstyle.api.TextBlock;
039    
040    public class CheckstyleSquidBridge extends Check {
041    
042      private static Logger         logger = LoggerFactory.getLogger(CheckstyleSquidBridge.class);
043      private static AstVisitor[]   visitors;
044      private static int[]          allTokens;
045      private static CodeRecognizer codeRecognizer;
046    
047      static void setASTVisitors(List<AstVisitor> visitors) {
048        CheckstyleSquidBridge.visitors = visitors.toArray(new AstVisitor[0]);
049        SortedSet<Integer> sorter = new TreeSet<Integer>();
050        for (AstVisitor visitor : visitors) {
051          sorter.addAll(visitor.getWantedTokens());
052          allTokens = new int[sorter.size()];
053          int i = 0;
054          for (Integer itSorted : sorter) {
055            allTokens[i++] = itSorted;
056          }
057        }
058      }
059    
060      static void setSquidConfiguration(SquidConfiguration conf) {
061        codeRecognizer = new CodeRecognizer(conf.getCommentedCodeThreshold(), new JavaFootprint());
062      }
063    
064      @Override
065      public int[] getDefaultTokens() {
066        return allTokens;
067      }
068    
069      @Override
070      public void beginTree(DetailAST ast) {
071        try {
072          Source source = createSource();
073          for (AstVisitor visitor : visitors) {
074            visitor.setFileContents(getFileContents());
075            visitor.setSource(source);
076            visitor.visitFile(ast);
077          }
078        } catch (RuntimeException e) {
079          // Exception are not propagated by Checkstyle engine
080          logger.error("Error occurs when analysing :" + getFileContents().getFilename(), e);
081        }
082      }
083    
084      private Source createSource() {
085        List<TextBlock> comments = new ArrayList<TextBlock>();
086        for (List<TextBlock> listTextBlock : (Collection<List<TextBlock>>) getFileContents().getCComments().values()) {
087          comments.addAll(listTextBlock);
088        }
089    
090        comments.addAll(getFileContents().getCppComments().values());
091        return new Source(getFileContents().getLines(), codeRecognizer, comments);
092      }
093    
094      @Override
095      public void visitToken(DetailAST ast) {
096        try {
097          for (AstVisitor visitor : visitors) {
098            if (visitor.getWantedTokens().contains(ast.getType())) {
099              visitor.visitToken(ast);
100            }
101          }
102        } catch (RuntimeException e) {
103          // Exception are not propagated by Checkstyle engine
104          logger.error("Error occurs when analysing :" + getFileContents().getFilename(), e);
105        }
106      }
107    
108      @Override
109      public void leaveToken(DetailAST ast) {
110        try {
111          for (int i = visitors.length - 1; i >= 0; i--) {
112            AstVisitor visitor = visitors[i];
113            if (visitor.getWantedTokens().contains(ast.getType())) {
114              visitor.leaveToken(ast);
115            }
116          }
117        } catch (RuntimeException e) {
118          // Exception are not propagated by Checkstyle engine
119          logger.error("Error occurs when analysing :" + getFileContents().getFilename(), e);
120        }
121      }
122    
123      @Override
124      public void finishTree(DetailAST ast) {
125        try {
126          for (int i = visitors.length - 1; i >= 0; i--) {
127            AstVisitor visitor = visitors[i];
128            visitor.leaveFile(ast);
129          }
130        } catch (RuntimeException e) {
131          // Exception are not propagated by Checkstyle engine
132          logger.error("Error occurs when analysing :" + getFileContents().getFilename(), e);
133        }
134      }
135    }