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

org.sonar.plugins.csharp.fxcop.FxCopResultParser Maven / Gradle / Ivy

Go to download

Plugin that runs FxCop analyses to check C# sources against rule violations.

There is a newer version: 1.4
Show newest version
/*
 * Sonar C# Plugin :: FxCop
 * Copyright (C) 2010 Jose Chillan, Alexandre Victoor and SonarSource
 * [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.plugins.csharp.fxcop;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;

import javax.xml.stream.XMLStreamException;

import org.apache.commons.io.IOUtils;
import org.codehaus.staxmate.SMInputFactory;
import org.codehaus.staxmate.in.SMEvent;
import org.codehaus.staxmate.in.SMHierarchicCursor;
import org.codehaus.staxmate.in.SMInputCursor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.BatchExtension;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.RuleFinder;
import org.sonar.api.rules.RuleQuery;
import org.sonar.api.rules.Violation;
import org.sonar.api.utils.SonarException;
import org.sonar.plugins.csharp.api.CSharpResourcesBridge;
import org.sonar.plugins.csharp.core.AbstractStaxParser;

/**
 * Parses the reports generated by a FXCop analysis.
 */
public class FxCopResultParser extends AbstractStaxParser implements BatchExtension {

  private static final Logger LOG = LoggerFactory.getLogger(FxCopResultParser.class);
  private static final String NAMESPACE = "Namespace";
  private static final String NAMESPACES = "Namespaces";
  private static final String TARGETS = "Targets";
  private static final String MESSAGE = "Message";
  private static final String MESSAGES = "Messages";
  private static final String MODULE = "Module";
  private static final String NAME = "Name";
  private static final String TYPENAME = "TypeName";
  private static final String LINE = "Line";

  private Project project;
  private SensorContext context;
  private RuleFinder ruleFinder;
  private CSharpResourcesBridge resourcesBridge;

  /**
   * Constructs a @link{FxCopResultParser}.
   * 
   * @param project
   * @param context
   * @param rulesManager
   * @param profile
   */
  public FxCopResultParser(Project project, SensorContext context, RuleFinder ruleFinder, CSharpResourcesBridge resourcesBridge) {
    super();
    this.project = project;
    this.context = context;
    this.ruleFinder = ruleFinder;
    this.resourcesBridge = resourcesBridge;
  }

  /**
   * Parses a processed violation file.
   * 
   * @param file
   *          the file to parse
   */
  public void parse(File file) {
    SMInputFactory inputFactory = initStax();
    FileInputStream fileInputStream = null;
    try {
      fileInputStream = new FileInputStream(file);
      SMHierarchicCursor cursor = inputFactory.rootElementCursor(new InputStreamReader(fileInputStream, getEncoding()));
      SMInputCursor mainCursor = cursor.advance().childElementCursor();
      while (mainCursor.getNext() != null) {
        if (NAMESPACES.equals(mainCursor.getQName().getLocalPart())) {
          parseNamespacesBloc(mainCursor);
        } else if (TARGETS.equals(mainCursor.getQName().getLocalPart())) {
          parseTargetsBloc(mainCursor);
        }
      }
      cursor.getStreamReader().closeCompletely();
    } catch (XMLStreamException e) {
      throw new SonarException("Error while reading FxCop result file: " + file.getAbsolutePath(), e);
    } catch (FileNotFoundException e) {
      throw new SonarException("Cannot find FxCop result file: " + file.getAbsolutePath(), e);
    } finally {
      IOUtils.closeQuietly(fileInputStream);
    }
  }

  private void parseNamespacesBloc(SMInputCursor cursor) throws XMLStreamException {
    // Cursor in on 
    SMInputCursor namespacesCursor = cursor.childElementCursor(NAMESPACE);
    while (namespacesCursor.getNext() != null) {
      SMInputCursor messagesCursor = namespacesCursor.descendantElementCursor(MESSAGE);
      while (messagesCursor.getNext() != null) {
        createViolationFromMessageAtProjectLevel(messagesCursor);
      }
    }
  }

