core/com.nokia.carbide.cpp.codescanner/src/com/nokia/carbide/cpp/internal/codescanner/CSCommandLauncher.java
/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/
package com.nokia.carbide.cpp.internal.codescanner;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.ProblemMarkerInfo;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import com.nokia.carbide.cdt.builder.builder.CarbideCommandLauncher;
import com.nokia.carbide.cpp.internal.codescanner.markers.CSMarker;
/**
* A class to handle CodeScanner commandline tool execution, error processing
* and generating CodeScanner specific markers.
*
*/
public class CSCommandLauncher extends CarbideCommandLauncher {
private Pattern CSMessagePattern = Pattern.compile("(\\w+):\\s+(\\w+):\\s+(\\w+):\\s+(.*)"); //$NON-NLS-1$;
/**
* Create an instance of the CSCommandLauncher with error parsing
* @param project - a valid IProject object interface
* @param monitor - a valid IProgressMonitor object interface
* @param errorParserIds - the list of error parser IDs used to parse the
* output streams, can be null or empyt array if
* no error parsing is required
* @param workingDir - location of program execution, used to initialize
* the ErrorParserManager
*/
public CSCommandLauncher(IProject project,
IProgressMonitor monitor,
String[] errorParserIds,
IPath workingDir) {
super(project, monitor, errorParserIds, workingDir);
}
/**
* Generate a CodeScanner specific marker
* @param problemMarkerInfo - a valid ProblemMarkerInfo object
*/
public void addMarker(ProblemMarkerInfo problemMarkerInfo) {
try {
IResource markerResource = problemMarkerInfo.file ;
if (markerResource == null) {
markerResource = stdoutStream.getProject();
}
if (markerResource != null) {
IMarker[] cur = markerResource.findMarkers(CSMarker.CS_PROBLEM_MARKER, false, IResource.DEPTH_ONE);
// try to find matching markers and don't put in duplicates
if ((cur != null) && (cur.length > 0)) {
for (int i = 0; i < cur.length; i++) {
int line = cur[i].getAttribute(IMarker.LINE_NUMBER, -1);
int sev = ((Integer) cur[i].getAttribute(IMarker.SEVERITY)).intValue();
String mesg = (String) cur[i].getAttribute(IMarker.MESSAGE);
if (line == problemMarkerInfo.lineNumber && sev == mapCSMarkerSeverity(problemMarkerInfo.severity) && mesg.equals(problemMarkerInfo.description)) {
return;
}
}
}
// create the marker and set its attributes
IMarker marker = markerResource.createMarker(CSMarker.CS_PROBLEM_MARKER);
if (marker != null) {
String message = getCSMessage(problemMarkerInfo.description);
String ruleName = getCSRuleName(problemMarkerInfo.description);
marker.setAttribute(IMarker.MESSAGE, message);
marker.setAttribute(IMarker.SEVERITY, mapCSMarkerSeverity(problemMarkerInfo.severity));
marker.setAttribute(IMarker.LINE_NUMBER, problemMarkerInfo.lineNumber);
marker.setAttribute(IMarker.CHAR_START, -1);
marker.setAttribute(IMarker.CHAR_END, -1);
marker.setAttribute(CSMarker.CS_MARKER_RULE_NAME, ruleName);
if (problemMarkerInfo.variableName != null) {
marker.setAttribute(CSMarker.CS_MARKER_VARIABLE, problemMarkerInfo.variableName);
}
if (problemMarkerInfo.externalPath != null) {
// try to make it absolute if not already
IPath absolutePath = problemMarkerInfo.externalPath;
if (!absolutePath.isAbsolute()) {
IPath projectPath = project.getLocation();
if (projectPath != null) {
absolutePath = projectPath.append(absolutePath);
}
}
// now canonicalize it
try {
absolutePath = new Path(absolutePath.toFile().getCanonicalPath());
} catch (IOException e) {
e.printStackTrace();
}
marker.setAttribute(CSMarker.CS_MARKER_EXTERNAL_LOCATION, absolutePath.toOSString());
}
}
}
}
catch (CoreException e) {
CCorePlugin.log(e.getStatus());
e.printStackTrace();
}
}
/**
* Map an IMarkerGenerator severity to an IMarker severity
* @param severity - an IMarkerGenerator severity
* @return an IMarker severity
*/
protected int mapCSMarkerSeverity(int severity) {
switch (severity) {
case SEVERITY_ERROR_BUILD :
case SEVERITY_ERROR_RESOURCE :
return IMarker.SEVERITY_ERROR;
case SEVERITY_INFO :
return IMarker.SEVERITY_INFO;
case SEVERITY_WARNING :
return IMarker.SEVERITY_WARNING;
}
return IMarker.SEVERITY_ERROR;
}
/**
* Reconstruct error/warning message from CodeScanner commandline tool
* to get rid of the name of the rule.
* @param message - error/warning message generated by CodeScanner
* @return error/warning message without the name of the rule
*/
private String getCSMessage(String message) {
String csMessage = message;
Matcher messageMatcher = CSMessagePattern.matcher(message);
if (messageMatcher.matches()) {
csMessage = messageMatcher.group(2) + ": " +
messageMatcher.group(3) + ": " +
messageMatcher.group(4);
}
return csMessage;
}
/**
* Retrieve the name of the rule embedded in error/warning message
* from CodeScanner commandline tool.
* @param message - error/warning message generated by CodeScanner
* @return name of the rule if found, null otherwise
*/
private String getCSRuleName(String message) {
String ruleName = null;
Matcher messageMatcher = CSMessagePattern.matcher(message);
if (messageMatcher.matches()) {
ruleName = messageMatcher.group(1);
}
return ruleName;
}
}