Skip to content

Commit

Permalink
Merge pull request #80 from firewave/verbose
Browse files Browse the repository at this point in the history
Added `Show Cppcheck XML Output` action to show the latest XML output - refs #53
  • Loading branch information
firewave committed Mar 27, 2023
2 parents 6bec888 + 2657c13 commit fdf161f
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 15 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ Deployment.

## Releases

### 1.6.3 - 20XX-XX-XX

- Added `Show Cppcheck XML Output` action to show the latest XML output.

### 1.6.2 - 2022-01-25

- Fixed `NullPointerException` with Cppcheck < 1.89 caused by missing `column` attribute in XML result.
Expand Down
6 changes: 4 additions & 2 deletions resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<idea-plugin>
<id>com.github.johnthagen.cppcheck</id>
<name>cppcheck</name>
<version>1.6.2</version>
<version>1.6.3</version>
<vendor email="johnthagen@gmail.com" url="http://github.com/johnthagen">johnthagen</vendor>

<description><![CDATA[
Expand Down Expand Up @@ -60,7 +60,7 @@
]]></description>

<change-notes><![CDATA[
- Fixed `NullPointerException` with Cppcheck < 1.89 caused by missing 'column' attribute in XML result.
- Added `Show Cppcheck XML Output` action to show the latest XML output.
]]>
</change-notes>

Expand All @@ -85,6 +85,8 @@

<actions>
<!-- Add your actions here -->
<action id="com.github.johnthagen.cppcheck.ShowOutputAction" class="com.github.johnthagen.cppcheck.ShowOutputAction"
text="Show Cppcheck XML Output" description="Show the raw Cppcheck --xml output of the latest analysis"/>
</actions>

</idea-plugin>
35 changes: 25 additions & 10 deletions src/com/github/johnthagen/cppcheck/CppCheckInspectionImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.util.DocumentUtil;
import com.intellij.util.execution.ParametersListUtil;
Expand Down Expand Up @@ -55,7 +56,7 @@ private static ProblemHighlightType severityToHighlightType(@NotNull final Strin
}

// TODO: make configurable
private static final boolean VERBOSE_LOG = false;
private static final int VERBOSE_LOG = 0;
private static final String INCONCLUSIVE_TEXT = ":inconclusive";

