All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.sonar.cxx.channels.PreprocessorChannel Maven / Gradle / Ivy

The newest version!
/*
 * Sonar C++ Plugin (Community)
 * Copyright (C) 2011 Waleri Enns and CONTACT Software GmbH
 * [email protected]
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
 */
package org.sonar.cxx.channels;

import com.sonar.sslr.api.Token;
import com.sonar.sslr.impl.Lexer;
import org.sonar.channel.Channel;
import org.sonar.channel.CodeReader;
import org.sonar.cxx.api.CxxTokenType;

public class PreprocessorChannel extends Channel {
  private static final char EOF = (char) -1;

  @Override
  public boolean consume(CodeReader code, Lexer output) {
    int line = code.getLinePosition();
    int column = code.getColumnPosition();

    char ch = code.charAt(0);
    if ((ch != '#')) {
      return false;
    }

    String tokenValue = read(code);
    output.addToken(Token.builder()
        .setLine(line)
        .setColumn(column)
        .setURI(output.getURI())
        .setValueAndOriginalValue(tokenValue)
        .setType(CxxTokenType.PREPROCESSOR)
        .build());

    return true;
  }

  private String read(CodeReader code) {
    StringBuilder sb = new StringBuilder();
    char ch;

    while (true) {
      ch = (char) code.pop();
      if (isNewline(ch) || ch == EOF) {
        break;
      }
      if (ch == '/' && code.charAt(0) == '*') {
        consumeComment(code);
      } else if (ch == '\\' && isNewline((char) code.peek())) {
        // the newline is escaped: we have a the multi line preprocessor directive
        // consume both the backslash and the newline, insert a space instead
        consumeNewline(code);
        sb.append(' ');
      }
      else {
        sb.append(ch);
      }
    }
    return sb.toString();
  }

  private static void consumeNewline(CodeReader code) {
    if ((code.charAt(0) == '\r') && (code.charAt(1) == '\n')) {
      // \r\n
      code.pop();
      code.pop();
    } else {
      // \r or \n
      code.pop();
    }
  }

  private static void consumeComment(CodeReader code) {
    char ch;
    
    code.pop(); // initial '*'
    while (true) {
      ch = (char)code.pop();
      if (ch == EOF) {
        break;
      }
      if (ch == '*' && code.charAt(0) == '/') {
        code.pop();
        break;
      }
    }
  }
  
  private static boolean isNewline(char ch) {
    return (ch == '\n') || (ch == '\r');
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy