Fix #4893 - throw if language is not supported

This commit is contained in:
Clément Fournier
2024-04-02 20:54:00 +02:00
committed by Juan Martín Sotuyo Dodero
parent 79d9570213
commit 6d35f14f6b
9 changed files with 144 additions and 2 deletions

View File

@ -89,6 +89,7 @@ public abstract class AbstractConfiguration {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Language '" + language.getId() + "' is not registered in " + getLanguageRegistry()); "Language '" + language.getId() + "' is not registered in " + getLanguageRegistry());
} }
checkLanguageIsAcceptable(language);
} }
public LanguageRegistry getLanguageRegistry() { public LanguageRegistry getLanguageRegistry() {
@ -167,6 +168,8 @@ public abstract class AbstractConfiguration {
* @param lang A language * @param lang A language
*/ */
public void setOnlyRecognizeLanguage(Language lang) { public void setOnlyRecognizeLanguage(Language lang) {
AssertionUtil.requireParamNotNull("language", lang);
checkLanguageIsRegistered(lang);
this.languageVersionDiscoverer.onlyRecognizeLanguages(LanguageRegistry.singleton(lang)); this.languageVersionDiscoverer.onlyRecognizeLanguages(LanguageRegistry.singleton(lang));
} }
@ -177,6 +180,8 @@ public abstract class AbstractConfiguration {
*/ */
public void setDefaultLanguageVersion(LanguageVersion languageVersion) { public void setDefaultLanguageVersion(LanguageVersion languageVersion) {
Objects.requireNonNull(languageVersion); Objects.requireNonNull(languageVersion);
checkLanguageIsRegistered(languageVersion.getLanguage());
languageVersionDiscoverer.setDefaultLanguageVersion(languageVersion); languageVersionDiscoverer.setDefaultLanguageVersion(languageVersion);
getLanguageProperties(languageVersion.getLanguage()).setLanguageVersion(languageVersion.getVersion()); getLanguageProperties(languageVersion.getLanguage()).setLanguageVersion(languageVersion.getVersion());
} }
@ -194,6 +199,14 @@ public abstract class AbstractConfiguration {
} }
} }
/**
* Check that it is correct to use the given language with this configuration.
* Throw if not.
*/
protected void checkLanguageIsAcceptable(Language lang) {
// do nothing
}
/** /**
* Get the LanguageVersion of the source file with given name. This depends * Get the LanguageVersion of the source file with given name. This depends
* on the fileName extension, and the java version. * on the fileName extension, and the java version.

View File

@ -24,6 +24,7 @@ import net.sourceforge.pmd.internal.util.ClasspathClassLoader;
import net.sourceforge.pmd.lang.Language; import net.sourceforge.pmd.lang.Language;
import net.sourceforge.pmd.lang.LanguageRegistry; import net.sourceforge.pmd.lang.LanguageRegistry;
import net.sourceforge.pmd.lang.LanguageVersion; import net.sourceforge.pmd.lang.LanguageVersion;
import net.sourceforge.pmd.lang.PmdCapableLanguage;
import net.sourceforge.pmd.lang.rule.RulePriority; import net.sourceforge.pmd.lang.rule.RulePriority;
import net.sourceforge.pmd.lang.rule.RuleSetLoader; import net.sourceforge.pmd.lang.rule.RuleSetLoader;
import net.sourceforge.pmd.renderers.Renderer; import net.sourceforge.pmd.renderers.Renderer;
@ -472,4 +473,12 @@ public class PMDConfiguration extends AbstractConfiguration {
public void setReportFile(Path reportFile) { public void setReportFile(Path reportFile) {
this.reportFile = reportFile; this.reportFile = reportFile;
} }
@Override
protected void checkLanguageIsAcceptable(Language lang) {
if (!(lang instanceof PmdCapableLanguage)) {
throw new UnsupportedOperationException("Language " + lang.getId() + " does not support analysis with PMD and cannot be used in a PMDConfiguration. " +
"You may be able to use it with CPD though.");
}
}
} }

View File

@ -20,11 +20,12 @@ import org.slf4j.LoggerFactory;
import net.sourceforge.pmd.AbstractConfiguration; import net.sourceforge.pmd.AbstractConfiguration;
import net.sourceforge.pmd.cpd.internal.CpdLanguagePropertiesDefaults; import net.sourceforge.pmd.cpd.internal.CpdLanguagePropertiesDefaults;
import net.sourceforge.pmd.lang.Language;
import net.sourceforge.pmd.lang.LanguageRegistry; import net.sourceforge.pmd.lang.LanguageRegistry;
import net.sourceforge.pmd.lang.PmdCapableLanguage;
import net.sourceforge.pmd.util.log.internal.SimpleMessageReporter; import net.sourceforge.pmd.util.log.internal.SimpleMessageReporter;
/** /**
*
* @author Brian Remedios * @author Brian Remedios
* @author Romain Pelisse - <belaran@gmail.com> * @author Romain Pelisse - <belaran@gmail.com>
*/ */
@ -268,4 +269,13 @@ public class CPDConfiguration extends AbstractConfiguration {
this.failOnViolation = failOnViolation; this.failOnViolation = failOnViolation;
} }
@Override
protected void checkLanguageIsAcceptable(Language lang) {
if (!(lang instanceof CpdCapableLanguage)) {
throw new UnsupportedOperationException("Language " + lang.getId() + " does not support analysis with CPD and cannot be used in a CPDConfiguration. " +
"You may be able to use it with PMD though.");
}
}
} }

