1. pmd -> 6.15.0
2. idea min version 2016.1
3. jdk min version 1.8
This commit is contained in:
caikang.ck
2019-06-12 14:56:03 +08:00
parent 8c25cddcda
commit fdfc82f1dc
123 changed files with 2362 additions and 1083 deletions

View File

@@ -2,7 +2,7 @@
<feature
id="com.alibaba.smartfox.eclipse.feature"
label="%feature.label"
version="1.0.6.qualifier"
version="2.0.0.qualifier"
provider-name="%feature.provider_name"
plugin="com.alibaba.smartfox.eclipse.plugin"
image="smartfox.png">

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>com.alibaba.smartfox.eclipse</groupId>
<artifactId>smartfox-eclipse</artifactId>
<version>1.0.6-SNAPSHOT</version>
<version>2.0.0-SNAPSHOT</version>
</parent>
<artifactId>com.alibaba.smartfox.eclipse.feature</artifactId>
<packaging>eclipse-feature</packaging>

View File

@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: com.alibaba.smartfox.eclipse.plugin
Bundle-SymbolicName: com.alibaba.smartfox.eclipse.plugin;singleton:=true
Bundle-Version: 1.0.6.qualifier
Bundle-Version: 2.0.0.qualifier
Bundle-Activator: com.alibaba.smartfox.eclipse.SmartfoxActivator
Bundle-Vendor: Alibaba
Require-Bundle: org.eclipse.ui,
@@ -22,7 +22,7 @@ Require-Bundle: org.eclipse.ui,
org.eclipse.equinox.p2.metadata.repository,
org.eclipse.equinox.p2.ui,
org.eclipse.equinox.p2.metadata
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Bundle-ActivationPolicy: lazy
Bundle-ClassPath: target/lib/antlr-runtime.jar,
target/lib/antlr4-runtime.jar,
@@ -51,6 +51,7 @@ Bundle-Localization: plugin
Export-Package: com.alibaba.smartfox.eclipse,
com.alibaba.smartfox.eclipse.handler,
com.alibaba.smartfox.eclipse.job,
com.alibaba.smartfox.eclipse.marker,
com.alibaba.smartfox.eclipse.pmd,
com.alibaba.smartfox.eclipse.pmd.rule,
com.alibaba.smartfox.eclipse.ui,

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>com.alibaba.smartfox.eclipse</groupId>
<artifactId>smartfox-eclipse</artifactId>
<version>1.0.6-SNAPSHOT</version>
<version>2.0.0-SNAPSHOT</version>
</parent>
<artifactId>com.alibaba.smartfox.eclipse.plugin</artifactId>
<packaging>eclipse-plugin</packaging>
@@ -22,11 +22,11 @@
<dependency>
<groupId>com.alibaba.p3c</groupId>
<artifactId>p3c-pmd</artifactId>
<version>1.3.5</version>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
@@ -63,7 +63,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.7</version>
<version>3.1.1</version>
<configuration>
<stripVersion>true</stripVersion>
<prependGroupId>false</prependGroupId>

View File

