Rework CPD's LanguageFactory to use ServiceLoader, too
This commit is contained in:
@ -9,10 +9,12 @@ import java.util.Properties;
|
|||||||
import net.sourceforge.pmd.util.filter.Filters;
|
import net.sourceforge.pmd.util.filter.Filters;
|
||||||
|
|
||||||
public abstract class AbstractLanguage implements Language {
|
public abstract class AbstractLanguage implements Language {
|
||||||
|
private final String name;
|
||||||
private final Tokenizer tokenizer;
|
private final Tokenizer tokenizer;
|
||||||
private final FilenameFilter fileFilter;
|
private final FilenameFilter fileFilter;
|
||||||
|
|
||||||
public AbstractLanguage(Tokenizer tokenizer, String... extensions) {
|
public AbstractLanguage(String name, Tokenizer tokenizer, String... extensions) {
|
||||||
|
this.name = name;
|
||||||
this.tokenizer = tokenizer;
|
this.tokenizer = tokenizer;
|
||||||
fileFilter = Filters.toFilenameFilter(Filters.getFileExtensionOrDirectoryFilter(extensions));
|
fileFilter = Filters.toFilenameFilter(Filters.getFileExtensionOrDirectoryFilter(extensions));
|
||||||
}
|
}
|
||||||
@ -28,4 +30,8 @@ public abstract class AbstractLanguage implements Language {
|
|||||||
public void setProperties(Properties properties) {
|
public void setProperties(Properties properties) {
|
||||||
// needs to be implemented by subclasses.
|
// needs to be implemented by subclasses.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,6 @@ package net.sourceforge.pmd.cpd;
|
|||||||
|
|
||||||
public class AnyLanguage extends AbstractLanguage {
|
public class AnyLanguage extends AbstractLanguage {
|
||||||
public AnyLanguage(String... extension) {
|
public AnyLanguage(String... extension) {
|
||||||
super(new AnyTokenizer(), extension);
|
super("any", new AnyTokenizer(), extension);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ public class CPDConfiguration extends AbstractConfiguration {
|
|||||||
if (languageString == null || "".equals(languageString)) {
|
if (languageString == null || "".equals(languageString)) {
|
||||||
languageString = DEFAULT_LANGUAGE;
|
languageString = DEFAULT_LANGUAGE;
|
||||||
}
|
}
|
||||||
return new LanguageFactory().createLanguage(languageString);
|
return LanguageFactory.createLanguage(languageString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,7 +150,7 @@ public class CPDConfiguration extends AbstractConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Language getLanguageFromString(String languageString) {
|
public static Language getLanguageFromString(String languageString) {
|
||||||
return new LanguageFactory().createLanguage(languageString);
|
return LanguageFactory.createLanguage(languageString);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setSystemProperties(CPDConfiguration configuration) {
|
public static void setSystemProperties(CPDConfiguration configuration) {
|
||||||
|
@ -96,7 +96,7 @@ public class CPDTask extends Task {
|
|||||||
if (ignoreAnnotations) {
|
if (ignoreAnnotations) {
|
||||||
p.setProperty(Tokenizer.IGNORE_ANNOTATIONS, "true");
|
p.setProperty(Tokenizer.IGNORE_ANNOTATIONS, "true");
|
||||||
}
|
}
|
||||||
return new LanguageFactory().createLanguage(language, p);
|
return LanguageFactory.createLanguage(language, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void report(CPD cpd) throws ReportException {
|
private void report(CPD cpd) throws ReportException {
|
||||||
|
@ -81,7 +81,7 @@ public class GUI implements CPDListener {
|
|||||||
};
|
};
|
||||||
|
|
||||||
private static abstract class LanguageConfig {
|
private static abstract class LanguageConfig {
|
||||||
public abstract Language languageFor(LanguageFactory lf, Properties p);
|
public abstract Language languageFor(Properties p);
|
||||||
public boolean canIgnoreIdentifiers() { return false; }
|
public boolean canIgnoreIdentifiers() { return false; }
|
||||||
public boolean canIgnoreLiterals() { return false; }
|
public boolean canIgnoreLiterals() { return false; }
|
||||||
public boolean canIgnoreAnnotations() { return false; }
|
public boolean canIgnoreAnnotations() { return false; }
|
||||||
@ -90,31 +90,31 @@ public class GUI implements CPDListener {
|
|||||||
|
|
||||||
private static final Object[][] LANGUAGE_SETS = new Object[][] {
|
private static final Object[][] LANGUAGE_SETS = new Object[][] {
|
||||||
{"Java", new LanguageConfig() {
|
{"Java", new LanguageConfig() {
|
||||||
public Language languageFor(LanguageFactory lf, Properties p) { return lf.createLanguage("java"); }
|
public Language languageFor(Properties p) { return LanguageFactory.createLanguage("java", p); }
|
||||||
public boolean canIgnoreIdentifiers() { return true; }
|
public boolean canIgnoreIdentifiers() { return true; }
|
||||||
public boolean canIgnoreLiterals() { return true; }
|
public boolean canIgnoreLiterals() { return true; }
|
||||||
public boolean canIgnoreAnnotations() { return true; }
|
public boolean canIgnoreAnnotations() { return true; }
|
||||||
public String[] extensions() { return new String[] {".java", ".class" }; }; } },
|
public String[] extensions() { return new String[] {".java", ".class" }; }; } },
|
||||||
{"JSP", new LanguageConfig() {
|
{"JSP", new LanguageConfig() {
|
||||||
public Language languageFor(LanguageFactory lf, Properties p) { return lf.createLanguage("jsp"); }
|
public Language languageFor(Properties p) { return LanguageFactory.createLanguage("jsp", p); }
|
||||||
public String[] extensions() { return new String[] {".jsp" }; }; } },
|
public String[] extensions() { return new String[] {".jsp" }; }; } },
|
||||||
{"C++", new LanguageConfig() {
|
{"C++", new LanguageConfig() {
|
||||||
public Language languageFor(LanguageFactory lf, Properties p) { return lf.createLanguage("cpp"); }
|
public Language languageFor(Properties p) { return LanguageFactory.createLanguage("cpp", p); }
|
||||||
public String[] extensions() { return new String[] {".cpp", ".c" }; }; } },
|
public String[] extensions() { return new String[] {".cpp", ".c" }; }; } },
|
||||||
{"Ruby", new LanguageConfig() {
|
{"Ruby", new LanguageConfig() {
|
||||||
public Language languageFor(LanguageFactory lf, Properties p) { return lf.createLanguage("ruby"); }
|
public Language languageFor(Properties p) { return LanguageFactory.createLanguage("ruby", p); }
|
||||||
public String[] extensions() { return new String[] {".rb" }; }; } },
|
public String[] extensions() { return new String[] {".rb" }; }; } },
|
||||||
{"Fortran", new LanguageConfig() {
|
{"Fortran", new LanguageConfig() {
|
||||||
public Language languageFor(LanguageFactory lf, Properties p) { return lf.createLanguage("fortran"); }
|
public Language languageFor(Properties p) { return LanguageFactory.createLanguage("fortran", p); }
|
||||||
public String[] extensions() { return new String[] {".for", ".f", ".f66", ".f77", ".f90" }; }; } },
|
public String[] extensions() { return new String[] {".for", ".f", ".f66", ".f77", ".f90" }; }; } },
|
||||||
{"PHP", new LanguageConfig() {
|
{"PHP", new LanguageConfig() {
|
||||||
public Language languageFor(LanguageFactory lf, Properties p) { return lf.createLanguage("php"); }
|
public Language languageFor(Properties p) { return LanguageFactory.createLanguage("php", p); }
|
||||||
public String[] extensions() { return new String[] {".php" }; }; } },
|
public String[] extensions() { return new String[] {".php" }; }; } },
|
||||||
{"C#", new LanguageConfig() {
|
{"C#", new LanguageConfig() {
|
||||||
public Language languageFor(LanguageFactory lf, Properties p) { return lf.createLanguage("cs"); }
|
public Language languageFor(Properties p) { return LanguageFactory.createLanguage("cs", p); }
|
||||||
public String[] extensions() { return new String[] {".cs" }; }; } },
|
public String[] extensions() { return new String[] {".cs" }; }; } },
|
||||||
{"PLSQL", new LanguageConfig() {
|
{"PLSQL", new LanguageConfig() {
|
||||||
public Language languageFor(LanguageFactory lf, Properties p) { return lf.createLanguage("plsql"); }
|
public Language languageFor(Properties p) { return LanguageFactory.createLanguage("plsql", p); }
|
||||||
public String[] extensions() { return new String[] {".sql"
|
public String[] extensions() { return new String[] {".sql"
|
||||||
,".trg"
|
,".trg"
|
||||||
,".prc",".fnc"
|
,".prc",".fnc"
|
||||||
@ -125,10 +125,10 @@ public class GUI implements CPDListener {
|
|||||||
,".tps",".tpb"
|
,".tps",".tpb"
|
||||||
}; }; } },
|
}; }; } },
|
||||||
{"Ecmascript", new LanguageConfig() {
|
{"Ecmascript", new LanguageConfig() {
|
||||||
public Language languageFor(LanguageFactory lf, Properties p) { return lf.createLanguage("js"); }
|
public Language languageFor(Properties p) { return LanguageFactory.createLanguage("js", p); }
|
||||||
public String[] extensions() { return new String[] {".js" }; }; } },
|
public String[] extensions() { return new String[] {".js" }; }; } },
|
||||||
{"by extension...", new LanguageConfig() {
|
{"by extension...", new LanguageConfig() {
|
||||||
public Language languageFor(LanguageFactory lf, Properties p) { return lf.createLanguage(LanguageFactory.BY_EXTENSION, p); }
|
public Language languageFor(Properties p) { return LanguageFactory.createLanguage(LanguageFactory.BY_EXTENSION, p); }
|
||||||
public String[] extensions() { return new String[] {"" }; }; } },
|
public String[] extensions() { return new String[] {"" }; }; } },
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -589,7 +589,7 @@ public class GUI implements CPDListener {
|
|||||||
p.setProperty(LanguageFactory.EXTENSION, extensionField.getText());
|
p.setProperty(LanguageFactory.EXTENSION, extensionField.getText());
|
||||||
|
|
||||||
LanguageConfig conf = languageConfigFor((String)languageBox.getSelectedItem());
|
LanguageConfig conf = languageConfigFor((String)languageBox.getSelectedItem());
|
||||||
Language language = conf.languageFor(new LanguageFactory(), p);
|
Language language = conf.languageFor(p);
|
||||||
config.setLanguage(language);
|
config.setLanguage(language);
|
||||||
|
|
||||||
CPDConfiguration.setSystemProperties(config);
|
CPDConfiguration.setSystemProperties(config);
|
||||||
|
@ -7,6 +7,7 @@ import java.io.FilenameFilter;
|
|||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
public interface Language {
|
public interface Language {
|
||||||
|
String getName();
|
||||||
|
|
||||||
Tokenizer getTokenizer();
|
Tokenizer getTokenizer();
|
||||||
|
|
||||||
|
@ -3,56 +3,52 @@
|
|||||||
*/
|
*/
|
||||||
package net.sourceforge.pmd.cpd;
|
package net.sourceforge.pmd.cpd;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import java.util.ServiceLoader;
|
||||||
|
|
||||||
public class LanguageFactory {
|
public class LanguageFactory {
|
||||||
|
|
||||||
/*
|
public static final String EXTENSION = "extension";
|
||||||
* TODO derive and provide this at runtime instead, used by outside IDEs
|
public static final String BY_EXTENSION = "by_extension";
|
||||||
* FIXME Can't we do something cleaner and
|
|
||||||
* more dynamic ? Maybe externalise to a properties files that will
|
|
||||||
* be generated when building pmd ? This will not have to add manually
|
|
||||||
* new language here ?
|
|
||||||
*/
|
|
||||||
public static String[] supportedLanguages =
|
|
||||||
new String[]{"java", "jsp", "cpp", "c", "php", "ruby", "fortran", "ecmascript", "cs", "plsql" };
|
|
||||||
|
|
||||||
private static final String SUFFIX = "Language";
|
private static LanguageFactory instance = new LanguageFactory();
|
||||||
public static final String EXTENSION = "extension";
|
|
||||||
public static final String BY_EXTENSION = "by_extension";
|
|
||||||
private static final String PACKAGE = "net.sourceforge.pmd.cpd.";
|
|
||||||
|
|
||||||
public Language createLanguage(String language) {
|
public static String[] supportedLanguages;
|
||||||
|
static {
|
||||||
|
supportedLanguages = instance.languages.keySet().toArray(new String[instance.languages.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Language> languages = new HashMap<String, Language>();
|
||||||
|
|
||||||
|
private LanguageFactory() {
|
||||||
|
ServiceLoader<Language> languageLoader = ServiceLoader.load(Language.class);
|
||||||
|
for (Language language : languageLoader) {
|
||||||
|
languages.put(language.getName().toLowerCase(), language);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Language createLanguage(String language) {
|
||||||
return createLanguage(language, new Properties());
|
return createLanguage(language, new Properties());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Language createLanguage(String language, Properties properties)
|
public static Language createLanguage(String language, Properties properties)
|
||||||
{
|
{
|
||||||
language = this.languageAliases(language);
|
Language implementation;
|
||||||
// First, we look for a parser following this syntax 'RubyLanguage'
|
if (BY_EXTENSION.equals(language)) {
|
||||||
Language implementation;
|
implementation = instance.getLanguageByExtension(properties.getProperty(EXTENSION));
|
||||||
try {
|
} else {
|
||||||
implementation = this.dynamicLanguageImplementationLoad(this.languageConventionSyntax(language));
|
implementation = instance.languages.get(instance.languageAliases(language).toLowerCase());
|
||||||
if ( implementation == null )
|
|
||||||
{
|
|
||||||
// if it failed, we look for a parser following this syntax 'CPPLanguage'
|
|
||||||
implementation = this.dynamicLanguageImplementationLoad(language.toUpperCase());
|
|
||||||
//TODO: Should we try to break the coupling with PACKAGE by try to load the class
|
|
||||||
// based on her sole name ?
|
|
||||||
if ( implementation == null )
|
|
||||||
{
|
|
||||||
// No proper implementation
|
|
||||||
// FIXME: We should log a warning, shouldn't we ?
|
|
||||||
return new AnyLanguage(language);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return implementation;
|
|
||||||
} catch (InstantiationException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
return null;
|
if (implementation == null) {
|
||||||
|
// No proper implementation
|
||||||
|
// FIXME: We should log a warning, shouldn't we ?
|
||||||
|
implementation = new AnyLanguage(language);
|
||||||
|
}
|
||||||
|
implementation.setProperties(properties);
|
||||||
|
return implementation;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String languageAliases(String language)
|
private String languageAliases(String language)
|
||||||
@ -63,32 +59,18 @@ public class LanguageFactory {
|
|||||||
}
|
}
|
||||||
return language;
|
return language;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Language getLanguageByExtension(String extension) {
|
||||||
|
Language result = null;
|
||||||
|
File dir = new File(".");
|
||||||
|
String filename = "file." + extension;
|
||||||
|
|
||||||
private Language dynamicLanguageImplementationLoad(String language) throws InstantiationException, IllegalAccessException
|
for (Language language : languages.values()) {
|
||||||
{
|
if (language.getFileFilter().accept(dir, filename)) {
|
||||||
try {
|
result = language;
|
||||||
return (Language) this.getClass().getClassLoader().loadClass(
|
break;
|
||||||
PACKAGE + language + SUFFIX).newInstance();
|
}
|
||||||
} catch (ClassNotFoundException e) {
|
}
|
||||||
// No class found, returning default implementation
|
return result;
|
||||||
// FIXME: There should be somekind of log of this
|
}
|
||||||
return null;
|
|
||||||
} catch (NoClassDefFoundError e) {
|
|
||||||
// Windows is case insensitive, so it may find the file, even though
|
|
||||||
// the name has a different case. Since Java is case sensitive, it
|
|
||||||
// will not accept the classname inside the file that was found and
|
|
||||||
// will throw a NoClassDefFoundError
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This method does simply this:
|
|
||||||
* ruby -> Ruby
|
|
||||||
* fortran -> Fortran
|
|
||||||
* ...
|
|
||||||
*/
|
|
||||||
private String languageConventionSyntax(String language) {
|
|
||||||
return Character.toUpperCase(language.charAt(0)) + language.substring(1, language.length()).toLowerCase();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -7,9 +7,9 @@ package net.sourceforge.pmd.cpd;
|
|||||||
* Sample language for testing LanguageFactory.
|
* Sample language for testing LanguageFactory.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class CpddummyLanguage extends AnyLanguage {
|
public class CpddummyLanguage extends AbstractLanguage {
|
||||||
|
|
||||||
public CpddummyLanguage() {
|
public CpddummyLanguage() {
|
||||||
super("dummy");
|
super("Cpddummy", new AnyTokenizer(), "dummy");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,8 +10,7 @@ public class LanguageFactoryTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSimple() {
|
public void testSimple() {
|
||||||
LanguageFactory f = new LanguageFactory();
|
assertTrue(LanguageFactory.createLanguage("Cpddummy") instanceof CpddummyLanguage);
|
||||||
assertTrue(f.createLanguage("Cpddummy") instanceof CpddummyLanguage);
|
assertTrue(LanguageFactory.createLanguage("not_existing_language") instanceof AnyLanguage);
|
||||||
assertTrue(f.createLanguage("not_existing_language") instanceof AnyLanguage);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
net.sourceforge.pmd.cpd.CpddummyLanguage
|
@ -5,6 +5,6 @@ package net.sourceforge.pmd.cpd;
|
|||||||
|
|
||||||
public class CPPLanguage extends AbstractLanguage {
|
public class CPPLanguage extends AbstractLanguage {
|
||||||
public CPPLanguage() {
|
public CPPLanguage() {
|
||||||
super(new CPPTokenizer(), ".h", ".hpp", ".hxx",".c", ".cpp", ".cxx", ".cc", ".C");
|
super("cpp", new CPPTokenizer(), ".h", ".hpp", ".hxx",".c", ".cpp", ".cxx", ".cc", ".C");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
net.sourceforge.pmd.cpd.CPPLanguage
|
@ -5,6 +5,6 @@ package net.sourceforge.pmd.cpd;
|
|||||||
|
|
||||||
public class CsLanguage extends AbstractLanguage {
|
public class CsLanguage extends AbstractLanguage {
|
||||||
public CsLanguage() {
|
public CsLanguage() {
|
||||||
super(new CsTokenizer(), ".cs");
|
super("cs", new CsTokenizer(), ".cs");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
net.sourceforge.pmd.cpd.CsLanguage
|
@ -9,6 +9,6 @@ package net.sourceforge.pmd.cpd;
|
|||||||
*/
|
*/
|
||||||
public class FortranLanguage extends AbstractLanguage {
|
public class FortranLanguage extends AbstractLanguage {
|
||||||
public FortranLanguage() {
|
public FortranLanguage() {
|
||||||
super(new FortranTokenizer(), ".for", ".f", ".f66", ".f77", ".f90");
|
super("fortran", new FortranTokenizer(), ".for", ".f", ".f66", ".f77", ".f90");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
net.sourceforge.pmd.cpd.FortranLanguage
|
@ -11,7 +11,7 @@ public class JavaLanguage extends AbstractLanguage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public JavaLanguage(Properties properties) {
|
public JavaLanguage(Properties properties) {
|
||||||
super(new JavaTokenizer(), ".java");
|
super("java", new JavaTokenizer(), ".java");
|
||||||
setProperties(properties);
|
setProperties(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
net.sourceforge.pmd.cpd.JavaLanguage
|
@ -9,6 +9,6 @@ package net.sourceforge.pmd.cpd;
|
|||||||
*/
|
*/
|
||||||
public class EcmascriptLanguage extends AbstractLanguage {
|
public class EcmascriptLanguage extends AbstractLanguage {
|
||||||
public EcmascriptLanguage() {
|
public EcmascriptLanguage() {
|
||||||
super(new EcmascriptTokenizer(), ".js");
|
super("ecmascript", new EcmascriptTokenizer(), ".js");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
net.sourceforge.pmd.cpd.EcmascriptLanguage
|
@ -5,6 +5,6 @@ package net.sourceforge.pmd.cpd;
|
|||||||
|
|
||||||
public class JSPLanguage extends AbstractLanguage {
|
public class JSPLanguage extends AbstractLanguage {
|
||||||
public JSPLanguage() {
|
public JSPLanguage() {
|
||||||
super(new JSPTokenizer(), ".jsp", ".jspx");
|
super("jsp", new JSPTokenizer(), ".jsp", ".jspx");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
net.sourceforge.pmd.cpd.JSPLanguage
|
@ -5,6 +5,6 @@ package net.sourceforge.pmd.cpd;
|
|||||||
|
|
||||||
public class PHPLanguage extends AbstractLanguage {
|
public class PHPLanguage extends AbstractLanguage {
|
||||||
public PHPLanguage() {
|
public PHPLanguage() {
|
||||||
super(new PHPTokenizer(), ".php", ".class");
|
super("php", new PHPTokenizer(), ".php", ".class");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
net.sourceforge.pmd.cpd.PHPLanguage
|
@ -11,7 +11,7 @@ import java.util.Properties;
|
|||||||
*/
|
*/
|
||||||
public class PLSQLLanguage extends AbstractLanguage {
|
public class PLSQLLanguage extends AbstractLanguage {
|
||||||
public PLSQLLanguage() {
|
public PLSQLLanguage() {
|
||||||
super(new PLSQLTokenizer()
|
super("plsql", new PLSQLTokenizer()
|
||||||
,".sql"
|
,".sql"
|
||||||
,".trg" //Triggers
|
,".trg" //Triggers
|
||||||
,".prc",".fnc" // Standalone Procedures and Functions
|
,".prc",".fnc" // Standalone Procedures and Functions
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
net.sourceforge.pmd.cpd.PLSQLLanguage
|
@ -9,6 +9,6 @@ package net.sourceforge.pmd.cpd;
|
|||||||
*/
|
*/
|
||||||
public class RubyLanguage extends AbstractLanguage {
|
public class RubyLanguage extends AbstractLanguage {
|
||||||
public RubyLanguage() {
|
public RubyLanguage() {
|
||||||
super(new RubyTokenizer(), ".rb", ".cgi", ".class");
|
super("ruby", new RubyTokenizer(), ".rb", ".cgi", ".class");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
net.sourceforge.pmd.cpd.RubyLanguage
|
Reference in New Issue
Block a user