View File

@ -35,7 +35,8 @@ public final class LanguageRegistry implements Iterable<Language> {
private static final Logger LOG = LoggerFactory.getLogger(LanguageRegistry.class); private static final Logger LOG = LoggerFactory.getLogger(LanguageRegistry.class);
private static final LanguageRegistry ALL_LANGUAGES = // test only
static final LanguageRegistry ALL_LANGUAGES =
loadLanguages(LanguageRegistry.class.getClassLoader()); loadLanguages(LanguageRegistry.class.getClassLoader());
/** /**

View File

@ -12,6 +12,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.File; import java.io.File;
@ -30,6 +31,9 @@ import org.junit.jupiter.api.io.TempDir;
import net.sourceforge.pmd.cache.internal.FileAnalysisCache; import net.sourceforge.pmd.cache.internal.FileAnalysisCache;
import net.sourceforge.pmd.cache.internal.NoopAnalysisCache; import net.sourceforge.pmd.cache.internal.NoopAnalysisCache;
import net.sourceforge.pmd.internal.util.ClasspathClassLoader; import net.sourceforge.pmd.internal.util.ClasspathClassLoader;
import net.sourceforge.pmd.lang.CpdOnlyDummyLanguage;
import net.sourceforge.pmd.lang.DummyLanguageModule;
import net.sourceforge.pmd.lang.LanguageRegistry;
import net.sourceforge.pmd.lang.rule.RulePriority; import net.sourceforge.pmd.lang.rule.RulePriority;
import net.sourceforge.pmd.renderers.CSVRenderer; import net.sourceforge.pmd.renderers.CSVRenderer;
import net.sourceforge.pmd.renderers.Renderer; import net.sourceforge.pmd.renderers.Renderer;
@ -230,4 +234,14 @@ class PmdConfigurationTest {
configuration.setIgnoreIncrementalAnalysis(true); configuration.setIgnoreIncrementalAnalysis(true);
assertTrue(configuration.getAnalysisCache() instanceof NoopAnalysisCache, "Ignoring incremental analysis should turn the cache into a noop"); assertTrue(configuration.getAnalysisCache() instanceof NoopAnalysisCache, "Ignoring incremental analysis should turn the cache into a noop");
} }
@Test
void testCpdOnlyLanguage() {
final PMDConfiguration configuration = new PMDConfiguration(LanguageRegistry.CPD);
assertThrows(UnsupportedOperationException.class,
() -> configuration.setOnlyRecognizeLanguage(CpdOnlyDummyLanguage.getInstance()));
assertThrows(UnsupportedOperationException.class,
() -> configuration.setDefaultLanguageVersion(CpdOnlyDummyLanguage.getInstance().getDefaultVersion()));
}
} }

View File

@ -9,6 +9,7 @@ import static org.hamcrest.Matchers.instanceOf;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.HashMap; import java.util.HashMap;
@ -16,6 +17,9 @@ import java.util.Map;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import net.sourceforge.pmd.lang.DummyLanguageNoCapabilities;
import net.sourceforge.pmd.lang.LanguageRegistry;
class CPDConfigurationTest { class CPDConfigurationTest {
@Test @Test
@ -59,4 +63,16 @@ class CPDConfigurationTest {
assertEquals(StandardCharsets.UTF_16.name(), ((XMLRenderer) renderer).getEncoding()); assertEquals(StandardCharsets.UTF_16.name(), ((XMLRenderer) renderer).getEncoding());
} }
@Test
void testCpdNotSupported() {
DummyLanguageNoCapabilities lang = DummyLanguageNoCapabilities.getInstance();
final CPDConfiguration configuration = new CPDConfiguration(LanguageRegistry.singleton(lang));
assertThrows(UnsupportedOperationException.class,
() -> configuration.setOnlyRecognizeLanguage(lang));
assertThrows(UnsupportedOperationException.class,
() -> configuration.setDefaultLanguageVersion(lang.getDefaultVersion()));
}
} }

View File

@ -0,0 +1,47 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang;
import java.util.Objects;
import net.sourceforge.pmd.cpd.AnyCpdLexer;
import net.sourceforge.pmd.cpd.CpdCapableLanguage;
import net.sourceforge.pmd.cpd.CpdLanguageProperties;
import net.sourceforge.pmd.cpd.CpdLexer;
import net.sourceforge.pmd.lang.ast.DummyNode;
import net.sourceforge.pmd.lang.ast.DummyNode.DummyRootNode;
import net.sourceforge.pmd.lang.ast.ParseException;
import net.sourceforge.pmd.lang.ast.Parser;
import net.sourceforge.pmd.lang.ast.Parser.ParserTask;
import net.sourceforge.pmd.lang.document.Chars;
import net.sourceforge.pmd.lang.document.TextDocument;
import net.sourceforge.pmd.lang.document.TextRegion;
import net.sourceforge.pmd.lang.impl.CpdOnlyLanguageModuleBase;
import net.sourceforge.pmd.lang.impl.SimpleLanguageModuleBase;
import net.sourceforge.pmd.reporting.RuleViolation;
import net.sourceforge.pmd.reporting.ViolationDecorator;
/**
* Dummy language used for testing PMD.
*/
public class CpdOnlyDummyLanguage extends CpdOnlyLanguageModuleBase {
public static final String NAME = "DummyCpdOnly";
public static final String TERSE_NAME = "dummy_cpd_only";
public CpdOnlyDummyLanguage() {
super(LanguageMetadata.withId(TERSE_NAME).name(NAME).extensions("dummy", "txt")
.addDefaultVersion("1.7", "7"));
}
public static CpdOnlyDummyLanguage getInstance() {
return (CpdOnlyDummyLanguage) Objects.requireNonNull(LanguageRegistry.CPD.getLanguageByFullName(NAME));
}
@Override
public CpdLexer createCpdLexer(LanguagePropertyBundle bundle) {
return new AnyCpdLexer();
}
}

View File

@ -0,0 +1,30 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang;
import java.util.Objects;
import net.sourceforge.pmd.cpd.AnyCpdLexer;
import net.sourceforge.pmd.cpd.CpdLexer;
import net.sourceforge.pmd.lang.impl.CpdOnlyLanguageModuleBase;
/**
* Dummy language used for testing PMD.
*/
public class DummyLanguageNoCapabilities extends LanguageModuleBase {
public static final String NAME = "DummyNoCapabilities";
public static final String TERSE_NAME = "dummy_no_capabilities";
public DummyLanguageNoCapabilities() {
super(LanguageMetadata.withId(TERSE_NAME).name(NAME).extensions("dummyxxx", "txt")
.addDefaultVersion("1.7", "7"));
}
public static DummyLanguageNoCapabilities getInstance() {
return (DummyLanguageNoCapabilities) Objects.requireNonNull(LanguageRegistry.ALL_LANGUAGES.getLanguageByFullName(NAME));
}
}

View File

@ -1,2 +1,4 @@
net.sourceforge.pmd.lang.DummyLanguageModule net.sourceforge.pmd.lang.DummyLanguageModule
net.sourceforge.pmd.lang.Dummy2LanguageModule net.sourceforge.pmd.lang.Dummy2LanguageModule
net.sourceforge.pmd.lang.CpdOnlyDummyLanguage
net.sourceforge.pmd.lang.DummyLanguageNoCapabilities