@@ -104,7 +104,7 @@ object CodeAnalysis {
private fun processFile(file: IFile): List<RuleViolation> {
val configuration = PMDConfiguration()
configuration.sourceEncoding = file.charset ?: Charsets.UTF_8.name()
configuration.setSourceEncoding(file.charset ?: Charsets.UTF_8.name())
configuration.inputPaths = file.fullPath.toPortableString()
val ctx = RuleContext()
ctx.setAttribute("eclipseFile", file)
@@ -120,7 +120,7 @@ object CodeAnalysis {
}
} catch (pmde: PMDException) {
log.debug("Error while processing file: " + niceFileName, pmde.cause)
report.addError(Report.ProcessingError(pmde.message, niceFileName))
report.addError(Report.ProcessingError(pmde, niceFileName))
} catch (ioe: IOException) {
log.error("Unable to read source file: " + niceFileName, ioe)
} catch (re: RuntimeException) {

View File

@@ -78,9 +78,9 @@ abstract class AbstractEclipseRule : AbstractJavaRule() {
return data
}
override fun setDescription(description: String) {
override fun setDescription(description: String?) {
try {
super.setDescription(P3cBundle.getMessage(description))
super.setDescription(P3cBundle.getMessage(description ?: ""))
} catch (e: MissingResourceException) {
super.setMessage(description)
}

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>com.alibaba.smartfox.eclipse</groupId>
<artifactId>smartfox-eclipse</artifactId>
<version>1.0.6-SNAPSHOT</version>
<version>2.0.0-SNAPSHOT</version>
</parent>
<artifactId>com.alibaba.smartfox.eclipse.updatesite</artifactId>
<packaging>eclipse-repository</packaging>

View File

@@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.alibaba.smartfox.eclipse</groupId>
<artifactId>smartfox-eclipse</artifactId>
<version>1.0.6-SNAPSHOT</version>
<version>2.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<inceptionYear>2017</inceptionYear>
<properties>
@@ -14,7 +14,7 @@
<eclipse-repo.url>http://download.eclipse.org/releases/neon</eclipse-repo.url>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<ajdt-eclipse-repo.url>http://download.eclipse.org/tools/ajdt/46/dev/update</ajdt-eclipse-repo.url>
<kotlin.version>1.2.21</kotlin.version>
<kotlin.version>1.3.30</kotlin.version>
<eclipse-release>juno</eclipse-release>
</properties>
<modules>
@@ -34,7 +34,7 @@
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
<version>${kotlin.version}</version>
<scope>compile</scope>
</dependency>
@@ -113,7 +113,7 @@
<artifactId>tycho-compiler-plugin</artifactId>
<version>${tycho.version}</version>
<configuration>
<compilerVersion>1.7</compilerVersion>
<compilerVersion>1.8</compilerVersion>
<compilerArguments>
<inlineJSR/>
<enableJavadoc/>

View File

@@ -20,7 +20,7 @@ allprojects {
apply plugin: 'kotlin'
apply plugin: 'maven-publish'
sourceCompatibility = 1.7
sourceCompatibility = 1.8
compileJava.options.encoding = 'UTF-8'
configurations.all {
resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
@@ -31,7 +31,7 @@ allprojects {
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
testCompile group: 'junit', name: 'junit', version: '4.11'
}
}

View File

@@ -1,9 +1,8 @@
kotlin_version=1.2.21
kotlin_version=1.3.30
#idea_version=171.3780.15
idea_version=14.1.7
idea_version=145.258.11
plugin_name=Alibaba Java Coding Guidelines
pmd_version=5.5.2
gradle_jetbrains_version=0.2.13
gradle_jetbrains_version=0.4.5
systemProp.file.encoding=UTF-8
plugin_version=1.0.6
plugin_version=2.0.0

View File

@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-bin.zip

View File

@@ -1,5 +1,5 @@
plugins {
id "org.jetbrains.intellij" version '0.2.17'
id "org.jetbrains.intellij" version '0.4.5'
}
apply plugin: 'kotlin'
apply plugin: 'idea'
@@ -32,13 +32,13 @@ intellij {
updateSinceUntilBuild false
sandboxDirectory "$project.buildDir/idea-sandbox/$idea_version"
}
version '1.0.6'
version '2.0.0'
ext.isReleaseVersion = !version.endsWith("SNAPSHOT")
dependencies {
compile group: 'org.freemarker', name: 'freemarker', version: '2.3.25-incubating'
compile 'com.alibaba.p3c:p3c-pmd:1.3.6'
compile 'com.alibaba.p3c:p3c-pmd:2.0.0'
compile group: 'org.javassist', name: 'javassist', version: '3.21.0-GA'
}

View File

@@ -21,7 +21,7 @@ import com.alibaba.p3c.idea.ep.InspectionActionExtensionPoint
import com.alibaba.p3c.idea.i18n.P3cBundle
import com.alibaba.p3c.idea.inspection.AliBaseInspection
import com.alibaba.p3c.idea.util.NumberConstants
import com.beust.jcommander.internal.Lists
import com.google.common.collect.Lists
import com.intellij.analysis.AnalysisScope
import com.intellij.analysis.AnalysisUIOptions
import com.intellij.analysis.BaseAnalysisActionDialog

View File

@@ -45,8 +45,8 @@ class ToggleProjectInspectionAction : AnAction() {
smartFoxConfig.projectInspectionClosed = !smartFoxConfig.projectInspectionClosed
}
override fun update(e: AnActionEvent?) {
val project = e!!.project ?: return
override fun update(e: AnActionEvent) {
val project = e.project ?: return
val smartFoxConfig = ServiceManager.getService(project, SmartFoxProjectConfig::class.java)
e.presentation.text = if (smartFoxConfig.projectInspectionClosed) {
e.presentation.icon = P3cIcons.PROJECT_INSPECTION_ON

View File

@@ -18,7 +18,6 @@ package com.alibaba.p3c.idea.config
import com.intellij.openapi.components.PersistentStateComponent
import com.intellij.openapi.components.State
import com.intellij.openapi.components.Storage
import com.intellij.openapi.components.StoragePathMacros
import com.intellij.util.xmlb.XmlSerializerUtil
import java.util.Locale
@@ -28,7 +27,7 @@ import java.util.Locale
* @author caikang
* @date 2017/06/19
*/
@State(name = "P3cConfig", storages = arrayOf(Storage(file = "${StoragePathMacros.APP_CONFIG}/smartfox/p3c.xml")))
@State(name = "P3cConfig", storages = [Storage(file = "smartfox/p3c.xml")])
class P3cConfig : PersistentStateComponent<P3cConfig> {
var astCacheTime = 1000L
var astCacheEnable = true
@@ -58,14 +57,10 @@ class P3cConfig : PersistentStateComponent<P3cConfig> {
return this
}
override fun loadState(state: P3cConfig?) {
if (state == null) {
return
}
override fun loadState(state: P3cConfig) {
XmlSerializerUtil.copyBean(state, this)
}
companion object {
val localeEn = Locale.ENGLISH.language!!
val localeZh = Locale.CHINESE.language!!

View File

@@ -15,10 +15,8 @@
*/
package com.alibaba.p3c.idea.config
import com.google.common.collect.Sets
import com.intellij.openapi.components.PersistentStateComponent
import com.intellij.openapi.components.State
import com.intellij.openapi.components.StoragePathMacros
import com.intellij.util.xmlb.XmlSerializerUtil
/**
@@ -27,22 +25,15 @@ import com.intellij.util.xmlb.XmlSerializerUtil
* @author caikang
* @date 2017/03/01
*/
@State(name = "SmartFoxProjectConfig",
storages = arrayOf(com.intellij.openapi.components.Storage(
file = "${StoragePathMacros.PROJECT_CONFIG_DIR}/smartfox_info.xml")))
@State(name = "SmartFoxProjectConfig", storages = [com.intellij.openapi.components.Storage(file = "smartfox_info.xml")])
class SmartFoxProjectConfig : PersistentStateComponent<SmartFoxProjectConfig> {
var inspectionProfileModifiedSet = Sets.newHashSet<String>()!!
var projectInspectionClosed = false
override fun getState(): SmartFoxProjectConfig? {
return this
}
override fun loadState(state: SmartFoxProjectConfig?) {
if (state == null) {
return
}
override fun loadState(state: SmartFoxProjectConfig) {
XmlSerializerUtil.copyBean(state, this)
}
}

View File

@@ -46,7 +46,7 @@ class AliPmdInspectionInvoker(
private val manager: InspectionManager,
private val rule: Rule
) {
val logger = Logger.getInstance(javaClass)
private val logger = Logger.getInstance(javaClass)
private var violations: List<RuleViolation> = emptyList()

View File

@@ -88,13 +88,13 @@ class AliDeprecationInspection : DeprecationInspection, AliBaseInspection {
holder.manager, holder.file, onTheFly) {
override fun registerProblem(psiElement: PsiElement,
@Nls(capitalization = Nls.Capitalization.Sentence) descriptionTemplate: String,
@Nls descriptionTemplate: String,
fixes: Array<LocalQuickFix>?) {
holder.registerProblem(psiElement, getMessage(descriptionTemplate), *(fixes ?: emptyArray()))
}
override fun registerProblem(psiElement: PsiElement,
@Nls(capitalization = Nls.Capitalization.Sentence) descriptionTemplate: String,
@Nls descriptionTemplate: String,
highlightType: ProblemHighlightType, fixes: Array<LocalQuickFix>?) {
holder.registerProblem(psiElement, getMessage(descriptionTemplate), highlightType, *(fixes ?: emptyArray()))
}

View File

@@ -15,12 +15,12 @@
*/
package com.alibaba.p3c.idea.inspection.standalone
import com.alibaba.p3c.idea.util.NumberConstants
import com.alibaba.p3c.idea.util.ObjectConstants
import com.alibaba.p3c.idea.i18n.P3cBundle
import com.alibaba.p3c.idea.inspection.AliBaseInspection
import com.alibaba.p3c.idea.util.HighlightDisplayLevels
import com.beust.jcommander.internal.Sets
import com.alibaba.p3c.idea.util.NumberConstants
import com.alibaba.p3c.idea.util.ObjectConstants
import com.google.common.collect.Sets
import com.intellij.codeHighlighting.HighlightDisplayLevel
import com.intellij.ide.highlighter.JavaFileType
import com.intellij.psi.CommonClassNames

View File

@@ -25,11 +25,11 @@ import net.sourceforge.pmd.PMDException
import net.sourceforge.pmd.Report
import net.sourceforge.pmd.Rule
import net.sourceforge.pmd.RuleContext
import net.sourceforge.pmd.RuleSet
import net.sourceforge.pmd.RuleSetFactory
import net.sourceforge.pmd.RuleSets
import net.sourceforge.pmd.RuleViolation
import net.sourceforge.pmd.RulesetsFactoryUtils
import net.sourceforge.pmd.util.ResourceLoader
import java.io.IOException
import java.io.StringReader
@@ -42,38 +42,39 @@ class AliPmdProcessor(val rule: Rule) {
private val configuration = PMDConfiguration()
init {
ruleSetFactory = RulesetsFactoryUtils.getRulesetFactory(configuration)
ruleSetFactory = RulesetsFactoryUtils.getRulesetFactory(configuration, ResourceLoader())
}
fun processFile(psiFile: PsiFile): List<RuleViolation> {
configuration.sourceEncoding = psiFile.virtualFile.charset.name()
configuration.setSourceEncoding(psiFile.virtualFile.charset.name())
configuration.inputPaths = psiFile.virtualFile.canonicalPath
val document = FileDocumentManager.getInstance().getDocument(psiFile.virtualFile) ?: return emptyList()
if (document.lineCount > 10000) {
return emptyList()
}
val ctx = RuleContext()
val processor = SourceCodeProcessor(configuration)
val niceFileName = psiFile.virtualFile.canonicalPath!!
val report = Report.createReport(ctx, niceFileName)
val ruleSets = RuleSets()
val ruleSet = RuleSet()
ruleSet.addRule(rule)
val ruleSet = ruleSetFactory.createSingleRuleRuleSet(rule)
ruleSets.addRuleSet(ruleSet)
LOG.debug("Processing " + ctx.sourceCodeFilename)
ruleSets.start(ctx)
try {
ctx.languageVersion = null
processor.processSourceCode(StringReader(document.text), ruleSets, ctx)
} catch (pmde: PMDException) {
LOG.debug("Error while processing file: " + niceFileName, pmde.cause)
report.addError(Report.ProcessingError(pmde.message, niceFileName))
LOG.debug("Error while processing file: $niceFileName", pmde.cause)
report.addError(Report.ProcessingError(pmde, niceFileName))
} catch (ioe: IOException) {
LOG.error("Unable to read source file: " + niceFileName, ioe)
LOG.error("Unable to read source file: $niceFileName", ioe)
} catch (re: RuntimeException) {
val root = Throwables.getRootCause(re)
if (root !is ApplicationUtil.CannotRunReadActionException) {
LOG.error("RuntimeException while processing file: " + niceFileName, re)
LOG.error("RuntimeException while processing file: $niceFileName", re)
}
}
ruleSets.end(ctx)
return ctx.report.toList()
}

View File

@@ -7,40 +7,71 @@ import com.alibaba.p3c.idea.config.P3cConfig
import com.google.common.cache.Cache
import com.google.common.cache.CacheBuilder
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.diagnostic.Logger
import net.sourceforge.pmd.PMD
import net.sourceforge.pmd.PMDConfiguration
import net.sourceforge.pmd.PMDException
import net.sourceforge.pmd.RuleContext
import net.sourceforge.pmd.RuleSets
import net.sourceforge.pmd.benchmark.Benchmark
import net.sourceforge.pmd.benchmark.Benchmarker
import net.sourceforge.pmd.benchmark.TimeTracker
import net.sourceforge.pmd.benchmark.TimedOperationCategory
import net.sourceforge.pmd.lang.Language
import net.sourceforge.pmd.lang.LanguageVersion
import net.sourceforge.pmd.lang.LanguageVersionHandler
import net.sourceforge.pmd.lang.Parser
import net.sourceforge.pmd.lang.ast.Node
import net.sourceforge.pmd.lang.ast.ParseException
import net.sourceforge.pmd.lang.xpath.Initializer
import org.apache.commons.io.IOUtils
import java.io.IOException
import java.io.InputStream
import java.io.InputStreamReader
import java.io.Reader
import java.util.concurrent.TimeUnit
class SourceCodeProcessor(private val configuration: PMDConfiguration) {
val logger = Logger.getInstance(javaClass)
/**
* Processes the input stream against a rule set using the given input encoding.
* If the LanguageVersion is `null` on the RuleContext, it will
* be automatically determined. Any code which wishes to process files for
* different Languages, will need to be sure to either properly set the
* Language on the RuleContext, or set it to `null` first.
* Processes the input stream against a rule set using the given input
* encoding.
*
* @param sourceCode
* The InputStream to analyze.
* @param ruleSets
* The collection of rules to process against the file.
* @param ctx
* The context in which PMD is operating.
* @throws PMDException
* if the input encoding is unsupported, the input stream could
* not be parsed, or other error is encountered.
* @see .processSourceCode
*/
@Throws(PMDException::class)
fun processSourceCode(sourceCode: InputStream, ruleSets: RuleSets, ctx: RuleContext) {
try {
InputStreamReader(sourceCode, configuration.sourceEncoding).use { streamReader -> processSourceCode(streamReader, ruleSets, ctx) }
} catch (e: IOException) {
throw PMDException("IO exception: " + e.message, e)
}
}
/**
* Processes the input stream against a rule set using the given input
* encoding. If the LanguageVersion is `null` on the RuleContext,
* it will be automatically determined. Any code which wishes to process
* files for different Languages, will need to be sure to either properly
* set the Language on the RuleContext, or set it to `null`
* first.
*
* @see RuleContext.setLanguageVersion
* @see PMDConfiguration.getLanguageVersionOfFile
* @param sourceCode The Reader to analyze.
* @param ruleSets The collection of rules to process against the file.
* @param ctx The context in which PMD is operating.
* @throws PMDException if the input encoding is unsupported, the input stream could
* @param sourceCode
* The Reader to analyze.
* @param ruleSets
* The collection of rules to process against the file.
* @param ctx
* The context in which PMD is operating.
* @throws PMDException
* if the input encoding is unsupported, the input stream could
* not be parsed, or other error is encountered.
*/
@Throws(PMDException::class)
@@ -49,61 +80,27 @@ class SourceCodeProcessor(private val configuration: PMDConfiguration) {
// make sure custom XPath functions are initialized
Initializer.initialize()
// Coarse check to see if any RuleSet applies to file, will need to do a finer RuleSet specific check later
try {
processSource(sourceCode, ruleSets, ctx)
try {
ruleSets.start(ctx)
processSource(sourceCode, ruleSets, ctx)
} catch (pe: ParseException) {
configuration.analysisCache.analysisFailed(ctx.sourceCodeFile)
throw PMDException("Error while parsing " + ctx.sourceCodeFilename, pe)
} catch (e: Exception) {
configuration.analysisCache.analysisFailed(ctx.sourceCodeFile)
throw PMDException("Error while processing " + ctx.sourceCodeFilename, e)
} catch (error: Error) {
throw PMDException("Error while processing ${ctx.sourceCodeFilename} ${error.message}")
} finally {
IOUtils.closeQuietly(sourceCode)
ruleSets.end(ctx)
}
}
private fun parse(ctx: RuleContext, sourceCode: Reader, parser: Parser): Node {
val start = System.nanoTime()
TimeTracker.startOperation(TimedOperationCategory.PARSER).use {
val rootNode = parser.parse(ctx.sourceCodeFilename, sourceCode)
ctx.report.suppress(parser.suppressMap)
val end = System.nanoTime()
Benchmarker.mark(Benchmark.Parser, end - start, 0)
return rootNode
}
private fun symbolFacade(rootNode: Node, languageVersionHandler: LanguageVersionHandler) {
val start = System.nanoTime()
languageVersionHandler.getSymbolFacade(configuration.classLoader).start(rootNode)
val end = System.nanoTime()
Benchmarker.mark(Benchmark.SymbolTable, end - start, 0)
}
private fun usesDFA(languageVersion: LanguageVersion, rootNode: Node, ruleSets: RuleSets) {
val start = System.nanoTime()
val dataFlowFacade = languageVersion.languageVersionHandler.dataFlowFacade
dataFlowFacade.start(rootNode)
val end = System.nanoTime()
Benchmarker.mark(Benchmark.DFA, end - start, 0)
}
private fun usesTypeResolution(languageVersion: LanguageVersion, rootNode: Node, ruleSets: RuleSets) {
if (ruleSets.usesTypeResolution(languageVersion.language)) {
val start = System.nanoTime()
languageVersion.languageVersionHandler.getTypeResolutionFacade(configuration.classLoader).start(rootNode)
val end = System.nanoTime()
Benchmarker.mark(Benchmark.TypeResolution, end - start, 0)
}
}
private fun processSource(sourceCode: Reader, ruleSets: RuleSets, ctx: RuleContext) {
val start = System.currentTimeMillis()
val acus = listOf(getRootNode(sourceCode, ruleSets, ctx))
logger.debug("elapsed ${System.currentTimeMillis() - start}ms to" +
" parse ast tree for file ${ctx.sourceCodeFilename}")
ruleSets.apply(acus, ctx, ctx.languageVersion.language)
}
private fun getRootNode(sourceCode: Reader, ruleSets: RuleSets, ctx: RuleContext): Node {
@@ -123,14 +120,79 @@ class SourceCodeProcessor(private val configuration: PMDConfiguration) {
val parser = PMD.parserFor(languageVersion, configuration)
val rootNode = parse(ctx, sourceCode, parser)
symbolFacade(rootNode, languageVersionHandler)
usesDFA(languageVersion, rootNode, ruleSets)
usesTypeResolution(languageVersion, rootNode, ruleSets)
val language = languageVersion.language
usesDFA(languageVersion, rootNode, ruleSets, language)
usesTypeResolution(languageVersion, rootNode, ruleSets, language)
nodeCache.put(ctx.sourceCodeFilename, rootNode)
return rootNode
}
private fun symbolFacade(rootNode: Node, languageVersionHandler: LanguageVersionHandler) {
TimeTracker.startOperation(TimedOperationCategory.SYMBOL_TABLE).use { to -> languageVersionHandler.getSymbolFacade(configuration.classLoader).start(rootNode) }
}
private fun resolveQualifiedNames(rootNode: Node, handler: LanguageVersionHandler) {
TimeTracker.startOperation(TimedOperationCategory.QUALIFIED_NAME_RESOLUTION).use { to -> handler.getQualifiedNameResolutionFacade(configuration.classLoader).start(rootNode) }
}
// private ParserOptions getParserOptions(final LanguageVersionHandler
// languageVersionHandler) {
// // TODO Handle Rules having different parser options.
// ParserOptions parserOptions =
// languageVersionHandler.getDefaultParserOptions();
// parserOptions.setSuppressMarker(configuration.getSuppressMarker());
// return parserOptions;
// }
private fun usesDFA(languageVersion: LanguageVersion, rootNode: Node, ruleSets: RuleSets, language: Language) {
if (ruleSets.usesDFA(language)) {
TimeTracker.startOperation(TimedOperationCategory.DFA).use { to ->
val dataFlowFacade = languageVersion.languageVersionHandler.dataFlowFacade
dataFlowFacade.start(rootNode)
}
}
}
private fun usesTypeResolution(languageVersion: LanguageVersion, rootNode: Node, ruleSets: RuleSets,
language: Language) {
if (ruleSets.usesTypeResolution(language)) {
TimeTracker.startOperation(TimedOperationCategory.TYPE_RESOLUTION).use { to ->
languageVersion.languageVersionHandler.getTypeResolutionFacade(configuration.classLoader)
.start(rootNode)
}
}
}
private fun usesMultifile(rootNode: Node, languageVersionHandler: LanguageVersionHandler, ruleSets: RuleSets,
language: Language) {
if (ruleSets.usesMultifile(language)) {
TimeTracker.startOperation(TimedOperationCategory.MULTIFILE_ANALYSIS).use { to -> languageVersionHandler.multifileFacade.start(rootNode) }
}
}
private fun processSource(sourceCode: Reader, ruleSets: RuleSets, ctx: RuleContext) {
val languageVersion = ctx.languageVersion
val languageVersionHandler = languageVersion.languageVersionHandler
val rootNode = getRootNode(sourceCode, ruleSets, ctx)
resolveQualifiedNames(rootNode, languageVersionHandler)
symbolFacade(rootNode, languageVersionHandler)
val language = languageVersion.language
usesDFA(languageVersion, rootNode, ruleSets, language)
usesTypeResolution(languageVersion, rootNode, ruleSets, language)
usesMultifile(rootNode, languageVersionHandler, ruleSets, language)
val acus = listOf(rootNode)
ruleSets.apply(acus, ctx, language)
}
private fun determineLanguage(ctx: RuleContext) {
// If LanguageVersion of the source file is not known, make a determination
// If LanguageVersion of the source file is not known, make a
// determination
if (ctx.languageVersion == null) {
val languageVersion = configuration.getLanguageVersionOfFile(ctx.sourceCodeFilename)
ctx.languageVersion = languageVersion

View File

@@ -1,51 +0,0 @@
/*
* Copyright 1999-2017 Alibaba Group.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.p3c.idea.pmd.index
import com.beust.jcommander.internal.Lists
import com.intellij.util.indexing.FileContent
import net.sourceforge.pmd.PMD
import net.sourceforge.pmd.PMDConfiguration
import net.sourceforge.pmd.RuleContext
import net.sourceforge.pmd.RuleSetFactory
import net.sourceforge.pmd.RuleViolation
import net.sourceforge.pmd.RulesetsFactoryUtils
import net.sourceforge.pmd.renderers.Renderer
import net.sourceforge.pmd.util.datasource.DataSource
/**
* @author caikang
* @date 2016/12/11
*/
class AliPmdProcessor {
private val ruleSetFactory: RuleSetFactory
private val configuration = PMDConfiguration()
init {
configuration.ruleSets = "java-ali-pmd,vm-ali-other"
configuration.threads = 0
ruleSetFactory = RulesetsFactoryUtils.getRulesetFactory(configuration)
}
fun processFile(fileContent: FileContent): List<RuleViolation> {
val renderer = InspectionRenderer()
val dataSources = Lists.newArrayList<DataSource>()
dataSources.add(InspectionDataSource(fileContent))
PMD.processFiles(configuration, ruleSetFactory, dataSources, RuleContext(),
listOf<Renderer>(renderer))
return renderer.getViolations()
}
}

View File

@@ -16,7 +16,6 @@
package com.alibaba.p3c.idea.quickfix
import com.alibaba.p3c.idea.i18n.P3cBundle
import com.google.common.base.Joiner
import com.google.common.base.Splitter
import com.intellij.codeInspection.ProblemDescriptor
import com.intellij.openapi.project.Project
@@ -46,16 +45,13 @@ object LowerCamelCaseVariableNamingQuickFix : AliQuickFix {
}
private fun toLowerCamelCase(identifier: String): String {
val list = Splitter.onPattern("[^a-z0-9A-Z]+").trimResults().omitEmptyStrings().splitToList(identifier)
val list = Splitter.onPattern("[^a-z0-9A-Z]+").trimResults()
.omitEmptyStrings().split(identifier).toList()
val result = list.mapIndexed { i, s ->
if (i == 0) {
s.toLowerCase()
} else {
val charArray = s.toLowerCase().toCharArray()
charArray[0] = charArray[0].toUpperCase()
val charArray = s.toCharArray()
charArray[0] = if (i == 0) charArray[0].toLowerCase() else charArray[0].toUpperCase()
String(charArray)
}
}
return Joiner.on("").join(result)
return result.joinToString("")
}
}

View File

@@ -1,5 +1,5 @@
plugins {
id "org.jetbrains.intellij" version '0.2.17'
id "org.jetbrains.intellij" version '0.4.5'
}
apply plugin: 'kotlin'
apply plugin: 'idea'
@@ -16,7 +16,6 @@ version plugin_version
dependencies {
compile group: 'org.freemarker', name: 'freemarker', version: '2.3.25-incubating'
//compile 'com.alibaba.p3c.idea:p3c-common:1.0.0'
compile project(':p3c-common')
compile group: 'org.javassist', name: 'javassist', version: '3.21.0-GA'
}

View File

@@ -5,6 +5,17 @@
<change-notes>
<![CDATA[
<ul>
2.0.0
<li>supported min idea version 2016.1(145.258.11)</li>
<li>supported min jdk version 1.8</li>
<li>fix persistent compatibility issue</li>
<li>fix https://github.com/alibaba/p3c/issues/430</li>
<li>fix https://github.com/alibaba/p3c/issues/454</li>
<li>fix https://github.com/alibaba/p3c/issues/409</li>
<li>add rule To judge the equivalence of floating-point numbers.</li>
<li>add annotation process for rule ClassMustHaveAuthorRule</li>
</ul>
<ul>1.0.6
<li>fix <a href="https://github.com/alibaba/p3c/issues/337">https://github.com/alibaba/p3c/issues/337</a> do not check annotation </li>
<li>PojoMustOverrideToStringRule do not check interface </li>
@@ -51,7 +62,7 @@
]]>
</change-notes>
<vendor>alibaba</vendor>
<version>1.0.0</version>
<version>2.0.0</version>
<idea-version since-build="141.0"/>
<depends optional="true">com.intellij.velocity</depends>
<depends optional="true" config-file="p3c.xml">com.intellij.modules.java</depends>

View File

@@ -1,22 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.sonatype.oss</groupId>
<artifactId>oss-parent</artifactId>
<version>9</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.alibaba.p3c</groupId>
<artifactId>p3c-pmd</artifactId>
<version>1.3.6</version>
<version>2.0.0</version>
<packaging>jar</packaging>
<name>p3c-pmd</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<pmd.version>5.5.2</pmd.version>
<pmd.version>6.15.0</pmd.version>
<maven.compiler.target>1.8</maven.compiler.target>
<annotation.version>1.3.2</annotation.version>
</properties>
<description>Alibaba Java Coding Guidelines PMD implementations</description>
<url>https://github.com/alibaba/p3c</url>
<inceptionYear>2017</inceptionYear>
@@ -70,8 +71,12 @@
<url>https://github.com/SeanCai</url>
<email>sean.caikang@gmail.com</email>
</developer>
<developer>
<name>MoYan</name>
<url>https://github.com/imu2008</url>
<email>panhuawenmail@gmail.com</email>
</developer>
</developers>
<dependencies>
<dependency>
<groupId>net.sourceforge.pmd</groupId>
@@ -89,19 +94,82 @@
<version>${pmd.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>${annotation.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<artifactId>maven-pmd-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<sourceEncoding>${project.build.sourceEncoding}</sourceEncoding>
<targetJdk>${maven.compiler.target}</targetJdk>
<printFailingErrors>true</printFailingErrors>
<rulesets>
<ruleset>rulesets/java/ali-comment.xml</ruleset>
<ruleset>rulesets/java/ali-concurrent.xml</ruleset>
<ruleset>rulesets/java/ali-constant.xml</ruleset>
<ruleset>rulesets/java/ali-exception.xml</ruleset>
<ruleset>rulesets/java/ali-flowcontrol.xml</ruleset>
<ruleset>rulesets/java/ali-naming.xml</ruleset>
<ruleset>rulesets/java/ali-oop.xml</ruleset>
<ruleset>rulesets/java/ali-orm.xml</ruleset>
<ruleset>rulesets/java/ali-other.xml</ruleset>
<ruleset>rulesets/java/ali-set.xml</ruleset>
</rulesets>
<excludes>
<exclude>**/FixClassTypeResolver.java</exclude>
</excludes>
</configuration>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>com.alibaba.p3c</groupId>
<artifactId>p3c-pmd</artifactId>
<version>2.0.0</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>${maven.compiler.target}</source>
<target>${maven.compiler.target}</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
@@ -122,7 +190,7 @@
</tags>
</configuration>
</plugin>
<plugin>
<!-- <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
@@ -135,7 +203,7 @@
</goals>
</execution>
</executions>
</plugin>
</plugin>-->
</plugins>
</build>
</project>

View File

@@ -58,7 +58,15 @@ public class I18nResources {
}
public static String getMessage(String key) {
if (key == null) {
// 暂时返回空字符串
return "";
}
try {
return resourceBundle.getString(key).trim();
} catch (MissingResourceException e) {
return key;
}
}
public static String getMessage(String key, Object... params) {
@@ -70,6 +78,10 @@ public class I18nResources {
}
public static String getMessageWithExceptionHandled(String key) {
if (key == null) {
// 暂时返回空字符串
return "";
}
try {
return resourceBundle.getString(key).trim();
} catch (MissingResourceException e) {

View File

@@ -18,7 +18,7 @@ package com.alibaba.p3c.pmd.lang.java.rule.comment;
import com.alibaba.p3c.pmd.I18nResources;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.rule.comments.AbstractCommentRule;
import net.sourceforge.pmd.lang.java.rule.documentation.AbstractCommentRule;
/**
* @author caikang

View File

@@ -15,11 +15,16 @@
*/
package com.alibaba.p3c.pmd.lang.java.rule.comment;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.regex.Pattern;
import com.alibaba.p3c.pmd.I18nResources;
import com.alibaba.p3c.pmd.lang.java.util.ViolationUtils;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.ast.ASTAnnotationTypeDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
import net.sourceforge.pmd.lang.java.ast.ASTEnumDeclaration;
@@ -39,21 +44,21 @@ public class ClassMustHaveAuthorRule extends AbstractAliCommentRule {
private static final String MESSAGE_KEY_PREFIX = "java.comment.ClassMustHaveAuthorRule.violation.msg";
/**
* Immediately return after visiting class/interface/enum/annotation,
* so that we don't need to deal with inner class/interface/enum/annotation declarations.
*
* @param decl
* @param data
* @return
*/
@Override
public Object visit(ASTClassOrInterfaceDeclaration decl, Object data) {
// Exclude nested classes
if (decl.isNested()) {
return super.visit(decl, data);
}
// Exclude inner classes
if (!decl.isPublic()) {
return super.visit(decl, data);
}
// If a CompilationUnit has multi class definition, only the public one will be checked.
if (decl.isPublic()) {
checkAuthorComment(decl, data);
return super.visit(decl, data);
}
return data;
}
@Override
@@ -70,8 +75,13 @@ public class ClassMustHaveAuthorRule extends AbstractAliCommentRule {
}
checkAuthorComment(decl, data);
return data;
}
return super.visit(decl, data);
@Override
public Object visit(ASTAnnotationTypeDeclaration decl, Object data) {
checkAuthorComment(decl, data);
return data;
}
@Override
@@ -81,6 +91,32 @@ public class ClassMustHaveAuthorRule extends AbstractAliCommentRule {
return super.visit(cUnit, data);
}
@Override
protected SortedMap<Integer, Node> orderedCommentsAndDeclarations(ASTCompilationUnit cUnit) {
SortedMap<Integer, Node> itemsByLineNumber = new TreeMap<>();
List<ASTClassOrInterfaceDeclaration> packageDecl = cUnit
.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class);
addDeclarations(itemsByLineNumber, packageDecl);
List<ASTEnumDeclaration> enumDecl = cUnit.findDescendantsOfType(ASTEnumDeclaration.class);
addDeclarations(itemsByLineNumber, enumDecl);
List<ASTAnnotationTypeDeclaration> annotationDecl = cUnit
.findDescendantsOfType(ASTAnnotationTypeDeclaration.class);
addDeclarations(itemsByLineNumber, annotationDecl);
addDeclarations(itemsByLineNumber, cUnit.getComments());
return itemsByLineNumber;
}
private void addDeclarations(SortedMap<Integer, Node> map, List<? extends Node> nodes) {
for (Node node : nodes) {
map.put((node.getBeginLine() << 16) + node.getBeginColumn(), node);
}
}
/**
* Check if node's comment contains author tag.
*

View File

@@ -25,6 +25,7 @@ import java.util.TreeMap;
import com.alibaba.p3c.pmd.I18nResources;
import com.alibaba.p3c.pmd.lang.java.rule.util.NodeSortUtils;
import com.alibaba.p3c.pmd.lang.java.util.VariableUtils;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.ast.ASTAnnotation;
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceBodyDeclaration;
@@ -56,27 +57,20 @@ public class CommentsMustBeJavadocFormatRule extends AbstractAliCommentRule {
@Override
public Object visit(final ASTClassOrInterfaceDeclaration decl, Object data) {
checkComment(decl, data, new MessageMaker() {
@Override
public String make() {
return I18nResources.getMessage(MESSAGE_KEY_PREFIX + ".class",
decl.getImage());
}
});
checkComment(decl, data, () -> I18nResources.getMessage(MESSAGE_KEY_PREFIX + ".class",
decl.getImage()));
return super.visit(decl, data);
}
@Override
public Object visit(final ASTConstructorDeclaration decl, Object data) {
checkComment(decl, data, new MessageMaker() {
@Override
public String make() {
checkComment(decl, data, () -> {
String constructorName = ((Token)decl.jjtGetFirstToken()).image;
if (decl.getParameters().getParameterCount() == 0) {
if (decl.getFormalParameters().getParameterCount() == 0) {
return I18nResources.getMessage(MESSAGE_KEY_PREFIX + ".constructor.default",
constructorName);
}
List<ASTFormalParameter> formalParameters = decl.getParameters()
List<ASTFormalParameter> formalParameters = decl.getFormalParameters()
.findChildrenOfType(ASTFormalParameter.class);
List<String> strings = new ArrayList<>(formalParameters.size());
@@ -88,44 +82,28 @@ public class CommentsMustBeJavadocFormatRule extends AbstractAliCommentRule {
.getMessage(MESSAGE_KEY_PREFIX + ".constructor.parameter",
constructorName,
StringUtils.join(strings, ","));
}
});
return super.visit(decl, data);
}
@Override
public Object visit(final ASTMethodDeclaration decl, Object data) {
checkComment(decl, data, new MessageMaker() {
@Override
public String make() {
return I18nResources.getMessage(MESSAGE_KEY_PREFIX + ".method",
decl.getMethodName());
}
});
checkComment(decl, data, () -> I18nResources.getMessage(MESSAGE_KEY_PREFIX + ".method",
decl.getMethodName()));
return super.visit(decl, data);
}
@Override
public Object visit(final ASTFieldDeclaration decl, Object data) {
checkComment(decl, data, new MessageMaker() {
@Override
public String make() {
return I18nResources.getMessage(MESSAGE_KEY_PREFIX + ".field",
decl.getVariableName());
}
});
checkComment(decl, data, () -> I18nResources.getMessage(MESSAGE_KEY_PREFIX + ".field",
VariableUtils.getVariableName(decl)));
return super.visit(decl, data);
}
@Override
public Object visit(final ASTEnumDeclaration decl, Object data) {
checkComment(decl, data, new MessageMaker() {
@Override
public String make() {
return I18nResources.getMessage(MESSAGE_KEY_PREFIX + ".enum",
decl.getImage());
}
});
checkComment(decl, data, () -> I18nResources.getMessage(MESSAGE_KEY_PREFIX + ".enum",
decl.getImage()));
return super.visit(decl, data);
}

View File

@@ -20,6 +20,8 @@ import java.util.Random;
import com.alibaba.p3c.pmd.lang.java.rule.AbstractAliRule;
import com.alibaba.p3c.pmd.lang.java.rule.util.NodeUtils;
import com.alibaba.p3c.pmd.lang.java.util.VariableUtils;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType;
@@ -67,7 +69,7 @@ public class AvoidConcurrentCompetitionRandomRule extends AbstractAliRule {
return super.visit(node, data);
}
for (ASTFieldDeclaration fieldDeclaration : fieldDeclarations) {
if (fieldDeclaration.getType() == Random.class
if (NodeUtils.getNodeType(fieldDeclaration) == Random.class
&& fieldDeclaration.isStatic()) {
checkRandom(fieldDeclaration, methodDeclarations, data);
}
@@ -101,7 +103,7 @@ public class AvoidConcurrentCompetitionRandomRule extends AbstractAliRule {
for (ASTMethodDeclaration methodDeclaration : methodDeclarations) {
try {
List<Node> nodes = methodDeclaration.findChildNodesWithXPath(String.format(XPATH_TPL,
fieldDeclaration.getVariableName()));
VariableUtils.getVariableName(fieldDeclaration)));
if (nodes == null || nodes.isEmpty()) {
continue;
}

View File

@@ -20,6 +20,7 @@ import java.util.concurrent.ThreadFactory;
import com.alibaba.p3c.pmd.lang.java.rule.AbstractAliRule;
import com.alibaba.p3c.pmd.lang.java.rule.util.NodeUtils;
import net.sourceforge.pmd.lang.java.ast.ASTAllocationExpression;
import net.sourceforge.pmd.lang.java.ast.ASTBlockStatement;
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
@@ -68,12 +69,12 @@ public class AvoidManuallyCreateThreadRule extends AbstractAliRule {
}
ASTFieldDeclaration fieldDeclaration = node.getFirstParentOfType(ASTFieldDeclaration.class);
//field declaration with thread allocated
if (fieldDeclaration != null && fieldDeclaration.getType() == Thread.class) {
if (fieldDeclaration != null && NodeUtils.getNodeType(fieldDeclaration) == Thread.class) {
return addViolationAndReturn(node, data);
}
//Declare thread factory field use lambda
if (node.getDataFlowNode() == null && node.getFirstParentOfType(ASTLambdaExpression.class) != null) {
if (fieldDeclaration == null || fieldDeclaration.getType() != ThreadFactory.class) {
if (fieldDeclaration == null || NodeUtils.getNodeType(fieldDeclaration) != ThreadFactory.class) {
return addViolationAndReturn(node, data);
}
return super.visit(node, data);

View File

@@ -19,6 +19,8 @@ import java.util.List;
import com.alibaba.p3c.pmd.I18nResources;
import com.alibaba.p3c.pmd.lang.java.rule.AbstractAliRule;
import com.alibaba.p3c.pmd.lang.java.rule.util.NodeUtils;
import com.alibaba.p3c.pmd.lang.java.util.VariableUtils;
import com.alibaba.p3c.pmd.lang.java.util.ViolationUtils;
import net.sourceforge.pmd.lang.ast.Node;
@@ -30,9 +32,9 @@ import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclarator;
import org.jaxen.JaxenException;
/**
* [Mandatory] Customized ThreadLocal variables must be recycled,
* especially when using thread pools in which threads are often reused.
* Otherwise, it may affect subsequent business logic and cause unexpected problems such as memory leak.
* [Mandatory] Customized ThreadLocal variables must be recycled, especially when using thread pools in which threads
* are often reused. Otherwise, it may affect subsequent business logic and cause unexpected problems such as memory
* leak.
*
* @author caikang
* @date 2017/03/29
@@ -52,7 +54,7 @@ public class ThreadLocalShouldRemoveRule extends AbstractAliRule {
return super.visit(node, data);
}
for (ASTFieldDeclaration fieldDeclaration : fieldDeclarations) {
if (fieldDeclaration.getType() == ThreadLocal.class) {
if (NodeUtils.getNodeType(fieldDeclaration) == ThreadLocal.class) {
if (checkThreadLocalWithInitalValue(fieldDeclaration)) { continue; }
checkThreadLocal(fieldDeclaration, node, data);
}
@@ -66,9 +68,11 @@ public class ThreadLocalShouldRemoveRule extends AbstractAliRule {
if (variableDeclarator == null) {
return false;
}
ASTMethodDeclarator initialValueMethod = variableDeclarator.getFirstDescendantOfType(ASTMethodDeclarator.class);
if (initialValueMethod != null && METHOD_INITIAL_VALUE.equals(initialValueMethod.getImage())) {
return true;
// ASTClassOrInterfaceBodyDeclaration.isFindBoundary=true使用getFirstDescendantOfType不能继续向方法内部查询
List<ASTMethodDeclarator> astMethodDeclaratorList = variableDeclarator.findDescendantsOfType(
ASTMethodDeclarator.class, true);
if (!astMethodDeclaratorList.isEmpty()) {
return METHOD_INITIAL_VALUE.equals(astMethodDeclaratorList.get(0).getImage());
}
ASTName name = variableDeclarator.getFirstDescendantOfType(ASTName.class);
return name != null && WITH_INITIAL.equals(name.getImage());
@@ -76,12 +80,13 @@ public class ThreadLocalShouldRemoveRule extends AbstractAliRule {
private void checkThreadLocal(ASTFieldDeclaration fieldDeclaration, ASTCompilationUnit node, Object data) {
try {
String variableName = VariableUtils.getVariableName(fieldDeclaration);
List<Node> nodes = node.findChildNodesWithXPath(String.format(XPATH_TPL,
fieldDeclaration.getVariableName()));
variableName));
if (nodes == null || nodes.isEmpty()) {
ViolationUtils.addViolationWithPrecisePosition(this, fieldDeclaration, data,
I18nResources.getMessage("java.concurrent.ThreadLocalShouldRemoveRule.violation.msg",
fieldDeclaration.getVariableName()));
variableName));
}
} catch (JaxenException ignore) {
}

View File

@@ -44,12 +44,14 @@ public class ThreadPoolCreationRule extends AbstractAliRule {
private static final String EXECUTORS_NEW = Executors.class.getSimpleName() + DOT + NEW;
private static final String FULL_EXECUTORS_NEW = Executors.class.getName() + DOT + NEW;
private static final String BRACKETS = "()";
private static final String NEW_SCHEDULED = "newScheduledThreadPool";
private static final String NEW_SINGLE_SCHEDULED = "newSingleThreadScheduledExecutor";
@Override
public Object visit(ASTCompilationUnit node, Object data) {
Object superResult = super.visit(node, data);
Info info = new Info();
List<ASTImportDeclaration> importDeclarations = node.findChildrenOfType(ASTImportDeclaration.class);
for (ASTImportDeclaration importDeclaration : importDeclarations) {
ASTName name = importDeclaration.getFirstChildOfType(ASTName.class);
@@ -75,6 +77,10 @@ public class ThreadPoolCreationRule extends AbstractAliRule {
private boolean checkInitStatement(Token token, Info info) {
String fullAssignStatement = getFullAssignStatement(token);
// do not check newScheduledThreadPool and newSingleThreadScheduledExecutor
if (NEW_SCHEDULED.equals(fullAssignStatement) || NEW_SINGLE_SCHEDULED.equals(fullAssignStatement)) {
return true;
}
if (fullAssignStatement.startsWith(EXECUTORS_NEW)) {
return false;
}

View File

@@ -29,6 +29,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTAllocationExpression;
import net.sourceforge.pmd.lang.java.ast.ASTArgumentList;
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTExpression;
import net.sourceforge.pmd.lang.java.ast.ASTFormalParameter;
import net.sourceforge.pmd.lang.java.ast.ASTFormalParameters;
import net.sourceforge.pmd.lang.java.ast.ASTLambdaExpression;
import net.sourceforge.pmd.lang.java.ast.ASTName;
import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId;
@@ -37,7 +39,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId;
* [Mandatory] A meaningful thread name is helpful to trace the error information,
* so assign a name when creating threads or thread pools.
*
* Detection rule //TODO should review
* Detection rule
* 1. Use specific constructor while create thread pool
* 2. Use Executors.defaultThreadFactory() is not allowed
*
@@ -78,6 +80,9 @@ public class ThreadShouldSetNameRule extends AbstractAliRule {
private Object checkThreadPoolExecutor(ASTAllocationExpression node, Object data) {
ASTArgumentList argumentList = node.getFirstDescendantOfType(ASTArgumentList.class);
if (argumentList.jjtGetNumChildren() > ARGUMENT_LENGTH_6) {
return true;
}
if (argumentList.jjtGetNumChildren() < ARGUMENT_LENGTH_6
|| !checkThreadFactoryArgument((ASTExpression)argumentList.jjtGetChild(ARGUMENT_LENGTH_6 - INDEX_1))) {
addViolationWithMessage(data, node, MESSAGE_KEY_PREFIX + ".ThreadPoolExecutor");
@@ -87,6 +92,9 @@ public class ThreadShouldSetNameRule extends AbstractAliRule {
private Object checkSchedulePoolExecutor(ASTAllocationExpression node, Object data) {
ASTArgumentList argumentList = node.getFirstDescendantOfType(ASTArgumentList.class);
if (argumentList.jjtGetNumChildren() > ARGUMENT_LENGTH_2) {
return true;
}
if (argumentList.jjtGetNumChildren() < ARGUMENT_LENGTH_2
|| !checkThreadFactoryArgument((ASTExpression)argumentList.jjtGetChild(ARGUMENT_LENGTH_2 - INDEX_1))) {
addViolationWithMessage(data, node, MESSAGE_KEY_PREFIX + ".ScheduledThreadPoolExecutor");
@@ -104,15 +112,35 @@ public class ThreadShouldSetNameRule extends AbstractAliRule {
}
ASTLambdaExpression lambdaExpression = expression.getFirstDescendantOfType(ASTLambdaExpression.class);
if (lambdaExpression != null) {
List<ASTVariableDeclaratorId> variableDeclaratorIds =
lambdaExpression.findChildrenOfType(ASTVariableDeclaratorId.class);
if (variableDeclaratorIds == null || variableDeclaratorIds.size() != SINGLE_LENGTH) {
return false;
}
return isThreadFactoryLambda(lambdaExpression);
} else if (expression.getType() != null
&& RejectedExecutionHandler.class.isAssignableFrom(expression.getType())) {
return false;
}
return true;
}
private boolean isThreadFactoryLambda(ASTLambdaExpression lambdaExpression) {
List<ASTVariableDeclaratorId> variableDeclaratorIds =
lambdaExpression.findChildrenOfType(ASTVariableDeclaratorId.class);
if (variableDeclaratorIds != null && !variableDeclaratorIds.isEmpty()) {
return variableDeclaratorIds.size() == SINGLE_LENGTH;
}
// like (Runnable r) ->
ASTFormalParameters parameters = lambdaExpression.getFirstChildOfType(ASTFormalParameters.class);
if (parameters == null) {
return false;
}
ASTFormalParameter parameter = parameters.getFirstChildOfType(ASTFormalParameter.class);
if (parameter == null) {
return false;
}
ASTVariableDeclaratorId variableDeclaratorId = parameter.getFirstChildOfType(ASTVariableDeclaratorId.class);
if (variableDeclaratorId == null) {
return false;
}
return Runnable.class == variableDeclaratorId.getType();
}
}

View File

@@ -29,6 +29,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTLiteral;
import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement;
import net.sourceforge.pmd.util.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.jaxen.JaxenException;
/**
@@ -66,7 +67,7 @@ public class UndefineMagicConstantRule extends AbstractAliRule {
for (ASTLiteral literal : literals) {
if (inBlackList(literal) && !currentLiterals.contains(literal)) {
currentLiterals.add(literal);
String imageReplace = StringUtil.replaceString(literal.getImage(), "{", "'{");
String imageReplace = StringUtils.replace(literal.getImage(), "{", "'{");
addViolationWithMessage(data, literal,
"java.constant.UndefineMagicConstantRule.violation.msg", new Object[] {imageReplace});
}
@@ -101,10 +102,7 @@ public class UndefineMagicConstantRule extends AbstractAliRule {
if (ifStatement != null && lineNum == ifStatement.getBeginLine()) {
ASTForStatement forStatement = ifStatement.getFirstParentOfType(ASTForStatement.class);
ASTWhileStatement whileStatement = ifStatement.getFirstParentOfType(ASTWhileStatement.class);
if (forStatement != null || whileStatement != null) {
return false;
}
return true;
return forStatement == null && whileStatement == null;
}
// judge magic value belongs to for statement

View File

@@ -39,6 +39,8 @@ public class TransactionMustHaveRollbackRule extends AbstractAliRule {
+ TRANSACTIONAL_ANNOTATION_NAME;
private static final String ROLLBACK_PREFIX = "rollback";
private static final String READ_ONLY = "readOnly";
private static final String PROPAGATION_NOT_SUPPORTED = "Propagation.NOT_SUPPORTED";
private static final String XPATH_FOR_ROLLBACK = "//StatementExpression/PrimaryExpression"
@@ -84,10 +86,11 @@ public class TransactionMustHaveRollbackRule extends AbstractAliRule {
private boolean shouldSkip(List<ASTMemberValuePair> memberValuePairList) {
for (ASTMemberValuePair pair : memberValuePairList) {
if (pair.getImage() == null) {
String image = pair.getImage();
if (image == null) {
continue;
}
if (pair.getImage().startsWith(ROLLBACK_PREFIX)) {
if (image.startsWith(ROLLBACK_PREFIX) || image.startsWith(READ_ONLY)) {
return true;
}
ASTName name = pair.getFirstDescendantOfType(ASTName.class);

View File

@@ -24,8 +24,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTStatement;
import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement;
/**
* [Mandatory] Braces are used with if, else, for, do and while statements, even if the body contains only
* a single statement. Avoid using the following example:
* [Mandatory] Braces are used with if, else, for, do and while statements, even if the body contains only a single
* statement. Avoid using the following example:
* <pre>
* if (condition) statements;
* </pre>
@@ -49,7 +49,7 @@ public class NeedBraceRule extends AbstractAliRule {
// IfStatement with else have 2 expression blocks, should never throws NPE
ASTStatement elseStms = node.findChildrenOfType(ASTStatement.class).get(1);
if (!elseStms.hasDecendantOfAnyType(ASTBlock.class, ASTIfStatement.class)) {
if (!elseStms.hasDescendantOfAnyType(ASTBlock.class, ASTIfStatement.class)) {
addViolationWithMessage(data, elseStms, MESSAGE_KEY, new Object[] {"else"});
}
}

View File

@@ -15,10 +15,9 @@
*/
package com.alibaba.p3c.pmd.lang.java.rule.naming;
import java.util.regex.Pattern;
import com.alibaba.p3c.pmd.I18nResources;
import com.alibaba.p3c.pmd.lang.java.rule.AbstractAliRule;
import com.alibaba.p3c.pmd.lang.java.util.StringAndCharConstants;
import com.alibaba.p3c.pmd.lang.java.util.ViolationUtils;
import net.sourceforge.pmd.lang.ast.Node;
@@ -28,6 +27,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclarator;
import net.sourceforge.pmd.lang.java.ast.ASTTypeDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId;
import java.util.regex.Pattern;
/**
* [Mandatory] Method names, parameter names, member variable names, and local variable names should be written in
* lowerCamelCase.
@@ -38,10 +39,14 @@ import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId;
public class LowerCamelCaseVariableNamingRule extends AbstractAliRule {
private static final String MESSAGE_KEY_PREFIX = "java.naming.LowerCamelCaseVariableNamingRule.violation.msg";
private Pattern pattern = Pattern.compile("^[a-z|$][a-z0-9]*([A-Z][a-z0-9]*)*(DO|DTO|VO|DAO)?$");
private Pattern pattern = Pattern.compile("^[a-z][a-z0-9]*([A-Z][a-z0-9]+)*(DO|DTO|VO|DAO)?$");
@Override
public Object visit(final ASTVariableDeclaratorId node, Object data) {
//避免与 AvoidStartWithDollarAndUnderLineNamingRule 重复判断(例: $myTest)
if (variableNamingStartOrEndWithDollarAndUnderLine(node.getImage())) {
return super.visit(node, data);
}
// Constant named does not apply to this rule
ASTTypeDeclaration typeDeclaration = node.getFirstParentOfType(ASTTypeDeclaration.class);
Node jjtGetChild = typeDeclaration.jjtGetChild(0);
@@ -65,12 +70,13 @@ public class LowerCamelCaseVariableNamingRule extends AbstractAliRule {
}
@Override
public Object visit(ASTMethodDeclarator node, Object data) {
if (!variableNamingStartOrEndWithDollarAndUnderLine(node.getImage())) {
if (!(pattern.matcher(node.getImage()).matches())) {
ViolationUtils.addViolationWithPrecisePosition(this, node, data,
I18nResources.getMessage(MESSAGE_KEY_PREFIX + ".method", node.getImage()));
}
}
return super.visit(node, data);
}
@@ -79,4 +85,9 @@ public class LowerCamelCaseVariableNamingRule extends AbstractAliRule {
//对所有注解内的内容不做检查
return null;
}
private boolean variableNamingStartOrEndWithDollarAndUnderLine(String variable) {
return variable.startsWith(StringAndCharConstants.DOLLAR)
|| variable.startsWith(StringAndCharConstants.UNDERSCORE);
}
}

View File

@@ -23,7 +23,7 @@ import com.alibaba.p3c.pmd.lang.java.util.ViolationUtils;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
import net.sourceforge.pmd.lang.java.rule.junit.AbstractJUnitRule;
import net.sourceforge.pmd.lang.java.rule.AbstractJUnitRule;
/**
* [Mandatory] Test cases shall be started with the class names to be tested and ended with Test.

View File

@@ -0,0 +1,78 @@
/*
* Copyright 1999-2017 Alibaba Group.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.p3c.pmd.lang.java.rule.oop;
import java.util.List;
import com.alibaba.p3c.pmd.lang.java.rule.AbstractAliRule;
import com.alibaba.p3c.pmd.lang.java.util.ViolationUtils;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.ast.ASTLiteral;
import net.sourceforge.pmd.lang.java.ast.ASTName;
import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix;
import net.sourceforge.pmd.lang.java.ast.ASTVariableInitializer;
import org.jaxen.JaxenException;
/**
* [Mandatory] Avoid using the constructor BigDecimal(double) to convert double value to a BigDecimal object.
*
* @author zenghou.fw
* @date 2019/04/02
*/
public class BigDecimalAvoidDoubleConstructorRule extends AbstractAliRule {
private static final String XPATH =
"Expression/PrimaryExpression/PrimaryPrefix/AllocationExpression/Arguments[preceding-sibling::ClassOrInterfaceType[@Image = 'BigDecimal']]"
+ "/ArgumentList/Expression/PrimaryExpression/PrimaryPrefix";
@Override
public Object visit(ASTVariableInitializer node, Object data) {
try {
List<Node> invocations = node.findChildNodesWithXPath(XPATH);
if (invocations == null || invocations.isEmpty()) {
return super.visit(node, data);
}
ASTPrimaryPrefix expression = (ASTPrimaryPrefix)invocations.get(0);
if (isDoubleLiteral(expression) || isDoubleVariable(expression)) {
addViolationWithMessage(data, node,
"java.oop.BigDecimalAvoidDoubleConstructorRule.violation.msg", null);
}
} catch (JaxenException e) {
throw new RuntimeException("XPath expression " + XPATH + " failed: " + e.getLocalizedMessage(), e);
}
return super.visit(node, data);
}
@Override
public void addViolation(Object data, Node node, String arg) {
ViolationUtils.addViolationWithPrecisePosition(this, node, data,
"java.oop.BigDecimalAvoidDoubleConstructorRule.violation.msg");
}
private boolean isDoubleLiteral(ASTPrimaryPrefix node) {
ASTLiteral literal = node.getFirstChildOfType(ASTLiteral.class);
return literal != null && literal.isDoubleLiteral();
}
private boolean isDoubleVariable(ASTPrimaryPrefix node) {
ASTName name = node.getFirstChildOfType(ASTName.class);
return name != null && Double.class == name.getType();
}
}

View File

@@ -19,6 +19,8 @@ import java.util.List;
import com.alibaba.p3c.pmd.lang.java.rule.AbstractPojoRule;
import com.alibaba.p3c.pmd.lang.java.rule.util.NodeUtils;
import com.alibaba.p3c.pmd.lang.java.util.VariableUtils;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
@@ -53,12 +55,12 @@ public class PojoMustUsePrimitiveFieldRule extends AbstractPojoRule {
if (!shouldProcess) {
continue;
}
Class type = field.getType();
Class type = NodeUtils.getNodeType(field);
// TODO works only in current compilation file, by crossing files will be null
if (type != null && type.isPrimitive()) {
addViolationWithMessage(data, field.getFirstDescendantOfType(ASTType.class),
"java.oop.PojoMustUsePrimitiveFieldRule.violation.msg",
new Object[] {field.getVariableName()});
new Object[] {VariableUtils.getVariableName(field)});
}
}
} catch (JaxenException e) {

View File

@@ -19,6 +19,7 @@ import java.util.List;
import com.alibaba.p3c.pmd.I18nResources;
import com.alibaba.p3c.pmd.lang.java.rule.AbstractPojoRule;
import com.alibaba.p3c.pmd.lang.java.util.VariableUtils;
import com.alibaba.p3c.pmd.lang.java.util.ViolationUtils;
import net.sourceforge.pmd.lang.ast.Node;
@@ -54,7 +55,7 @@ public class PojoNoDefaultValueRule extends AbstractPojoRule {
}
ViolationUtils.addViolationWithPrecisePosition(this, field, data,
I18nResources.getMessage("java.oop.PojoNoDefaultValueRule.violation.msg",
field.getVariableName()));
VariableUtils.getVariableName(field)));
}
} catch (JaxenException e) {
throw new RuntimeException(e.getMessage(), e);

View File

@@ -22,6 +22,7 @@ import java.util.Set;
import com.alibaba.p3c.pmd.I18nResources;
import com.alibaba.p3c.pmd.lang.java.rule.AbstractAliRule;
import com.alibaba.p3c.pmd.lang.java.util.VariableUtils;
import com.alibaba.p3c.pmd.lang.java.util.ViolationUtils;
import net.sourceforge.pmd.lang.ast.Node;
@@ -52,6 +53,7 @@ public class IbatisMethodQueryForListRule extends AbstractAliRule {
private static final String PRIMARY_METHOD_ARGUMENT_XPATH
= "PrimarySuffix/Arguments/ArgumentList/Expression/PrimaryExpression/PrimaryPrefix/Literal";
private static final String FIELDS_XPATH = "ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/FieldDeclaration";
private static final int LITERALS_SIZE = 3;
@Override
public Object visit(ASTCompilationUnit node, Object data) {
@@ -65,12 +67,12 @@ public class IbatisMethodQueryForListRule extends AbstractAliRule {
return super.visit(node, data);
}
for (ASTClassOrInterfaceDeclaration classOrInterfaceDeclaration : classOrInterfaceDeclarations) {
visitASTClassOrInterfaceDeclaration(classOrInterfaceDeclaration, data);
visitAstClassOrInterfaceDeclaration(classOrInterfaceDeclaration, data);
}
return super.visit(node, data);
}
private void visitASTClassOrInterfaceDeclaration(ASTClassOrInterfaceDeclaration classOrInterfaceDeclaration,
private void visitAstClassOrInterfaceDeclaration(ASTClassOrInterfaceDeclaration classOrInterfaceDeclaration,
Object data) {
try {
List<Node> fieldDeclarations = classOrInterfaceDeclaration.findChildNodesWithXPath(FIELDS_XPATH);
@@ -95,7 +97,7 @@ public class IbatisMethodQueryForListRule extends AbstractAliRule {
for (Node node : fieldDeclarations) {
ASTFieldDeclaration fieldDeclaration = (ASTFieldDeclaration)node;
if (sqlMapClientField(fieldDeclaration)) {
set.add(fieldDeclaration.getVariableName());
set.add(VariableUtils.getVariableName(fieldDeclaration));
}
}
return set;
@@ -146,7 +148,7 @@ public class IbatisMethodQueryForListRule extends AbstractAliRule {
}
//method parameters not match
List<Node> literals = node.findChildNodesWithXPath(PRIMARY_METHOD_ARGUMENT_XPATH);
if (!(literals != null && (literals.size() == 3))) {
if (literals == null || (literals.size() != LITERALS_SIZE)) {
continue;
}
boolean firstMethodArgumentString = "java.lang.String".equals(

View File

@@ -0,0 +1,42 @@
package com.alibaba.p3c.pmd.lang.java.rule.other;
import com.alibaba.p3c.pmd.lang.java.rule.AbstractAliRule;
import com.alibaba.p3c.pmd.lang.java.util.ViolationUtils;
import net.sourceforge.pmd.lang.java.ast.ASTEqualityExpression;
import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression;
import java.util.List;
/**
* @author changle.lq
* @date 2018/12/12
*/
public class AvoidDoubleOrFloatEqualCompareRule extends AbstractAliRule {
private static final String FLOAT = "float";
private static final String DOUBLE = "double";
private static final int LIST_SIZE = 2;
@Override
public Object visit(ASTEqualityExpression node, Object data) {
List<ASTPrimaryExpression> list = node.findDescendantsOfType(ASTPrimaryExpression.class);
if (list.size() != LIST_SIZE) {
return super.visit(node, data);
}
ASTPrimaryExpression left = list.get(0);
ASTPrimaryExpression right = list.get(1);
Class<?> leftType = left.getType();
Class<?> rightType = right.getType();
if (leftType == null || rightType == null) {
return super.visit(node, data);
}
if (FLOAT.equals(leftType.getName()) && FLOAT.equals(rightType.getName())) {
ViolationUtils.addViolationWithPrecisePosition(this, node, data);
} else if (DOUBLE.equals(leftType.getName()) && DOUBLE.equals(rightType.getName())) {
ViolationUtils.addViolationWithPrecisePosition(this, node, data);
}
return super.visit(node, data);
}
}

View File

@@ -17,6 +17,7 @@ package com.alibaba.p3c.pmd.lang.java.rule.other;
import com.alibaba.p3c.pmd.I18nResources;
import com.alibaba.p3c.pmd.lang.AbstractXpathRule;
import com.alibaba.p3c.pmd.lang.java.util.VariableUtils;
import com.alibaba.p3c.pmd.lang.java.util.ViolationUtils;
import net.sourceforge.pmd.lang.ast.Node;
@@ -51,7 +52,7 @@ public class AvoidPatternCompileInMethodRule extends AbstractXpathRule {
} else {
ViolationUtils.addViolationWithPrecisePosition(this, node, data,
I18nResources.getMessage("java.other.AvoidPatternCompileInMethodRule.violation.msg",
localVariableDeclaration.getVariableName()));
VariableUtils.getVariableName(localVariableDeclaration)));
}
}
}

View File

@@ -15,20 +15,33 @@
*/
package com.alibaba.p3c.pmd.lang.java.rule.other;
import java.util.List;
import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.TreeMap;
import com.alibaba.p3c.pmd.I18nResources;
import com.alibaba.p3c.pmd.lang.java.rule.AbstractAliRule;
import com.alibaba.p3c.pmd.lang.java.rule.util.NodeSortUtils;
import com.alibaba.p3c.pmd.lang.java.util.ViolationUtils;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.ast.ASTAnnotation;
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceBodyDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
import net.sourceforge.pmd.lang.java.ast.ASTExpression;
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
import net.sourceforge.pmd.lang.java.ast.AbstractJavaNode;
import net.sourceforge.pmd.lang.java.ast.Comment;
import net.sourceforge.pmd.lang.java.ast.FormalComment;
import net.sourceforge.pmd.lang.java.ast.MultiLineComment;
import net.sourceforge.pmd.lang.java.ast.SingleLineComment;
import net.sourceforge.pmd.lang.java.ast.Token;
/**
* [Recommended] The total number of lines for a method should not be more than 80.
* Note: The total number of lines, including the method signature, closing brace, codes, comments,
* blank lines, line breaks and any invisible lines, should not be more than 80.
* Note: The total number of lines, including the method signature, closing brace, codes, blank lines,
* line breaks and any invisible lines, should not be more than 80 (comments are not included).
*
* @author keriezhang
* @date 2018/1/9
@@ -38,6 +51,17 @@ public class MethodTooLongRule extends AbstractAliRule {
private static final int MAX_LINE_COUNT = 80;
private static final String ANNOTATION_PREFIX = "@";
/**
* sortedMap will be reinitialized for each source file.
*/
private SortedMap<Integer, Node> sortedNodeAndComment;
@Override
public Object visit(ASTCompilationUnit cUnit, Object data) {
sortedNodeAndComment = orderedCommentsAndExpressions(cUnit);
return super.visit(cUnit, data);
}
@Override
public Object visit(ASTMethodDeclaration node, Object data) {
// Include method modifiers.
@@ -62,10 +86,68 @@ public class MethodTooLongRule extends AbstractAliRule {
}
}
if (endLine - startLine + 1 > MAX_LINE_COUNT) {
// Get comment line count.
int commentLineCount = getCommentLineCount(node);
if (endLine - startLine - commentLineCount + 1 > MAX_LINE_COUNT) {
ViolationUtils.addViolationWithPrecisePosition(this, node, data,
I18nResources.getMessage("java.other.MethodTooLongRule.violation.msg", node.getName()));
}
return super.visit(node, data);
return data;
}
/**
* Order comments and expressions.
*
* @param cUnit compilation unit
* @return sorted comments and expressions
*/
protected SortedMap<Integer, Node> orderedCommentsAndExpressions(ASTCompilationUnit cUnit) {
SortedMap<Integer, Node> itemsByLineNumber = new TreeMap<>();
// expression nodes
List<ASTExpression> expressionNodes = cUnit.findDescendantsOfType(ASTExpression.class);
NodeSortUtils.addNodesToSortedMap(itemsByLineNumber, expressionNodes);
NodeSortUtils.addNodesToSortedMap(itemsByLineNumber, cUnit.getComments());
return itemsByLineNumber;
}
/**
* Get number of comment lines
*
* @param methodDecl
* @return
*/
private int getCommentLineCount(ASTMethodDeclaration methodDecl) {
int lineCount = 0;
AbstractJavaNode lastNode = null;
for (Entry<Integer, Node> entry : sortedNodeAndComment.entrySet()) {
Node value = entry.getValue();
if (value.getBeginLine() <= methodDecl.getBeginLine()) {
continue;
}
if (value.getBeginLine() > methodDecl.getEndLine()) {
break;
}
// value should be either expression or comment.
if (value instanceof AbstractJavaNode) {
lastNode = (AbstractJavaNode)value;
} else if (value instanceof FormalComment || value instanceof MultiLineComment) {
Comment comment = (Comment)value;
lineCount += comment.getEndLine() - comment.getBeginLine() + 1;
} else if (value instanceof SingleLineComment) {
SingleLineComment singleLineComment = (SingleLineComment)value;
// Comment may in the same line with node.
if (lastNode == null || singleLineComment.getBeginLine() != lastNode.getBeginLine()) {
lineCount += 1;
}
}
}
return lineCount;
}
}

View File

@@ -1,10 +1,17 @@
package com.alibaba.p3c.pmd.lang.java.rule.other;
import java.util.List;
import com.alibaba.p3c.pmd.lang.AbstractXpathRule;
import com.alibaba.p3c.pmd.lang.java.rule.AbstractAliRule;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.ast.ASTAllocationExpression;
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType;
import net.sourceforge.pmd.lang.java.ast.ASTLiteral;
import net.sourceforge.pmd.lang.java.ast.ASTName;
import org.apache.commons.lang3.StringUtils;
import org.jaxen.JaxenException;
/**
* [Mandatory] When doing date formatting, "y" should be written in lowercase for "year" in a pattern statement.

View File

@@ -18,6 +18,7 @@ package com.alibaba.p3c.pmd.lang.java.rule.util;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression;
import net.sourceforge.pmd.lang.java.ast.AbstractJavaAccessTypeNode;
import net.sourceforge.pmd.lang.java.typeresolution.TypeHelper;
/**
@@ -59,4 +60,8 @@ public class NodeUtils {
public static boolean isConstant(ASTFieldDeclaration field) {
return field != null && field.isStatic() && field.isFinal();
}
public static Class<?> getNodeType(AbstractJavaAccessTypeNode node) {
return node == null ? null : node.getType();
}
}

View File

@@ -26,4 +26,6 @@ public final class StringAndCharConstants {
}
public static final char DOT = '.';
public static final String DOLLAR = "$";
public static final String UNDERSCORE = "_";
}

View File

@@ -0,0 +1,18 @@
package com.alibaba.p3c.pmd.lang.java.util;
import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId;
import net.sourceforge.pmd.lang.java.ast.AbstractJavaAccessNode;
/**
* @author caikang
* @date 2019/04/22
*/
public class VariableUtils {
public static String getVariableName(AbstractJavaAccessNode typeNode) {
ASTVariableDeclaratorId decl = typeNode.getFirstDescendantOfType(ASTVariableDeclaratorId.class);
if (decl != null) {
return decl.getImage();
}
return null;
}
}

View File

@@ -162,11 +162,11 @@
</entry>
<entry key="java.concurrent.ThreadPoolCreationRule.rule.desc">
<![CDATA[
说明Executors各个方法的弊端:
1newFixedThreadPool和newSingleThreadExecutor:
主要问题是堆积的请求处理队列可能会耗费非常大的内存,甚至OOM。
2newCachedThreadPool和newScheduledThreadPool:
主要问题是线程数最大数是Integer.MAX_VALUE可能会创建数量非常多的线程,甚至OOM。]]>
说明Executors返回的线程池对象的弊端如下
1FixedThreadPool和SingleThreadPool:
允许的请求队列长度为Integer.MAX_VALUE可能会堆积大量的请求从而导致OOM。
2CachedThreadPool:
允许的创建线程数量为Integer.MAX_VALUE可能会创建大量的线程,从而导致OOM。]]>
</entry>
<entry key="java.concurrent.ThreadShouldSetNameRule.violation.msg.ThreadPoolExecutor">
@@ -275,7 +275,6 @@
</entry>
<!-- oop -->
<entry key="java.oop.EqualsAvoidNullRule.violation.msg">
<![CDATA[【%s】应该作为equals的参数而不是调用方]]>
@@ -339,6 +338,16 @@
<![CDATA[说明反编译出的字节码文件显示每次循环都会new出一个StringBuilder对象然后进行append操作最后通过toString方法返回String对象造成内存资源浪费。]]>
</entry>
<entry key="java.oop.BigDecimalAvoidDoubleConstructorRule.violation.msg">
<![CDATA[使用了new BigDecimal(double)构造函数]]>
</entry>
<entry key="java.oop.BigDecimalAvoidDoubleConstructorRule.rule.msg">
<![CDATA[禁止使用构造方法BigDecimal(double)的方式把double值转化为BigDecimal对象]]>
</entry>
<entry key="java.oop.BigDecimalAvoidDoubleConstructorRule.rule.msg.desc">
<![CDATA[说明BigDecimal(double)存在精度损失风险,在精确计算或值比较的场景中可能会导致业务逻辑异常。]]>
</entry>
<!-- comment -->
<entry key="java.comment.CommentsMustBeJavadocFormatRule.rule.msg">
<![CDATA[类、类属性、类方法的注释必须使用javadoc规范使用/**内容*/格式,不得使用//xxx方式和/*xxx*/方式。]]>
@@ -477,7 +486,7 @@
<entry key="java.other.MethodTooLongRule.rule.desc">
<![CDATA[
说明:包括方法签名、结束右大括号、方法内代码、注释、空行、回车及任何不可见字符的总行数不超过80行。
说明:除注释之外的方法签名、结束右大括号、方法内代码、空行、回车及任何不可见字符的总行数不超过80行。
]]>
</entry>
@@ -505,5 +514,36 @@
<![CDATA[变量【%s】使用的时候应在$后加感叹号]]>
</entry>
<entry key="java.other.AvoidDoubleOrFloatEqualCompareRule.rule.msg">
<![CDATA[浮点数之间的等值判断,基本数据类型不能用==来比较包装数据类型不能用equals来判断]]>
</entry>
<entry key="java.other.AvoidDoubleOrFloatEqualCompareRule.rule.desc">
<![CDATA[
浮点数采用“尾数+阶码”的编码方式,类似于科学计数法的“有效数字+指数”的表示方式。二进制无法精确表示大部分的十进制小数,具体原理参考《码出高效》
改进方式:
1指定一个误差范围两个浮点数的差值在此范围之内则认为是相等的
float a = 1.0f - 0.9f;
float b = 0.9f - 0.8f;
float diff = 1e-6f;
if (Math.abs(a - b) < diff) {
System.out.println("true");
}
2) 使用BigDecimal来定义值再进行浮点数的运算操作
BigDecimal a = new BigDecimal("1.0");
BigDecimal b = new BigDecimal("0.9");
BigDecimal c = new BigDecimal("0.8");
BigDecimal x = a.subtract(b);
BigDecimal y = b.subtract(c);
if (x.equals(y)) {
System.out.println("true");
}
]]>
</entry>
<entry key="java.other.AvoidDoubleOrFloatEqualCompareRule.rule.msg">
<![CDATA[浮点数之间的等值判断,基本数据类型不能用==来比较包装数据类型不能用equals来判断。]]>
</entry>
</properties>

View File

@@ -167,7 +167,7 @@ Note: In JDK8, Instant can be used to replace Date, Calendar is replaced by Loca
Note: Below are the problems created by usage of Executors for thread pool creation:
1) FixedThreadPool and SingleThreadPool:
Maximum request queue size Integer.MAX_VALUE. A large number of requests might cause OOM.
2) CachedThreadPool and ScheduledThreadPool:
2) CachedThreadPool:
The number of threads which are allowed to be created is Integer.MAX_VALUE. Creating too many threads might lead to OOM.]]>
</entry>
@@ -339,6 +339,16 @@ Note: Below are the problems created by usage of Executors for thread pool creat
<![CDATA[Note: According to the decompiled bytecode file, for each loop, it allocates a StringBuilder object, appends a string, and finally returns a String object via the toString method. This is a tremendous waste of memory.]]>
</entry>
<entry key="java.oop.BigDecimalAvoidDoubleConstructorRule.violation.msg">
<![CDATA[Constructor BigDecimal(double) is invoked]]>
</entry>
<entry key="java.oop.BigDecimalAvoidDoubleConstructorRule.rule.msg">
<![CDATA[Avoid using the constructor BigDecimal(double) to convert double value to a BigDecimal object.]]>
</entry>
<entry key="java.oop.BigDecimalAvoidDoubleConstructorRule.rule.msg.desc">
<![CDATA[NoteUse the constructor BigDecimal(String) or valueOf method of BigDecimal. Inside valueOf the toString of Double is executed, which truncate the mantissa according to the precision of double.]]>
</entry>
<!-- comment -->
<entry key="java.comment.CommentsMustBeJavadocFormatRule.rule.msg">
<![CDATA[Javadoc should be used for classes, class variables and methods. The format should be '/** comment **/', rather than '// xxx'.]]>
@@ -385,13 +395,13 @@ Javadoc should include method instruction, description of parameters, return val
<![CDATA[please javadoc the purpose of method [%s] in detail]]>
</entry>
<entry key="java.comment.AbstractMethodOrInterfaceMethodMustUseJavadocRule.violation.msg.parameter">
<![CDATA[method [%s] should have javadoc for parameter [%s]]]>
<![CDATA[parameter [%s] of method [%s] should have javadoc]]>
</entry>
<entry key="java.comment.AbstractMethodOrInterfaceMethodMustUseJavadocRule.violation.msg.return">
<![CDATA[return value of method [%s] should have javadoc]]>
</entry>
<entry key="java.comment.AbstractMethodOrInterfaceMethodMustUseJavadocRule.violation.msg.exception">
<![CDATA[method [%s] should have javadoc for exception [%s]]]>
<![CDATA[exception [%s] of method [%s] should have javadoc]]>
</entry>
<entry key="java.comment.AvoidCommentBehindStatementRule.rule.msg">
@@ -478,7 +488,7 @@ Note: In order to get a more accurate time, use System.nanoTime(). In JDK8, use
<entry key="java.other.MethodTooLongRule.rule.desc">
<![CDATA[
Note: The total number of lines, including the method signature, closing brace, codes, comments, blank lines, line breaks and any invisible lines, should not be more than 80.
Note: The total number of lines, including the method signature, closing brace, codes, blank lines, line breaks and any invisible lines, should not be more than 80 (comments are not included).
]]>
</entry>
@@ -508,4 +518,38 @@ Note: If attribute is null or does not exist, ${var} will be shown directly on w
<![CDATA[variable [%s] should add ! after $]]>
</entry>
<entry key="java.other.AvoidDoubleOrFloatEqualCompareRule.rule.msg">
<![CDATA[To judge the equivalence of floating-point numbers, == cannot be used for primitive types, while equals cannot be used for wrapper classes.]]>
</entry>
<entry key="java.other.AvoidDoubleOrFloatEqualCompareRule.rule.desc">
<![CDATA[
Floating-point numbers are composed by mantissa and exponent, which is similar to the coefficient and exponent of scientific notation. Most decimal fractions cannot be represented precisely by binary. For more details please refer to "Easy Coding".
Positive example:
1) Specify an error range. Consider two floating-pointing numbers as equal if the difference between them is within this range.
float a = 1.0f - 0.9f;
float b = 0.9f - 0.8f;
float diff = 1e-6f;
if (Math.abs(a - b) < diff) {
System.out.println("true");
}
2) Use BigDecimal to operate.
BigDecimal a = new BigDecimal("1.0");
BigDecimal b = new BigDecimal("0.9");
BigDecimal c = new BigDecimal("0.8");
BigDecimal x = a.subtract(b);
BigDecimal y = b.subtract(c);
if (x.equals(y)) {
System.out.println("true");
}
]]>
</entry>
<entry key="java.other.AvoidDoubleOrFloatEqualCompareRule.rule.msg">
<![CDATA[To judge the equivalence of floating-point numbers, == cannot be used for primitive types, while equals cannot be used for wrapper classes.]]>
</entry>
</properties>

View File

@@ -3,7 +3,7 @@
<ruleset name="AlibabaJavaComments" xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">
<description>AlibabaJavaComments</description>
<rule name="CommentsMustBeJavadocFormatRule" message="java.comment.CommentsMustBeJavadocFormatRule.rule.msg"
class="com.alibaba.p3c.pmd.lang.java.rule.comment.CommentsMustBeJavadocFormatRule">

View File

@@ -3,6 +3,7 @@
xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">
<description>AlibabaJavaConcurrent</description>
<rule name="ThreadPoolCreationRule"
language="java"
@@ -117,9 +118,7 @@ Positive example 3
<![CDATA[
public class TimerTaskThread extends Thread {
public TimerTaskThread(){
super.setName("TimerTaskThread");
// do something
}
super.setName("TimerTaskThread");
}
]]>
</example>
@@ -138,7 +137,7 @@ Positive example 1
private static final String FORMAT = "yyyy-MM-dd HH:mm:ss";
public String getFormat(Date date){
SimpleDateFormat dateFormat = new SimpleDateFormat(FORMAT);
return dateFormat.format(date);
return sdf.format(date);
}
]]>
</example>
@@ -147,10 +146,9 @@ Positive example 1
Positive example 2
private static final SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public void getFormat(){
synchronized(SIMPLE_DATE_FORMAT) {
SIMPLE_DATE_FORMAT.format(new Date());
// do something
}
synchronized (sdf){
sdf.format(new Date());
….;
}
]]>
</example>

View File

@@ -3,7 +3,7 @@
<ruleset name="AlibabaJavaConstants" xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">
<description>AlibabaJavaConstants</description>
<rule name="UpperEllRule"
message="java.constant.UpperEllRule.rule.msg"

View File

@@ -3,6 +3,7 @@
<ruleset name="AlibabaJavaExceptions" xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">
<description>AlibabaJavaExceptions</description>
<rule name="MethodReturnWrapperTypeRule"
language="java"

View File

@@ -3,6 +3,7 @@
<ruleset name="AlibabaJavaFlowControl" xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">
<description>AlibabaJavaFlowControl</description>
<rule name="SwitchStatementRule"
language="java"

View File

@@ -3,6 +3,7 @@
<ruleset name="AlibabaJavaNaming" xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">
<description>AlibabaJavaNaming</description>
<rule name="ClassNamingShouldBeCamelRule"

View File

@@ -3,6 +3,7 @@
<ruleset name="AlibabaJavaOop" xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">
<description>AlibabaJavaOop</description>
<rule name="EqualsAvoidNullRule"
language="java"
@@ -131,4 +132,26 @@ Positive example:
</example>
</rule>
<rule name="BigDecimalAvoidDoubleConstructorRule"
language="java"
message="java.oop.BigDecimalAvoidDoubleConstructorRule.rule.msg"
class="com.alibaba.p3c.pmd.lang.java.rule.oop.BigDecimalAvoidDoubleConstructorRule">
<description>java.oop.StringConcatRule.rule.msg.desc</description>
<priority>3</priority>
<example>
<![CDATA[
Negative example:
BigDecimal good1 = new BigDecimal(0.1);
]]>
</example>
<example>
<![CDATA[
Positive example:
BigDecimal good1 = new BigDecimal("0.1");
BigDecimal good2 = BigDecimal.valueOf(0.1);
]]>
</example>
</rule>
</ruleset>

View File

@@ -3,6 +3,7 @@
<ruleset name="AlibabaJavaOrm" xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">
<description>AlibabaJavaOrm</description>
<rule name="IbatisMethodQueryForListRule"
language="java"

View File

@@ -3,6 +3,7 @@
<ruleset name="AlibabaJavaOthers" xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">
<description>AlibabaJavaOthers</description>
<rule name="AvoidPatternCompileInMethodRule" language="java"
message="java.other.AvoidPatternCompileInMethodRule.rule.msg"
@@ -101,6 +102,32 @@ Negative example:
<![CDATA[
Positive example:
SimpleDateFormat format = new SimpleDateFormat("YYYY-mm-dd HH:mm:ss");
]]>
</example>
</rule>
<rule name="AvoidDoubleOrFloatEqualCompareRule" language="java"
message="java.other.AvoidDoubleOrFloatEqualCompareRule.rule.msg"
class="com.alibaba.p3c.pmd.lang.java.rule.other.AvoidDoubleOrFloatEqualCompareRule">
<description>java.other.AvoidDoubleOrFloatEqualCompareRule.rule.desc</description>
<priority>2</priority>
<example>
<![CDATA[
Negative example:
float g = 0.7f-0.6f;
float h = 0.8f-0.7f;
if (g == h) {
System.out.println("true");
}
]]>
</example>
<example>
<![CDATA[
Positive example:
double dis = 1e-6;
double d1 = 0.0000001d;
double d2 = 0d;
System.out.println(Math.abs(d1 - d2) < dis);
]]>
</example>
</rule>

View File

@@ -3,6 +3,7 @@
<ruleset name="AlibabaJavaSets" xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">
<description>AlibabaJavaSets</description>
<rule name="ClassCastExceptionWithToArrayRule"
message="java.set.ClassCastExceptionWithToArrayRule.rule.msg"

View File

@@ -3,7 +3,7 @@
<ruleset name="AlibabaVelocityOthers" xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">
<description>AlibabaVelocityOthers</description>
<rule name="UseQuietReferenceNotationRule" language="vm"
message="vm.other.UseQuietReferenceNotationRule.rule.msg"
class="com.alibaba.p3c.pmd.lang.vm.rule.other.UseQuietReferenceNotationRule">

View File

@@ -37,5 +37,6 @@ public class OopRuleTest extends SimpleAggregatorTst {
addRule(RULESET, "PojoMustUsePrimitiveFieldRule");
addRule(RULESET, "PojoMustOverrideToStringRule");
addRule(RULESET, "StringConcatRule");
addRule(RULESET, "BigDecimalAvoidDoubleConstructorRule");
}
}

View File

@@ -37,12 +37,10 @@ public class OtherRulesTest extends SimpleAggregatorTst {
addRule(RULESET, "AvoidMissUseOfMathRandomRule");
addRule(RULESET, "MethodTooLongRule");
addRule(RULESET,"UseRightCaseForDateFormatRule");
}
@Test
public void testUseRightCaseForDateFormatRule() {
runTests(findRule(RULESET, "UseRightCaseForDateFormatRule"));
addRule(RULESET,"AvoidDoubleOrFloatEqualCompareRule");
}
}

View File

@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<test-data>
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
<code-fragment id="non-abstract-method-in-abstract-class"><![CDATA[
public abstract class AbstractClassOrInterfaceMethodMustUseJavadoc {
public String getName(String firstName, String secondName) throws XPathException, IOException {
@@ -40,7 +42,7 @@ public abstract class AbstractClassOrInterfaceMethodMustUseJavadoc {
function, return, parameters and exceptions.
</description>
<expected-problems>6</expected-problems>
<expected-linenumbers>4</expected-linenumbers>
<expected-linenumbers>4,4,4,4,4,4</expected-linenumbers>
<code-ref id="abstract-method-with-part-of-comment-in-abstract-class" />
</test-code>
@@ -115,7 +117,7 @@ public interface AbstractClassOrInterfaceMethodMustUseJavadoc {
function, return, parameters and exceptions.
</description>
<expected-problems>6</expected-problems>
<expected-linenumbers>4</expected-linenumbers>
<expected-linenumbers>4,4,4,4,4,4</expected-linenumbers>
<code-ref id="method-in-interface-with-part-of-comment" />
</test-code>

View File

@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<test-data>
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
<code-fragment id="comments-before-code"><![CDATA[
public class AvoidCommentBehindStatementRule {

View File

@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<test-data>
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
<code-fragment id="class-without-author"><![CDATA[
public class ClassMustHaveAuthorRule {}
@@ -164,4 +166,65 @@ public interface Vehicle {
<code-ref id="upper-case-author-annotation" />
</test-code>
<code-fragment id="annotation-type-without-author"><![CDATA[
public @interface Vehicle {
}
]]>
</code-fragment>
<test-code>
<description>Annotation type without author</description>
<expected-problems>1</expected-problems>
<expected-linenumbers>1</expected-linenumbers>
<code-ref id="annotation-type-without-author" />
</test-code>
<code-fragment id="annotation-type-with-author"><![CDATA[
/**
* @author keriezhang
* @date 2018/11/07
*/
public @interface Vehicle {
}
]]>
</code-fragment>
<test-code>
<description>Annotation type with author</description>
<expected-problems>0</expected-problems>
<code-ref id="annotation-type-with-author" />
</test-code>
<code-fragment id="annotation-type-inside-class"><![CDATA[
/**
* @author keriezhang
* @date 2018/11/07
*/
public class NotEmpty {
public @interface List {
}
}
]]>
</code-fragment>
<test-code>
<description>Annotation type inside class</description>
<expected-problems>0</expected-problems>
<code-ref id="annotation-type-inside-class" />
</test-code>
<code-fragment id="non-public-class"><![CDATA[
/**
* @author keriezhang
* @date 2018/11/07
*/
public class One {
}
class Two {
}
]]>
</code-fragment>
<test-code>
<description>Non public class</description>
<expected-problems>0</expected-problems>
<code-ref id="non-public-class" />
</test-code>
</test-data>

View File

@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<test-data>
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
<code-fragment id="class-without-comments"><![CDATA[
public class CommentsMustBeJavadocFormat {

View File

@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<test-data>
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
<code-fragment id="enum-without-comment"><![CDATA[
public enum Level {

View File

@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<test-data>
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
<code-fragment id="commented-code"><![CDATA[
//import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;

View File

@@ -1,9 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<test-data>
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
<test-code>
<description>AvoidCallStaticSimpleDateFormatRule</description>
<expected-problems>4</expected-problems>
<expected-linenumbers>30,22,18,45</expected-linenumbers>
<expected-linenumbers>18,22,30,45</expected-linenumbers>
<code><![CDATA[
package com.alibaba.idea.pmd.rule.calendar;

View File

@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<test-data>
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
<test-code>
<description>AvoidConcurrentCompetitionRandomRule</description>
<expected-problems>1</expected-problems>

View File

@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<test-data>
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
<test-code>
<description>AvoidManuallyCreateThreadRule</description>
<expected-problems>3</expected-problems>

View File

@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<test-data>
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
<test-code>
<description>AvoidUseTimer</description>
<expected-problems>3</expected-problems>

View File

@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<test-data>
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
<test-code>
<description>CountDownShouldInFinallyRule</description>
<expected-problems>1</expected-problems>

View File

@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<test-data>
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
<test-code>
<description>ThreadLocalShouldRemoveRule</description>
<expected-problems>2</expected-problems>

View File

@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<test-data>
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
<test-code>
<description>Executors.new</description>
<expected-problems>5</expected-problems>

View File

@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<test-data>
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
<test-code>
<description>ThreadShouldSetNameRule</description>
<expected-problems>3</expected-problems>
@@ -65,6 +67,29 @@ public class TestScheduledExecutorService {
<description>right</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
import java.util.concurrent.ScheduledThreadPoolExecutor;
/**
* @author caikang
* @date 2017/03/07
*/
public class Main {
public static void main(String[] args) {
new ScheduledThreadPoolExecutor(1, (Runnable r) -> {
Thread thread = new Thread();
thread.setName("111");
return thread;
});
}
}
]]></code>
</test-code>
<test-code>
<description>right</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
package com.alibaba.idea.pmd.test.thread;
import java.util.concurrent.Executors;

View File

@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<test-data>
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
<code-fragment id="constants-ok"><![CDATA[
public class Foo {

View File

@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<test-data>
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
<code-fragment id="constants-uppercase-L"><![CDATA[
public class Foo {

View File

@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<test-data>
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
<code-fragment id="finally-has-return">
<![CDATA[
public class Example {

View File

@@ -1,4 +1,6 @@
<test-data>
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
<code-fragment id="MethodReturnWrapperTypeRule">
<![CDATA[
@@ -54,7 +56,7 @@ public class Add{
<test-code>
<description>If the return type is primitive, return a value of wrapper class may cause NullPointerException</description>
<expected-problems>8</expected-problems>
<code-ref id="MethodReturnWrapperTypeRule"/>
<expected-linenumbers>11,19,23,27,31,35,39,43</expected-linenumbers>
<code-ref id="MethodReturnWrapperTypeRule"/>
</test-code>
</test-data>

View File

@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<test-data>
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
<test-code>
<description>TransactionMustHaveRollbackRule</description>
<expected-problems>1</expected-problems>
@@ -28,6 +30,33 @@ public class TestTransactional {
]]></code>
</test-code>
<test-code>
<description>readOnly</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
package com.alibaba.p3c.example.concurrent;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.ResourceTransactionManager;
import org.springframework.transaction.support.SimpleTransactionStatus;
/**
* @author caikang
* @date 2017/03/29
*/
public class TestTransactional {
private ResourceTransactionManager manager;
@Transactional(readOnly = true)
@Override
public void test(){
//manager.rollback(new SimpleTransactionStatus());
}
}
]]></code>
</test-code>
<test-code>
<description>with rollback</description>
<expected-problems>0</expected-problems>

View File

@@ -1,5 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<test-data>
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
<code-fragment id="complex-condition">
<![CDATA[
public class Example {
@@ -13,13 +16,28 @@
public int fn2(int a, int b, int c) {
return (a == 0 || b != 0 && c > 0) ? 1 : 0;
}
public int fn3(int a, int b, int c) {
if (a == 0 || b !=0 || c > 0) {
return 1;
}
return 0;
}
public int fn4(int a, int b, int c) {
return (a == 0 && b != 0 && c > 0) ? 1 : 0;
}
public int fn5(int a, int b, boolean c) {
return (a == 0 && b != 0 && c) ? 1 : 0;
}
}
]]>
</code-fragment>
<test-code>
<description>complex conditional expression in if condition</description>
<expected-problems>2</expected-problems>
<expected-linenumbers>3,10</expected-linenumbers> 0 0 ˘ 0 /expected-linenumbers>
<expected-linenumbers>3,10</expected-linenumbers>
<code-ref id="complex-condition"/>
</test-code>

View File

@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<test-data>
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
<code-fragment id="unnecessary-not-expression">
<![CDATA[
public class Example {

View File

@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<test-data>
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
<code-fragment id="if-no-brace">
<![CDATA[
public class Example {

View File

@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<test-data>
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
<code-fragment id="switch-no-default-1">
<![CDATA[
public class Example {

View File

@@ -1,4 +1,7 @@
<test-data>
<?xml version="1.0" encoding="UTF-8"?>
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
<code-fragment id="AbstractNamingRuleStartWithabstract">
<![CDATA[
public abstract class abstractNameRuleTest {
@@ -8,8 +11,8 @@ public abstract class abstractNameRuleTest {
<test-code>
<description>abstract class name should start with Abstract or Base</description>
<expected-problems>1</expected-problems>
<code-ref id="AbstractNamingRuleStartWithabstract" />
<expected-linenumbers>1</expected-linenumbers>
<code-ref id="AbstractNamingRuleStartWithabstract" />
</test-code>
<code-fragment id="AbstractNamingRuleStartWithAbstract">
@@ -45,7 +48,7 @@ public abstract class baseAbstractNameRuleTest {
<test-code>
<description>abstract class name should start with Abstract or Base</description>
<expected-problems>1</expected-problems>
<code-ref id="AbstractNamingRuleStartWithbase" />
<expected-linenumbers>1</expected-linenumbers>
<code-ref id="AbstractNamingRuleStartWithbase" />
</test-code>
</test-data>

View File

@@ -1,4 +1,7 @@
<test-data>
<?xml version="1.0" encoding="UTF-8"?>
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
<code-fragment id="ArrayTypeStyleTest">
<![CDATA[
public class ArrayTypeStyleTest{
@@ -14,8 +17,8 @@
<test-code>
<description>array should be array[]</description>
<expected-problems>2</expected-problems>
<code-ref id="ArrayTypeStyleTest" />
<expected-linenumbers>2,6</expected-linenumbers>
<code-ref id="ArrayTypeStyleTest" />
</test-code>
<code-fragment id="ArrayTypeStyleTest1">

View File

@@ -1,4 +1,6 @@
<test-data>
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
<code-fragment id="AvoidStartWithDollarAndUnderLine">
<![CDATA[
public class AvoidStartWithDollarAndUnderLineNamingRuleTest {
@@ -12,8 +14,8 @@ public class AvoidStartWithDollarAndUnderLineNamingRuleTest {
<test-code>
<description>name should not be start with $ and _</description>
<expected-problems>4</expected-problems>
<code-ref id="AvoidStartWithDollarAndUnderLine" />
<expected-linenumbers>2,3,4,5</expected-linenumbers>
<code-ref id="AvoidStartWithDollarAndUnderLine"></code-ref>
</test-code>
<code-fragment id="AvoidStartWithDollarAndUnderLine1">

View File

@@ -1,4 +1,6 @@
<test-data>
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
<code-fragment id="boolean-property-in-POJO-class">
<![CDATA[
public class BooleanPropertyNamingRuleTestDO{
@@ -15,8 +17,8 @@
<test-code>
<description>issuccess should not contain is</description>
<expected-problems>2</expected-problems>
<expected-linenumbers>2,3</expected-linenumbers>
<code-ref id="boolean-property-in-POJO-class" />
<expected-problems>2,3</expected-problems>
</test-code>

View File

@@ -1,4 +1,6 @@
<test-data>
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
<code-fragment id="CamelClassNaming">
<![CDATA[
public class CamelClassNameRuleTest {
@@ -27,8 +29,8 @@ public class CamelClassNameRuleTest {
<test-code>
<description>Class Name Should Camel</description>
<expected-problems>6</expected-problems>
<code-ref id="CamelClassNaming" />
<expected-linenumbers>4,5,7,13,14,18</expected-linenumbers>
<code-ref id="CamelClassNaming" />
</test-code>

View File

@@ -1,4 +1,6 @@
<test-data>
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
<code-fragment id="ConstantFieldNamingRule">
<![CDATA[
public class ConstantFieldNameRuleTest {
@@ -19,8 +21,8 @@
<test-code>
<description>Constant name should be upper case</description>
<expected-problems>2</expected-problems>
<code-ref id="ConstantFieldNamingRule" />
<expected-linenumbers>7,9</expected-linenumbers>
<code-ref id="ConstantFieldNamingRule" />
</test-code>
<code-fragment id="ConstantFieldNamingRule1">

View File

@@ -1,4 +1,6 @@
<test-data>
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
<code-fragment id="ExceptionNamingRuleTest1">
<![CDATA[
public class EndWithExceptionRuleTest extends Exception {
@@ -8,8 +10,8 @@ public class EndWithExceptionRuleTest extends Exception {
<test-code>
<description>Exception class name should end with Exception</description>
<expected-problems>1</expected-problems>
<code-ref id="ExceptionNamingRuleTest1" />
<expected-linenumbers>1</expected-linenumbers>
<code-ref id="ExceptionNamingRuleTest1" />
</test-code>
<code-fragment id="ExceptionNamingRuleTest2">

View File

@@ -1,4 +1,6 @@
<test-data>
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
<code-fragment id="LowerCamelCaseVariableNamingRuleTest">
<![CDATA[
public class VariableNameRuleTest {
@@ -13,9 +15,9 @@
</code-fragment>
<test-code>
<description>Variable name should be lowerCamelCase</description>
<expected-problems>1</expected-problems>
<expected-problems>2</expected-problems>
<expected-linenumbers>2,3</expected-linenumbers>
<code-ref id="LowerCamelCaseVariableNamingRuleTest" />
<expected-linenumbers>3</expected-linenumbers>
</test-code>
<code-fragment id="LowerCamelCaseVariableNamingRuleTest1">
@@ -59,8 +61,8 @@ public class PluginConstants {
<test-code>
<description>Variable name should be lowerCamelCase3</description>
<expected-problems>2</expected-problems>
<code-ref id="LowerCamelCaseVariableNamingRuleTest3" />
<expected-linenumbers>2,3</expected-linenumbers>
<code-ref id="LowerCamelCaseVariableNamingRuleTest3" />
</test-code>
<code-fragment id="LowerCamelCaseVariableNamingRuleTest4">
@@ -141,16 +143,27 @@ public interface BizConstants {
<code-ref id="LowerCamelCaseVariableNamingRuleTest8" />
</test-code>
<code-fragment id="VariableNamingStartOrEndWithDollarAndUnderLine">
<![CDATA[
public class Example {
public void test(){
String $myName = "zhangsan";
int _myAge = 18;
}
}
]]>
</code-fragment>
<test-code>
<description>Variable Naming Start Or End With Dollar And UnderLine</description>
<expected-problems>0</expected-problems>
<code-ref id="VariableNamingStartOrEndWithDollarAndUnderLine" />
</test-code>
<code-fragment id="LowerCamelCaseVariableNamingRuleTest9">
<![CDATA[
@Document
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface TYPE {
int DO_NO_THING = 0;
int DO_ONE_START_TO_END_ROUTE = 1;
int DO_ONE_CAR_TO_START_ROUTE = 2;
int DO_TWO_ROUTE = 3;
public @interface ValueType {
int TYPE_NULL = 0;
}
]]>
</code-fragment>
@@ -159,25 +172,6 @@ public interface BizConstants {
<expected-problems>0</expected-problems>
<code-ref id="LowerCamelCaseVariableNamingRuleTest9" />
</test-code>
<code-fragment id="LowerCamelCaseVariableNamingRuleTest10">
<![CDATA[
@Document
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public class Type {
int DO_NO_THING = 0;
int DO_ONE_START_TO_END_ROUTE = 1;
int DO_ONE_CAR_TO_START_ROUTE = 2;
int DO_TWO_ROUTE = 3;
}
]]>
</code-fragment>
<test-code>
<description>Variable name should be lowerCamelCase10</description>
<expected-problems>4</expected-problems>
<code-ref id="LowerCamelCaseVariableNamingRuleTest10" />
</test-code>
</test-data>

View File

@@ -1,4 +1,6 @@
<test-data>
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
<code-fragment id="PackageNamingRule">
<![CDATA[
@@ -11,8 +13,8 @@
<test-code>
<description>Package Name should be lowercase</description>
<expected-problems>1</expected-problems>
<code-ref id="PackageNamingRule" />
<expected-linenumbers>2</expected-linenumbers>
<code-ref id="PackageNamingRule" />
</test-code>

View File

@@ -1,4 +1,6 @@
<test-data>
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
<code-fragment id="ServiceClassNamingRule">
<![CDATA[
public class ServiceNameRuleTest implements TestDAO{
@@ -17,8 +19,8 @@ public class ServiceNameRuleTest implements TestDAO{
<test-code>
<description>Service Class Name should be end with Impl</description>
<expected-problems>2</expected-problems>
<code-ref id="ServiceClassNamingRule" />
<expected-linenumbers>1,2</expected-linenumbers>
<code-ref id="ServiceClassNamingRule" />
</test-code>

View File

@@ -1,6 +1,9 @@
<test-data>
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
<code-fragment id="TestClassNameEndWithTest">
<![CDATA[
import org.junit.Test;
public class TestClassNameRuleTest {
@Test
public void testCase() {
@@ -11,13 +14,14 @@ public class TestClassNameRuleTest {
</code-fragment>
<test-code>
<description>Test Class Name Should End With Test</description>
<code-ref id="TestClassNameEndWithTest" />
<expected-problems>0</expected-problems>
<code-ref id="TestClassNameEndWithTest" />
</test-code>
<code-fragment id="TestClassNameNotEndWithTest">
<![CDATA[
import org.junit.Test;
public class TestClassNameRuleErrorExample {
@Test
public void testCase() {
@@ -29,7 +33,7 @@ public class TestClassNameRuleErrorExample {
<test-code>
<description>Test Class Name Should End With Test</description>
<expected-problems>1</expected-problems>
<expected-linenumbers>2</expected-linenumbers>
<code-ref id="TestClassNameNotEndWithTest" />
<expected-linenumbers>1</expected-linenumbers>
</test-code>
</test-data>

Some files were not shown because too many files have changed in this diff Show More