Create system to declare processing stages in an extensible fashion

This commit is contained in:
Clément Fournier
2018-11-01 18:53:18 +01:00
parent efc22da116
commit 5eb1d23a38
27 changed files with 578 additions and 63 deletions

View File

@ -6,7 +6,7 @@ package net.sourceforge.pmd.lang.apex;
import java.io.Writer;
import net.sourceforge.pmd.lang.AbstractLanguageVersionHandler;
import net.sourceforge.pmd.lang.AbstractPmdLanguageVersionHandler;
import net.sourceforge.pmd.lang.Parser;
import net.sourceforge.pmd.lang.ParserOptions;
import net.sourceforge.pmd.lang.VisitorStarter;
@ -18,7 +18,7 @@ import net.sourceforge.pmd.lang.apex.rule.ApexRuleViolationFactory;
import net.sourceforge.pmd.lang.ast.xpath.DefaultASTXPathHandler;
import net.sourceforge.pmd.lang.rule.RuleViolationFactory;
public class ApexHandler extends AbstractLanguageVersionHandler {
public class ApexHandler extends AbstractPmdLanguageVersionHandler {
@Override
public VisitorStarter getMultifileFacade() {

View File

@ -266,6 +266,7 @@ public interface Rule extends PropertySource {
/**
* Sets whether this Rule uses Data Flow Analysis.
*/
@Deprecated
void setDfa(boolean isDfa);
/**
@ -282,6 +283,7 @@ public interface Rule extends PropertySource {
*
* @return <code>true</code> if Data Flow Analysis is used.
*/
@Deprecated
boolean isDfa();
/**
@ -294,6 +296,7 @@ public interface Rule extends PropertySource {
/**
* Sets whether this Rule uses Type Resolution.
*/
@Deprecated
void setTypeResolution(boolean usingTypeResolution);
/**
@ -311,6 +314,7 @@ public interface Rule extends PropertySource {
*
* @return <code>true</code> if Type Resolution is used.
*/
@Deprecated
boolean isTypeResolution();
/**
@ -323,6 +327,7 @@ public interface Rule extends PropertySource {
/**
* Sets whether this Rule uses multi-file analysis.
*/
@Deprecated
void setMultifile(boolean multifile);
/**
@ -340,6 +345,7 @@ public interface Rule extends PropertySource {
*
* @return <code>true</code> if the multi file analysis is used.
*/
@Deprecated
boolean isMultifile();
/**

View File

@ -596,6 +596,8 @@ public class RuleSet implements ChecksumAware {
return includePatterns;
}
/**
* Does any Rule for the given Language use the DFA layer?
*
@ -604,6 +606,7 @@ public class RuleSet implements ChecksumAware {
* @return <code>true</code> if a Rule for the Language uses the DFA layer,
* <code>false</code> otherwise.
*/
@Deprecated
public boolean usesDFA(Language language) {
for (Rule r : rules) {
if (r.getLanguage().equals(language) && r.isDfa()) {
@ -621,6 +624,7 @@ public class RuleSet implements ChecksumAware {
* @return <code>true</code> if a Rule for the Language uses Type
* Resolution, <code>false</code> otherwise.
*/
@Deprecated
public boolean usesTypeResolution(Language language) {
for (Rule r : rules) {
if (r.getLanguage().equals(language) && r.isTypeResolution()) {
@ -640,6 +644,7 @@ public class RuleSet implements ChecksumAware {
* @return {@code true} if a Rule for the Language uses multi file analysis,
* {@code false} otherwise.
*/
@Deprecated
public boolean usesMultifile(Language language) {
for (Rule r : rules) {
if (r.getLanguage().equals(language) && r.isMultifile()) {

View File

@ -161,6 +161,7 @@ public class RuleSets {
* the language of a source
* @return true if any rule in the RuleSet needs the DFA layer
*/
@Deprecated
public boolean usesDFA(Language language) {
for (RuleSet ruleSet : ruleSets) {
if (ruleSet.usesDFA(language)) {
@ -210,6 +211,7 @@ public class RuleSets {
* @return <code>true</code> if a Rule for the Language uses Type
* Resolution, <code>false</code> otherwise.
*/
@Deprecated
public boolean usesTypeResolution(Language language) {
for (RuleSet ruleSet : ruleSets) {
if (ruleSet.usesTypeResolution(language)) {
@ -228,6 +230,7 @@ public class RuleSets {
* @return {@code true} if a Rule for the Language uses multi file analysis,
* {@code false} otherwise.
*/
@Deprecated
public boolean usesMultifile(Language language) {
for (RuleSet ruleSet : ruleSets) {
if (ruleSet.usesMultifile(language)) {

View File

@ -173,6 +173,34 @@ public class SourceCodeProcessor {
Parser parser = PMD.parserFor(languageVersion, configuration);
Node rootNode = parse(ctx, sourceCode, parser);
// basically:
// 1. make the union of all stage dependencies of each rule, by language, for the Rulesets
// 2. order them by dependency
// 3. run them and time them if needed
// The problem is the first two steps need only be done once.
// They're probably costly and if we do this here without changing anything,
// they'll be done on each file! Btw currently the "usesDfa" and such are nested loops testing
// all rules of all rulesets, but they're run on each file too!
// Also, the benchmarking framework needs a small refactor. TimedOperationCategory needs to be
// made extensible -> probably should be turned to a class with static constants + factory methods
// and not an enum.
// With mutable RuleSets, caching of the value can't be guaranteed to be accurate...
// The approach I'd like to take is either
// * to create a new RunnableRulesets class which is immutable, and performs all these preliminary
// computations upon construction.
// * or to modify Ruleset and Rulesets to be immutable. This IMO is a better option because it makes
// these objects easier to reason about and pass around from thread to thread. It also avoid creating
// a new class, and breaking SourceCodeProcessor's API too much.
//
// The "preliminary computations" also include:
// * removing dysfunctional rules
// * separating rulechain rules from normal rules
// * grouping rules by language/ file extension
// * etc.
resolveQualifiedNames(rootNode, languageVersionHandler);
symbolFacade(rootNode, languageVersionHandler);
Language language = languageVersion.getLanguage();

View File

@ -0,0 +1,34 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang;
import java.util.Collections;
import java.util.List;
import net.sourceforge.pmd.lang.ast.AstProcessingStage;
import net.sourceforge.pmd.lang.rule.RuleViolationFactory;
/**
* Base language version handler for languages that only support CPD.
*
* @author Clément Fournier
* @since 6.10.0
*/
public abstract class AbstractCpdLanguageVersionHandler extends AbstractLanguageVersionHandler {
@Override
public List<? extends AstProcessingStage<?>> getProcessingStages() {
return Collections.emptyList();
}
protected abstract String getLanguageName();
@Override
public RuleViolationFactory getRuleViolationFactory() {
throw new UnsupportedOperationException("getRuleViolationFactory() is not supported for " + getLanguageName());
}
}

View File

@ -0,0 +1,56 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang;
import java.util.Collections;
import java.util.List;
import org.apache.commons.lang3.EnumUtils;
import net.sourceforge.pmd.lang.ast.AstProcessingStage;
/**
* Base language version handler for languages that support PMD, i.e. can build an AST
* and support AST processing stages.
*
* @author Clément Fournier
* @since 6.10.0
*/
public abstract class AbstractPmdLanguageVersionHandler extends AbstractLanguageVersionHandler {
private final List<? extends AstProcessingStage<?>> processingStages;
/**
* Declare processing stages within an enum. An enum is the best way
* to declare them since the illegality of forward references naturally
* prevents circular dependencies to be declared. The natural ordering
* on enums is also a sound and stable ordering for processing stages.
*
* @param processingStagesEnum Enum class
* @param <T> Type of the enum class
*/
protected <T extends Enum<T> & AstProcessingStage<T>> AbstractPmdLanguageVersionHandler(Class<T> processingStagesEnum) {
this.processingStages = EnumUtils.getEnumList(processingStagesEnum);
}
/**
* Declare no optional processing stages as of yet.
*/
protected AbstractPmdLanguageVersionHandler() {
this.processingStages = Collections.emptyList();
}
@Override
public final List<? extends AstProcessingStage<?>> getProcessingStages() {
return processingStages;
}
}

View File

@ -5,10 +5,14 @@
package net.sourceforge.pmd.lang;
import java.io.Writer;
import java.util.List;
import net.sourceforge.pmd.annotation.Experimental;
import net.sourceforge.pmd.lang.dfa.DFAGraphRule;
import net.sourceforge.pmd.lang.ast.AstProcessingStage;
import net.sourceforge.pmd.lang.rule.RuleViolationFactory;
/**
* Interface for obtaining the classes necessary for checking source files of a
* specific language.
@ -17,20 +21,21 @@ import net.sourceforge.pmd.lang.rule.RuleViolationFactory;
*/
public interface LanguageVersionHandler {
/**
* Get the DataFlowHandler.
*/
DataFlowHandler getDataFlowHandler();
/**
* Get the XPathHandler.
*/
XPathHandler getXPathHandler();
/**
* Get the RuleViolationFactory.
* Returns the list of all supported optional processing stages.
*
* @return A list of all optional processing stages.
*/
RuleViolationFactory getRuleViolationFactory();
@Experimental
List<? extends AstProcessingStage<?>> getProcessingStages();
/**
* Get the default ParserOptions.
@ -39,6 +44,7 @@ public interface LanguageVersionHandler {
*/
ParserOptions getDefaultParserOptions();
/**
* Get the Parser.
*
@ -46,46 +52,70 @@ public interface LanguageVersionHandler {
*/
Parser getParser(ParserOptions parserOptions);
/**
* Get the RuleViolationFactory.
*/
RuleViolationFactory getRuleViolationFactory();
/**
* Get the DumpFacade.
*
* @param writer The writer to dump to.
*
* @return VisitorStarter
*/
// TODO should we deprecate? Not much use to it.
// Plus if it's not implemented, then it does nothing to the writer which is unexpected.
VisitorStarter getDumpFacade(Writer writer, String prefix, boolean recurse);
/**
* Get the DataFlowHandler.
*/
@Deprecated
DataFlowHandler getDataFlowHandler();
/**
* Get the DataFlowFacade.
*
* @return VisitorStarter
*/
@Deprecated
VisitorStarter getDataFlowFacade();
/**
* Get the SymbolFacade.
*
* @return VisitorStarter
*/
VisitorStarter getSymbolFacade();
/**
* Get the SymbolFacade.
*
* @param classLoader
* A ClassLoader to use for resolving Types.
* @return VisitorStarter
*/
@Deprecated
VisitorStarter getSymbolFacade();
/**
* Get the SymbolFacade.
*
* @param classLoader A ClassLoader to use for resolving Types.
*
* @return VisitorStarter
*/
@Deprecated
VisitorStarter getSymbolFacade(ClassLoader classLoader);
/**
* Get the TypeResolutionFacade.
*
* @param classLoader
* A ClassLoader to use for resolving Types.
* @return VisitorStarter
*/
VisitorStarter getTypeResolutionFacade(ClassLoader classLoader);
/**
* Get the DumpFacade.
* @param classLoader A ClassLoader to use for resolving Types.
*
* @param writer
* The writer to dump to.
* @return VisitorStarter
*/
VisitorStarter getDumpFacade(Writer writer, String prefix, boolean recurse);
@Deprecated
VisitorStarter getTypeResolutionFacade(ClassLoader classLoader);
/**
@ -93,6 +123,7 @@ public interface LanguageVersionHandler {
*
* @return The visitor starter
*/
@Deprecated
VisitorStarter getMultifileFacade();
@ -104,8 +135,10 @@ public interface LanguageVersionHandler {
*
* @return The visitor starter
*/
@Deprecated
VisitorStarter getQualifiedNameResolutionFacade(ClassLoader classLoader);
@Deprecated
DFAGraphRule getDFAGraphRule();
}

View File

@ -48,6 +48,9 @@ public interface XPathHandler {
/**
* Get a Jaxen Navigator for this Language. May return <code>null</code> if
* there is no Jaxen Navigation for this language.
*
* @deprecated PMD 7.0.0 will remove support for Jaxen
*/
@Deprecated
Navigator getNavigator();
}

View File

@ -0,0 +1,34 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.ast;
import net.sourceforge.pmd.annotation.Experimental;
import net.sourceforge.pmd.lang.LanguageVersion;
/**
* Configuration relevant to e.g. an {@link AstProcessingStage}.
*
* @author Clément Fournier
* @since 6.10.0
*/
@Experimental
public interface AstAnalysisConfiguration {
/**
* Gets the classloader used for type resolution.
*
* @return The classloader.
*/
ClassLoader getTypeResolutionClassLoader();
/**
* Returns the language version used for this analysis.
*/
LanguageVersion getLanguageVersion();
}

View File

@ -0,0 +1,110 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.ast;
import java.util.List;
import net.sourceforge.pmd.Rule;
import net.sourceforge.pmd.RuleSets;
import net.sourceforge.pmd.annotation.Experimental;
import net.sourceforge.pmd.lang.LanguageVersionHandler;
// @formatter:off
/**
* Represents one of the stages applying on the AST
* after parsing is done. Each of these stages implicitly
* depends on the parser stage.
*
* <p>An analysis on a file goes through the following stages:
* <ul>
* <li> Parsing stage: taking the source and configuration, and returning an AST
* <li> Language-specific AST visits: sequence of stages specific to each language.
* Each stage performs side effects on the AST, e.g. to resolve such things as comments,
* types, DFA graph, etc.
* <li> Rulechain application: all rulechain rules are run on the final AST
* <li> Rule application: other rules are run
* </ul>
*
* <p>These steps are run on each file during the analysis, unless the cache entry of the file is up-to-date.
* They're all run sequentially by the same thread. Rule application performs side-effects on the Report,
* which is rendered after all files have been processed.
*
* <p>Parsing and rule[chain] application stages are considered special and are handled differently for now.
* A {@link LanguageVersionHandler} is responsible for listing all available {@link AstProcessingStage}s
* (see {@link LanguageVersionHandler#getProcessingStages()}). The actual set of stages that will get executed
* for a run is the union of the dependencies of the rules in the run {@link RuleSets}.
*
* <p>Additional doc, to be moved elsewhere probably:
* <p>PMD's execution goes through other more global stages (not sure about the exact order):
* <ul>
* <li> Rule loading: creates a {@link RuleSets} from the ruleset files
* <li> Cache loading: loads the cache file for incremental analysis if any, creates the new cache
* <li> Report creation: creates a report object for the rules to act on
* <li> File collection: collects the files to analyse and dispatches them to worker threads.
* Each file undergoes the steps described above.
* <li> Report rendering
* <li> Cache persisting
* </ul>
*
*
* @author Clément Fournier
* @since 6.10.0
*/
// @formatter:on
@Experimental
public interface AstProcessingStage<T extends AstProcessingStage<T>> extends Comparable<T> {
/**
* Gets the stages on which this stage depends.
* E.g. the type resolution stage may depend on the
* qualified name resolution stage.
*
* <p>Returns an empty list if this stage only depends
* on the parser stage.
*/
List<T> getDependencies();
/**
* Returns the name of this stage, used e.g. to display in a
* benchmark report.
*
* @return The name of the stage.
*/
String getDisplayName();
/**
* Performs some side effects on the AST, e.g. to resolve something.
*
* @param rootNode Root of the tree
* @param configuration Configuration
*/
void processAST(RootNode rootNode, AstAnalysisConfiguration configuration);
/**
* Returns true if the given rule depends on this stage,
* in which case, any ruleset containing that rule depends
* on this stage too.
*
* @param rule Rule to test
*
* @return true if the given rule depends on this stage.
*/
// This can be customized for each step.
// For now we use the Rule.isDfa() / Rule.isTypeRes()
// In the future we can check an annotation.
// If the rule is an XPath rule, then additional work
// performed by the XPath analyser will be taken into account.
// This separation based on the type of rule means that the
// method for dependency determination should probably be on the
// Rule interface, but I don't know for now.
@Experimental
boolean ruleDependsOnThisStage(Rule rule);
}

View File

@ -318,6 +318,7 @@ public abstract class AbstractRule extends AbstractPropertySource implements Rul
@Override
public void addRuleChainVisit(Class<? extends Node> nodeClass) {
if (!nodeClass.getSimpleName().startsWith("AST")) {
// Classes under the Comment hierarchy and stuff need to be refactored in the Java AST
throw new IllegalArgumentException("Node class does not start with 'AST' prefix: " + nodeClass);
}
addRuleChainVisit(nodeClass.getSimpleName().substring("AST".length()));

View File

@ -61,7 +61,7 @@ public class DummyLanguageModule extends BaseLanguageModule {
}
}
public static class Handler extends AbstractLanguageVersionHandler {
public static class Handler extends AbstractPmdLanguageVersionHandler {
@Override
public RuleViolationFactory getRuleViolationFactory() {
return new RuleViolationFactory();

View File

@ -4,21 +4,21 @@
package net.sourceforge.pmd.lang.cpp;
import net.sourceforge.pmd.lang.AbstractLanguageVersionHandler;
import net.sourceforge.pmd.lang.AbstractCpdLanguageVersionHandler;
import net.sourceforge.pmd.lang.Parser;
import net.sourceforge.pmd.lang.ParserOptions;
import net.sourceforge.pmd.lang.rule.RuleViolationFactory;
/**
* Implementation of LanguageVersionHandler for the C++ Language.
*/
public class CppHandler extends AbstractLanguageVersionHandler {
public class CppHandler extends AbstractCpdLanguageVersionHandler {
@Override
public RuleViolationFactory getRuleViolationFactory() {
throw new UnsupportedOperationException("getRuleViolationFactory() is not supported for C++");
protected String getLanguageName() {
return "C++";
}
@Override
public Parser getParser(ParserOptions parserOptions) {
return new CppParser(parserOptions);

View File

@ -6,7 +6,7 @@ package net.sourceforge.pmd.lang.java;
import java.io.Writer;
import net.sourceforge.pmd.lang.AbstractLanguageVersionHandler;
import net.sourceforge.pmd.lang.AbstractPmdLanguageVersionHandler;
import net.sourceforge.pmd.lang.DataFlowHandler;
import net.sourceforge.pmd.lang.LanguageRegistry;
import net.sourceforge.pmd.lang.VisitorStarter;
@ -40,7 +40,12 @@ import net.sf.saxon.sxpath.IndependentContext;
*
* @author pieter_van_raemdonck - Application Engineers NV/SA - www.ae.be
*/
public abstract class AbstractJavaHandler extends AbstractLanguageVersionHandler {
public abstract class AbstractJavaHandler extends AbstractPmdLanguageVersionHandler {
protected AbstractJavaHandler() {
super(JavaProcessingStage.class);
}
@Override
public DataFlowHandler getDataFlowHandler() {

View File

@ -0,0 +1,103 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import net.sourceforge.pmd.Rule;
import net.sourceforge.pmd.lang.ast.RootNode;
import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
import net.sourceforge.pmd.lang.java.dfa.DataFlowFacade;
import net.sourceforge.pmd.lang.java.qname.QualifiedNameResolver;
import net.sourceforge.pmd.lang.java.symboltable.SymbolFacade;
import net.sourceforge.pmd.lang.java.typeresolution.TypeResolutionFacade;
import net.sourceforge.pmd.lang.ast.AstAnalysisConfiguration;
import net.sourceforge.pmd.lang.ast.AstProcessingStage;
/**
* Java processing stages.
*
* @author Clément Fournier
* @since 6.10.0
*/
public enum JavaProcessingStage implements AstProcessingStage<JavaProcessingStage> {
/**
* Qualified name resolution.
*/
QNAME_RESOLUTION("Qualified name resolution") {
@Override
public void processAST(RootNode rootNode, AstAnalysisConfiguration configuration) {
new QualifiedNameResolver().initializeWith(configuration.getTypeResolutionClassLoader(), (ASTCompilationUnit) rootNode);
}
},
/**
* Symbol table analysis.
*/
SYMBOL_RESOLUTION("Symbol table") {
@Override
public void processAST(RootNode rootNode, AstAnalysisConfiguration configuration) {
new SymbolFacade().initializeWith(configuration.getTypeResolutionClassLoader(), (ASTCompilationUnit) rootNode);
}
},
/**
* Type resolution, depends on QName resolution.
*/
TYPE_RESOLUTION("Type resolution", QNAME_RESOLUTION) {
@Override
public void processAST(RootNode rootNode, AstAnalysisConfiguration configuration) {
new TypeResolutionFacade().initializeWith(configuration.getTypeResolutionClassLoader(), (ASTCompilationUnit) rootNode);
}
},
/**
* Data flow analysis.
*/
DFA("Data flow analysis") {
@Override
public void processAST(RootNode rootNode, AstAnalysisConfiguration configuration) {
new DataFlowFacade().initializeWith(new JavaDataFlowHandler(), (ASTCompilationUnit) rootNode);
}
@Override
public boolean ruleDependsOnThisStage(Rule rule) {
return rule.isDfa();
}
};
private final String displayName;
private final List<JavaProcessingStage> dependencies;
JavaProcessingStage(String displayName, JavaProcessingStage... dependencies) {
this.displayName = displayName;
this.dependencies = Collections.unmodifiableList(Arrays.asList(dependencies));
}
@Override
public List<JavaProcessingStage> getDependencies() {
return dependencies;
}
@Override
public String getDisplayName() {
return displayName;
}
@Override
public boolean ruleDependsOnThisStage(Rule rule) {
// most stages are enabled by default in java
return true;
}
}

View File

@ -6,7 +6,7 @@ package net.sourceforge.pmd.lang.ecmascript;
import java.io.Writer;
import net.sourceforge.pmd.lang.AbstractLanguageVersionHandler;
import net.sourceforge.pmd.lang.AbstractPmdLanguageVersionHandler;
import net.sourceforge.pmd.lang.Parser;
import net.sourceforge.pmd.lang.ParserOptions;
import net.sourceforge.pmd.lang.VisitorStarter;
@ -21,7 +21,7 @@ import net.sourceforge.pmd.lang.rule.RuleViolationFactory;
/**
* Implementation of LanguageVersionHandler for the ECMAScript Version 3.
*/
public class Ecmascript3Handler extends AbstractLanguageVersionHandler {
public class Ecmascript3Handler extends AbstractPmdLanguageVersionHandler {
@Override
public XPathHandler getXPathHandler() {

View File

@ -7,6 +7,7 @@ package net.sourceforge.pmd.lang.jsp;
import java.io.Writer;
import net.sourceforge.pmd.lang.AbstractLanguageVersionHandler;
import net.sourceforge.pmd.lang.AbstractPmdLanguageVersionHandler;
import net.sourceforge.pmd.lang.Parser;
import net.sourceforge.pmd.lang.ParserOptions;
import net.sourceforge.pmd.lang.VisitorStarter;
@ -23,7 +24,7 @@ import net.sourceforge.pmd.lang.rule.RuleViolationFactory;
*
* @author pieter_van_raemdonck - Application Engineers NV/SA - www.ae.be
*/
public class JspHandler extends AbstractLanguageVersionHandler {
public class JspHandler extends AbstractPmdLanguageVersionHandler {
@Override
public XPathHandler getXPathHandler() {

View File

@ -4,21 +4,22 @@
package net.sourceforge.pmd.lang.matlab;
import net.sourceforge.pmd.lang.AbstractLanguageVersionHandler;
import net.sourceforge.pmd.lang.AbstractCpdLanguageVersionHandler;
import net.sourceforge.pmd.lang.Parser;
import net.sourceforge.pmd.lang.ParserOptions;
import net.sourceforge.pmd.lang.rule.RuleViolationFactory;
/**
* Implementation of LanguageVersionHandler for the Matlab Language.
*/
public class MatlabHandler extends AbstractLanguageVersionHandler {
public class MatlabHandler extends AbstractCpdLanguageVersionHandler {
@Override
public RuleViolationFactory getRuleViolationFactory() {
throw new UnsupportedOperationException("getRuleViolationFactory() is not supported for Matlab");
protected String getLanguageName() {
return "Matlab";
}
@Override
public Parser getParser(ParserOptions parserOptions) {
return new MatlabParser(parserOptions);

View File

@ -4,21 +4,22 @@
package net.sourceforge.pmd.lang.objectivec;
import net.sourceforge.pmd.lang.AbstractLanguageVersionHandler;
import net.sourceforge.pmd.lang.AbstractCpdLanguageVersionHandler;
import net.sourceforge.pmd.lang.Parser;
import net.sourceforge.pmd.lang.ParserOptions;
import net.sourceforge.pmd.lang.rule.RuleViolationFactory;
/**
* Implementation of LanguageVersionHandler for the Objective-C Language.
*/
public class ObjectiveCHandler extends AbstractLanguageVersionHandler {
public class ObjectiveCHandler extends AbstractCpdLanguageVersionHandler {
@Override
public RuleViolationFactory getRuleViolationFactory() {
throw new UnsupportedOperationException("getRuleViolationFactory() is not supported for Objective-C");
protected String getLanguageName() {
return "Objective-C";
}
@Override
public Parser getParser(ParserOptions parserOptions) {
return new ObjectiveCParser(parserOptions);

View File

@ -6,7 +6,7 @@ package net.sourceforge.pmd.lang.plsql;
import java.io.Writer;
import net.sourceforge.pmd.lang.AbstractLanguageVersionHandler;
import net.sourceforge.pmd.lang.AbstractPmdLanguageVersionHandler;
import net.sourceforge.pmd.lang.DataFlowHandler;
import net.sourceforge.pmd.lang.Parser;
import net.sourceforge.pmd.lang.ParserOptions;
@ -30,7 +30,12 @@ import net.sourceforge.pmd.lang.rule.RuleViolationFactory;
*
* @author sturton - PLDoc - pldoc.sourceforge.net
*/
public class PLSQLHandler extends AbstractLanguageVersionHandler {
public class PLSQLHandler extends AbstractPmdLanguageVersionHandler {
public PLSQLHandler() {
super(PlsqlProcessingStage.class);
}
@Override
public Parser getParser(ParserOptions parserOptions) {

View File

@ -0,0 +1,84 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.plsql;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import net.sourceforge.pmd.Rule;
import net.sourceforge.pmd.lang.ast.RootNode;
import net.sourceforge.pmd.lang.plsql.ast.ASTInput;
import net.sourceforge.pmd.lang.plsql.dfa.DataFlowFacade;
import net.sourceforge.pmd.lang.plsql.symboltable.SymbolFacade;
import net.sourceforge.pmd.lang.ast.AstAnalysisConfiguration;
import net.sourceforge.pmd.lang.ast.AstProcessingStage;
/**
* PL-SQL AST processing stages.
*
* @author Clément Fournier
* @since 6.10.0
*/
public enum PlsqlProcessingStage implements AstProcessingStage<PlsqlProcessingStage> {
/**
* Symbol table analysis.
*/
SYMBOL_RESOLUTION("Symbol table") {
@Override
public void processAST(RootNode rootNode, AstAnalysisConfiguration configuration) {
new SymbolFacade().initializeWith((ASTInput) rootNode);
}
@Override
public boolean ruleDependsOnThisStage(Rule rule) {
return true;
}
},
/**
* Data flow analysis.
*/
DFA("Data flow analysis") {
@Override
public void processAST(RootNode rootNode, AstAnalysisConfiguration configuration) {
new DataFlowFacade().initializeWith(new PLSQLDataFlowHandler(), (ASTInput) rootNode);
}
@Override
public boolean ruleDependsOnThisStage(Rule rule) {
return rule.isDfa();
}
};
private final String displayName;
private final List<PlsqlProcessingStage> dependencies;
PlsqlProcessingStage(String displayName, PlsqlProcessingStage... dependencies) {
this.displayName = displayName;
this.dependencies = Collections.unmodifiableList(Arrays.asList(dependencies));
}
@Override
public List<PlsqlProcessingStage> getDependencies() {
return dependencies;
}
@Override
public String getDisplayName() {
return displayName;
}
}

View File

@ -4,21 +4,23 @@
package net.sourceforge.pmd.lang.python;
import net.sourceforge.pmd.lang.AbstractLanguageVersionHandler;
import net.sourceforge.pmd.lang.AbstractCpdLanguageVersionHandler;
import net.sourceforge.pmd.lang.Parser;
import net.sourceforge.pmd.lang.ParserOptions;
import net.sourceforge.pmd.lang.rule.RuleViolationFactory;
/**
* Implementation of LanguageVersionHandler for the Python Language.
*/
public class PythonHandler extends AbstractLanguageVersionHandler {
public class PythonHandler extends AbstractCpdLanguageVersionHandler {
@Override
public RuleViolationFactory getRuleViolationFactory() {
throw new UnsupportedOperationException("getRuleViolationFactory() is not supported for Python");
protected String getLanguageName() {
return "Python";
}
@Override
public Parser getParser(ParserOptions parserOptions) {
return new PythonParser(parserOptions);

View File

@ -14,8 +14,8 @@ import java.util.Map;
import net.sourceforge.pmd.Rule;
import net.sourceforge.pmd.RuleContext;
import net.sourceforge.pmd.RuleViolation;
import net.sourceforge.pmd.lang.AbstractLanguageVersionHandler;
import net.sourceforge.pmd.lang.AbstractParser;
import net.sourceforge.pmd.lang.AbstractPmdLanguageVersionHandler;
import net.sourceforge.pmd.lang.BaseLanguageModule;
import net.sourceforge.pmd.lang.Parser;
import net.sourceforge.pmd.lang.ParserOptions;
@ -67,7 +67,7 @@ public class DummyLanguageModule extends BaseLanguageModule {
}
}
public static class Handler extends AbstractLanguageVersionHandler {
public static class Handler extends AbstractPmdLanguageVersionHandler {
@Override
public RuleViolationFactory getRuleViolationFactory() {
return new RuleViolationFactory();

View File

@ -6,7 +6,7 @@ package net.sourceforge.pmd.lang.vf;
import java.io.Writer;
import net.sourceforge.pmd.lang.AbstractLanguageVersionHandler;
import net.sourceforge.pmd.lang.AbstractPmdLanguageVersionHandler;
import net.sourceforge.pmd.lang.Parser;
import net.sourceforge.pmd.lang.ParserOptions;
import net.sourceforge.pmd.lang.VisitorStarter;
@ -18,7 +18,7 @@ import net.sourceforge.pmd.lang.vf.ast.DumpFacade;
import net.sourceforge.pmd.lang.vf.ast.VfNode;
import net.sourceforge.pmd.lang.vf.rule.VfRuleViolationFactory;
public class VfHandler extends AbstractLanguageVersionHandler {
public class VfHandler extends AbstractPmdLanguageVersionHandler {
@Override
public XPathHandler getXPathHandler() {

View File

@ -6,7 +6,7 @@ package net.sourceforge.pmd.lang.vm;
import java.io.Writer;
import net.sourceforge.pmd.lang.AbstractLanguageVersionHandler;
import net.sourceforge.pmd.lang.AbstractPmdLanguageVersionHandler;
import net.sourceforge.pmd.lang.Parser;
import net.sourceforge.pmd.lang.ParserOptions;
import net.sourceforge.pmd.lang.VisitorStarter;
@ -21,7 +21,7 @@ import net.sourceforge.pmd.lang.vm.rule.VmRuleViolationFactory;
* Implementation of LanguageVersionHandler for the VM parser.
*
*/
public class VmHandler extends AbstractLanguageVersionHandler {
public class VmHandler extends AbstractPmdLanguageVersionHandler {
@Override
public XPathHandler getXPathHandler() {

View File

@ -6,7 +6,7 @@ package net.sourceforge.pmd.lang.xml;
import java.io.Writer;
import net.sourceforge.pmd.lang.AbstractLanguageVersionHandler;
import net.sourceforge.pmd.lang.AbstractPmdLanguageVersionHandler;
import net.sourceforge.pmd.lang.Parser;
import net.sourceforge.pmd.lang.ParserOptions;
import net.sourceforge.pmd.lang.VisitorStarter;
@ -21,7 +21,7 @@ import net.sourceforge.pmd.lang.xml.rule.XmlRuleViolationFactory;
/**
* Implementation of LanguageVersionHandler for the XML.
*/
public class XmlHandler extends AbstractLanguageVersionHandler {
public class XmlHandler extends AbstractPmdLanguageVersionHandler {
@Override
public XPathHandler getXPathHandler() {