mirror of
https://github.com/alibaba/p3c.git
synced 2025-10-14 23:21:32 +00:00
v2.0.0
1. pmd -> 6.15.0 2. idea min version 2016.1 3. jdk min version 1.8
This commit is contained in:
@@ -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">
|
||||
|
@@ -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>
|
||||
|
@@ -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,
|
||||
|
@@ -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>
|
||||
|
@@ -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) {
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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>
|
||||
|
@@ -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/>
|
||||
|
@@ -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'
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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'
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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!!
|
||||
|
@@ -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)
|
||||
}
|
||||
}
|
||||
|
@@ -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()
|
||||
|
||||
|
@@ -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()))
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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()
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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()
|
||||
}
|
||||
}
|
@@ -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("")
|
||||
}
|
||||
}
|
||||
|
@@ -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'
|
||||
}
|
||||
|
@@ -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>
|
||||
|
@@ -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>
|
||||
|
@@ -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) {
|
||||
|
@@ -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
|
||||
|
@@ -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.
|
||||
*
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -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) {
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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();
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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"});
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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.
|
||||
|
@@ -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();
|
||||
}
|
||||
}
|
@@ -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) {
|
||||
|
@@ -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);
|
||||
|
@@ -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(
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -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.
|
||||
|
@@ -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();
|
||||
}
|
||||
}
|
||||
|
@@ -26,4 +26,6 @@ public final class StringAndCharConstants {
|
||||
}
|
||||
|
||||
public static final char DOT = '.';
|
||||
public static final String DOLLAR = "$";
|
||||
public static final String UNDERSCORE = "_";
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -162,11 +162,11 @@
|
||||
</entry>
|
||||
<entry key="java.concurrent.ThreadPoolCreationRule.rule.desc">
|
||||
<![CDATA[
|
||||
说明:Executors各个方法的弊端:
|
||||
1)newFixedThreadPool和newSingleThreadExecutor:
|
||||
主要问题是堆积的请求处理队列可能会耗费非常大的内存,甚至OOM。
|
||||
2)newCachedThreadPool和newScheduledThreadPool:
|
||||
主要问题是线程数最大数是Integer.MAX_VALUE,可能会创建数量非常多的线程,甚至OOM。]]>
|
||||
说明:Executors返回的线程池对象的弊端如下:
|
||||
1)FixedThreadPool和SingleThreadPool:
|
||||
允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM。
|
||||
2)CachedThreadPool:
|
||||
允许的创建线程数量为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>
|
||||
|
@@ -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[Note:Use 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>
|
||||
|
@@ -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">
|
||||
|
@@ -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>
|
||||
|
@@ -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"
|
||||
|
@@ -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"
|
||||
|
@@ -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"
|
||||
|
@@ -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"
|
||||
|
@@ -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>
|
||||
|
@@ -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"
|
||||
|
@@ -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>
|
||||
|
@@ -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"
|
||||
|
@@ -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">
|
||||
|
@@ -37,5 +37,6 @@ public class OopRuleTest extends SimpleAggregatorTst {
|
||||
addRule(RULESET, "PojoMustUsePrimitiveFieldRule");
|
||||
addRule(RULESET, "PojoMustOverrideToStringRule");
|
||||
addRule(RULESET, "StringConcatRule");
|
||||
addRule(RULESET, "BigDecimalAvoidDoubleConstructorRule");
|
||||
}
|
||||
}
|
||||
|
@@ -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");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@@ -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>
|
||||
|
||||
|
@@ -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 {
|
||||
|
@@ -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>
|
||||
|
@@ -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 {
|
||||
|
@@ -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 {
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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>
|
||||
|
@@ -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>
|
||||
|
@@ -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>
|
||||
|
@@ -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>
|
||||
|
@@ -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>
|
||||
|
@@ -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>
|
||||
|
@@ -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;
|
||||
|
@@ -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 {
|
||||
|
@@ -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 {
|
||||
|
@@ -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 {
|
||||
|
@@ -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>
|
||||
|
@@ -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>
|
||||
|
@@ -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>
|
||||
|
||||
|
@@ -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 {
|
||||
|
@@ -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 {
|
||||
|
@@ -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 {
|
||||
|
@@ -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>
|
||||
|
@@ -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">
|
||||
|
@@ -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">
|
||||
|
@@ -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>
|
||||
|
||||
|
||||
|
@@ -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>
|
||||
|
||||
|
||||
|
@@ -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">
|
||||
|
@@ -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">
|
||||
|
@@ -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>
|
||||
|
||||
|
||||
|
@@ -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>
|
||||
|
||||
|
||||
|
@@ -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>
|
||||
|
||||
|
||||
|
@@ -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
Reference in New Issue
Block a user