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.text;
021    
022    public class MultiLinesCommentHandler extends LineContextHandler {
023    
024      private StringBuilder currentLineComment;
025      private boolean isFirstLineOfComment = false;
026    
027      private boolean isJavadoc = false;
028      private boolean isLicenseHeader = false;
029    
030      private boolean commentStarted = false;
031    
032      private static final String START_COMMENT_TAG = "/*";
033      private static final String START_JAVADOC_TAG = "/**";
034      private static final String START_GWT_NATIVE_CODE_TAG = "/*-{";
035      private static final String END_COMMENT_TAG = "*/";
036    
037      @Override
038      boolean matchToEnd(Line line, StringBuilder pendingLine) {
039        if (!commentStarted) {
040          throw new IllegalStateException("Method doContextBegin(StringBuilder pendingLine) has not been called first (line = '" + pendingLine
041              + "').");
042        }
043        currentLineComment.append(getLastCharacter(pendingLine));
044        if (isJavaDoc()) {
045          isJavadoc = true;
046        }
047        if (isGwtNativeCode()) {
048          initProperties();
049          return true;
050        }
051        boolean match = matchEndOfString(pendingLine, END_COMMENT_TAG);
052        if (match) {
053          endOfCommentLine(line);
054          initProperties();
055          return true;
056        }
057        return false;
058      }
059    
060      private boolean isGwtNativeCode() {
061        return isFirstLineOfComment && currentLineComment.length() == START_GWT_NATIVE_CODE_TAG.length()
062            && currentLineComment.toString().equals(START_GWT_NATIVE_CODE_TAG);
063      }
064    
065      private boolean isJavaDoc() {
066        return isFirstLineOfComment && currentLineComment.length() == START_JAVADOC_TAG.length()
067            && currentLineComment.toString().equals(START_JAVADOC_TAG);
068      }
069    
070      @Override
071      boolean matchToBegin(Line line, StringBuilder pendingLine) {
072        boolean match = matchEndOfString(pendingLine, START_COMMENT_TAG);
073        if (match) {
074          isFirstLineOfComment = true;
075          commentStarted = true;
076          currentLineComment = new StringBuilder(START_COMMENT_TAG);
077          isLicenseHeader = (line.getLineIndex() == 1);
078        }
079        return match;
080      }
081    
082      @Override
083      boolean matchWithEndOfLine(Line line, StringBuilder pendingLine) {
084        endOfCommentLine(line);
085        return false;
086      }
087    
088      private void endOfCommentLine(Line line) {
089        line.setComment(currentLineComment.toString(), isJavadoc, isLicenseHeader);
090        currentLineComment = new StringBuilder();
091        isFirstLineOfComment = false;
092      }
093    
094      private void initProperties() {
095        commentStarted = false;
096        isJavadoc = false;
097        isLicenseHeader = false;
098        currentLineComment = new StringBuilder();
099        isFirstLineOfComment = false;
100      }
101    }