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(
"Language '" + language.getId() + "' is not registered in " + getLanguageRegistry());
}
checkLanguageIsAcceptable(language);
}
public LanguageRegistry getLanguageRegistry() {
@ -167,6 +168,8 @@ public abstract class AbstractConfiguration {
* @param lang A language
*/
public void setOnlyRecognizeLanguage(Language lang) {
AssertionUtil.requireParamNotNull("language", lang);
checkLanguageIsRegistered(lang);
this.languageVersionDiscoverer.onlyRecognizeLanguages(LanguageRegistry.singleton(lang));
}
@ -177,6 +180,8 @@ public abstract class AbstractConfiguration {
*/
public void setDefaultLanguageVersion(LanguageVersion languageVersion) {
Objects.requireNonNull(languageVersion);
checkLanguageIsRegistered(languageVersion.getLanguage());
languageVersionDiscoverer.setDefaultLanguageVersion(languageVersion);
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
* 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.LanguageRegistry;
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.RuleSetLoader;
import net.sourceforge.pmd.renderers.Renderer;
@ -472,4 +473,12 @@ public class PMDConfiguration extends AbstractConfiguration {
public void setReportFile(Path 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.cpd.internal.CpdLanguagePropertiesDefaults;
import net.sourceforge.pmd.lang.Language;
import net.sourceforge.pmd.lang.LanguageRegistry;
import net.sourceforge.pmd.lang.PmdCapableLanguage;
import net.sourceforge.pmd.util.log.internal.SimpleMessageReporter;
/**
*
* @author Brian Remedios
* @author Romain Pelisse - <belaran@gmail.com>
*/
@ -268,4 +269,13 @@ public class CPDConfiguration extends AbstractConfiguration {
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 LanguageRegistry ALL_LANGUAGES =
// test only
static final LanguageRegistry ALL_LANGUAGES =
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.assertNotNull;
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 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.NoopAnalysisCache;
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.renderers.CSVRenderer;
import net.sourceforge.pmd.renderers.Renderer;
@ -230,4 +234,14 @@ class PmdConfigurationTest {
configuration.setIgnoreIncrementalAnalysis(true);
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.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
@ -16,6 +17,9 @@ import java.util.Map;
import org.junit.jupiter.api.Test;
import net.sourceforge.pmd.lang.DummyLanguageNoCapabilities;
import net.sourceforge.pmd.lang.LanguageRegistry;
class CPDConfigurationTest {
@Test
@ -59,4 +63,16 @@ class CPDConfigurationTest {
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.Dummy2LanguageModule
net.sourceforge.pmd.lang.CpdOnlyDummyLanguage
net.sourceforge.pmd.lang.DummyLanguageNoCapabilities