From 5e277c8211b932c6fbe1755516eca0a548d430cc Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 1 Mar 2024 14:50:35 +0100 Subject: [PATCH] [core] Fix NPE in AbstractAnalysisCache in case of processing errors --- .../cache/internal/AbstractAnalysisCache.java | 7 ++++- .../cache/internal/FileAnalysisCacheTest.java | 30 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cache/internal/AbstractAnalysisCache.java b/pmd-core/src/main/java/net/sourceforge/pmd/cache/internal/AbstractAnalysisCache.java index 7108a368b7..0d12db7d7c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/cache/internal/AbstractAnalysisCache.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cache/internal/AbstractAnalysisCache.java @@ -215,13 +215,18 @@ abstract class AbstractAnalysisCache implements AnalysisCache { final FileId fileName = file.getFileId(); return new FileAnalysisListener() { + private boolean failed = false; + @Override public void onRuleViolation(RuleViolation violation) { - updatedResultsCache.get(fileName).addViolation(violation); + if (!failed) { + updatedResultsCache.get(fileName).addViolation(violation); + } } @Override public void onError(ProcessingError error) { + failed = true; analysisFailed(file); } }; diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/cache/internal/FileAnalysisCacheTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/cache/internal/FileAnalysisCacheTest.java index 2f11170415..253abd19dd 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/cache/internal/FileAnalysisCacheTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/cache/internal/FileAnalysisCacheTest.java @@ -48,6 +48,7 @@ import net.sourceforge.pmd.lang.rule.Rule; import net.sourceforge.pmd.lang.rule.internal.RuleSets; import net.sourceforge.pmd.reporting.FileAnalysisListener; import net.sourceforge.pmd.reporting.InternalApiBridge; +import net.sourceforge.pmd.reporting.Report; import net.sourceforge.pmd.reporting.RuleViolation; class FileAnalysisCacheTest { @@ -146,6 +147,35 @@ class FileAnalysisCacheTest { assertEquals(textLocation.getEndColumn(), cachedViolation.getEndColumn()); } + @Test + void testStorePersistsFilesWithViolationsAndProcessingErrors() throws IOException { + final FileAnalysisCache cache = new FileAnalysisCache(newCacheFile); + cache.checkValidity(mock(RuleSets.class), mock(ClassLoader.class), setOf(sourceFileBackend)); + final FileAnalysisListener cacheListener = cache.startFileAnalysis(sourceFile); + + cache.isUpToDate(sourceFile); + + cacheListener.onError(new Report.ProcessingError(new RuntimeException("some rule failed"), sourceFile.getFileId())); + + final RuleViolation rv = mock(RuleViolation.class); + final TextRange2d textLocation = TextRange2d.range2d(1, 2, 3, 4); + when(rv.getLocation()).thenReturn(FileLocation.range(sourceFile.getFileId(), textLocation)); + final Rule rule = mock(Rule.class, Mockito.RETURNS_SMART_NULLS); + when(rule.getLanguage()).thenReturn(mock(Language.class)); + when(rv.getRule()).thenReturn(rule); + + // the next rule wants to report a violation + cacheListener.onRuleViolation(rv); + cache.persist(); + + final FileAnalysisCache reloadedCache = new FileAnalysisCache(newCacheFile); + reloadedCache.checkValidity(mock(RuleSets.class), mock(ClassLoader.class), setOf(sourceFileBackend)); + assertFalse(reloadedCache.isUpToDate(sourceFile), + "Cache believes file is up to date although processing errors happened earlier"); + + final List cachedViolations = reloadedCache.getCachedViolations(sourceFile); + assertTrue(cachedViolations.isEmpty(), "There should be no cached rule violations"); + } @Test void testDisplayNameIsRespected() throws Exception {