@NotNull
Expand All @@ -65,10 +66,11 @@ public static List<ProblemDescriptor> parseOutput(@NotNull final PsiFile psiFile
@NotNull final String cppcheckOutput,
@NotNull final String sourceFileName) throws IOException, SAXException, ParserConfigurationException {

if (VERBOSE_LOG) {
final VirtualFile vFile = psiFile.getVirtualFile();
if (VERBOSE_LOG >= 1) {
// TODO: provide XML output via a "Show Cppcheck output" action - event log messages are truncated
CppcheckNotification.send("execution output for " + psiFile.getVirtualFile().getCanonicalPath(),
cppcheckOutput,
CppcheckNotification.send("finished analysis for " + vFile.getCanonicalPath(),
"",
NotificationType.INFORMATION);
}

Expand Down Expand Up @@ -127,7 +129,7 @@ public static List<ProblemDescriptor> parseOutput(@NotNull final PsiFile psiFile
}

// suppress this warning for headers until Cppcheck handles them in a better way
if (SupportedExtensions.isHeaderFile(psiFile.getVirtualFile()) && id.equals("unusedStructMember")) {
if (SupportedExtensions.isHeaderFile(vFile) && id.equals("unusedStructMember")) {
continue;
}

Expand All @@ -150,7 +152,7 @@ public static List<ProblemDescriptor> parseOutput(@NotNull final PsiFile psiFile

// ignore entries without location e.g. missingIncludeSystem
if (location == null) {
CppcheckNotification.send("no location for " + psiFile.getVirtualFile().getCanonicalPath(),
CppcheckNotification.send("no location for " + vFile.getCanonicalPath(),
id + " " + severity + " " + inconclusive + " " + errorMessage,
NotificationType.ERROR);
continue;
Expand All @@ -167,6 +169,12 @@ public static List<ProblemDescriptor> parseOutput(@NotNull final PsiFile psiFile
column = Integer.parseInt(columnAttr.getNodeValue());
}

if (VERBOSE_LOG >= 4) {
CppcheckNotification.send(id + " for " + vFile.getCanonicalPath(),
id + " " + severity + " " + inconclusive + " " + errorMessage + " " + fileName + " " + lineNumber + " " + column,
NotificationType.INFORMATION);
}

// If a file #include's header files, Cppcheck will also run on the header files and print
// any errors. These errors don't apply to the current file and should not be drawn. They can
// be distinguished by checking the file name.
Expand All @@ -176,7 +184,7 @@ public static List<ProblemDescriptor> parseOutput(@NotNull final PsiFile psiFile

// Cppcheck error
if (lineNumber <= 0 || lineNumber > document.getLineCount()) {
CppcheckNotification.send("line number out-of-bounds for " + psiFile.getVirtualFile().getCanonicalPath(),
CppcheckNotification.send("line number out-of-bounds for " + vFile.getCanonicalPath(),
id + " " + severity + " " + inconclusive + " " + errorMessage + " " + fileName + " " + lineNumber + " " + column,
NotificationType.ERROR);
continue;
Expand All @@ -201,20 +209,27 @@ public static List<ProblemDescriptor> parseOutput(@NotNull final PsiFile psiFile

private static final int TIMEOUT_MS = 60 * 1000;

public static String executeCommandOnFile(@NotNull final String command,
public static String executeCommandOnFile(@NotNull final VirtualFile vFile,
@NotNull final String command,
@NotNull final String options,
@NotNull final String filePath,
@NotNull final File filePath,
final String cppcheckMisraPath) throws CppcheckError, ExecutionException {
final GeneralCommandLine cmd = new GeneralCommandLine()
.withExePath(command)
.withParameters(ParametersListUtil.parse(options))
.withParameters(ParametersListUtil.parse("\"" + filePath + "\""));
.withParameters(ParametersListUtil.parse("\"" + filePath.getAbsolutePath() + "\""));

// Need to be able to get python from the system env
if (cppcheckMisraPath != null && !cppcheckMisraPath.isEmpty()) {
cmd.withParentEnvironmentType(GeneralCommandLine.ParentEnvironmentType.SYSTEM);
}

if (VERBOSE_LOG >= 2) {
CppcheckNotification.send("options for " + vFile.getCanonicalPath(),
cmd.getCommandLineString(),
NotificationType.INFORMATION);
}

final CapturingProcessHandler processHandler = new CapturingProcessHandler(cmd);
final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
final ProcessOutput output = processHandler.runProcessWithProgressIndicator(
Expand Down
13 changes: 10 additions & 3 deletions src/com/github/johnthagen/cppcheck/CppcheckInspection.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,13 @@
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

class CppcheckInspection extends LocalInspectionTool {
final static Path LATEST_RESULT_FILE = Paths.get(FileUtil.getTempDirectory(), "clion-cppcheck-latest.xml");

@Nullable
@Override
public ProblemDescriptor[] checkFile(@NotNull final PsiFile file,
Expand Down Expand Up @@ -57,14 +61,17 @@ public ProblemDescriptor[] checkFile(@NotNull final PsiFile file,
tempFile = FileUtil.createTempFile(RandomStringUtils.randomAlphanumeric(8) + "_", vFile.getName(), true);
FileUtil.writeToFile(tempFile, document.getText());
final String cppcheckOutput =
CppCheckInspectionImpl.executeCommandOnFile(cppcheckPath, prependIncludeDir(cppcheckOptions, vFile),
tempFile.getAbsolutePath(), cppcheckMisraPath);
CppCheckInspectionImpl.executeCommandOnFile(vFile, cppcheckPath, prependIncludeDir(cppcheckOptions, vFile),
tempFile, cppcheckMisraPath);

// store the output of the latest analysis
FileUtil.writeToFile(LATEST_RESULT_FILE.toFile(), cppcheckOutput);

final List<ProblemDescriptor> descriptors = CppCheckInspectionImpl.parseOutput(file, manager, document, cppcheckOutput,
tempFile.getName());
return descriptors.toArray(new ProblemDescriptor[0]);
} catch (final ExecutionException | CppcheckError | IOException | SAXException | ParserConfigurationException ex) {
CppcheckNotification.send("execution failed for " + file.getVirtualFile().getCanonicalPath(),
CppcheckNotification.send("execution failed for " + vFile.getCanonicalPath(),
ex.getClass().getSimpleName() + ": " + ex.getMessage(),
NotificationType.ERROR);
} finally {
Expand Down
31 changes: 31 additions & 0 deletions src/com/github/johnthagen/cppcheck/ShowOutputAction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.github.johnthagen.cppcheck;

import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;

import static com.github.johnthagen.cppcheck.CppcheckInspection.LATEST_RESULT_FILE;

public class ShowOutputAction extends AnAction {
@Override
public void actionPerformed(@NotNull final AnActionEvent anActionEvent) {
final VirtualFile vFile = LocalFileSystem.getInstance().findFileByIoFile(LATEST_RESULT_FILE.toFile());
if (vFile == null) {
return;
}

final Project project = anActionEvent.getProject();
if (project == null) {
return;
}

// TODO: make it possible to view the output for the currently open file
// TODO: find a way to display this without writing to the file system
FileEditorManager.getInstance(project).openTextEditor(new OpenFileDescriptor(project, vFile), true);
}
}

0 comments on commit fdf161f

Please sign in to comment.