  private void parseTargetsBloc(SMInputCursor cursor) throws XMLStreamException {
    // Cursor on 
    SMInputCursor modulesCursor = cursor.descendantElementCursor(MODULE);
    while (modulesCursor.getNext() != null) {
      parseModuleMessagesBloc(modulesCursor);
    }
  }

  private void parseModuleMessagesBloc(SMInputCursor cursor) throws XMLStreamException {
    // Cursor on 
    SMInputCursor moduleChildrenCursor = cursor.childElementCursor();
    while (moduleChildrenCursor.getNext() != null) {
      if (MESSAGES.equals(moduleChildrenCursor.getQName().getLocalPart())) {
        // We are on , look for 
        SMInputCursor messagesCursor = moduleChildrenCursor.childElementCursor(MESSAGE);
        while (messagesCursor.getNext() != null) {
          createViolationFromMessageAtProjectLevel(messagesCursor);
        }
      } else if (NAMESPACES.equals(moduleChildrenCursor.getQName().getLocalPart())) {
        // We are on , get 
        SMInputCursor namespaceCursor = moduleChildrenCursor.childElementCursor();
        while (namespaceCursor.getNext() != null) {
          String namespaceName = namespaceCursor.getAttrValue(NAME);
          SMInputCursor typeCursor = namespaceCursor.childElementCursor().advance().childElementCursor();
          while (typeCursor.getNext() != null) {
            parseTypeBloc(namespaceName, typeCursor);
          }
        }
      }
    }
  }

  private void parseTypeBloc(String namespaceName, SMInputCursor cursor) throws XMLStreamException {
    // Cursor on 
    String typeName = cursor.getAttrValue(NAME);
    Resource resource = resourcesBridge.getFromTypeName(namespaceName, typeName);
    SMInputCursor messagesCursor = cursor.descendantElementCursor(MESSAGE);
    while (messagesCursor.getNext() != null) {
      // Cursor on 
      if (messagesCursor.getCurrEvent() == SMEvent.START_ELEMENT) {

        Rule currentRule = ruleFinder.find(RuleQuery.create().withRepositoryKey(FxCopConstants.REPOSITORY_KEY)
            .withKey(messagesCursor.getAttrValue(TYPENAME)));
        if (currentRule != null) {
          // look for all potential issues
          SMInputCursor issueCursor = messagesCursor.childElementCursor();
          while (issueCursor.getNext() != null) {
            // Cursor on Issue
            Violation violation = Violation.create(currentRule, resource);
            String lineNumber = issueCursor.getAttrValue(LINE);
            if (lineNumber != null) {
              violation.setLineId(Integer.parseInt(lineNumber));
            }
            violation.setMessage(issueCursor.collectDescendantText().trim());
            violation.setSeverity(currentRule.getSeverity());
            context.saveViolation(violation);
          }
        } else {
          LOG.warn("Could not find the following rule in the FxCop rule repository: " + messagesCursor.getAttrValue(TYPENAME));
        }

      }
    }
  }

  private void createViolationFromMessageAtProjectLevel(SMInputCursor messagesCursor) throws XMLStreamException {
    Rule currentRule = ruleFinder.find(RuleQuery.create().withRepositoryKey(FxCopConstants.REPOSITORY_KEY)
        .withKey(messagesCursor.getAttrValue(TYPENAME)));
    if (currentRule != null) {
      // the violation is saved at project level, not on a specific resource
      Violation violation = Violation.create(currentRule, project);
      violation.setMessage(messagesCursor.collectDescendantText().trim());
      violation.setSeverity(currentRule.getSeverity());
      context.saveViolation(violation);
    } else {
      LOG.debug("Could not find the following rule in the FxCop rule repository: " + messagesCursor.getAttrValue(TYPENAME));
    }
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy