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