Source code
@ -0,0 +1,95 @@
|
||||
# Gradle
|
||||
build
|
||||
.gradle
|
||||
|
||||
testdata/
|
||||
# Java gitignore #
|
||||
.class
|
||||
.log
|
||||
|
||||
# Package Files #
|
||||
|
||||
*.war
|
||||
*.ear
|
||||
|
||||
#hsf files
|
||||
configuration
|
||||
|
||||
# maven gitignore#
|
||||
target/**
|
||||
|
||||
.svn/
|
||||
|
||||
# intelliJ.gitignore #
|
||||
.idea
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
|
||||
|
||||
# Eclipse git ignore#
|
||||
*.pydevproject
|
||||
.project
|
||||
.metadata
|
||||
bin/**
|
||||
*/bin/**
|
||||
tmp/**
|
||||
tmp/**/*
|
||||
configuration/**
|
||||
*.tmp
|
||||
*.bak
|
||||
*.orig
|
||||
*.swp
|
||||
*~.nib
|
||||
.classpath
|
||||
.settings/
|
||||
.loadpath
|
||||
.fileTable*
|
||||
.cache
|
||||
|
||||
# External tool builders
|
||||
.externalToolBuilders/
|
||||
|
||||
# Locally stored "Eclipse launch configurations"
|
||||
*.launch
|
||||
|
||||
# CDT-specific
|
||||
.cproject
|
||||
|
||||
# PDT-specific
|
||||
.buildpath
|
||||
|
||||
#log
|
||||
*.log
|
||||
*.log.*
|
||||
|
||||
# Windows Thumbs.db
|
||||
*.db
|
||||
|
||||
# OSX
|
||||
.DS_Store
|
||||
|
||||
# sass gitignore#
|
||||
.sass-cache
|
||||
.idea
|
||||
|
||||
# tcc_coverage
|
||||
coverage.ec
|
||||
|
||||
|
||||
|
||||
config.client.*
|
||||
|
||||
temp/
|
||||
*.pid
|
||||
*.orig
|
||||
|
||||
hsf.configuration/
|
||||
|
||||
# code coverage report
|
||||
*.ec
|
||||
|
||||
#hsf test
|
||||
*.instance
|
||||
out
|
||||
!/p3c-idea/src/main/kotlin/com/alibaba/smartfox/work/tools/aone/ui/AoneBranchView.kt
|
@ -0,0 +1,96 @@
|
||||
# Gradle
|
||||
build
|
||||
.gradle
|
||||
|
||||
testdata/
|
||||
# Java gitignore #
|
||||
.class
|
||||
.log
|
||||
|
||||
# Package Files #
|
||||
|
||||
*.war
|
||||
*.ear
|
||||
|
||||
#hsf files
|
||||
configuration
|
||||
|
||||
# maven gitignore#
|
||||
target/**
|
||||
|
||||
.svn/
|
||||
|
||||
# intelliJ.gitignore #
|
||||
.idea
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
*.bat
|
||||
|
||||
# Eclipse git ignore#
|
||||
*.pydevproject
|
||||
.project
|
||||
.metadata
|
||||
bin/**
|
||||
*/bin/**
|
||||
tmp/**
|
||||
tmp/**/*
|
||||
configuration/**
|
||||
*.tmp
|
||||
*.bak
|
||||
*.orig
|
||||
*.swp
|
||||
*~.nib
|
||||
.classpath
|
||||
.settings/
|
||||
.loadpath
|
||||
.fileTable*
|
||||
.cache
|
||||
|
||||
# External tool builders
|
||||
.externalToolBuilders/
|
||||
|
||||
# Locally stored "Eclipse launch configurations"
|
||||
*.launch
|
||||
|
||||
# CDT-specific
|
||||
.cproject
|
||||
|
||||
# PDT-specific
|
||||
.buildpath
|
||||
|
||||
#log
|
||||
*.log
|
||||
*.log.*
|
||||
|
||||
# Windows Thumbs.db
|
||||
*.db
|
||||
|
||||
# OSX
|
||||
.DS_Store
|
||||
|
||||
# sass gitignore#
|
||||
.sass-cache
|
||||
.idea
|
||||
|
||||
# tcc_coverage
|
||||
coverage.ec
|
||||
|
||||
|
||||
|
||||
config.client.*
|
||||
|
||||
temp/
|
||||
*.pid
|
||||
*.orig
|
||||
|
||||
hsf.configuration/
|
||||
|
||||
# code coverage report
|
||||
*.ec
|
||||
|
||||
#hsf test
|
||||
*.instance
|
||||
**/target
|
||||
.pmd
|
||||
**/.pmd
|
@ -0,0 +1,31 @@
|
||||
# Eclipse Plugin
|
||||
---
|
||||
## <font color="green">Prepare</font>
|
||||
- Eclipse Juno+
|
||||
- maven3.+
|
||||
- JDK 1.7+
|
||||
|
||||
## <font color="green">Build</font>
|
||||
```
|
||||
mvn -U clean install
|
||||
```
|
||||
|
||||
## <font color="green">Install</font>
|
||||
1. <font color="blue">Help >> Install New Software
|
||||
then enter this update site URL [https://p3c.alibaba.com/plugin/eclipse/update](https://p3c.alibaba.com/plugin/eclipse/update)</font>
|
||||
|
||||
![Install Plugin](doc/images/install.png)
|
||||
|
||||
2. <font color="blue">Follow the wizard, restart Eclipse to take effect after install success.</font>
|
||||
|
||||
## <font color="green">Use</font>
|
||||
1. <font color="blue">Switch language</font>
|
||||
|
||||
![Switch language](doc/images/eclipse_switch_language.png)
|
||||
|
||||
2. <font color="blue">Code Analyze </font>
|
||||
|
||||
![Analyze](doc/images/eclipse_analyze.png)
|
||||
|
||||
![Analyze](doc/images/analyze_result.png)
|
||||
|
@ -0,0 +1,7 @@
|
||||
bin.includes = feature.xml,\
|
||||
feature.properties,\
|
||||
smartfox.png
|
||||
src.includes = build.properties,\
|
||||
feature.properties,\
|
||||
feature.xml,\
|
||||
smartfox.png
|
@ -0,0 +1,26 @@
|
||||
feature.label = Ali-CodeAnalysis
|
||||
feature.provider_name = Alibaba
|
||||
feature.update_site_name = Alibaba IDE Portal
|
||||
|
||||
description.text = Alibaba Java Coding Guidelines
|
||||
description.url = https://github.com/alibaba/p3c
|
||||
|
||||
copyright.text =\
|
||||
Copyright 2017 Alibaba Java Coding Guidelines
|
||||
|
||||
license.url = https://github.com/alibaba/p3c
|
||||
license.text =\
|
||||
Copyright 1999-2017 Alibaba Group. \n\
|
||||
\n\
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); \n\
|
||||
you may not use this file except in compliance with the License. \n\
|
||||
You may obtain a copy of the License at \n\
|
||||
\n\
|
||||
http://www.apache.org/licenses/LICENSE-2.0 \n\
|
||||
\n\
|
||||
Unless required by applicable law or agreed to in writing, software \n\
|
||||
distributed under the License is distributed on an "AS IS" BASIS, \n\
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. \n\
|
||||
See the License for the specific language governing permissions and \n\
|
||||
limitations under the License. \n\
|
||||
|
@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<feature
|
||||
id="com.alibaba.smartfox.eclipse.feature"
|
||||
label="%feature.label"
|
||||
version="1.0.0.qualifier"
|
||||
provider-name="%feature.provider_name"
|
||||
plugin="com.alibaba.smartfox.eclipse.plugin"
|
||||
image="smartfox.png">
|
||||
|
||||
<description url="%description.url">
|
||||
Alibaba Java Coding Guidelines
|
||||
</description>
|
||||
|
||||
<copyright>
|
||||
%copyright.text
|
||||
</copyright>
|
||||
|
||||
<license url="%license.url">
|
||||
%license.text
|
||||
</license>
|
||||
|
||||
<url>
|
||||
<update label="%feature.update_site_name" url="https://p3c.alibaba.com/plugin/eclipse/update"/>
|
||||
</url>
|
||||
|
||||
<requires>
|
||||
<import plugin="org.eclipse.ui"/>
|
||||
<import plugin="org.eclipse.core.runtime"/>
|
||||
<import plugin="org.eclipse.jdt.core"/>
|
||||
<import plugin="org.eclipse.ui.ide"/>
|
||||
<import plugin="org.eclipse.ui.views"/>
|
||||
<import plugin="org.eclipse.core.resources"/>
|
||||
<import plugin="org.eclipse.jface.text"/>
|
||||
<import plugin="org.eclipse.ui.workbench.texteditor"/>
|
||||
<import plugin="org.eclipse.ltk.core.refactoring"/>
|
||||
<import plugin="org.eclipse.jdt.ui"/>
|
||||
<import plugin="org.eclipse.core.filebuffers"/>
|
||||
</requires>
|
||||
|
||||
<plugin
|
||||
id="com.alibaba.smartfox.eclipse.plugin"
|
||||
download-size="0"
|
||||
install-size="0"
|
||||
version="0.0.0"/>
|
||||
|
||||
</feature>
|
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.alibaba.smartfox.eclipse</groupId>
|
||||
<artifactId>smartfox-eclipse</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>com.alibaba.smartfox.eclipse.feature</artifactId>
|
||||
<packaging>eclipse-feature</packaging>
|
||||
<inceptionYear>2017</inceptionYear>
|
||||
</project>
|
After Width: | Height: | Size: 2.5 KiB |
@ -0,0 +1,60 @@
|
||||
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.0.qualifier
|
||||
Bundle-Activator: com.alibaba.smartfox.eclipse.SmartfoxActivator
|
||||
Bundle-Vendor: Alibaba
|
||||
Require-Bundle: org.eclipse.ui,
|
||||
org.eclipse.core.runtime,
|
||||
org.eclipse.jdt.core,
|
||||
org.eclipse.ui.ide,
|
||||
org.eclipse.ui.views,
|
||||
org.eclipse.core.resources,
|
||||
org.eclipse.jface.text,
|
||||
org.eclipse.ui.workbench.texteditor,
|
||||
org.eclipse.ltk.core.refactoring,
|
||||
org.eclipse.jdt.ui,
|
||||
org.eclipse.core.filebuffers,
|
||||
org.eclipse.equinox.p2.core,
|
||||
org.eclipse.equinox.p2.engine,
|
||||
org.eclipse.equinox.p2.operations,
|
||||
org.eclipse.equinox.p2.metadata.repository,
|
||||
org.eclipse.equinox.p2.ui,
|
||||
org.eclipse.equinox.p2.metadata
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Bundle-ClassPath: target/lib/antlr-runtime.jar,
|
||||
target/lib/antlr4-runtime.jar,
|
||||
target/lib/asm.jar,
|
||||
target/lib/commons-io.jar,
|
||||
target/lib/commons-lang3.jar,
|
||||
target/lib/gson.jar,
|
||||
target/lib/javacc.jar,
|
||||
target/lib/jaxen.jar,
|
||||
target/lib/jcommander.jar,
|
||||
target/lib/log4j.jar,
|
||||
target/lib/pmd-core.jar,
|
||||
target/lib/pmd-java.jar,
|
||||
target/lib/pmd-javascript.jar,
|
||||
target/lib/pmd-vm.jar,
|
||||
target/lib/rhino.jar,
|
||||
target/lib/saxon-dom.jar,
|
||||
target/lib/saxon.jar,
|
||||
target/lib/p3c-pmd.jar,
|
||||
target/lib/kotlin-stdlib.jar,
|
||||
target/lib/statistics-client.jar,
|
||||
target/lib/fastjson.jar,
|
||||
target/lib/guava.jar,
|
||||
target/classes/,
|
||||
.
|
||||
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,
|
||||
com.alibaba.smartfox.eclipse.ui.pmd,
|
||||
com.alibaba.smartfox.eclipse.util
|
@ -0,0 +1,14 @@
|
||||
bin.includes = .,\
|
||||
META-INF/,\
|
||||
plugin.xml,\
|
||||
icons/,\
|
||||
target/lib/
|
||||
src.includes = icons/,\
|
||||
META-INF/,\
|
||||
plugin.xml,\
|
||||
messages.properties,\
|
||||
target/lib/,\
|
||||
src/main/kotlin,\
|
||||
pom.xml
|
||||
source.. = src/main/java/,src/main/resources
|
||||
output.. = target/classes/
|
After Width: | Height: | Size: 163 B |
After Width: | Height: | Size: 220 B |
After Width: | Height: | Size: 403 B |
After Width: | Height: | Size: 381 B |
After Width: | Height: | Size: 367 B |
After Width: | Height: | Size: 430 B |
After Width: | Height: | Size: 605 B |
After Width: | Height: | Size: 628 B |
After Width: | Height: | Size: 219 B |
After Width: | Height: | Size: 371 B |
After Width: | Height: | Size: 754 B |
@ -0,0 +1,153 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?eclipse version="3.4"?>
|
||||
<plugin>
|
||||
<extension
|
||||
id="SmartFoxViews"
|
||||
name="SmartFoxViews"
|
||||
point="org.eclipse.ui.views">
|
||||
<category
|
||||
name="SmartFoxViews"
|
||||
id="com.alibaba.smartfox.eclipse.ui">
|
||||
</category>
|
||||
<view
|
||||
name="P3C Results"
|
||||
allowMultiple="false"
|
||||
icon="icons/view/smartfox_logo.png"
|
||||
category="com.alibaba.smartfox.eclipse.ui"
|
||||
class="com.alibaba.smartfox.eclipse.ui.InspectionResultView"
|
||||
id="com.alibaba.smartfox.eclipse.ui.InspectionResultView">
|
||||
</view>
|
||||
<view
|
||||
name="Rule Detail"
|
||||
allowMultiple="false"
|
||||
icon="icons/view/smartfox_logo.png"
|
||||
category="com.alibaba.smartfox.eclipse.ui"
|
||||
class="com.alibaba.smartfox.eclipse.ui.RuleDetailView"
|
||||
id="com.alibaba.smartfox.eclipse.ui.RuleDetailView">
|
||||
</view>
|
||||
<stickyView
|
||||
location="LEFT"
|
||||
id="com.alibaba.smartfox.eclipse.ui.RuleDetailView">
|
||||
</stickyView>
|
||||
</extension>
|
||||
|
||||
<extension point="org.eclipse.core.expressions.definitions">
|
||||
<definition id="when.alibaba.analysis.is.active">
|
||||
<or>
|
||||
<with variable="activePartId">
|
||||
<equals
|
||||
value="org.eclipse.jdt.ui.PackageExplorer">
|
||||
</equals>
|
||||
</with>
|
||||
<with variable="activePartId">
|
||||
<equals
|
||||
value="org.eclipse.ui.navigator.ProjectExplorer">
|
||||
</equals>
|
||||
</with>
|
||||
<with variable="activeSite">
|
||||
<adapt
|
||||
type="org.eclipse.ui.IEditorSite">
|
||||
</adapt>
|
||||
|
||||
</with>
|
||||
</or>
|
||||
|
||||
</definition>
|
||||
</extension>
|
||||
<extension
|
||||
point="org.eclipse.ui.commands">
|
||||
<category
|
||||
description="Alibaba Code Analysis"
|
||||
id="alibaba.ui.commands"
|
||||
name="Alibaba Command">
|
||||
</category>
|
||||
<command
|
||||
categoryId="alibaba.ui.commands"
|
||||
description="Alibaba Code Analysis"
|
||||
id="com.alibaba.smartfox.eclipse.command.analysis"
|
||||
name="Alibaba Code Analysis"/>
|
||||
<command
|
||||
categoryId="alibaba.ui.commands"
|
||||
description="Alibaba Code Analysis"
|
||||
id="com.alibaba.smartfox.eclipse.handler.SwitchLanguageHandler"
|
||||
name="Switch Language"/>
|
||||
</extension>
|
||||
<extension
|
||||
point="org.eclipse.ui.bindings">
|
||||
<key
|
||||
commandId="com.alibaba.smartfox.eclipse.command.analysis"
|
||||
contextId="org.eclipse.ui.contexts.window"
|
||||
schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
|
||||
sequence="Ctrl+Shift+Alt+J">
|
||||
</key>
|
||||
</extension>
|
||||
<extension
|
||||
point="org.eclipse.ui.handlers">
|
||||
<handler
|
||||
class="com.alibaba.smartfox.eclipse.handler.CodeAnalysisHandler"
|
||||
commandId="com.alibaba.smartfox.eclipse.command.analysis">
|
||||
<enabledWhen>
|
||||
<reference
|
||||
definitionId="when.alibaba.analysis.is.active">
|
||||
</reference>
|
||||
</enabledWhen>
|
||||
</handler>
|
||||
<handler
|
||||
class="com.alibaba.smartfox.eclipse.handler.SwitchLanguageHandler"
|
||||
commandId="com.alibaba.smartfox.eclipse.handler.SwitchLanguageHandler">
|
||||
</handler>
|
||||
</extension>
|
||||
<extension point="org.eclipse.ui.menus">
|
||||
<menuContribution allPopups="false"
|
||||
locationURI="popup:org.eclipse.ui.popup.any">
|
||||
<command
|
||||
commandId="com.alibaba.smartfox.eclipse.command.analysis"
|
||||
icon="icons/ali-ide-run.png"
|
||||
label="Alibaba Code Guidelines"
|
||||
style="push">
|
||||
<visibleWhen
|
||||
checkEnabled="false">
|
||||
<reference definitionId="when.alibaba.analysis.is.active"/>
|
||||
</visibleWhen>
|
||||
</command>
|
||||
</menuContribution>
|
||||
<menuContribution
|
||||
allPopups="false"
|
||||
locationURI="toolbar:org.eclipse.ui.main.toolbar?after=additions">
|
||||
<toolbar
|
||||
id="com.alibaba.smartfox.eclipse.plugin.toolbar3">
|
||||
<command
|
||||
commandId="com.alibaba.smartfox.eclipse.command.analysis"
|
||||
icon="icons/ali-ide-run.png"
|
||||
label="Alibaba Code Guidelines"
|
||||
style="push"
|
||||
tooltip="Alibaba Code Guidelines">
|
||||
</command>
|
||||
<command
|
||||
commandId="com.alibaba.smartfox.eclipse.handler.SwitchLanguageHandler"
|
||||
icon="icons/language.png"
|
||||
label="Switch Language"
|
||||
style="push"
|
||||
tooltip="Switch Language">
|
||||
</command>
|
||||
</toolbar>
|
||||
</menuContribution>
|
||||
</extension>
|
||||
<extension
|
||||
id="p3cMarker"
|
||||
name="P3C Violations"
|
||||
point="org.eclipse.core.resources.markers">
|
||||
<persistent value="false"/>
|
||||
<super type="org.eclipse.core.resources.problemmarker"/>
|
||||
</extension>
|
||||
<extension point="org.eclipse.ui.ide.markerResolution">
|
||||
<markerResolutionGenerator
|
||||
markerType="com.alibaba.smartfox.eclipse.plugin.p3cMarker"
|
||||
class="com.alibaba.smartfox.eclipse.QuickFixGenerator"/>
|
||||
</extension>
|
||||
<extension point="org.eclipse.ui.preferencePages">
|
||||
<page name="Alibaba Code Analysis"
|
||||
class="com.alibaba.smartfox.eclipse.ui.AllRulesPreferencePage"
|
||||
id="com.alibaba.smartfox.eclipse.ui.AllRulesPreferencePage"/>
|
||||
</extension>
|
||||
</plugin>
|
@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.alibaba.smartfox.eclipse</groupId>
|
||||
<artifactId>smartfox-eclipse</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>com.alibaba.smartfox.eclipse.plugin</artifactId>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
<inceptionYear>2017</inceptionYear>
|
||||
<properties>
|
||||
<kotlin.compiler.incremental>false</kotlin.compiler.incremental>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
<version>1.2.17</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.p3c</groupId>
|
||||
<artifactId>p3c-pmd</artifactId>
|
||||
<version>1.3.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-stdlib</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>20.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<sourceDirectory>src/main/kotlin</sourceDirectory>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-maven-plugin</artifactId>
|
||||
<version>${kotlin.version}</version>
|
||||
|
||||
<executions>
|
||||
<execution>
|
||||
<id>compile</id>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
|
||||
<execution>
|
||||
<id>test-compile</id>
|
||||
<phase>test-compile</phase>
|
||||
<goals>
|
||||
<goal>test-compile</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<version>2.7</version>
|
||||
<configuration>
|
||||
<stripVersion>true</stripVersion>
|
||||
<prependGroupId>false</prependGroupId>
|
||||
<outputDirectory>${project.build.directory}/lib</outputDirectory>
|
||||
<!-- exclude the apex (transitive) dependencies - we use the shaded
|
||||
version instead -->
|
||||
<excludeGroupIds>p2.eclipse-plugin,apex</excludeGroupIds>
|
||||
<excludeArtifactIds>com.alibaba.smartfox.eclipse.plugin
|
||||
</excludeArtifactIds>
|
||||
<useRepositoryLayout>false</useRepositoryLayout>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>get-dependencies</id>
|
||||
<phase>process-sources</phase>
|
||||
<goals>
|
||||
<goal>copy-dependencies</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<!--This plugin's configuration is used to store Eclipse m2e settings
|
||||
only. It has no influence on the Maven build itself. -->
|
||||
<plugin>
|
||||
<groupId>org.eclipse.m2e</groupId>
|
||||
<artifactId>lifecycle-mapping</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<configuration>
|
||||
<lifecycleMappingMetadata>
|
||||
<pluginExecutions>
|
||||
<pluginExecution>
|
||||
<pluginExecutionFilter>
|
||||
<groupId>
|
||||
org.apache.maven.plugins
|
||||
</groupId>
|
||||
<artifactId>
|
||||
maven-dependency-plugin
|
||||
</artifactId>
|
||||
<versionRange>[0,)</versionRange>
|
||||
<goals>
|
||||
<goal>copy-dependencies</goal>
|
||||
</goals>
|
||||
</pluginExecutionFilter>
|
||||
<action>
|
||||
<ignore></ignore>
|
||||
</action>
|
||||
</pluginExecution>
|
||||
</pluginExecutions>
|
||||
</lifecycleMappingMetadata>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
</project>
|
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* 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.smartfox.eclipse
|
||||
|
||||
import com.alibaba.p3c.pmd.lang.java.rule.constant.UpperEllRule
|
||||
import com.alibaba.p3c.pmd.lang.java.rule.oop.EqualsAvoidNullRule
|
||||
import com.alibaba.smartfox.eclipse.ui.InspectionResults
|
||||
import com.alibaba.smartfox.eclipse.util.getRule
|
||||
import com.google.common.io.Files
|
||||
import org.eclipse.core.resources.IFile
|
||||
import org.eclipse.core.resources.IMarker
|
||||
import org.eclipse.core.runtime.NullProgressMonitor
|
||||
import org.eclipse.ltk.core.refactoring.TextFileChange
|
||||
import org.eclipse.text.edits.ReplaceEdit
|
||||
import org.eclipse.ui.IMarkerResolution
|
||||
import org.eclipse.ui.IMarkerResolutionGenerator
|
||||
import java.nio.charset.Charset
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author caikang
|
||||
* @date 2017/06/14
|
||||
*/
|
||||
class QuickFixGenerator : IMarkerResolutionGenerator {
|
||||
override fun getResolutions(marker: IMarker): Array<IMarkerResolution> {
|
||||
if (!marker.exists()) {
|
||||
return emptyArray()
|
||||
}
|
||||
val rule = marker.getRule()
|
||||
val quickFix = quickFixes[rule.name] ?: return emptyArray()
|
||||
return arrayOf(quickFix)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val quickFixes = mapOf(UpperEllRule::class.java.simpleName to UpperEllQuickFix,
|
||||
EqualsAvoidNullRule::class.java.simpleName to EqualsAvoidNullQuickFix)
|
||||
}
|
||||
}
|
||||
|
||||
interface RunWithoutViewRefresh : IMarkerResolution {
|
||||
fun run(marker: IMarker, refresh: Boolean)
|
||||
|
||||
override fun run(marker: IMarker) {
|
||||
run(marker, true)
|
||||
}
|
||||
}
|
||||
|
||||
abstract class BaseQuickFix : RunWithoutViewRefresh {
|
||||
override fun run(marker: IMarker, refresh: Boolean) {
|
||||
if (!marker.exists()) {
|
||||
return
|
||||
}
|
||||
val file = marker.resource as IFile
|
||||
doRun(marker, file)
|
||||
marker.delete()
|
||||
if (refresh) {
|
||||
InspectionResults.removeMarker(marker)
|
||||
}
|
||||
}
|
||||
|
||||
abstract fun doRun(marker: IMarker, file: IFile)
|
||||
}
|
||||
|
||||
object UpperEllQuickFix : BaseQuickFix() {
|
||||
override fun doRun(marker: IMarker, file: IFile) {
|
||||
val offset = marker.getAttribute(IMarker.CHAR_START, 0)
|
||||
val end = marker.getAttribute(IMarker.CHAR_END, 0)
|
||||
val content = Files.toString(file.rawLocation.toFile(), Charset.forName(file.charset))
|
||||
val replaceString = content.substring(offset, end + 1).replace("l", "L")
|
||||
val edit = ReplaceEdit(offset, replaceString.length, replaceString)
|
||||
val change = TextFileChange("", file)
|
||||
change.edit = edit
|
||||
change.perform(NullProgressMonitor())
|
||||
}
|
||||
|
||||
override fun getLabel(): String {
|
||||
return "Replace 'l' to 'L'."
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
object EqualsAvoidNullQuickFix : BaseQuickFix() {
|
||||
val equalsName = ".equals("
|
||||
|
||||
override fun doRun(marker: IMarker, file: IFile) {
|
||||
val offset = marker.getAttribute(IMarker.CHAR_START, 0)
|
||||
val end = marker.getAttribute(IMarker.CHAR_END, 0)
|
||||
val content = Files.toString(file.rawLocation.toFile(), Charset.forName(file.charset))
|
||||
val string = content.substring(offset, end)
|
||||
val list = string.split(equalsName).filterNotNull()
|
||||
if (list.size != 2) {
|
||||
return
|
||||
}
|
||||
val replace = "${list[1].substringBeforeLast(')')}$equalsName${list[0]})"
|
||||
val edit = ReplaceEdit(offset, string.length, replace)
|
||||
val change = TextFileChange("", file)
|
||||
change.edit = edit
|
||||
change.perform(NullProgressMonitor())
|
||||
}
|
||||
|
||||
override fun getLabel(): String {
|
||||
return "Flip equals."
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* 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.smartfox.eclipse
|
||||
|
||||
import com.alibaba.p3c.pmd.I18nResources
|
||||
import net.sourceforge.pmd.Rule
|
||||
import net.sourceforge.pmd.RuleSetFactory
|
||||
import net.sourceforge.pmd.RuleSets
|
||||
import org.apache.log4j.Logger
|
||||
import org.eclipse.core.runtime.IStatus
|
||||
import org.eclipse.core.runtime.Status
|
||||
import org.eclipse.jface.dialogs.MessageDialog
|
||||
import org.eclipse.jface.resource.ImageDescriptor
|
||||
import org.eclipse.swt.graphics.Image
|
||||
import org.eclipse.swt.widgets.Display
|
||||
import org.eclipse.ui.plugin.AbstractUIPlugin
|
||||
import org.osgi.framework.BundleContext
|
||||
|
||||
/**
|
||||
* @author caikang
|
||||
* @date 2017/06/14
|
||||
*/
|
||||
class SmartfoxActivator : AbstractUIPlugin() {
|
||||
|
||||
init {
|
||||
aDefault = this
|
||||
}
|
||||
|
||||
private val logger = Logger.getLogger(javaClass)!!
|
||||
lateinit var ruleSets: RuleSets
|
||||
private val localeKey = "p3c.locale"
|
||||
|
||||
lateinit var ruleMap: Map<String, Rule>
|
||||
|
||||
@Throws(Exception::class) override fun start(context: BundleContext) {
|
||||
super.start(context)
|
||||
I18nResources.changeLanguage(locale)
|
||||
ruleSets = createRuleSets()
|
||||
ruleMap = ruleSets.allRules.associateBy {
|
||||
it.name
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(Exception::class) override fun stop(context: BundleContext?) {
|
||||
aDefault = null
|
||||
super.stop(context)
|
||||
}
|
||||
|
||||
|
||||
fun getImage(key: String, iconPath: String = key): Image {
|
||||
val registry = imageRegistry
|
||||
var image: Image? = registry.get(key)
|
||||
if (image == null) {
|
||||
val descriptor = getImageDescriptor(iconPath)
|
||||
registry.put(key, descriptor)
|
||||
image = registry.get(key)
|
||||
}
|
||||
|
||||
return image!!
|
||||
}
|
||||
|
||||
val locale: String get() {
|
||||
val lang = preferenceStore.getString(localeKey)
|
||||
return if (lang.isNullOrBlank()) {
|
||||
"zh"
|
||||
} else {
|
||||
lang
|
||||
}
|
||||
}
|
||||
|
||||
fun toggleLocale() {
|
||||
preferenceStore.setValue(localeKey, when (locale) {
|
||||
"en" -> "zh"
|
||||
else -> "en"
|
||||
})
|
||||
}
|
||||
|
||||
fun getRule(rule: String): Rule {
|
||||
return ruleMap[rule]!!
|
||||
}
|
||||
|
||||
fun showError(message: String, t: Throwable) {
|
||||
logError(message, t)
|
||||
Display.getDefault().syncExec {
|
||||
MessageDialog.openError(Display.getCurrent().activeShell, "错误", message + "\n" + t.toString())
|
||||
}
|
||||
}
|
||||
|
||||
fun logError(message: String, t: Throwable) {
|
||||
log.log(Status(IStatus.ERROR, bundle.symbolicName, 0, message + t.message, t))
|
||||
logger.error(message, t)
|
||||
}
|
||||
|
||||
fun logError(status: IStatus) {
|
||||
log.log(status)
|
||||
logger.error(status.message, status.exception)
|
||||
}
|
||||
|
||||
fun logInformation(message: String) {
|
||||
log.log(Status(IStatus.INFO, bundle.symbolicName, 0, message, null))
|
||||
}
|
||||
|
||||
fun logWarn(message: String) {
|
||||
log.log(Status(IStatus.WARNING, bundle.symbolicName, 0, message, null))
|
||||
}
|
||||
|
||||
companion object {
|
||||
// The plug-in ID
|
||||
val PLUGIN_ID = "com.alibaba.smartfox.eclipse.plugin"
|
||||
|
||||
var aDefault: SmartfoxActivator? = null
|
||||
private set
|
||||
|
||||
val instance: SmartfoxActivator get() = aDefault!!
|
||||
|
||||
fun getImageDescriptor(path: String): ImageDescriptor {
|
||||
return AbstractUIPlugin.imageDescriptorFromPlugin(PLUGIN_ID, path)
|
||||
}
|
||||
|
||||
fun createRuleSets(): RuleSets {
|
||||
val ruleSetFactory = RuleSetFactory()
|
||||
val ruleSet = ruleSetFactory.createRuleSet("java-ali-pmd,vm-ali-other")
|
||||
return RuleSets(ruleSet)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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.smartfox.eclipse.handler
|
||||
|
||||
import com.alibaba.smartfox.eclipse.job.CodeAnalysis.processResources
|
||||
import com.alibaba.smartfox.eclipse.message.P3cBundle
|
||||
import com.google.common.collect.Sets
|
||||
import org.apache.log4j.Logger
|
||||
import org.eclipse.core.commands.AbstractHandler
|
||||
import org.eclipse.core.commands.ExecutionEvent
|
||||
import org.eclipse.core.commands.ExecutionException
|
||||
import org.eclipse.core.resources.IFile
|
||||
import org.eclipse.core.resources.IResource
|
||||
import org.eclipse.core.resources.IResourceVisitor
|
||||
import org.eclipse.core.runtime.IAdaptable
|
||||
import org.eclipse.jface.viewers.IStructuredSelection
|
||||
import org.eclipse.ui.IFileEditorInput
|
||||
import org.eclipse.ui.IWorkingSet
|
||||
import org.eclipse.ui.commands.IElementUpdater
|
||||
import org.eclipse.ui.handlers.HandlerUtil
|
||||
import org.eclipse.ui.menus.UIElement
|
||||
import org.eclipse.ui.part.EditorPart
|
||||
import org.eclipse.ui.part.ViewPart
|
||||
|
||||
/**
|
||||
* @author caikang
|
||||
* @date 2016/12/27
|
||||
*/
|
||||
open class CodeAnalysisHandler : AbstractHandler(), IElementUpdater {
|
||||
override fun updateElement(element: UIElement, parameters: MutableMap<Any?, Any?>?) {
|
||||
val text = P3cBundle.getMessage("com.alibaba.smartfox.eclipse.handler.CodeAnalysisHandler")
|
||||
element.setText(text)
|
||||
element.setTooltip(text)
|
||||
}
|
||||
|
||||
@Throws(ExecutionException::class) override fun execute(executionEvent: ExecutionEvent): Any? {
|
||||
val selection = HandlerUtil.getCurrentSelectionChecked(executionEvent)
|
||||
val part = HandlerUtil.getActivePart(executionEvent)
|
||||
if (part is ViewPart) {
|
||||
if (selection is IStructuredSelection) {
|
||||
processForMutiFiles(selection)
|
||||
}
|
||||
} else if (part is EditorPart) {
|
||||
val editorInput = HandlerUtil.getActiveEditorInput(executionEvent)
|
||||
if (editorInput is IFileEditorInput) {
|
||||
processResources(setOf(editorInput.file))
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun processForMutiFiles(selection: IStructuredSelection) {
|
||||
val resources = getSelectionResources(selection)
|
||||
processResources(resources)
|
||||
}
|
||||
|
||||
private fun getSelectionResources(selection: IStructuredSelection): MutableSet<IResource> {
|
||||
val resources = mutableSetOf<IResource>()
|
||||
selection.toList().forEach {
|
||||
when (it) {
|
||||
is IWorkingSet -> it.elements.mapTo(resources) { it.getAdapter(IResource::class.java) as IResource }
|
||||
is IAdaptable -> {
|
||||
val file = it.getAdapter(IResource::class.java) as? IResource ?: return@forEach
|
||||
resources.add(file)
|
||||
}
|
||||
else -> log.warn("The selected object is not adaptable : ${it.toString()}")
|
||||
}
|
||||
}
|
||||
return resources
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
private val log = Logger.getLogger(CodeAnalysisHandler::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
class FileCollectVisitor : IResourceVisitor {
|
||||
val fileSet = Sets.newLinkedHashSet<IFile>()!!
|
||||
|
||||
override fun visit(resource: IResource?): Boolean {
|
||||
if (resource == null) {
|
||||
return false
|
||||
}
|
||||
val file = resource.getAdapter(IFile::class.java) as? IFile ?: return true
|
||||
if (file.exists() && (file.fileExtension == "java" || file.fileExtension == "vm")) {
|
||||
fileSet.add(file)
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.smartfox.eclipse.handler
|
||||
|
||||
import com.alibaba.smartfox.eclipse.SmartfoxActivator
|
||||
import com.alibaba.smartfox.eclipse.message.P3cBundle
|
||||
import org.eclipse.core.commands.AbstractHandler
|
||||
import org.eclipse.core.commands.ExecutionEvent
|
||||
import org.eclipse.jface.dialogs.MessageDialog
|
||||
import org.eclipse.ui.PlatformUI
|
||||
import org.eclipse.ui.commands.IElementUpdater
|
||||
import org.eclipse.ui.menus.UIElement
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author caikang
|
||||
* @date 2017/06/21
|
||||
*/
|
||||
class SwitchLanguageHandler : AbstractHandler(), IElementUpdater {
|
||||
val handlerKey = "com.alibaba.smartfox.eclipse.handler.SwitchLanguageHandler"
|
||||
val textKey = "$handlerKey.text.cur_"
|
||||
|
||||
override fun execute(executionEvent: ExecutionEvent): Any? {
|
||||
SmartfoxActivator.instance.toggleLocale()
|
||||
if (!MessageDialog.openConfirm(null, "Tips",
|
||||
P3cBundle.getMessage("$handlerKey.success.${SmartfoxActivator.instance.locale}"))) {
|
||||
return null
|
||||
}
|
||||
PlatformUI.getWorkbench().restart()
|
||||
return null
|
||||
}
|
||||
|
||||
override fun updateElement(element: UIElement, parameters: MutableMap<Any?, Any?>?) {
|
||||
val text = P3cBundle.getMessage("$textKey${SmartfoxActivator.instance.locale}")
|
||||
element.setText(text)
|
||||
element.setTooltip(text)
|
||||
}
|
||||
}
|
@ -0,0 +1,129 @@
|
||||
/*
|
||||
* 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.smartfox.eclipse.job
|
||||
|
||||
import com.alibaba.p3c.pmd.lang.java.util.GeneratedCodeUtils
|
||||
import com.alibaba.smartfox.eclipse.SmartfoxActivator
|
||||
import com.alibaba.smartfox.eclipse.handler.CodeAnalysisHandler
|
||||
import com.alibaba.smartfox.eclipse.handler.FileCollectVisitor
|
||||
import com.alibaba.smartfox.eclipse.ui.InspectionResultView
|
||||
import com.alibaba.smartfox.eclipse.ui.InspectionResults
|
||||
import com.alibaba.smartfox.eclipse.ui.MarkerViolation
|
||||
import com.alibaba.smartfox.eclipse.util.MarkerUtil
|
||||
import com.google.common.io.Files
|
||||
import net.sourceforge.pmd.PMDConfiguration
|
||||
import net.sourceforge.pmd.PMDException
|
||||
import net.sourceforge.pmd.Report
|
||||
import net.sourceforge.pmd.RuleContext
|
||||
import net.sourceforge.pmd.RuleViolation
|
||||
import net.sourceforge.pmd.SourceCodeProcessor
|
||||
import org.apache.log4j.Logger
|
||||
import org.eclipse.core.resources.IFile
|
||||
import org.eclipse.core.resources.IResource
|
||||
import org.eclipse.core.runtime.IProgressMonitor
|
||||
import org.eclipse.core.runtime.IStatus
|
||||
import org.eclipse.core.runtime.Status
|
||||
import org.eclipse.core.runtime.SubMonitor
|
||||
import org.eclipse.core.runtime.jobs.Job
|
||||
import java.io.IOException
|
||||
import java.io.StringReader
|
||||
import java.nio.charset.Charset
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author caikang
|
||||
* @date 2017/06/14
|
||||
*/
|
||||
object CodeAnalysis {
|
||||
private val log = Logger.getLogger(CodeAnalysisHandler::class.java)
|
||||
|
||||
fun processResources(resources: Set<IResource>) {
|
||||
InspectionResultView.activeViews()
|
||||
val job = object : Job("P3C Code Analysis") {
|
||||
override fun run(monitor: IProgressMonitor): IStatus {
|
||||
val fileVisitor = FileCollectVisitor()
|
||||
monitor.setTaskName("Collect files")
|
||||
resources.forEach {
|
||||
if (monitor.isCanceled) {
|
||||
return@run Status.CANCEL_STATUS
|
||||
}
|
||||
if(it.isAccessible){
|
||||
it.accept(fileVisitor)
|
||||
}
|
||||
}
|
||||
if (monitor.isCanceled) {
|
||||
return Status.CANCEL_STATUS
|
||||
}
|
||||
val subMonitor = SubMonitor.convert(monitor, "Analysis files", fileVisitor.fileSet.size)
|
||||
monitor.setTaskName("Analysis files")
|
||||
fileVisitor.fileSet.forEach { iFile ->
|
||||
if (monitor.isCanceled) {
|
||||
return@run Status.CANCEL_STATUS
|
||||
}
|
||||
MarkerUtil.removeAllMarkers(iFile)
|
||||
monitor.subTask(iFile.fullPath.toPortableString())
|
||||
val markers = processFileToMakers(iFile, monitor)
|
||||
subMonitor.newChild(1)
|
||||
InspectionResults.updateFileViolations(iFile, markers)
|
||||
}
|
||||
return Status.OK_STATUS
|
||||
}
|
||||
}
|
||||
job.rule = P3CMutex
|
||||
job.schedule()
|
||||
}
|
||||
|
||||
fun processFileToMakers(file: IFile, monitor: IProgressMonitor): List<MarkerViolation> {
|
||||
file.refreshLocal(IResource.DEPTH_ZERO, monitor)
|
||||
val ruleViolations = processFile(file)
|
||||
|
||||
MarkerUtil.removeAllMarkers(file)
|
||||
val markers = ruleViolations.map {
|
||||
MarkerViolation(MarkerUtil.addMarker(file, it), it)
|
||||
}
|
||||
return markers
|
||||
}
|
||||
|
||||
private fun processFile(file: IFile): List<RuleViolation> {
|
||||
val configuration = PMDConfiguration()
|
||||
configuration.sourceEncoding = file.charset ?: Charsets.UTF_8.name()
|
||||
configuration.inputPaths = file.fullPath.toPortableString()
|
||||
val ctx = RuleContext()
|
||||
ctx.setAttribute("eclipseFile", file)
|
||||
val niceFileName = configuration.inputPaths
|
||||
val report = Report.createReport(ctx, niceFileName)
|
||||
SmartfoxActivator.instance.ruleSets.start(ctx)
|
||||
val processor = SourceCodeProcessor(configuration)
|
||||
try {
|
||||
ctx.languageVersion = null
|
||||
val content = Files.toString(file.rawLocation.toFile(), Charset.forName(file.charset))
|
||||
if (!GeneratedCodeUtils.isGenerated(content)) {
|
||||
processor.processSourceCode(StringReader(content), SmartfoxActivator.instance.ruleSets, ctx)
|
||||
}
|
||||
} catch (pmde: PMDException) {
|
||||
log.debug("Error while processing file: " + niceFileName, pmde.cause)
|
||||
report.addError(Report.ProcessingError(pmde.message, niceFileName))
|
||||
} catch (ioe: IOException) {
|
||||
log.error("Unable to read source file: " + niceFileName, ioe)
|
||||
} catch (re: RuntimeException) {
|
||||
log.error("RuntimeException while processing file: " + niceFileName, re)
|
||||
} finally {
|
||||
SmartfoxActivator.instance.ruleSets.end(ctx)
|
||||
}
|
||||
return report.toList()
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.smartfox.eclipse.job
|
||||
|
||||
import org.eclipse.core.resources.IResource
|
||||
import org.eclipse.core.runtime.jobs.ISchedulingRule
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author caikang
|
||||
* @date 2017/06/14
|
||||
*/
|
||||
object P3CMutex : ISchedulingRule {
|
||||
override fun contains(rule: ISchedulingRule?): Boolean {
|
||||
return isConflicting(rule)
|
||||
}
|
||||
|
||||
override fun isConflicting(rule: ISchedulingRule?): Boolean {
|
||||
return rule == this || rule is IResource
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.smartfox.eclipse.message
|
||||
|
||||
|
||||
import com.alibaba.p3c.pmd.I18nResources
|
||||
import com.alibaba.smartfox.eclipse.SmartfoxActivator
|
||||
import java.util.Locale
|
||||
import java.util.ResourceBundle
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author caikang
|
||||
* @date 2017/06/20
|
||||
*/
|
||||
object P3cBundle {
|
||||
private val resourceBundle = ResourceBundle.getBundle("messages.P3cBundle",
|
||||
Locale(SmartfoxActivator.instance.locale), I18nResources.XmlControl())
|
||||
|
||||
fun getMessage(key: String): String {
|
||||
return resourceBundle.getString(key)
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.smartfox.eclipse.pmd
|
||||
|
||||
enum class RulePriority(val priority: Int, val title: String) {
|
||||
|
||||
Blocker(1, "Blocker"), Critical(2, "Critical"), Major(3, "Major");
|
||||
|
||||
override fun toString(): String {
|
||||
return title
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun valueOf(priority: Int): RulePriority {
|
||||
try {
|
||||
return RulePriority.values()[priority - 1]
|
||||
} catch (e: ArrayIndexOutOfBoundsException) {
|
||||
return Major
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,185 @@
|
||||
/*
|
||||
* 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.smartfox.eclipse.pmd.rule
|
||||
|
||||
import com.alibaba.smartfox.eclipse.message.P3cBundle
|
||||
import net.sourceforge.pmd.Rule
|
||||
import net.sourceforge.pmd.RuleContext
|
||||
import net.sourceforge.pmd.RuleViolation
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit
|
||||
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule
|
||||
import org.eclipse.core.resources.IFile
|
||||
import org.eclipse.core.runtime.NullProgressMonitor
|
||||
import org.eclipse.jdt.core.ICompilationUnit
|
||||
import org.eclipse.jdt.core.IProblemRequestor
|
||||
import org.eclipse.jdt.core.JavaCore
|
||||
import org.eclipse.jdt.core.JavaModelException
|
||||
import org.eclipse.jdt.core.WorkingCopyOwner
|
||||
import org.eclipse.jdt.core.compiler.IProblem
|
||||
import org.eclipse.jdt.core.dom.ASTNode
|
||||
import org.eclipse.jdt.core.dom.ASTVisitor
|
||||
import org.eclipse.jdt.core.dom.CompilationUnit
|
||||
import java.util.MissingResourceException
|
||||
|
||||
/**
|
||||
* @author caikang
|
||||
* @date 2016/12/26
|
||||
*/
|
||||
abstract class AbstractEclipseRule : AbstractJavaRule() {
|
||||
|
||||
open fun getErrorMessage(): String {
|
||||
return message
|
||||
}
|
||||
|
||||
override fun visit(node: ASTCompilationUnit, data: Any): Any? {
|
||||
val result = super.visit(node, data)
|
||||
val ruleContext = data as RuleContext
|
||||
val file = ruleContext.getAttribute("eclipseFile") as? IFile ?: return result
|
||||
val compilationUnit = JavaCore.createCompilationUnitFrom(file) ?: return data
|
||||
try {
|
||||
val requestor = object : IProblemRequestor {
|
||||
override fun acceptProblem(problem: IProblem) {}
|
||||
|
||||
override fun beginReporting() {}
|
||||
|
||||
override fun endReporting() {}
|
||||
|
||||
override fun isActive(): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
val workingCopy = compilationUnit.getWorkingCopy(null)
|
||||
val ast = workingCopy.reconcile(JLS8, ICompilationUnit.FORCE_PROBLEM_DETECTION
|
||||
or ICompilationUnit.ENABLE_BINDINGS_RECOVERY or ICompilationUnit.ENABLE_STATEMENTS_RECOVERY,
|
||||
object : WorkingCopyOwner() {
|
||||
override fun getProblemRequestor(workingCopy: ICompilationUnit?): IProblemRequestor {
|
||||
return requestor
|
||||
}
|
||||
}, NullProgressMonitor()) ?: return data
|
||||
ast.accept(getVisitor(ast, ruleContext))
|
||||
|
||||
} catch (e: JavaModelException) {
|
||||
throw RuntimeException(e)
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
override fun setDescription(description: String) {
|
||||
try {
|
||||
super.setDescription(P3cBundle.getMessage(description))
|
||||
} catch (e: MissingResourceException) {
|
||||
super.setMessage(description)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun setMessage(message: String) {
|
||||
try {
|
||||
super.setMessage(P3cBundle.getMessage(message))
|
||||
} catch (e: MissingResourceException) {
|
||||
super.setMessage(message)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
protected abstract fun getVisitor(ast: CompilationUnit, ruleContext: RuleContext): ASTVisitor
|
||||
|
||||
internal fun addRuleViolation(ruleContext: RuleContext, ast: CompilationUnit, nodeInfo: NodeInfo) {
|
||||
val rule = this
|
||||
val ruleViolation = object : RuleViolation {
|
||||
override fun getRule(): Rule {
|
||||
return rule
|
||||
}
|
||||
|
||||
override fun getDescription(): String {
|
||||
return getErrorMessage().trim { it <= ' ' }
|
||||
}
|
||||
|
||||
override fun isSuppressed(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun getFilename(): String {
|
||||
return ruleContext.sourceCodeFilename
|
||||
}
|
||||
|
||||
override fun getBeginLine(): Int {
|
||||
return ast.getLineNumber(nodeInfo.startPosition)
|
||||
}
|
||||
|
||||
override fun getBeginColumn(): Int {
|
||||
return ast.getColumnNumber(nodeInfo.startPosition)
|
||||
}
|
||||
|
||||
override fun getEndLine(): Int {
|
||||
return ast.getLineNumber(nodeInfo.endPosition)
|
||||
}
|
||||
|
||||
override fun getEndColumn(): Int {
|
||||
return ast.getColumnNumber(nodeInfo.endPosition)
|
||||
}
|
||||
|
||||
override fun getPackageName(): String? {
|
||||
return nodeInfo.packageName
|
||||
}
|
||||
|
||||
override fun getClassName(): String? {
|
||||
return nodeInfo.className
|
||||
}
|
||||
|
||||
override fun getMethodName(): String? {
|
||||
return nodeInfo.methodName
|
||||
}
|
||||
|
||||
override fun getVariableName(): String? {
|
||||
return nodeInfo.variableName
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return rule.toString()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
ruleContext.report.addRuleViolation(ruleViolation)
|
||||
}
|
||||
|
||||
protected fun violation(rc: RuleContext, node: ASTNode, ast: CompilationUnit) {
|
||||
val nodeInfo = NodeInfo()
|
||||
nodeInfo.className = ast.javaElement.elementName
|
||||
nodeInfo.packageName = ast.`package`.name.fullyQualifiedName
|
||||
nodeInfo.startPosition = node.startPosition
|
||||
nodeInfo.endPosition = node.startPosition + node.length
|
||||
|
||||
addRuleViolation(rc, ast, nodeInfo)
|
||||
}
|
||||
|
||||
inner class NodeInfo {
|
||||
internal var packageName: String? = null
|
||||
internal var className: String? = null
|
||||
internal var methodName: String? = null
|
||||
internal var variableName: String? = null
|
||||
internal var startPosition: Int = 0
|
||||
internal var endPosition: Int = 0
|
||||
}
|
||||
|
||||
companion object {
|
||||
val JLS8 = 8
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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.smartfox.eclipse.pmd.rule
|
||||
|
||||
import net.sourceforge.pmd.RuleContext
|
||||
import org.eclipse.jdt.core.dom.ASTVisitor
|
||||
import org.eclipse.jdt.core.dom.ClassInstanceCreation
|
||||
import org.eclipse.jdt.core.dom.CompilationUnit
|
||||
import org.eclipse.jdt.core.dom.FieldAccess
|
||||
import org.eclipse.jdt.core.dom.IVariableBinding
|
||||
import org.eclipse.jdt.core.dom.MethodInvocation
|
||||
import org.eclipse.jdt.core.dom.Modifier
|
||||
import org.eclipse.jdt.core.dom.QualifiedName
|
||||
import org.eclipse.jdt.core.dom.SimpleName
|
||||
import org.eclipse.jdt.core.dom.VariableDeclarationFragment
|
||||
|
||||
/**
|
||||
* @author caikang
|
||||
* @date 2016/12/27
|
||||
*/
|
||||
class AvoidAccessStaticViaInstanceRule : AbstractEclipseRule() {
|
||||
override fun getVisitor(ast: CompilationUnit, ruleContext: RuleContext): ASTVisitor {
|
||||
return object : ASTVisitor() {
|
||||
override fun visit(node: QualifiedName?): Boolean {
|
||||
if (node!!.parent !is MethodInvocation && node.parent !is VariableDeclarationFragment) {
|
||||
return false
|
||||
}
|
||||
val name = node.name
|
||||
val binding = name.resolveBinding()
|
||||
if (binding !is IVariableBinding || binding.getModifiers() and Modifier.STATIC == 0) {
|
||||
return true
|
||||
}
|
||||
val qualifier = node.qualifier
|
||||
val typeBinding = qualifier.resolveTypeBinding()
|
||||
if (qualifier.isSimpleName && typeBinding.name != qualifier.fullyQualifiedName) {
|
||||
violation(ruleContext, node, ast)
|
||||
return false
|
||||
}
|
||||
if (qualifier.isQualifiedName) {
|
||||
val qualifiedName = qualifier as QualifiedName
|
||||
if (typeBinding.name != qualifiedName.name.identifier) {
|
||||
violation(ruleContext, node, ast)
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun visit(node: FieldAccess): Boolean {
|
||||
val variableBinding = node.resolveFieldBinding() ?: return false
|
||||
if (variableBinding.modifiers and Modifier.STATIC == 0) {
|
||||
return true
|
||||
}
|
||||
if (node.expression is ClassInstanceCreation) {
|
||||
violation(ruleContext, node, ast)
|
||||
return true
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun visit(node: MethodInvocation?): Boolean {
|
||||
val methodBinding = node?.resolveMethodBinding() ?: return false
|
||||
if (methodBinding.modifiers and Modifier.STATIC == 0) {
|
||||
return true
|
||||
}
|
||||
if (node.expression is ClassInstanceCreation) {
|
||||
violation(ruleContext, node, ast)
|
||||
return true
|
||||
}
|
||||
val expression = node.expression
|
||||
if (expression is SimpleName && expression.identifier != expression.resolveTypeBinding().name) {
|
||||
violation(ruleContext, node, ast)
|
||||
return true
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 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.smartfox.eclipse.pmd.rule
|
||||
|
||||
import net.sourceforge.pmd.RuleContext
|
||||
import org.eclipse.jdt.core.dom.ASTVisitor
|
||||
import org.eclipse.jdt.core.dom.ClassInstanceCreation
|
||||
import org.eclipse.jdt.core.dom.CompilationUnit
|
||||
import org.eclipse.jdt.core.dom.FieldAccess
|
||||
import org.eclipse.jdt.core.dom.IVariableBinding
|
||||
import org.eclipse.jdt.core.dom.ImportDeclaration
|
||||
import org.eclipse.jdt.core.dom.MethodInvocation
|
||||
import org.eclipse.jdt.core.dom.Modifier
|
||||
import org.eclipse.jdt.core.dom.QualifiedName
|
||||
import org.eclipse.jdt.core.dom.TypeDeclaration
|
||||
import org.eclipse.jdt.core.dom.VariableDeclarationFragment
|
||||
|
||||
/**
|
||||
* @author caikang
|
||||
* @date 2016/12/27
|
||||
*/
|
||||
class AvoidUseDeprecationRule : AbstractEclipseRule() {
|
||||
override fun getVisitor(ast: CompilationUnit, ruleContext: RuleContext): ASTVisitor {
|
||||
return object : ASTVisitor() {
|
||||
override fun visit(node: ImportDeclaration?): Boolean {
|
||||
if (node!!.resolveBinding() != null && node.resolveBinding().isDeprecated) {
|
||||
violation(ruleContext, node, ast)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun visit(node: QualifiedName?): Boolean {
|
||||
if (node!!.parent !is MethodInvocation && node.parent !is VariableDeclarationFragment) {
|
||||
return false
|
||||
}
|
||||
val name = node.name
|
||||
val binding = name.resolveBinding()
|
||||
if (binding !is IVariableBinding || binding.getModifiers() and Modifier.STATIC == 0) {
|
||||
return true
|
||||
}
|
||||
if (binding.isDeprecated()) {
|
||||
violation(ruleContext, node, ast)
|
||||
return false
|
||||
}
|
||||
val qualifier = node.qualifier
|
||||
val typeBinding = qualifier.resolveTypeBinding()
|
||||
if (typeBinding.isDeprecated) {
|
||||
violation(ruleContext, node, ast)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun visit(node: TypeDeclaration?): Boolean {
|
||||
val superClass = node!!.superclassType
|
||||
if (superClass != null && superClass.resolveBinding().isDeprecated) {
|
||||
violation(ruleContext, node, ast)
|
||||
return true
|
||||
}
|
||||
val interfaces = node.resolveBinding().interfaces
|
||||
for (tb in interfaces) {
|
||||
if (tb.isDeprecated) {
|
||||
violation(ruleContext, node, ast)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun visit(node: FieldAccess?): Boolean {
|
||||
val variableBinding = node!!.resolveFieldBinding() ?: return false
|
||||
if (variableBinding.isDeprecated) {
|
||||
violation(ruleContext, node, ast)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun visit(node: MethodInvocation): Boolean {
|
||||
val methodBinding = node.resolveMethodBinding() ?: return false
|
||||
if (methodBinding.isDeprecated) {
|
||||
violation(ruleContext, node, ast)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun visit(node: ClassInstanceCreation?): Boolean {
|
||||
if (node!!.resolveTypeBinding().isDeprecated) {
|
||||
violation(ruleContext, node, ast)
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* 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.smartfox.eclipse.pmd.rule
|
||||
|
||||
import net.sourceforge.pmd.RuleContext
|
||||
import org.eclipse.jdt.core.dom.ASTVisitor
|
||||
import org.eclipse.jdt.core.dom.CompilationUnit
|
||||
import org.eclipse.jdt.core.dom.ITypeBinding
|
||||
import org.eclipse.jdt.core.dom.MethodInvocation
|
||||
import org.eclipse.jdt.core.dom.VariableDeclarationStatement
|
||||
|
||||
/**
|
||||
* @author zenghou.fw
|
||||
* @date 2016/12/27
|
||||
*/
|
||||
class MapOrSetKeyShouldOverrideHashCodeEqualsRule : AbstractEclipseRule() {
|
||||
|
||||
val methodEquals = "equals"
|
||||
val methodHashCode = "hashCode"
|
||||
val methodAdd = "add"
|
||||
val methodPut = "put"
|
||||
|
||||
override fun getVisitor(ast: CompilationUnit, ruleContext: RuleContext): ASTVisitor {
|
||||
return object : ASTVisitor() {
|
||||
|
||||
override fun visit(node: VariableDeclarationStatement): Boolean {
|
||||
if (!node.type.isParameterizedType) {
|
||||
return true
|
||||
}
|
||||
val typeBinding = node.type.resolveBinding()
|
||||
if (isSet(typeBinding) || isMap(typeBinding)) {
|
||||
val argumentTypes = typeBinding.typeArguments
|
||||
if (argumentTypes != null && argumentTypes.isNotEmpty()) {
|
||||
if (!isOverrideEqualsAndHashCode(argumentTypes[0])) {
|
||||
violation(ruleContext, node, ast)
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun visit(node: MethodInvocation): Boolean {
|
||||
val methodBinding = node.resolveMethodBinding() ?: return false
|
||||
val callerType = methodBinding.declaringClass
|
||||
|
||||
if (methodAdd == methodBinding.name) {
|
||||
if (!isSet(callerType)) {
|
||||
return true
|
||||
}
|
||||
val parameterTypes = methodBinding.parameterTypes
|
||||
if (parameterTypes != null && parameterTypes.isNotEmpty()) {
|
||||
if (!isOverrideEqualsAndHashCode(parameterTypes[0])) {
|
||||
violation(ruleContext, node, ast)
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (methodPut == methodBinding.name) {
|
||||
if (!isMap(callerType)) {
|
||||
return true
|
||||
}
|
||||
val parameterTypes = methodBinding.parameterTypes
|
||||
if (parameterTypes != null && parameterTypes.isNotEmpty()) {
|
||||
if (!isOverrideEqualsAndHashCode(parameterTypes[0])) {
|
||||
violation(ruleContext, node, ast)
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun isOverrideEqualsAndHashCode(genericType: ITypeBinding): Boolean {
|
||||
// skip enum
|
||||
if (genericType.isEnum || genericType.isInterface || genericType.isTypeVariable || genericType.isWildcardType) {
|
||||
return true
|
||||
}
|
||||
|
||||
val methodBindings = genericType.declaredMethods ?: return false
|
||||
|
||||
val overrideCount = methodBindings.asSequence().filter {
|
||||
//find equals(Object o) and hashCode() with @Override
|
||||
methodEquals == it.name || methodHashCode == it.name
|
||||
}.filter {
|
||||
when (it.name) {
|
||||
methodEquals -> {
|
||||
val parameterTypes = it.parameterTypes
|
||||
parameterTypes != null && parameterTypes.isNotEmpty()
|
||||
&& Object::class.java.name == parameterTypes[0].qualifiedName
|
||||
}
|
||||
methodHashCode -> {
|
||||
val parameterTypes = it.parameterTypes
|
||||
parameterTypes == null || parameterTypes.isEmpty()
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
}.count()
|
||||
return overrideCount == 2
|
||||
}
|
||||
|
||||
private fun isSet(typeBinding: ITypeBinding): Boolean {
|
||||
return java.util.Set::class.java.name == typeBinding.binaryName
|
||||
}
|
||||
|
||||
private fun isMap(typeBinding: ITypeBinding): Boolean {
|
||||
return java.util.Map::class.java.name == typeBinding.binaryName
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.smartfox.eclipse.pmd.rule
|
||||
|
||||
import com.alibaba.smartfox.eclipse.message.P3cBundle
|
||||
import net.sourceforge.pmd.RuleContext
|
||||
import org.eclipse.jdt.core.dom.ASTVisitor
|
||||
import org.eclipse.jdt.core.dom.CompilationUnit
|
||||
import org.eclipse.jdt.core.dom.MethodDeclaration
|
||||
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding
|
||||
import java.util.Arrays
|
||||
import javax.annotation.Generated
|
||||
|
||||
/**
|
||||
* @author caikang
|
||||
* @date 2016/12/24
|
||||
*/
|
||||
class MissingOverrideAnnotationRule : AbstractEclipseRule() {
|
||||
override fun getErrorMessage(): String {
|
||||
return P3cBundle.getMessage("rule.standalone.MissingOverrideAnnotationRule.error")
|
||||
}
|
||||
|
||||
override fun getVisitor(ast: CompilationUnit, ruleContext: RuleContext): ASTVisitor {
|
||||
return MissingOverrideVisitor(ast, ruleContext)
|
||||
}
|
||||
|
||||
private inner class MissingOverrideVisitor(private val ast: CompilationUnit,
|
||||
private val ruleContext: RuleContext) : ASTVisitor() {
|
||||
|
||||
override fun visit(node: MethodDeclaration?): Boolean {
|
||||
val methodBinding = node!!.resolveBinding()
|
||||
val declaringClass = methodBinding.declaringClass ?: return super.visit(node)
|
||||
if (declaringClass.isInterface) {
|
||||
return super.visit(node)
|
||||
}
|
||||
val abs = methodBinding.annotations
|
||||
if (abs.any {
|
||||
Override::class.java.canonicalName == it.annotationType.binaryName
|
||||
}) {
|
||||
return super.visit(node)
|
||||
}
|
||||
try {
|
||||
val field = methodBinding.javaClass.getDeclaredField("binding")
|
||||
field.isAccessible = true
|
||||
val internalBinding = field.get(methodBinding) as MethodBinding
|
||||
if (internalBinding.isStatic || !(internalBinding.isImplementing || internalBinding.isOverriding)
|
||||
|| isGenerated(internalBinding)) {
|
||||
return super.visit(node)
|
||||
}
|
||||
violation(ruleContext, node, ast)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
return super.visit(node)
|
||||
}
|
||||
|
||||
/**
|
||||
* skip @Override check for generated code by lombok
|
||||
* @param internalBinding
|
||||
* @return
|
||||
*/
|
||||
private fun isGenerated(internalBinding: MethodBinding): Boolean {
|
||||
val annotationBindings = internalBinding.annotations ?: return false
|
||||
return annotationBindings.any {
|
||||
it.annotationType != null && Arrays.equals(Generated::class.java.name.toCharArray(),
|
||||
it.annotationType.readableName())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.smartfox.eclipse.ui
|
||||
|
||||
import org.eclipse.jface.preference.PreferencePage
|
||||
import org.eclipse.swt.widgets.Composite
|
||||
import org.eclipse.swt.widgets.Control
|
||||
import org.eclipse.ui.IWorkbench
|
||||
import org.eclipse.ui.IWorkbenchPreferencePage
|
||||
|
||||
/**
|
||||
*
|
||||
* @author caikang
|
||||
* @date 2017/09/01
|
||||
*/
|
||||
class AllRulesPreferencePage : PreferencePage(), IWorkbenchPreferencePage {
|
||||
override fun init(parent: IWorkbench?) {
|
||||
}
|
||||
|
||||
override fun createContents(parent: Composite): Control {
|
||||
return AllRulesView(parent).content
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.smartfox.eclipse.ui
|
||||
|
||||
import com.alibaba.smartfox.eclipse.SmartfoxActivator
|
||||
import org.eclipse.swt.SWT
|
||||
import org.eclipse.swt.layout.FillLayout
|
||||
import org.eclipse.swt.widgets.Composite
|
||||
import org.eclipse.swt.widgets.List
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author caikang
|
||||
* @date 2017/09/01
|
||||
*/
|
||||
class AllRulesView(parent: Composite) {
|
||||
val content = Composite(parent, SWT.NONE)
|
||||
|
||||
private val ruleList = SmartfoxActivator.instance.ruleSets.allRules.toList()
|
||||
|
||||
init {
|
||||
content.layout = FillLayout()
|
||||
val list = List(content, SWT.BORDER or SWT.SINGLE or SWT.V_SCROLL or SWT.PUSH or SWT.H_SCROLL)
|
||||
ruleList.forEach {
|
||||
list.add(it.message)
|
||||
}
|
||||
val ruleDetail = RuleDetailComposite(content, SWT.PUSH)
|
||||
list.addListener(SWT.Selection) {
|
||||
val index = list.selectionIndex
|
||||
val rule = ruleList.getOrNull(index) ?: return@addListener
|
||||
ruleDetail.refresh(rule)
|
||||
}
|
||||
list.select(0)
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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.smartfox.eclipse.ui
|
||||
|
||||
import org.eclipse.jface.viewers.ITreeContentProvider
|
||||
import org.eclipse.jface.viewers.Viewer
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author caikang
|
||||
* @date 2017/06/08
|
||||
*/
|
||||
object InspectionResultTreeContentProvider : ITreeContentProvider {
|
||||
private lateinit var input: InspectionResults
|
||||
|
||||
override fun getParent(element: Any?): Any {
|
||||
return input
|
||||
}
|
||||
|
||||
override fun hasChildren(element: Any?): Boolean {
|
||||
return element is InspectionResults || element is LevelViolations || element is RuleViolations
|
||||
|| element is FileMarkers
|
||||
}
|
||||
|
||||
override fun getChildren(parentElement: Any?): Array<Any> {
|
||||
if (parentElement is InspectionResults) {
|
||||
return parentElement.errors.toTypedArray()
|
||||
}
|
||||
if (parentElement is LevelViolations) {
|
||||
return parentElement.rules.toTypedArray()
|
||||
}
|
||||
if (parentElement is RuleViolations) {
|
||||
return parentElement.files.toTypedArray()
|
||||
}
|
||||
if (parentElement is FileMarkers) {
|
||||
return parentElement.markers.toTypedArray()
|
||||
}
|
||||
return emptyArray()
|
||||
}
|
||||
|
||||
override fun getElements(inputElement: Any?): Array<Any> {
|
||||
return input.errors.toTypedArray()
|
||||
}
|
||||
|
||||
override fun inputChanged(viewer: Viewer?, oldInput: Any?, newInput: Any?) {
|
||||
if (newInput == null) {
|
||||
return
|
||||
}
|
||||
this.input = newInput as InspectionResults
|
||||
}
|
||||
|
||||
override fun dispose() {
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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.smartfox.eclipse.ui
|
||||
|
||||
import com.alibaba.smartfox.eclipse.SmartfoxActivator
|
||||
import com.alibaba.smartfox.eclipse.pmd.RulePriority
|
||||
import org.eclipse.jface.viewers.LabelProvider
|
||||
import org.eclipse.swt.graphics.Image
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author caikang
|
||||
* @date 2017/06/08
|
||||
*/
|
||||
object InspectionResultTreeLabelProvider : LabelProvider() {
|
||||
override fun getImage(element: Any?): Image? {
|
||||
if (element is LevelViolations) {
|
||||
val imageName = when (element.level) {
|
||||
RulePriority.Blocker.title, RulePriority.Critical.title -> "${element.level}.gif".toLowerCase()
|
||||
else -> "${element.level}.png".toLowerCase()
|
||||
}
|
||||
return SmartfoxActivator.instance.getImage("icons/view/$imageName")
|
||||
}
|
||||
if (element is FileMarkers) {
|
||||
if (element.file.fullPath.toPortableString().endsWith("java")) {
|
||||
return SmartfoxActivator.instance.getImage("icons/view/class_obj.png")
|
||||
}
|
||||
return SmartfoxActivator.instance.getImage("icons/view/file_obj.png")
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
override fun getText(element: Any?): String {
|
||||
if (element is LevelViolations) {
|
||||
return "${element.level} (${element.count} Violations)"
|
||||
}
|
||||
if (element is RuleViolations) {
|
||||
val rule = SmartfoxActivator.instance.getRule(element.rule)
|
||||
return "${rule.message} (${element.count} Violations)"
|
||||
}
|
||||
if (element is FileMarkers) {
|
||||
return element.file.fullPath.toPortableString().substringAfterLast("/") +
|
||||
" (${element.markers.size} Violations)"
|
||||
}
|
||||
if (element is MarkerViolation) {
|
||||
val desc = element.violation.description
|
||||
return "$desc (at line ${element.violation.beginLine})"
|
||||
}
|
||||
return element.toString()
|
||||
}
|
||||
}
|
@ -0,0 +1,249 @@
|
||||
/*
|
||||
* 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.smartfox.eclipse.ui
|
||||
|
||||
import com.alibaba.smartfox.eclipse.SmartfoxActivator
|
||||
import com.alibaba.smartfox.eclipse.job.P3CMutex
|
||||
import com.alibaba.smartfox.eclipse.util.MarkerUtil
|
||||
import org.eclipse.core.resources.IFile
|
||||
import org.eclipse.core.resources.IMarker
|
||||
import org.eclipse.core.runtime.IProgressMonitor
|
||||
import org.eclipse.core.runtime.IStatus
|
||||
import org.eclipse.core.runtime.Status
|
||||
import org.eclipse.core.runtime.jobs.Job
|
||||
import org.eclipse.jface.action.Action
|
||||
import org.eclipse.jface.action.Separator
|
||||
import org.eclipse.jface.util.OpenStrategy
|
||||
import org.eclipse.jface.viewers.ISelection
|
||||
import org.eclipse.jface.viewers.IStructuredSelection
|
||||
import org.eclipse.jface.viewers.ITreeSelection
|
||||
import org.eclipse.jface.viewers.TreeViewer
|
||||
import org.eclipse.swt.SWT
|
||||
import org.eclipse.swt.layout.FillLayout
|
||||
import org.eclipse.swt.widgets.Composite
|
||||
import org.eclipse.swt.widgets.Display
|
||||
import org.eclipse.ui.IWorkbenchPage
|
||||
import org.eclipse.ui.OpenAndLinkWithEditorHelper
|
||||
import org.eclipse.ui.PartInitException
|
||||
import org.eclipse.ui.PlatformUI
|
||||
import org.eclipse.ui.ide.IDE
|
||||
import org.eclipse.ui.ide.ResourceUtil
|
||||
import org.eclipse.ui.internal.views.markers.MarkerSupportInternalUtilities
|
||||
import org.eclipse.ui.part.ViewPart
|
||||
import org.eclipse.ui.texteditor.ITextEditor
|
||||
import java.util.HashSet
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author caikang
|
||||
* @date 2017/06/08
|
||||
*/
|
||||
class InspectionResultView : ViewPart() {
|
||||
lateinit var treeViewer: TreeViewer
|
||||
|
||||
private val quickFixAction = QuickFixAction(this)
|
||||
|
||||
override fun setFocus() {
|
||||
treeViewer.control.setFocus()
|
||||
}
|
||||
|
||||
override fun createPartControl(parent: Composite) {
|
||||
parent.layout = FillLayout()
|
||||
treeViewer = TreeViewer(parent, SWT.MULTI or SWT.H_SCROLL or SWT.V_SCROLL)
|
||||
treeViewer.setUseHashlookup(true)
|
||||
treeViewer.contentProvider = InspectionResultTreeContentProvider
|
||||
treeViewer.labelProvider = InspectionResultTreeLabelProvider
|
||||
treeViewer.input = InspectionResults
|
||||
|
||||
InspectionResults.view = this
|
||||
|
||||
addDoubleClickListener()
|
||||
|
||||
addSelectionChangedListener()
|
||||
|
||||
initToolBar()
|
||||
|
||||
addLinkWithEditorSupport()
|
||||
site.selectionProvider = treeViewer
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
InspectionResults.clear()
|
||||
refreshView(InspectionResults)
|
||||
}
|
||||
|
||||
fun refreshView(input: InspectionResults) {
|
||||
Display.getDefault().asyncExec {
|
||||
treeViewer.refresh(input, true)
|
||||
contentDescription = input.contentDescription
|
||||
}
|
||||
}
|
||||
|
||||
private fun addSelectionChangedListener() {
|
||||
treeViewer.addSelectionChangedListener inner@ {
|
||||
val selection = it.selection as? IStructuredSelection ?: return@inner
|
||||
val item = selection.firstElement ?: return@inner
|
||||
val ruleDetailView = RuleDetailView.showAndGetView()
|
||||
when (item) {
|
||||
is MarkerViolation -> {
|
||||
ruleDetailView.refresh(item.violation.rule)
|
||||
quickFixAction.updateFileMarkers(listOf(FileMarkers(item.marker.resource as IFile, listOf(item))))
|
||||
}
|
||||
is FileMarkers -> {
|
||||
ruleDetailView.refresh(item.markers.first().violation.rule)
|
||||
quickFixAction.updateFileMarkers(listOf(item))
|
||||
}
|
||||
is RuleViolations -> {
|
||||
ruleDetailView.refresh(SmartfoxActivator.instance.getRule(item.rule))
|
||||
quickFixAction.updateFileMarkers(item.files)
|
||||
}
|
||||
else -> {
|
||||
quickFixAction.updateFileMarkers(emptyList())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun initToolBar() {
|
||||
val bars = viewSite.actionBars
|
||||
val tm = bars.toolBarManager
|
||||
|
||||
val clearAction = object : Action("Clear Markers") {
|
||||
override fun run() {
|
||||
val job = object : Job("Clear Markers") {
|
||||
override fun run(monitor: IProgressMonitor): IStatus {
|
||||
if (monitor.isCanceled) {
|
||||
Status.CANCEL_STATUS
|
||||
}
|
||||
clear()
|
||||
return Status.OK_STATUS
|
||||
}
|
||||
}
|
||||
job.rule = P3CMutex
|
||||
job.schedule()
|
||||
}
|
||||
}
|
||||
|
||||
clearAction.imageDescriptor = SmartfoxActivator.getImageDescriptor("icons/actions/clear.png")
|
||||
|
||||
tm.add(Separator("Markers"))
|
||||
tm.add(clearAction)
|
||||
|
||||
tm.add(Separator("FilterGroup"))
|
||||
tm.add(quickFixAction)
|
||||
}
|
||||
|
||||
private fun addLinkWithEditorSupport() {
|
||||
object : OpenAndLinkWithEditorHelper(treeViewer) {
|
||||
override fun activate(selection: ISelection) {
|
||||
val currentMode = OpenStrategy.getOpenMethod()
|
||||
try {
|
||||
OpenStrategy.setOpenMethod(OpenStrategy.DOUBLE_CLICK)
|
||||
openSelectedMarkers()
|
||||
} finally {
|
||||
OpenStrategy.setOpenMethod(currentMode)
|
||||
}
|
||||
}
|
||||
|
||||
override fun linkToEditor(selection: ISelection?) {
|
||||
}
|
||||
|
||||
override fun open(selection: ISelection, activate: Boolean) {
|
||||
val structured = selection as ITreeSelection
|
||||
val element = structured.firstElement as? MarkerViolation ?: return
|
||||
val page = site.page
|
||||
if (element.marker.exists()) {
|
||||
openMarkerInEditor(element.marker, page)
|
||||
return
|
||||
}
|
||||
val file = element.marker.resource as IFile
|
||||
val editor = IDE.openEditor(page, file) as ITextEditor
|
||||
editor.selectAndReveal(MarkerUtil.getAbsoluteRange(file, element.violation).start, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun openSelectedMarkers() {
|
||||
val markers = getOpenableMarkers()
|
||||
for (marker in markers) {
|
||||
val page = site.page
|
||||
openMarkerInEditor(marker, page)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getOpenableMarkers(): Array<IMarker> {
|
||||
val structured = treeViewer.selection as ITreeSelection
|
||||
val elements = structured.iterator()
|
||||
val result = HashSet<IMarker>()
|
||||
|
||||
while (elements.hasNext()) {
|
||||
val marker = elements.next() as? IMarker ?: return emptyArray()
|
||||
result.add(marker)
|
||||
}
|
||||
return result.toTypedArray()
|
||||
}
|
||||
|
||||
|
||||
fun openMarkerInEditor(marker: IMarker?, page: IWorkbenchPage) {
|
||||
val editor = page.activeEditor
|
||||
if (editor != null) {
|
||||
val input = editor.editorInput
|
||||
val file = ResourceUtil.getFile(input)
|
||||
if (file != null) {
|
||||
if (marker!!.resource == file && OpenStrategy.activateOnOpen()) {
|
||||
page.activate(editor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (marker != null && marker.resource is IFile) {
|
||||
try {
|
||||
IDE.openEditor(page, marker, OpenStrategy.activateOnOpen())
|
||||
} catch (e: PartInitException) {
|
||||
MarkerSupportInternalUtilities.showViewError(e)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private fun addDoubleClickListener() {
|
||||
treeViewer.addDoubleClickListener({ event ->
|
||||
val selection = event.selection
|
||||
if (selection !is ITreeSelection || selection.size() != 1) {
|
||||
return@addDoubleClickListener
|
||||
}
|
||||
val obj = selection.firstElement
|
||||
if (treeViewer.isExpandable(obj)) {
|
||||
treeViewer.setExpandedState(obj, !treeViewer.getExpandedState(obj))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
companion object {
|
||||
val viewId = "com.alibaba.smartfox.eclipse.ui.InspectionResultView"
|
||||
|
||||
fun activeViews() {
|
||||
PlatformUI.getWorkbench().activeWorkbenchWindow.activePage.showView(viewId)
|
||||
RuleDetailView.showAndGetView()
|
||||
}
|
||||
|
||||
fun getView(): InspectionResultView {
|
||||
return PlatformUI.getWorkbench().activeWorkbenchWindow.activePage.findView(viewId) as InspectionResultView
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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.smartfox.eclipse.ui
|
||||
|
||||
import com.alibaba.smartfox.eclipse.pmd.RulePriority
|
||||
import com.alibaba.smartfox.eclipse.util.MarkerUtil
|
||||
import org.eclipse.core.resources.IFile
|
||||
import org.eclipse.core.resources.IMarker
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author caikang
|
||||
* @date 2017/06/13
|
||||
*/
|
||||
object InspectionResults {
|
||||
val fileViolations = linkedMapOf<IFile, List<MarkerViolation>>()
|
||||
|
||||
var contentDescription = ""
|
||||
|
||||
val errors: List<LevelViolations> get() = run {
|
||||
val result = toLevelViolationList(fileViolations.values.flatten())
|
||||
contentDescription = getContentDescription(result)
|
||||
result
|
||||
}
|
||||
|
||||
lateinit var view: InspectionResultView
|
||||
|
||||
|
||||
fun clear() {
|
||||
fileViolations.forEach { t, u ->
|
||||
MarkerUtil.removeAllMarkers(t)
|
||||
}
|
||||
fileViolations.clear()
|
||||
// update contentDescription
|
||||
errors
|
||||
}
|
||||
|
||||
private fun toLevelViolationList(markers: Collection<MarkerViolation>): List<LevelViolations> {
|
||||
return markers.groupBy {
|
||||
it.violation.rule.priority.priority
|
||||
}.mapValues {
|
||||
it.value.groupBy {
|
||||
it.violation.rule.name
|
||||
}.mapValues {
|
||||
it.value.groupBy {
|
||||
it.marker.resource as IFile
|
||||
}.map {
|
||||
FileMarkers(it.key, it.value)
|
||||
}
|
||||
}.map {
|
||||
RuleViolations(it.key, it.value)
|
||||
}
|
||||
}.toSortedMap().map {
|
||||
val level = RulePriority.valueOf(it.key).title
|
||||
LevelViolations(level, it.value)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateFileViolations(file: IFile, markers: List<MarkerViolation>) {
|
||||
if (markers.isEmpty()) {
|
||||
fileViolations.remove(file)
|
||||
} else {
|
||||
fileViolations[file] = markers
|
||||
}
|
||||
view.refreshView(this)
|
||||
}
|
||||
|
||||
fun removeMarker(marker: IMarker) {
|
||||
val file = marker.resource as IFile
|
||||
val list = fileViolations[file] ?: return
|
||||
val result = list.filter {
|
||||
it.marker != marker
|
||||
}
|
||||
fileViolations[file] = result
|
||||
marker.delete()
|
||||
view.refreshView(this)
|
||||
}
|
||||
|
||||
fun getContentDescription(errors: List<LevelViolations>): String {
|
||||
val map = errors.associateBy {
|
||||
it.level
|
||||
}
|
||||
|
||||
return "${map[RulePriority.Blocker.title]?.count ?: 0} Blockers," +
|
||||
"${map[RulePriority.Critical.title]?.count ?: 0} Criticals," +
|
||||
"${map[RulePriority.Major.title]?.count ?: 0} Majors"
|
||||
}
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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.smartfox.eclipse.ui
|
||||
|
||||
import com.alibaba.p3c.pmd.lang.java.rule.flowcontrol.NeedBraceRule
|
||||
import com.alibaba.smartfox.eclipse.RunWithoutViewRefresh
|
||||
import com.alibaba.smartfox.eclipse.SmartfoxActivator
|
||||
import com.alibaba.smartfox.eclipse.job.CodeAnalysis
|
||||
import com.alibaba.smartfox.eclipse.job.P3CMutex
|
||||
import com.alibaba.smartfox.eclipse.pmd.rule.MissingOverrideAnnotationRule
|
||||
import com.alibaba.smartfox.eclipse.util.CleanUps
|
||||
import com.alibaba.smartfox.eclipse.util.getResolution
|
||||
import org.eclipse.core.runtime.IProgressMonitor
|
||||
import org.eclipse.core.runtime.IStatus
|
||||
import org.eclipse.core.runtime.Status
|
||||
import org.eclipse.core.runtime.SubMonitor
|
||||
import org.eclipse.core.runtime.jobs.Job
|
||||
import org.eclipse.jface.action.Action
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author caikang
|
||||
* @date 2017/06/14
|
||||
*/
|
||||
class QuickFixAction(val view: InspectionResultView) : Action("Quick Fix") {
|
||||
init {
|
||||
imageDescriptor = SmartfoxActivator.getImageDescriptor("icons/actions/quickfixBulb.png")
|
||||
isEnabled = false
|
||||
}
|
||||
|
||||
var markers = listOf<FileMarkers>()
|
||||
|
||||
fun updateFileMarkers(markers: List<FileMarkers>) {
|
||||
this.markers = markers
|
||||
isEnabled = enabled()
|
||||
}
|
||||
|
||||
override fun run() {
|
||||
if (markers.isEmpty()) {
|
||||
return
|
||||
}
|
||||
runJob()
|
||||
}
|
||||
|
||||
private fun runJob() {
|
||||
val job = object : Job("Perform Quick Fix") {
|
||||
override fun run(monitor: IProgressMonitor): IStatus {
|
||||
val subMonitor = SubMonitor.convert(monitor, markers.size)
|
||||
monitor.setTaskName("Process File")
|
||||
markers.forEach {
|
||||
if (monitor.isCanceled) {
|
||||
return@run Status.CANCEL_STATUS
|
||||
}
|
||||
monitor.subTask(it.file.name)
|
||||
val childMonitor = subMonitor.newChild(1)
|
||||
if (useCleanUpRefactoring()) {
|
||||
CleanUps.fix(it.file, childMonitor)
|
||||
} else {
|
||||
it.markers.filter { it.marker.exists() }.forEach {
|
||||
(it.marker.getResolution() as RunWithoutViewRefresh).run(it.marker, true)
|
||||
}
|
||||
}
|
||||
val markers = CodeAnalysis.processFileToMakers(it.file, monitor)
|
||||
InspectionResults.updateFileViolations(it.file, markers)
|
||||
}
|
||||
|
||||
return Status.OK_STATUS
|
||||
}
|
||||
}
|
||||
job.rule = P3CMutex
|
||||
job.schedule()
|
||||
|
||||
}
|
||||
|
||||
fun enabled(): Boolean {
|
||||
if (useCleanUpRefactoring()) {
|
||||
return true
|
||||
}
|
||||
if (markers.isEmpty()) {
|
||||
return false
|
||||
}
|
||||
val marker = markers.first().markers.first().marker
|
||||
return marker.exists() && marker.getResolution() != null
|
||||
}
|
||||
|
||||
private fun useCleanUpRefactoring(): Boolean {
|
||||
if (markers.isEmpty()) {
|
||||
return false
|
||||
}
|
||||
val ruleName = markers.first().markers.first().violation.rule.name
|
||||
return ruleName == MissingOverrideAnnotationRule::class.java.simpleName
|
||||
|| ruleName == NeedBraceRule::class.java.simpleName
|
||||
}
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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.smartfox.eclipse.ui
|
||||
|
||||
import com.alibaba.smartfox.eclipse.pmd.RulePriority
|
||||
import com.alibaba.smartfox.eclipse.ui.pmd.ContentBuilder
|
||||
import com.alibaba.smartfox.eclipse.ui.pmd.StringArranger
|
||||
import net.sourceforge.pmd.Rule
|
||||
import org.eclipse.swt.SWT
|
||||
import org.eclipse.swt.custom.StyledText
|
||||
import org.eclipse.swt.layout.FillLayout
|
||||
import org.eclipse.swt.widgets.Composite
|
||||
|
||||
/**
|
||||
*
|
||||
* @author caikang
|
||||
* @date 2017/09/01
|
||||
*/
|
||||
class RuleDetailComposite(parent: Composite, style: Int = SWT.NONE) {
|
||||
private val viewField: StyledText
|
||||
private val contentBuilder = ContentBuilder()
|
||||
private val arranger = StringArranger(" ")
|
||||
private val panel = Composite(parent, style)
|
||||
|
||||
init {
|
||||
panel.layout = FillLayout()
|
||||
|
||||
viewField = StyledText(panel, SWT.BORDER or SWT.H_SCROLL or SWT.V_SCROLL)
|
||||
viewField.wordWrap = true
|
||||
viewField.tabs = 20
|
||||
viewField.text = "Select a result item to show rule detail."
|
||||
viewField.editable = false
|
||||
}
|
||||
|
||||
fun refresh(rule: Rule) {
|
||||
contentBuilder.clear()
|
||||
viewField.text = ""
|
||||
contentBuilder.addHeading("Name")
|
||||
contentBuilder.addText(rule.name)
|
||||
contentBuilder.addHeading("Severity")
|
||||
contentBuilder.addText(RulePriority.valueOf(rule.priority.priority).title)
|
||||
contentBuilder.addHeading("Message")
|
||||
contentBuilder.addText(rule.message)
|
||||
if (!rule.description.isNullOrBlank()) {
|
||||
contentBuilder.addHeading("Description")
|
||||
contentBuilder.addRawText(arranger.format(rule.description).toString())
|
||||
}
|
||||
|
||||
val examples = rule.examples
|
||||
if (examples.isEmpty()) {
|
||||
contentBuilder.showOn(viewField)
|
||||
return
|
||||
}
|
||||
|
||||
contentBuilder.setLanguage(rule.language)
|
||||
|
||||
contentBuilder.addHeading("Examples")
|
||||
contentBuilder.addText("")
|
||||
for (example in rule.examples) {
|
||||
contentBuilder.addCode(example.trim { it <= ' ' })
|
||||
contentBuilder.addText("")
|
||||
}
|
||||
contentBuilder.showOn(viewField)
|
||||
|
||||
if (contentBuilder.hasLinks()) {
|
||||
contentBuilder.addLinkHandler(viewField)
|
||||
}
|
||||
viewField.update()
|
||||
}
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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.smartfox.eclipse.ui
|
||||
|
||||
import com.alibaba.smartfox.eclipse.SmartfoxActivator
|
||||
import net.sourceforge.pmd.Rule
|
||||
import org.eclipse.jface.action.Action
|
||||
import org.eclipse.jface.action.Separator
|
||||
import org.eclipse.swt.SWT
|
||||
import org.eclipse.swt.custom.ScrolledComposite
|
||||
import org.eclipse.swt.layout.FillLayout
|
||||
import org.eclipse.swt.widgets.Composite
|
||||
import org.eclipse.swt.widgets.Display
|
||||
import org.eclipse.swt.widgets.Shell
|
||||
import org.eclipse.ui.IWorkbenchPage
|
||||
import org.eclipse.ui.PlatformUI
|
||||
import org.eclipse.ui.part.ViewPart
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author caikang
|
||||
* @date 2017/06/12
|
||||
*/
|
||||
open class RuleDetailView : ViewPart() {
|
||||
|
||||
private lateinit var ruleDetailComposite: RuleDetailComposite
|
||||
|
||||
override fun setFocus() {
|
||||
}
|
||||
|
||||
override fun createPartControl(parent: Composite) {
|
||||
ruleDetailComposite = RuleDetailComposite(parent)
|
||||
initToolBar()
|
||||
}
|
||||
|
||||
fun refresh(rule: Rule) {
|
||||
ruleDetailComposite.refresh(rule)
|
||||
}
|
||||
|
||||
|
||||
private fun initToolBar() {
|
||||
val bars = viewSite.actionBars
|
||||
val tm = bars.toolBarManager
|
||||
|
||||
val rulesAction = object : Action("Show Rules") {
|
||||
override fun run() {
|
||||
val shell = Shell(Display.getDefault())
|
||||
shell.text = "All Rules"
|
||||
shell.layout = FillLayout()
|
||||
|
||||
val sc = ScrolledComposite(shell, SWT.V_SCROLL or SWT.H_SCROLL)
|
||||
|
||||
val rulesView = AllRulesView(sc)
|
||||
|
||||
sc.expandHorizontal = true
|
||||
sc.expandVertical = true
|
||||
|
||||
sc.content = rulesView.content
|
||||
|
||||
shell.open()
|
||||
}
|
||||
}
|
||||
|
||||
rulesAction.imageDescriptor = SmartfoxActivator.getImageDescriptor("icons/actions/rules.png")
|
||||
|
||||
tm.add(Separator("Markers"))
|
||||
tm.add(rulesAction)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun showAndGetView(): RuleDetailView {
|
||||
return PlatformUI.getWorkbench().activeWorkbenchWindow.activePage.showView(
|
||||
"com.alibaba.smartfox.eclipse.ui.RuleDetailView", null,
|
||||
IWorkbenchPage.VIEW_VISIBLE) as RuleDetailView
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.smartfox.eclipse.ui
|
||||
|
||||
import com.alibaba.smartfox.eclipse.util.MarkerUtil
|
||||
import net.sourceforge.pmd.RuleViolation
|
||||
import org.eclipse.core.resources.IFile
|
||||
import org.eclipse.core.resources.IMarker
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author caikang
|
||||
* @date 2017/06/13
|
||||
*/
|
||||
data class LevelViolations(var level: String, var rules: List<RuleViolations>,
|
||||
var count: Int = rules.sumBy { it.count }) {
|
||||
fun removeMarkers() {
|
||||
rules.forEach {
|
||||
it.removeMarkers()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class RuleViolations(var rule: String, var files: List<FileMarkers>,
|
||||
var count: Int = files.sumBy { it.markers.size }) {
|
||||
fun removeMarkers() {
|
||||
files.forEach {
|
||||
it.removeMarkers()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class FileMarkers(var file: IFile, var markers: List<MarkerViolation>) {
|
||||
fun removeMarkers() {
|
||||
MarkerUtil.removeAllMarkers(file)
|
||||
}
|
||||
}
|
||||
|
||||
data class MarkerViolation(val marker: IMarker, val violation: RuleViolation)
|
@ -0,0 +1,20 @@
|
||||
package com.alibaba.smartfox.eclipse.ui.pmd
|
||||
|
||||
import org.eclipse.swt.custom.LineStyleEvent
|
||||
import org.eclipse.swt.custom.LineStyleListener
|
||||
|
||||
/**
|
||||
* This class performs the syntax highlighting and styling for Pmpe
|
||||
* * PmpeLineStyleListener constructor
|
||||
|
||||
* @param theSyntaxData the syntax data to use
|
||||
*/
|
||||
class BasicLineStyleListener(theSyntaxData: SyntaxData) : StyleExtractor(theSyntaxData), LineStyleListener {
|
||||
/**
|
||||
* Called by StyledText to get styles for a line
|
||||
*/
|
||||
override fun lineGetStyle(event: LineStyleEvent) {
|
||||
val styles = lineStylesFor(event.lineText, event.lineOffset, event.lineText.length)
|
||||
event.styles = styles.toTypedArray()
|
||||
}
|
||||
}
|
@ -0,0 +1,158 @@
|
||||
package com.alibaba.smartfox.eclipse.ui.pmd
|
||||
|
||||
import net.sourceforge.pmd.lang.Language
|
||||
import org.eclipse.swt.SWT
|
||||
import org.eclipse.swt.custom.StyleRange
|
||||
import org.eclipse.swt.custom.StyledText
|
||||
import org.eclipse.swt.graphics.Point
|
||||
import org.eclipse.swt.widgets.Display
|
||||
import org.eclipse.ui.PlatformUI
|
||||
import java.net.URL
|
||||
import java.util.ArrayList
|
||||
import java.util.Arrays
|
||||
import java.util.HashMap
|
||||
|
||||
/**
|
||||
*
|
||||
* @author caikang
|
||||
* @date 2017/07/20
|
||||
*/
|
||||
class ContentBuilder {
|
||||
private val CR = '\n'
|
||||
private val buffer = StringBuilder()
|
||||
private val headingSpans = ArrayList<IntArray>()
|
||||
private val codeSpans = ArrayList<IntArray>()
|
||||
private val linksBySpan = HashMap<IntArray, String>()
|
||||
|
||||
private val indentDepth: Int = 3
|
||||
|
||||
private val codeStyleExtractor = StyleExtractor(SyntaxManager.getSyntaxData("java"))
|
||||
|
||||
private val background = Display.getCurrent().getSystemColor(SWT.COLOR_WHITE)
|
||||
|
||||
private val headingColor = Display.getCurrent().getSystemColor(SWT.COLOR_BLUE)
|
||||
|
||||
private val codeStyle = FontBuilder("Courier", 11, SWT.NORMAL).style(Display.getCurrent())
|
||||
|
||||
fun clear() {
|
||||
buffer.setLength(0)
|
||||
headingSpans.clear()
|
||||
codeSpans.clear()
|
||||
linksBySpan.clear()
|
||||
}
|
||||
|
||||
fun addHeading(heading: String) {
|
||||
var length = buffer.length
|
||||
if (length > 0) {
|
||||
buffer.append(CR)
|
||||
length += 1
|
||||
}
|
||||
|
||||
headingSpans.add(intArrayOf(length, length + heading.length))
|
||||
buffer.append(heading).append(CR)
|
||||
}
|
||||
|
||||
fun addText(text: String) {
|
||||
for (i in 0 until indentDepth) {
|
||||
buffer.append(' ')
|
||||
}
|
||||
buffer.append(text).append(CR)
|
||||
}
|
||||
|
||||
fun addRawText(text: String) {
|
||||
buffer.append(text)
|
||||
}
|
||||
|
||||
fun addCode(code: String) {
|
||||
val length = buffer.length
|
||||
codeSpans.add(intArrayOf(length, length + code.length))
|
||||
buffer.append(code)
|
||||
}
|
||||
|
||||
fun setLanguage(language: Language) {
|
||||
val syntax = SyntaxManager.getSyntaxData(language.terseName)
|
||||
codeStyleExtractor.syntax(syntax)
|
||||
}
|
||||
|
||||
fun hasLinks(): Boolean {
|
||||
return linksBySpan.isNotEmpty()
|
||||
}
|
||||
|
||||
fun addLinkHandler(widget: StyledText) {
|
||||
|
||||
widget.addListener(SWT.MouseDown) { event ->
|
||||
// It is up to the application to determine when and how a link
|
||||
// should be activated.
|
||||
// In this snippet links are activated on mouse down when the
|
||||
// control key is held down
|
||||
// if ((event.stateMask & SWT.MOD1) != 0) {
|
||||
try {
|
||||
val offset = widget.getOffsetAtLocation(Point(event.x, event.y))
|
||||
val link = linkAt(offset)
|
||||
if (link != null) {
|
||||
launchBrowser(link)
|
||||
}
|
||||
|
||||
} catch (e: IllegalArgumentException) {
|
||||
// no character under event.x, event.y
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun linkAt(textIndex: Int): String? {
|
||||
var span: IntArray
|
||||
for ((key, value) in linksBySpan) {
|
||||
span = key
|
||||
if (span[0] <= textIndex && textIndex <= span[1]) {
|
||||
return value
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun launchBrowser(link: String) {
|
||||
try {
|
||||
val browser = PlatformUI.getWorkbench().browserSupport.externalBrowser
|
||||
browser.openURL(URL(link))
|
||||
} catch (ex: Exception) {
|
||||
ex.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
fun showOn(widget: StyledText) {
|
||||
val text = buffer.toString()
|
||||
widget.text = text
|
||||
val ranges = ArrayList<StyleRange>()
|
||||
var span: IntArray
|
||||
for (i in headingSpans.indices) {
|
||||
span = headingSpans[i]
|
||||
ranges.add(StyleRange(span[0], span[1] - span[0], headingColor, background, SWT.BOLD))
|
||||
}
|
||||
for (spn in linksBySpan.keys) {
|
||||
val style = StyleRange(spn[0], spn[1] - spn[0], headingColor, background, SWT.UNDERLINE_LINK)
|
||||
style.underline = true
|
||||
ranges.add(style)
|
||||
}
|
||||
val crStr = Character.toString(CR)
|
||||
var sr: StyleRange
|
||||
|
||||
for (i in codeSpans.indices) {
|
||||
span = codeSpans[i]
|
||||
sr = StyleRange(codeStyle)
|
||||
sr.start = span[0]
|
||||
sr.length = span[1] - span[0]
|
||||
|
||||
val colorRanges = codeStyleExtractor.stylesFor(text, sr.start, sr.length, crStr)
|
||||
ranges += colorRanges
|
||||
}
|
||||
// must be in order!
|
||||
val styles = sort(ranges)
|
||||
widget.styleRanges = styles
|
||||
}
|
||||
|
||||
private fun sort(ranges: List<StyleRange>): Array<StyleRange> {
|
||||
val styles = ranges.toTypedArray()
|
||||
Arrays.sort(styles) { sr1, sr2 -> sr1.start - sr2.start }
|
||||
return styles
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package com.alibaba.smartfox.eclipse.ui.pmd
|
||||
|
||||
import org.eclipse.swt.graphics.Font
|
||||
import org.eclipse.swt.graphics.TextStyle
|
||||
import org.eclipse.swt.widgets.Display
|
||||
|
||||
/**
|
||||
* @author Brian Remedios
|
||||
*/
|
||||
class FontBuilder(val name: String, val size: Int, val style: Int, val colorIdx: Int = -1) {
|
||||
|
||||
fun build(display: Display): Font {
|
||||
return Font(display, name, size, style)
|
||||
}
|
||||
|
||||
fun style(display: Display): TextStyle {
|
||||
return TextStyle(build(display), if (colorIdx < 0) null else display.getSystemColor(colorIdx), null)
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package com.alibaba.smartfox.eclipse.ui.pmd
|
||||
|
||||
import net.sourceforge.pmd.util.StringUtil
|
||||
import java.util.ArrayList
|
||||
|
||||
/**
|
||||
* @author Brian Remedios
|
||||
*/
|
||||
class StringArranger(private val indentString: String) {
|
||||
|
||||
fun withIndent(rawText: String): String {
|
||||
return indentString + rawText
|
||||
}
|
||||
|
||||
fun format(rawText: String): StringBuilder {
|
||||
|
||||
val sb = StringBuilder()
|
||||
for (line in trimmedLinesIn(rawText)) {
|
||||
sb.append(indentString)
|
||||
sb.append(line).append(CR)
|
||||
}
|
||||
|
||||
return sb
|
||||
}
|
||||
|
||||
fun trimmedLinesIn(text: String): List<String> {
|
||||
|
||||
val lines = text.split("\n".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
if (lines.isEmpty()) {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
val lineSet = ArrayList<String>(lines.size)
|
||||
|
||||
var startLine = 0
|
||||
while (startLine < lines.size && StringUtil.isEmpty(lines[startLine])) {
|
||||
startLine++
|
||||
}
|
||||
|
||||
var endLine = lines.size - 1
|
||||
while (endLine >= 0 && StringUtil.isEmpty(lines[endLine])) {
|
||||
endLine--
|
||||
}
|
||||
|
||||
lines.mapTo(lineSet) {
|
||||
it.trim { it <= ' ' }
|
||||
}
|
||||
return lineSet
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val CR = '\n'
|
||||
}
|
||||
}
|
@ -0,0 +1,275 @@
|
||||
package com.alibaba.smartfox.eclipse.ui.pmd
|
||||
|
||||
import net.sourceforge.pmd.util.StringUtil
|
||||
import org.eclipse.swt.SWT
|
||||
import org.eclipse.swt.custom.StyleRange
|
||||
import org.eclipse.swt.widgets.Display
|
||||
import java.util.ArrayList
|
||||
import java.util.LinkedList
|
||||
|
||||
/**
|
||||
* @author Brian Remedios
|
||||
*/
|
||||
open class StyleExtractor(private var syntaxData: SyntaxData?) {
|
||||
private val commentOffsets: MutableList<IntArray>
|
||||
|
||||
init {
|
||||
commentOffsets = LinkedList<IntArray>()
|
||||
}
|
||||
|
||||
fun syntax(theSyntax: SyntaxData?) {
|
||||
syntaxData = theSyntax
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the offsets for all multiline comments in the parent
|
||||
* StyledText. The parent StyledText should call this whenever its text is
|
||||
* modified. Note that this code doesn't ignore comment markers inside
|
||||
* strings.
|
||||
|
||||
* @param text the text from the StyledText
|
||||
*/
|
||||
fun refreshMultilineComments(text: String) {
|
||||
// Clear any stored offsets
|
||||
commentOffsets.clear()
|
||||
|
||||
if (syntaxData != null) {
|
||||
// Go through all the instances of COMMENT_START
|
||||
var pos = text.indexOf(syntaxData!!.multiLineCommentStart!!)
|
||||
while (pos > -1) {
|
||||
// offsets[0] holds the COMMENT_START offset
|
||||
// and COMMENT_END holds the ending offset
|
||||
val offsets = IntArray(2)
|
||||
offsets[0] = pos
|
||||
|
||||
// Find the corresponding end comment.
|
||||
pos = text.indexOf(syntaxData!!.multiLineCommentEnd!!, pos)
|
||||
|
||||
// If no corresponding end comment, use the end of the text
|
||||
offsets[1] = if (pos == -1) text.length - 1 else pos + syntaxData!!.multiLineCommentEnd!!.length - 1
|
||||
pos = offsets[1]
|
||||
// Add the offsets to the collection
|
||||
commentOffsets.add(offsets)
|
||||
pos = text.indexOf(syntaxData!!.multiLineCommentStart!!, pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the specified section of text begins inside a multiline
|
||||
* comment. Returns the index of the closing comment, or the end of the line
|
||||
* if the whole line is inside the comment. Returns -1 if the line doesn't
|
||||
* begin inside a comment.
|
||||
|
||||
* @param start the starting offset of the text
|
||||
* @param length the length of the text
|
||||
* @return int
|
||||
*/
|
||||
private fun getBeginsInsideComment(start: Int, length: Int): Int {
|
||||
// Assume section doesn't being inside a comment
|
||||
var index = -1
|
||||
|
||||
// Go through the multiline comment ranges
|
||||
var i = 0
|
||||
val n = commentOffsets.size
|
||||
while (i < n) {
|
||||
val offsets = commentOffsets[i]
|
||||
|
||||
// If starting offset is past range, quit
|
||||
if (offsets[0] > start + length) {
|
||||
break
|
||||
}
|
||||
// Check to see if section begins inside a comment
|
||||
if (offsets[0] <= start && offsets[1] >= start) {
|
||||
// It does; determine if the closing comment marker is inside
|
||||
// this section
|
||||
index = if (offsets[1] > start + length) start + length
|
||||
else offsets[1] + syntaxData!!.multiLineCommentEnd!!.length - 1
|
||||
}
|
||||
i++
|
||||
}
|
||||
return index
|
||||
}
|
||||
|
||||
private fun isDefinedVariable(text: String): Boolean {
|
||||
return StringUtil.isNotEmpty(text)
|
||||
}
|
||||
|
||||
private fun atMultiLineCommentStart(text: String, position: Int): Boolean {
|
||||
return text.indexOf(syntaxData!!.multiLineCommentStart!!, position) == position
|
||||
}
|
||||
|
||||
private fun atStringStart(text: String, position: Int): Boolean {
|
||||
return text.indexOf(syntaxData!!.stringStart!!, position) == position
|
||||
}
|
||||
|
||||
private fun atVarnameReference(text: String, position: Int): Boolean {
|
||||
return syntaxData!!.varnameReference != null && text.indexOf(syntaxData!!.varnameReference!!,
|
||||
position) == position
|
||||
}
|
||||
|
||||
private fun atSingleLineComment(text: String, position: Int): Boolean {
|
||||
return syntaxData!!.comment != null && text.indexOf(syntaxData!!.comment!!, position) == position
|
||||
}
|
||||
|
||||
private fun getKeywordEnd(lineText: String, start: Int): Int {
|
||||
|
||||
val length = lineText.length
|
||||
|
||||
val buf = StringBuilder(length)
|
||||
var i = start
|
||||
|
||||
// Call any consecutive letters a word
|
||||
while (i < length && Character.isLetter(lineText[i])) {
|
||||
buf.append(lineText[i])
|
||||
i++
|
||||
}
|
||||
|
||||
return if (syntaxData!!.isKeyword(buf.toString())) i else 0 - i
|
||||
}
|
||||
|
||||
/**
|
||||
* Chop up the text into individual lines starting from offset and then
|
||||
* determine the required styles for each. Ensures the offset is properly
|
||||
* accounted for in each.
|
||||
|
||||
* @param text
|
||||
* @param offset
|
||||
* @param length
|
||||
* @return
|
||||
*/
|
||||
fun stylesFor(text: String, offset: Int, length: Int, lineSeparator: String): List<StyleRange> {
|
||||
|
||||
if (syntaxData == null) {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
val content = text.substring(offset, offset + length)
|
||||
val lines = content.split(lineSeparator.toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
|
||||
val styles = ArrayList<StyleRange>()
|
||||
|
||||
val separatorLength = lineSeparator.length
|
||||
|
||||
var currentOffset = offset
|
||||
|
||||
for (line in lines) {
|
||||
val lineLength = line.length
|
||||
val lineStyles = lineStylesFor(line, 0, lineLength)
|
||||
|
||||
for (sr in lineStyles) {
|
||||
sr.start += currentOffset
|
||||
}
|
||||
styles.addAll(lineStyles)
|
||||
currentOffset += lineLength + separatorLength
|
||||
}
|
||||
|
||||
return styles
|
||||
}
|
||||
|
||||
fun lineStylesFor(lineText: String, lineOffset: Int, length: Int): List<StyleRange> {
|
||||
|
||||
val styles = ArrayList<StyleRange>()
|
||||
|
||||
var start = 0
|
||||
|
||||
// Check if line begins inside a multiline comment
|
||||
val mlIndex = getBeginsInsideComment(lineOffset, lineText.length)
|
||||
if (mlIndex > -1) {
|
||||
// Line begins inside multiline comment; create the range
|
||||
styles.add(StyleRange(lineOffset, mlIndex - lineOffset, COMMENT_COLOR, COMMENT_BACKGROUND))
|
||||
start = mlIndex
|
||||
}
|
||||
// Do punctuation, single-line comments, and keywords
|
||||
while (start < length) {
|
||||
// Check for multiline comments that begin inside this line
|
||||
if (atMultiLineCommentStart(lineText, start)) {
|
||||
// Determine where comment ends
|
||||
var endComment = lineText.indexOf(syntaxData!!.multiLineCommentEnd!!, start)
|
||||
|
||||
// If comment doesn't end on this line, extend range to end of
|
||||
// line
|
||||
if (endComment == -1) {
|
||||
endComment = length
|
||||
} else {
|
||||
endComment += syntaxData!!.multiLineCommentEnd!!.length
|
||||
}
|
||||
styles.add(StyleRange(lineOffset + start, endComment - start, COMMENT_COLOR, COMMENT_BACKGROUND))
|
||||
|
||||
start = endComment
|
||||
} else if (atStringStart(lineText, start)) {
|
||||
// Determine where comment ends
|
||||
var endString = lineText.indexOf(syntaxData!!.stringEnd!!, start + 1)
|
||||
|
||||
// If string doesn't end on this line, extend range to end of
|
||||
// line
|
||||
if (endString == -1) {
|
||||
endString = length
|
||||
} else {
|
||||
endString += syntaxData!!.stringEnd!!.length
|
||||
}
|
||||
styles.add(StyleRange(lineOffset + start, endString - start, STRING_COLOR, COMMENT_BACKGROUND))
|
||||
|
||||
start = endString
|
||||
} else if (atSingleLineComment(lineText, start)) {
|
||||
// line comments
|
||||
|
||||
styles.add(StyleRange(lineOffset + start, length - start, COMMENT_COLOR, COMMENT_BACKGROUND))
|
||||
start = length
|
||||
} else if (atVarnameReference(lineText, start)) {
|
||||
// variable
|
||||
// references
|
||||
|
||||
val buf = StringBuilder()
|
||||
var i = start + syntaxData!!.varnameReference!!.length
|
||||
// Call any consecutive letters a word
|
||||
while (i < length && Character.isLetter(lineText[i])) {
|
||||
buf.append(lineText[i])
|
||||
i++
|
||||
}
|
||||
|
||||
// See if the word is a variable
|
||||
if (isDefinedVariable(buf.toString())) {
|
||||
// It's a keyword; create the StyleRange
|
||||
styles.add(StyleRange(lineOffset + start, i - start, REFERENCED_VAR_COLOR, null, SWT.BOLD))
|
||||
}
|
||||
// Move the marker to the last char (the one that wasn't a
|
||||
// letter)
|
||||
// so it can be retested in the next iteration through the loop
|
||||
start = i
|
||||
} else if (syntaxData!!.isPunctuation(lineText[start])) {
|
||||
// Add range for punctuation
|
||||
styles.add(StyleRange(lineOffset + start, 1, PUNCTUATION_COLOR, null))
|
||||
++start
|
||||
} else if (Character.isLetter(lineText[start])) {
|
||||
|
||||
val kwEnd = getKeywordEnd(lineText, start)
|
||||
// is a keyword
|
||||
|
||||
if (kwEnd > start) {
|
||||
styles.add(StyleRange(lineOffset + start, kwEnd - start, KEYWORD_COLOR, null))
|
||||
}
|
||||
|
||||
// Move the marker to the last char (the one that wasn't a
|
||||
// letter)
|
||||
// so it can be retested in the next iteration through the loop
|
||||
start = Math.abs(kwEnd)
|
||||
} else {
|
||||
++start // It's nothing we're interested in; advance the marker
|
||||
}// Check for punctuation
|
||||
}
|
||||
|
||||
return styles
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private val COMMENT_COLOR = Display.getCurrent().getSystemColor(SWT.COLOR_DARK_GREEN)
|
||||
private val REFERENCED_VAR_COLOR = Display.getCurrent().getSystemColor(SWT.COLOR_DARK_GREEN)
|
||||
private val UNREFERENCED_VAR_COLOR = Display.getCurrent().getSystemColor(SWT.COLOR_YELLOW)
|
||||
private val COMMENT_BACKGROUND = Display.getCurrent().getSystemColor(SWT.COLOR_WHITE)
|
||||
private val PUNCTUATION_COLOR = Display.getCurrent().getSystemColor(SWT.COLOR_BLACK)
|
||||
private val KEYWORD_COLOR = Display.getCurrent().getSystemColor(SWT.COLOR_DARK_MAGENTA)
|
||||
private val STRING_COLOR = Display.getCurrent().getSystemColor(SWT.COLOR_BLUE)
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package com.alibaba.smartfox.eclipse.ui.pmd
|
||||
|
||||
/**
|
||||
* This class contains information for syntax coloring and styling for an
|
||||
* extension
|
||||
*/
|
||||
class SyntaxData(val extension: String) {
|
||||
|
||||
var varnameReference: String? = null
|
||||
var stringStart: String? = null
|
||||
var stringEnd: String? = null
|
||||
private var keywords: Collection<String>? = null
|
||||
private var punctuation: String? = null
|
||||
var comment: String? = null
|
||||
var multiLineCommentStart: String? = null
|
||||
var multiLineCommentEnd: String? = null
|
||||
|
||||
fun matches(otherExtension: String): Boolean {
|
||||
return extension == otherExtension
|
||||
}
|
||||
|
||||
fun isKeyword(word: String): Boolean {
|
||||
return keywords != null && keywords!!.contains(word)
|
||||
}
|
||||
|
||||
fun isPunctuation(ch: Char): Boolean {
|
||||
return punctuation != null && punctuation!!.indexOf(ch) >= 0
|
||||
}
|
||||
|
||||
fun setKeywords(keywords: Collection<String>) {
|
||||
this.keywords = keywords
|
||||
}
|
||||
|
||||
fun setPunctuation(thePunctuationChars: String) {
|
||||
punctuation = thePunctuationChars
|
||||
}
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
package com.alibaba.smartfox.eclipse.ui.pmd
|
||||
|
||||
import org.eclipse.swt.custom.StyledText
|
||||
import org.eclipse.swt.events.ModifyListener
|
||||
import java.util.HashSet
|
||||
import java.util.Hashtable
|
||||
import java.util.MissingResourceException
|
||||
import java.util.ResourceBundle
|
||||
import java.util.StringTokenizer
|
||||
|
||||
/**
|
||||
* This class manages the syntax coloring and styling data
|
||||
*/
|
||||
object SyntaxManager {
|
||||
|
||||
private val syntaxByExtension = Hashtable<String, SyntaxData>()
|
||||
|
||||
fun adapt(codeField: StyledText, languageCode: String, oldListener: ModifyListener?): ModifyListener? {
|
||||
|
||||
if (oldListener != null) {
|
||||
codeField.removeModifyListener(oldListener)
|
||||
}
|
||||
|
||||
val sd = SyntaxManager.getSyntaxData(languageCode) ?: return null
|
||||
|
||||
val blsl = BasicLineStyleListener(sd)
|
||||
codeField.addLineStyleListener(blsl)
|
||||
|
||||
val ml = ModifyListener {
|
||||
blsl.refreshMultilineComments(codeField.text)
|
||||
codeField.redraw()
|
||||
}
|
||||
codeField.addModifyListener(ml)
|
||||
|
||||
return ml
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the syntax data for an extension
|
||||
*/
|
||||
@Synchronized fun getSyntaxData(extension: String): SyntaxData? {
|
||||
// Check in cache
|
||||
var sd: SyntaxData? = syntaxByExtension[extension]
|
||||
if (sd == null) {
|
||||
// Not in cache; load it and put in cache
|
||||
sd = loadSyntaxData(extension)
|
||||
if (sd != null) {
|
||||
syntaxByExtension.put(sd.extension, sd)
|
||||
}
|
||||
}
|
||||
return sd
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the syntax data for an extension
|
||||
* @return SyntaxData
|
||||
*/
|
||||
private fun loadSyntaxData(filename: String): SyntaxData? {
|
||||
var sd: SyntaxData? = null
|
||||
try {
|
||||
val rb = ResourceBundle.getBundle("/syntax/$filename")
|
||||
sd = SyntaxData(filename)
|
||||
|
||||
sd.stringStart = rb.getString("stringstart")
|
||||
sd.stringEnd = rb.getString("stringend")
|
||||
sd.multiLineCommentStart = rb.getString("multilinecommentstart")
|
||||
sd.multiLineCommentEnd = rb.getString("multilinecommentend")
|
||||
|
||||
// Load the keywords
|
||||
val keywords = HashSet<String>()
|
||||
val st = StringTokenizer(rb.getString("keywords"), " ")
|
||||
while (st.hasMoreTokens()) {
|
||||
keywords.add(st.nextToken())
|
||||
}
|
||||
sd.setKeywords(keywords)
|
||||
|
||||
// Load the punctuation
|
||||
sd.setPunctuation(rb.getString("punctuation"))
|
||||
|
||||
if (rb.containsKey("comment")) {
|
||||
sd.comment = rb.getString("comment")
|
||||
}
|
||||
|
||||
if (rb.containsKey("varnamedelimiter")) {
|
||||
sd.varnameReference = rb.getString("varnamedelimiter")
|
||||
}
|
||||
|
||||
} catch (e: MissingResourceException) {
|
||||
// Ignore
|
||||
}
|
||||
|
||||
return sd
|
||||
}
|
||||
}
|
@ -0,0 +1,361 @@
|
||||
// =====================================================================
|
||||
//
|
||||
// Copyright (C) 2012 - 2016, Philip Graf
|
||||
//
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// which accompanies this distribution, and is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// =====================================================================
|
||||
package com.alibaba.smartfox.eclipse.util
|
||||
|
||||
import com.alibaba.smartfox.eclipse.SmartfoxActivator
|
||||
import org.eclipse.core.filebuffers.FileBuffers
|
||||
import org.eclipse.core.filebuffers.ITextFileBuffer
|
||||
import org.eclipse.core.filebuffers.LocationKind
|
||||
import org.eclipse.core.resources.IFile
|
||||
import org.eclipse.core.runtime.Assert
|
||||
import org.eclipse.core.runtime.CoreException
|
||||
import org.eclipse.core.runtime.IProgressMonitor
|
||||
import org.eclipse.core.runtime.IStatus
|
||||
import org.eclipse.core.runtime.NullProgressMonitor
|
||||
import org.eclipse.core.runtime.Status
|
||||
import org.eclipse.jdt.core.ICompilationUnit
|
||||
import org.eclipse.jdt.core.IJavaProject
|
||||
import org.eclipse.jdt.core.JavaCore
|
||||
import org.eclipse.jdt.core.dom.CompilationUnit
|
||||
import org.eclipse.jdt.internal.corext.fix.CleanUpConstants
|
||||
import org.eclipse.jdt.internal.corext.fix.CleanUpRefactoring
|
||||
import org.eclipse.jdt.internal.corext.fix.FixMessages
|
||||
import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser
|
||||
import org.eclipse.jdt.internal.ui.JavaPlugin
|
||||
import org.eclipse.jdt.internal.ui.actions.ActionUtil
|
||||
import org.eclipse.jdt.internal.ui.fix.MapCleanUpOptions
|
||||
import org.eclipse.jdt.ui.SharedASTProvider
|
||||
import org.eclipse.jdt.ui.cleanup.CleanUpContext
|
||||
import org.eclipse.jdt.ui.cleanup.CleanUpOptions
|
||||
import org.eclipse.jdt.ui.cleanup.ICleanUp
|
||||
import org.eclipse.jface.text.BadLocationException
|
||||
import org.eclipse.jface.text.IDocument
|
||||
import org.eclipse.jface.text.IDocumentExtension4
|
||||
import org.eclipse.jface.window.Window
|
||||
import org.eclipse.ltk.core.refactoring.Change
|
||||
import org.eclipse.ltk.core.refactoring.CompositeChange
|
||||
import org.eclipse.ltk.core.refactoring.IRefactoringCoreStatusCodes
|
||||
import org.eclipse.ltk.core.refactoring.NullChange
|
||||
import org.eclipse.ltk.core.refactoring.PerformChangeOperation
|
||||
import org.eclipse.ltk.core.refactoring.RefactoringCore
|
||||
import org.eclipse.ltk.core.refactoring.RefactoringStatus
|
||||
import org.eclipse.ltk.core.refactoring.TextFileChange
|
||||
import org.eclipse.ltk.ui.refactoring.RefactoringUI
|
||||
import org.eclipse.text.edits.MalformedTreeException
|
||||
import org.eclipse.text.edits.TextEdit
|
||||
import org.eclipse.text.edits.UndoEdit
|
||||
import org.eclipse.ui.PlatformUI
|
||||
import java.util.ArrayList
|
||||
import java.util.HashMap
|
||||
import java.util.LinkedList
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author caikang
|
||||
* @date 2017/06/15
|
||||
*/
|
||||
object CleanUps {
|
||||
|
||||
private val WARNING_VALUE = "warning"
|
||||
private val ERROR_VALUE = "error"
|
||||
|
||||
val cleanUpSettings = mapOf(CleanUpConstants.ADD_MISSING_ANNOTATIONS to CleanUpOptions.TRUE,
|
||||
CleanUpConstants.CONTROL_STATMENTS_USE_BLOCKS_ALWAYS to CleanUpOptions.TRUE,
|
||||
CleanUpConstants.ADD_MISSING_ANNOTATIONS_OVERRIDE to CleanUpOptions.TRUE,
|
||||
CleanUpConstants.CONTROL_STATEMENTS_USE_BLOCKS to CleanUpOptions.TRUE,
|
||||
CleanUpConstants.ADD_MISSING_ANNOTATIONS_OVERRIDE_FOR_INTERFACE_METHOD_IMPLEMENTATION to
|
||||
CleanUpOptions.TRUE)
|
||||
|
||||
fun fix(file: IFile, monitor: IProgressMonitor) {
|
||||
val compilationUnit = JavaCore.createCompilationUnitFrom(file) ?: return
|
||||
doCleanUp(compilationUnit, monitor)
|
||||
}
|
||||
|
||||
@Throws(CoreException::class) fun doCleanUp(unit: ICompilationUnit, monitor: IProgressMonitor) {
|
||||
|
||||
monitor.beginTask("Fix", IProgressMonitor.UNKNOWN)
|
||||
|
||||
if (!ActionUtil.isOnBuildPath(unit)) return
|
||||
val result = CompositeChange(FixMessages.CleanUpPostSaveListener_SaveAction_ChangeName)
|
||||
val undoEdits = LinkedList<UndoEdit>()
|
||||
val oldFileValue = unit.resource.modificationStamp
|
||||
val oldDocValue = getDocumentStamp(unit.resource as IFile, monitor)
|
||||
val manager = RefactoringCore.getUndoManager()
|
||||
var success = false
|
||||
|
||||
try {
|
||||
manager.aboutToPerformChange(result)
|
||||
success = doCleanUp(unit, monitor, result, undoEdits)
|
||||
} finally {
|
||||
manager.changePerformed(result, success)
|
||||
}
|
||||
|
||||
if (undoEdits.size > 0) {
|
||||
val undoEditArray = undoEdits.toTypedArray()
|
||||
val undo = CleanUpSaveUndo(result.name, unit.resource as IFile, undoEditArray, oldDocValue, oldFileValue)
|
||||
undo.initializeValidationData(NullProgressMonitor())
|
||||
manager.addUndo(result.name, undo)
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(CoreException::class) private fun getDocumentStamp(file: IFile, monitor: IProgressMonitor): Long {
|
||||
val manager = FileBuffers.getTextFileBufferManager()
|
||||
val path = file.fullPath
|
||||
|
||||
monitor.beginTask("", 2)
|
||||
|
||||
var buffer: ITextFileBuffer? = null
|
||||
try {
|
||||
manager.connect(path, LocationKind.IFILE, monitor)
|
||||
buffer = manager.getTextFileBuffer(path, LocationKind.IFILE)
|
||||
val document = buffer!!.document
|
||||
|
||||
if (document is IDocumentExtension4) {
|
||||
return document.modificationStamp
|
||||
} else {
|
||||
return file.modificationStamp
|
||||
}
|
||||
} finally {
|
||||
if (buffer != null) manager.disconnect(path, LocationKind.IFILE, monitor)
|
||||
monitor.done()
|
||||
}
|
||||
}
|
||||
|
||||
private fun doCleanUp(unit: ICompilationUnit, monitor: IProgressMonitor, result: CompositeChange,
|
||||
undoEdits: LinkedList<UndoEdit>): Boolean {
|
||||
val cleanUps = JavaPlugin.getDefault().cleanUpRegistry.createCleanUps(
|
||||
setOf("org.eclipse.jdt.ui.cleanup.java50", "org.eclipse.jdt.ui.cleanup.control_statements"))
|
||||
val preCondition = RefactoringStatus()
|
||||
val postCondition = RefactoringStatus()
|
||||
cleanUps.forEach { cleanUp ->
|
||||
cleanUp.setOptions(MapCleanUpOptions(cleanUpSettings))
|
||||
|
||||
preCondition.merge(cleanUp.checkPreConditions(unit.javaProject, arrayOf(unit), monitor))
|
||||
|
||||
val options = HashMap<String, String>(cleanUp.requirements.compilerOptions ?: emptyMap())
|
||||
|
||||
var ast = CleanUps.createAst(unit, options, monitor)
|
||||
if (cleanUp.requirements.requiresAST()) {
|
||||
ast = createAst(unit, options, monitor)
|
||||
}
|
||||
|
||||
val context = CleanUpContext(unit, ast)
|
||||
|
||||
val undoneCleanUps = ArrayList<ICleanUp>()
|
||||
val change = CleanUpRefactoring.calculateChange(context, arrayOf(cleanUp), undoneCleanUps, null)
|
||||
|
||||
postCondition.merge(cleanUp.checkPostConditions(monitor))
|
||||
if (showStatus(postCondition) != Window.OK) {
|
||||
return@doCleanUp false
|
||||
}
|
||||
|
||||
if (change == null) {
|
||||
return@forEach
|
||||
}
|
||||
result.add(change)
|
||||
|
||||
change.initializeValidationData(NullProgressMonitor())
|
||||
|
||||
val performChangeOperation = PerformChangeOperation(change)
|
||||
performChangeOperation.setSchedulingRule(unit.schedulingRule)
|
||||
performChangeOperation.run(monitor)
|
||||
performChangeOperation.undoChange
|
||||
undoEdits.addFirst(change.undoEdit)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun showStatus(status: RefactoringStatus): Int {
|
||||
if (!status.hasError()) return Window.OK
|
||||
|
||||
val shell = PlatformUI.getWorkbench().activeWorkbenchWindow.shell
|
||||
|
||||
val dialog = RefactoringUI.createRefactoringStatusDialog(status, shell, "", false)
|
||||
return dialog.open()
|
||||
}
|
||||
|
||||
private fun createAst(unit: ICompilationUnit, cleanUpOptions: Map<String, String>,
|
||||
monitor: IProgressMonitor): CompilationUnit {
|
||||
val project = unit.javaProject
|
||||
if (compatibleOptions(project, cleanUpOptions)) {
|
||||
val ast = SharedASTProvider.getAST(unit, SharedASTProvider.WAIT_NO, monitor)
|
||||
if (ast != null) return ast
|
||||
}
|
||||
|
||||
val parser = CleanUpRefactoring.createCleanUpASTParser()
|
||||
parser.setSource(unit)
|
||||
|
||||
val compilerOptions = RefactoringASTParser.getCompilerOptions(unit.javaProject)
|
||||
compilerOptions.putAll(cleanUpOptions)
|
||||
parser.setCompilerOptions(compilerOptions)
|
||||
|
||||
return parser.createAST(monitor) as CompilationUnit
|
||||
}
|
||||
|
||||
private fun compatibleOptions(project: IJavaProject, cleanUpOptions: Map<String, String>): Boolean {
|
||||
if (cleanUpOptions.isEmpty()) {
|
||||
return true
|
||||
}
|
||||
|
||||
val projectOptions = project.getOptions(true)
|
||||
|
||||
return !cleanUpOptions.keys.any {
|
||||
val projectOption = projectOptions[it]?.toString()
|
||||
val cleanUpOption = cleanUpOptions[it]?.toString()
|
||||
!strongerEquals(projectOption, cleanUpOption)
|
||||
}
|
||||
}
|
||||
|
||||
private fun strongerEquals(projectOption: String?, cleanUpOption: String?): Boolean {
|
||||
if (projectOption == null) return false
|
||||
|
||||
if (ERROR_VALUE == cleanUpOption) {
|
||||
return ERROR_VALUE == projectOption
|
||||
} else if (WARNING_VALUE == cleanUpOption) {
|
||||
return ERROR_VALUE == projectOption || WARNING_VALUE == projectOption
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private class CleanUpSaveUndo(name: String, private val fFile: IFile, private val fUndos: Array<UndoEdit>,
|
||||
private val fDocumentStamp: Long, private val fFileStamp: Long) : TextFileChange(name,
|
||||
fFile) {
|
||||
|
||||
init {
|
||||
Assert.isNotNull(fUndos)
|
||||
}
|
||||
|
||||
public override fun needsSaving(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
@Throws(CoreException::class) override fun perform(monitor: IProgressMonitor?): Change {
|
||||
val pm = monitor ?: NullProgressMonitor()
|
||||
if (isValid(pm).hasFatalError()) return NullChange()
|
||||
|
||||
val manager = FileBuffers.getTextFileBufferManager()
|
||||
pm.beginTask("", 2)
|
||||
var buffer: ITextFileBuffer? = null
|
||||
|
||||
try {
|
||||
manager.connect(fFile.fullPath, LocationKind.IFILE, pm)
|
||||
buffer = manager.getTextFileBuffer(fFile.fullPath, LocationKind.IFILE)
|
||||
|
||||
val document = buffer!!.document
|
||||
val oldFileValue = fFile.modificationStamp
|
||||
val undoEditCollector = LinkedList<UndoEdit>()
|
||||
val oldDocValue = LongArray(1)
|
||||
val setContentStampSuccess = booleanArrayOf(false)
|
||||
|
||||
if (!buffer.isSynchronizationContextRequested) {
|
||||
performEdit(document, oldFileValue, undoEditCollector, oldDocValue, setContentStampSuccess)
|
||||
|
||||
} else {
|
||||
val fileBufferManager = FileBuffers.getTextFileBufferManager()
|
||||
|
||||
class UIRunnable : Runnable {
|
||||
var fDone: Boolean = false
|
||||
var fException: Exception? = null
|
||||
|
||||
override fun run() {
|
||||
synchronized(this) {
|
||||
try {
|
||||
performEdit(document, oldFileValue, undoEditCollector, oldDocValue,
|
||||
setContentStampSuccess)
|
||||
} catch (e: BadLocationException) {
|
||||
fException = e
|
||||
} catch (e: MalformedTreeException) {
|
||||
fException = e
|
||||
} catch (e: CoreException) {
|
||||
fException = e
|
||||
} finally {
|
||||
fDone = true
|
||||
(this as Object).notifyAll()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val runnable = UIRunnable()
|
||||
|
||||
synchronized(runnable) {
|
||||
fileBufferManager.execute(runnable)
|
||||
while (!runnable.fDone) {
|
||||
try {
|
||||
(runnable as Object).wait(500)
|
||||
} catch (x: InterruptedException) {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (runnable.fException != null) {
|
||||
if (runnable.fException is BadLocationException) {
|
||||
throw runnable.fException as BadLocationException
|
||||
} else if (runnable.fException is MalformedTreeException) {
|
||||
throw runnable.fException as MalformedTreeException
|
||||
} else if (runnable.fException is CoreException) {
|
||||
throw runnable.fException as CoreException
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buffer.commit(pm, false)
|
||||
if (!setContentStampSuccess[0]) {
|
||||
fFile.revertModificationStamp(fFileStamp)
|
||||
}
|
||||
|
||||
return CleanUpSaveUndo(name, fFile, undoEditCollector.toTypedArray(), oldDocValue[0], oldFileValue)
|
||||
} catch (e: BadLocationException) {
|
||||
throw wrapBadLocationException(e)
|
||||
} finally {
|
||||
if (buffer != null) manager.disconnect(fFile.fullPath, LocationKind.IFILE, pm)
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(MalformedTreeException::class, BadLocationException::class,
|
||||
CoreException::class) private fun performEdit(document: IDocument, oldFileValue: Long,
|
||||
editCollector: LinkedList<UndoEdit>,
|
||||
oldDocValue: LongArray,
|
||||
setContentStampSuccess: BooleanArray) {
|
||||
if (document is IDocumentExtension4) {
|
||||
oldDocValue[0] = document.modificationStamp
|
||||
} else {
|
||||
oldDocValue[0] = oldFileValue
|
||||
}
|
||||
|
||||
// perform the changes
|
||||
fUndos.map { it.apply(document, TextEdit.CREATE_UNDO) }.forEach { editCollector.addFirst(it) }
|
||||
|
||||
if (document is IDocumentExtension4 && fDocumentStamp != IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP) {
|
||||
try {
|
||||
document.replace(0, 0, "", fDocumentStamp)
|
||||
setContentStampSuccess[0] = true
|
||||
} catch (e: BadLocationException) {
|
||||
throw wrapBadLocationException(e)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun wrapBadLocationException(e: BadLocationException): CoreException {
|
||||
var message: String? = e.message
|
||||
if (message == null) message = "BadLocationException"
|
||||
return CoreException(
|
||||
Status(IStatus.ERROR, SmartfoxActivator.PLUGIN_ID, IRefactoringCoreStatusCodes.BAD_LOCATION, message,
|
||||
e))
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,136 @@
|
||||
// =====================================================================
|
||||
//
|
||||
// Copyright (C) 2012 - 2016, Philip Graf
|
||||
//
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// which accompanies this distribution, and is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// =====================================================================
|
||||
package com.alibaba.smartfox.eclipse.util
|
||||
|
||||
import com.alibaba.smartfox.eclipse.QuickFixGenerator
|
||||
import com.alibaba.smartfox.eclipse.SmartfoxActivator
|
||||
import com.google.common.io.Files
|
||||
import net.sourceforge.pmd.Rule
|
||||
import net.sourceforge.pmd.RulePriority
|
||||
import net.sourceforge.pmd.RuleViolation
|
||||
import org.eclipse.core.resources.IFile
|
||||
import org.eclipse.core.resources.IMarker
|
||||
import org.eclipse.core.resources.IProject
|
||||
import org.eclipse.core.resources.IResource
|
||||
import org.eclipse.core.runtime.CoreException
|
||||
import org.eclipse.jface.text.BadLocationException
|
||||
import org.eclipse.jface.text.Document
|
||||
import org.eclipse.ui.IMarkerResolution
|
||||
import java.nio.charset.Charset
|
||||
|
||||
/**
|
||||
* @author caikang
|
||||
* @date 2017/06/08
|
||||
*/
|
||||
object MarkerUtil {
|
||||
|
||||
private val PMD_TAB_SIZE = 8
|
||||
|
||||
private val MARKER_TYPE = "${SmartfoxActivator.PLUGIN_ID}.p3cMarker"
|
||||
|
||||
@Throws(CoreException::class)
|
||||
fun removeAllMarkers(file: IFile) {
|
||||
try {
|
||||
if (file.exists()) {
|
||||
file.deleteMarkers(MARKER_TYPE, true, IResource.DEPTH_ZERO)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
SmartfoxActivator.instance.logError(e.message ?: "", e)
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(CoreException::class)
|
||||
fun removeAllMarkers(project: IProject) {
|
||||
project.deleteMarkers(MARKER_TYPE, true, IResource.DEPTH_INFINITE)
|
||||
}
|
||||
|
||||
@Throws(CoreException::class)
|
||||
fun addMarker(file: IFile, violation: RuleViolation): IMarker {
|
||||
|
||||
val marker = file.createMarker(MARKER_TYPE)
|
||||
marker.setAttribute(IMarker.MESSAGE, violation.description)
|
||||
val severity = when (violation.rule.priority) {
|
||||
RulePriority.HIGH -> IMarker.SEVERITY_ERROR
|
||||
RulePriority.MEDIUM_HIGH -> IMarker.SEVERITY_WARNING
|
||||
else -> IMarker.SEVERITY_INFO
|
||||
}
|
||||
marker.setRule(violation.rule.name)
|
||||
marker.setAttribute(IMarker.SEVERITY, severity)
|
||||
marker.setAttribute(IMarker.LINE_NUMBER, Math.max(violation.beginLine, 0))
|
||||
val range = getAbsoluteRange(file, violation)
|
||||
val start = Math.max(range.start, 0)
|
||||
marker.setAttribute(IMarker.CHAR_START, start)
|
||||
val end = Math.max(range.end, 0)
|
||||
marker.setAttribute(IMarker.CHAR_END, end)
|
||||
return marker
|
||||
}
|
||||
|
||||
|
||||
fun getAbsoluteRange(file: IFile, violation: RuleViolation): Range {
|
||||
val content = Files.toString(file.rawLocation.toFile(), Charset.forName(file.charset))
|
||||
try {
|
||||
return calculateAbsoluteRange(content, violation)
|
||||
} catch (e: BadLocationException) {
|
||||
return Range(0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(BadLocationException::class) private fun calculateAbsoluteRange(content: String,
|
||||
violation: RuleViolation): Range {
|
||||
val document = Document(content)
|
||||
|
||||
// violation line and column start at one, the marker's start and end positions at zero
|
||||
val start = getAbsolutePosition(content, document.getLineOffset(violation.beginLine - 1), violation.beginColumn)
|
||||
val end = getAbsolutePosition(content, document.getLineOffset(violation.endLine - 1), violation.endColumn)
|
||||
|
||||
// for some rules PMD creates violations with the end position before the start position
|
||||
val range = if (start <= end) {
|
||||
Range(start - 1, end)
|
||||
} else {
|
||||
Range(end - 1, start)
|
||||
}
|
||||
|
||||
return range
|
||||
}
|
||||
|
||||
private fun getAbsolutePosition(content: String, lineOffset: Int, pmdCharOffset: Int): Int {
|
||||
var pmdCharCounter = 0
|
||||
var absoluteOffset = lineOffset
|
||||
while (pmdCharCounter < pmdCharOffset) {
|
||||
if (absoluteOffset < content.length) {
|
||||
val c = content[absoluteOffset]
|
||||
if (c == '\t') {
|
||||
pmdCharCounter = (pmdCharCounter / PMD_TAB_SIZE + 1) * PMD_TAB_SIZE
|
||||
} else {
|
||||
pmdCharCounter++
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
absoluteOffset++
|
||||
}
|
||||
return absoluteOffset
|
||||
}
|
||||
}
|
||||
|
||||
fun IMarker.setRule(rule: String) {
|
||||
this.setAttribute("rule", rule)
|
||||
}
|
||||
|
||||
fun IMarker.getRule(): Rule {
|
||||
return SmartfoxActivator.instance.getRule(this.getAttribute("rule") as String)
|
||||
}
|
||||
|
||||
fun IMarker.getResolution(): IMarkerResolution? {
|
||||
return QuickFixGenerator.quickFixes[getRule().name]
|
||||
}
|
||||
|
||||
data class Range(val start: Int, val end: Int)
|
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="alibaba-pmd"
|
||||
xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
|
||||
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">
|
||||
<rule ref="rulesets/java/ali-concurrent.xml"/>
|
||||
<rule ref="rulesets/java/ali-comment.xml"/>
|
||||
<rule ref="rulesets/java/ali-naming.xml"/>
|
||||
<rule ref="rulesets/java/ali-constant.xml"/>
|
||||
<rule ref="rulesets/java/ali-other.xml"/>
|
||||
<rule ref="rulesets/java/ali-flowcontrol.xml"/>
|
||||
<rule ref="rulesets/java/ali-oop.xml"/>
|
||||
<rule ref="rulesets/java/ali-orm.xml"/>
|
||||
<rule ref="rulesets/java/ali-exception.xml"/>
|
||||
<rule ref="rulesets/java/ali-set.xml"/>
|
||||
<rule ref="rulesets/java/ali-ruleOnEclipse.xml"/>
|
||||
</ruleset>
|
@ -0,0 +1,42 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="AlibabaRuleOnEclipse"
|
||||
xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
|
||||
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">
|
||||
|
||||
<rule name="MissingOverrideAnnotationRule" message="rule.standalone.MissingOverrideAnnotationRule.msg"
|
||||
class="com.alibaba.smartfox.eclipse.pmd.rule.MissingOverrideAnnotationRule">
|
||||
<description>rule.standalone.MissingOverrideAnnotationRule.desc</description>
|
||||
<priority>1</priority>
|
||||
|
||||
<example>
|
||||
<![CDATA[
|
||||
/**
|
||||
* @author caikang
|
||||
* @date 2016/12/24
|
||||
*/
|
||||
public class MissingOverrideAnnotationRule extends AbstractEclipseRule {
|
||||
@Override
|
||||
public Object visit(ASTCompilationUnit node, Object data) {
|
||||
return super.visit(node, data);
|
||||
}
|
||||
}
|
||||
]]>
|
||||
</example>
|
||||
</rule>
|
||||
<rule name="AvoidAccessStaticViaInstanceRule" message="rule.standalone.AvoidAccessStaticViaInstanceRule.msg"
|
||||
class="com.alibaba.smartfox.eclipse.pmd.rule.AvoidAccessStaticViaInstanceRule">
|
||||
<priority>1</priority>
|
||||
</rule>
|
||||
<rule name="AvoidUseDeprecationRule" message="rule.standalone.AvoidUseDeprecationRule.msg"
|
||||
class="com.alibaba.smartfox.eclipse.pmd.rule.AvoidUseDeprecationRule">
|
||||
<description>rule.standalone.AvoidUseDeprecationRule.desc</description>
|
||||
<priority>2</priority>
|
||||
</rule>
|
||||
|
||||
<rule name="MapOrSetKeyShouldOverrideHashCodeEqualsRule" message="rule.standalone.MapOrSetKeyShouldOverrideHashCodeEqualsRule.msg"
|
||||
class="com.alibaba.smartfox.eclipse.pmd.rule.MapOrSetKeyShouldOverrideHashCodeEqualsRule">
|
||||
<description>rule.standalone.MapOrSetKeyShouldOverrideHashCodeEqualsRule.desc</description>
|
||||
<priority>1</priority>
|
||||
</rule>
|
||||
</ruleset>
|
@ -0,0 +1,8 @@
|
||||
# This file contains the syntax data for .java files
|
||||
comment=//
|
||||
stringstart="
|
||||
stringend="
|
||||
multilinecommentstart=/*
|
||||
multilinecommentend=*/
|
||||
punctuation=(){};:?<>=+-*/&|~!%.[]
|
||||
keywords=abstract assert boolean break byte case catch char class const continue do double else enum extends false final finally for if implements import int interface native new null package protected public private return static strictfp super switch synchronized this throws true try void volatile while
|
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<site>
|
||||
<description url="https://p3c.alibaba.com/plugin/eclipse/update">
|
||||
Alibaba Java Coding Guidelines
|
||||
</description>
|
||||
<feature id="com.alibaba.smartfox.eclipse.feature" version="0.0.0">
|
||||
<category name="Smartfox"/>
|
||||
</feature>
|
||||
<category-def name="Smartfox" label="Smartfox Eclipse Plugin"/>
|
||||
</site>
|
@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.alibaba.smartfox.eclipse</groupId>
|
||||
<artifactId>smartfox-eclipse</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>com.alibaba.smartfox.eclipse.updatesite</artifactId>
|
||||
<packaging>eclipse-repository</packaging>
|
||||
<inceptionYear>2017</inceptionYear>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>publish-to-update-site</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.eclipse.tycho.extras</groupId>
|
||||
<artifactId>tycho-p2-extras-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>publish</id>
|
||||
<phase>install</phase>
|
||||
<goals>
|
||||
<goal>mirror</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<source>
|
||||
<repository>
|
||||
<url>${project.build.directory}/repository</url>
|
||||
</repository>
|
||||
</source>
|
||||
<append>true</append>
|
||||
<destination>${eclipse.updatesite.path}</destination>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
After Width: | Height: | Size: 232 KiB |
After Width: | Height: | Size: 189 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 87 KiB |
@ -0,0 +1,338 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.alibaba.smartfox.eclipse</groupId>
|
||||
<artifactId>smartfox-eclipse</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<inceptionYear>2017</inceptionYear>
|
||||
<properties>
|
||||
<tycho.version>1.0.0</tycho.version>
|
||||
<tycho-extras.version>${tycho.version}</tycho-extras.version>
|
||||
<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.1.51</kotlin.version>
|
||||
<eclipse-release>juno</eclipse-release>
|
||||
</properties>
|
||||
<modules>
|
||||
<module>com.alibaba.smartfox.eclipse.plugin</module>
|
||||
<module>com.alibaba.smartfox.eclipse.feature</module>
|
||||
<module>com.alibaba.smartfox.eclipse.updatesite</module>
|
||||
</modules>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.11</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-stdlib</artifactId>
|
||||
<version>${kotlin.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
<!--<repositories>
|
||||
<repository>
|
||||
<id>neon</id>
|
||||
<url>${eclipse-repo.url}</url>
|
||||
<layout>p2</layout>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>ajdt</id>
|
||||
<url>${ajdt-eclipse-repo.url}</url>
|
||||
<layout>p2</layout>
|
||||
</repository>
|
||||
</repositories>-->
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.eclipse.tycho</groupId>
|
||||
<artifactId>tycho-maven-plugin</artifactId>
|
||||
<version>${tycho.version}</version>
|
||||
<extensions>true</extensions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.eclipse.tycho</groupId>
|
||||
<artifactId>target-platform-configuration</artifactId>
|
||||
<configuration>
|
||||
<environments>
|
||||
<environment>
|
||||
<os>linux</os>
|
||||
<ws>gtk</ws>
|
||||
<arch>x86</arch>
|
||||
</environment>
|
||||
<environment>
|
||||
<os>linux</os>
|
||||
<ws>gtk</ws>
|
||||
<arch>x86_64</arch>
|
||||
</environment>
|
||||
<environment>
|
||||
<os>win32</os>
|
||||
<ws>win32</ws>
|
||||
<arch>x86</arch>
|
||||
</environment>
|
||||
<environment>
|
||||
<os>win32</os>
|
||||
<ws>win32</ws>
|
||||
<arch>x86_64</arch>
|
||||
</environment>
|
||||
<environment>
|
||||
<os>macosx</os>
|
||||
<ws>cocoa</ws>
|
||||
<arch>x86_64</arch>
|
||||
</environment>
|
||||
</environments>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.eclipse.tycho</groupId>
|
||||
<artifactId>target-platform-configuration</artifactId>
|
||||
<version>${tycho.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.eclipse.tycho</groupId>
|
||||
<artifactId>tycho-compiler-plugin</artifactId>
|
||||
<version>${tycho.version}</version>
|
||||
<configuration>
|
||||
<compilerVersion>1.7</compilerVersion>
|
||||
<compilerArguments>
|
||||
<inlineJSR/>
|
||||
<enableJavadoc/>
|
||||
<encoding>UTF-8</encoding>
|
||||
</compilerArguments>
|
||||
<compilerArgument>-err:-forbidden</compilerArgument>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>aspectj-maven-plugin</artifactId>
|
||||
<version>${aspectj.plugin.version}</version>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjtools</artifactId>
|
||||
<version>${aspectj.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.eclipse.tycho</groupId>
|
||||
<artifactId>tycho-packaging-plugin</artifactId>
|
||||
<version>${tycho.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.eclipse.tycho</groupId>
|
||||
<artifactId>tycho-surefire-plugin</artifactId>
|
||||
<version>${tycho.version}</version>
|
||||
<configuration>
|
||||
<testFailureIgnore>true</testFailureIgnore>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.eclipse.tycho</groupId>
|
||||
<artifactId>tycho-source-plugin</artifactId>
|
||||
<version>${tycho.version}</version>
|
||||
<configuration>
|
||||
<strictSrcIncludes>false</strictSrcIncludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.eclipse.tycho</groupId>
|
||||
<artifactId>tycho-p2-director-plugin</artifactId>
|
||||
<version>${tycho.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.eclipse.tycho</groupId>
|
||||
<artifactId>tycho-p2-repository-plugin</artifactId>
|
||||
<version>${tycho.version}</version>
|
||||
<configuration>
|
||||
<finalName>smartfox-eclipse-plugin</finalName>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.eclipse.tycho.extras</groupId>
|
||||
<artifactId>tycho-source-feature-plugin</artifactId>
|
||||
<version>${tycho-extras.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.eclipse.tycho.extras</groupId>
|
||||
<artifactId>tycho-custom-bundle-plugin</artifactId>
|
||||
<version>${tycho-extras.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.eclipse.tycho</groupId>
|
||||
<artifactId>tycho-p2-plugin</artifactId>
|
||||
<version>${tycho.version}</version>
|
||||
<configuration>
|
||||
<baselineMode>warn</baselineMode>
|
||||
<baselineReplace>none</baselineReplace>
|
||||
<baselineRepositories>
|
||||
<repository>
|
||||
<url>http://download.eclipse.org/eclipse/updates/4.4</url>
|
||||
</repository>
|
||||
</baselineRepositories>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
<profiles>
|
||||
|
||||
<profile>
|
||||
<id>macosx-jvm-flags</id>
|
||||
<activation>
|
||||
<os>
|
||||
<family>mac</family>
|
||||
</os>
|
||||
</activation>
|
||||
<properties>
|
||||
<!-- tycho-surefire-plugin needs -XstartOnFirstThread on mac os -->
|
||||
<os-jvm-flags>-XstartOnFirstThread</os-jvm-flags>
|
||||
</properties>
|
||||
</profile>
|
||||
|
||||
<!-- <profile>
|
||||
<id>eclipse-indigo</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>!eclipse-release</name>
|
||||
</property>
|
||||
</activation>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>indigo</id>
|
||||
<layout>p2</layout>
|
||||
<url>http://download.eclipse.org/releases/indigo/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>swtbot</id>
|
||||
<layout>p2</layout>
|
||||
<url>http://download.eclipse.org/technology/swtbot/releases/2.2.1/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
</profile>
|
||||
-->
|
||||
<profile>
|
||||
<id>eclipse-juno</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>!eclipse-release</name>
|
||||
</property>
|
||||
</activation>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>juno</id>
|
||||
<layout>p2</layout>
|
||||
<url>http://mirrors.ustc.edu.cn/eclipse/releases/juno/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>swtbot</id>
|
||||
<layout>p2</layout>
|
||||
<url>http://mirrors.ustc.edu.cn/eclipse/technology/swtbot/releases/2.5.0/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>eclipse-kepler</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>eclipse-release</name>
|
||||
<value>kepler</value>
|
||||
</property>
|
||||
</activation>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>kepler</id>
|
||||
<layout>p2</layout>
|
||||
<url>http://download.eclipse.org/releases/kepler/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>swtbot</id>
|
||||
<layout>p2</layout>
|
||||
<url>http://download.eclipse.org/technology/swtbot/releases/2.3.0/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>eclipse-luna</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>eclipse-release</name>
|
||||
<value>luna</value>
|
||||
</property>
|
||||
</activation>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>luna</id>
|
||||
<layout>p2</layout>
|
||||
<url>http://download.eclipse.org/releases/luna/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>swtbot</id>
|
||||
<layout>p2</layout>
|
||||
<url>http://download.eclipse.org/technology/swtbot/releases/2.3.0/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>eclipse-mars</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>eclipse-release</name>
|
||||
<value>mars</value>
|
||||
</property>
|
||||
</activation>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>mars</id>
|
||||
<layout>p2</layout>
|
||||
<url>http://download.eclipse.org/releases/mars/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>swtbot</id>
|
||||
<layout>p2</layout>
|
||||
<url>http://download.eclipse.org/technology/swtbot/releases/2.3.0/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>eclipse-neon</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>eclipse-release</name>
|
||||
<value>neon</value>
|
||||
</property>
|
||||
</activation>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>neon</id>
|
||||
<layout>p2</layout>
|
||||
<url>http://download.eclipse.org/releases/neon/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>swtbot</id>
|
||||
<layout>p2</layout>
|
||||
<url>http://download.eclipse.org/technology/swtbot/releases/2.3.0/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
</profile>
|
||||
|
||||
</profiles>
|
||||
</project>
|
@ -0,0 +1,94 @@
|
||||
# Gradle
|
||||
build
|
||||
.gradle
|
||||
|
||||
testdata/
|
||||
# Java gitignore #
|
||||
.class
|
||||
.log
|
||||
|
||||
# Package Files #
|
||||
|
||||
*.war
|
||||
*.ear
|
||||
|
||||
#hsf files
|
||||
configuration
|
||||
|
||||
# maven gitignore#
|
||||
target/**
|
||||
|
||||
.svn/
|
||||
|
||||
# intelliJ.gitignore #
|
||||
.idea
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
|
||||
# Eclipse git ignore#
|
||||
*.pydevproject
|
||||
.project
|
||||
.metadata
|
||||
bin/**
|
||||
*/bin/**
|
||||
tmp/**
|
||||
tmp/**/*
|
||||
configuration/**
|
||||
*.tmp
|
||||
*.bak
|
||||
*.orig
|
||||
*.swp
|
||||
*~.nib
|
||||
.classpath
|
||||
.settings/
|
||||
.loadpath
|
||||
.fileTable*
|
||||
.cache
|
||||
|
||||
# External tool builders
|
||||
.externalToolBuilders/
|
||||
|
||||
# Locally stored "Eclipse launch configurations"
|
||||
*.launch
|
||||
|
||||
# CDT-specific
|
||||
.cproject
|
||||
|
||||
# PDT-specific
|
||||
.buildpath
|
||||
|
||||
#log
|
||||
*.log
|
||||
*.log.*
|
||||
|
||||
# Windows Thumbs.db
|
||||
*.db
|
||||
|
||||
# OSX
|
||||
.DS_Store
|
||||
|
||||
# sass gitignore#
|
||||
.sass-cache
|
||||
.idea
|
||||
|
||||
# tcc_coverage
|
||||
coverage.ec
|
||||
|
||||
|
||||
|
||||
config.client.*
|
||||
|
||||
temp/
|
||||
*.pid
|
||||
*.orig
|
||||
|
||||
hsf.configuration/
|
||||
|
||||
# code coverage report
|
||||
*.ec
|
||||
|
||||
#hsf test
|
||||
*.instance
|
||||
out
|
||||
**/idea-sandbox
|
@ -0,0 +1,38 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
maven {
|
||||
url "https://oss.sonatype.org/content/repositories/snapshots/"
|
||||
}
|
||||
maven {
|
||||
url 'http://dl.bintray.com/jetbrains/intellij-plugin-service'
|
||||
}
|
||||
mavenCentral()
|
||||
|
||||
}
|
||||
dependencies {
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
group 'com.alibaba.p3c.idea'
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'kotlin'
|
||||
apply plugin: 'maven-publish'
|
||||
|
||||
sourceCompatibility = 1.7
|
||||
compileJava.options.encoding = 'UTF-8'
|
||||
configurations.all {
|
||||
resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
|
||||
}
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
|
||||
testCompile group: 'junit', name: 'junit', version: '4.11'
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 193 KiB |
After Width: | Height: | Size: 70 KiB |
After Width: | Height: | Size: 70 KiB |
After Width: | Height: | Size: 119 KiB |
After Width: | Height: | Size: 267 KiB |
After Width: | Height: | Size: 243 KiB |
After Width: | Height: | Size: 79 KiB |
After Width: | Height: | Size: 122 KiB |
@ -0,0 +1,9 @@
|
||||
kotlin_version=1.1.51
|
||||
#idea_version=171.3780.15
|
||||
idea_version=14.1.7
|
||||
plugin_name=Alibaba Java Coding Guidelines
|
||||
pmd_version=5.5.2
|
||||
gradle_jetbrains_version=0.2.13
|
||||
systemProp.file.encoding=UTF-8
|
||||
|
||||
plugin_version=1.0.0
|
@ -0,0 +1,6 @@
|
||||
#Wed Nov 30 15:31:46 CST 2016
|
||||
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
|
@ -0,0 +1,172 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn ( ) {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die ( ) {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save ( ) {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=$(save "$@")
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "$@"
|
@ -0,0 +1,84 @@
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
@ -0,0 +1,94 @@
|
||||
plugins {
|
||||
id "org.jetbrains.intellij" version '0.2.17'
|
||||
}
|
||||
apply plugin: 'kotlin'
|
||||
apply plugin: 'idea'
|
||||
apply plugin: 'maven'
|
||||
apply plugin: 'signing'
|
||||
|
||||
javadoc {
|
||||
options.tags = [ "date" ]
|
||||
}
|
||||
|
||||
task javadocJar(type: Jar, dependsOn: javadoc) {
|
||||
classifier = 'javadoc'
|
||||
from 'build/docs/javadoc'
|
||||
}
|
||||
|
||||
task sourcesJar(type: Jar) {
|
||||
classifier = 'sources'
|
||||
from sourceSets.main.allSource
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives jar
|
||||
archives javadocJar
|
||||
archives sourcesJar
|
||||
}
|
||||
|
||||
intellij {
|
||||
version idea_version
|
||||
pluginName plugin_name
|
||||
updateSinceUntilBuild false
|
||||
sandboxDirectory "$project.buildDir/idea-sandbox/$idea_version"
|
||||
}
|
||||
version '1.0.0'
|
||||
|
||||
dependencies {
|
||||
compile group: 'org.freemarker', name: 'freemarker', version: '2.3.25-incubating'
|
||||
compile 'com.alibaba.p3c:p3c-pmd:1.3.0'
|
||||
compile group: 'org.javassist', name: 'javassist', version: '3.21.0-GA'
|
||||
}
|
||||
|
||||
uploadArchives {
|
||||
repositories {
|
||||
mavenDeployer {
|
||||
beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
|
||||
|
||||
repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") {
|
||||
authentication(userName: ossrhUsername, password: ossrhPassword)
|
||||
}
|
||||
|
||||
snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") {
|
||||
authentication(userName: ossrhUsername, password: ossrhPassword)
|
||||
}
|
||||
|
||||
pom.project {
|
||||
name 'p3c-common'
|
||||
packaging 'jar'
|
||||
description 'P3c Idea Plugin Common.'
|
||||
url 'https://github.com/alibaba/p3c'
|
||||
|
||||
scm {
|
||||
url 'https://github.com/alibaba/p3c'
|
||||
connection 'scm:git:https://git@github.com/alibaba/p3c.git'
|
||||
}
|
||||
|
||||
licenses {
|
||||
license {
|
||||
name 'The Apache Software License, Version 2.0'
|
||||
url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
|
||||
distribution 'repo'
|
||||
}
|
||||
}
|
||||
|
||||
developers {
|
||||
developer {
|
||||
id 'junlie'
|
||||
name 'Junlie'
|
||||
email 'sean.caikang@gmail.com'
|
||||
}
|
||||
developer {
|
||||
id 'ZengHou'
|
||||
name 'ZengHou'
|
||||
email 'fengwei1983@gmail.com'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
signing {
|
||||
sign configurations.archives
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* @author caikang
|
||||
* @date 2016/12/28
|
||||
*/
|
||||
public interface NumberConstants {
|
||||
int INTEGER_SIZE_OR_LENGTH_0 = 0;
|
||||
int INTEGER_SIZE_OR_LENGTH_1 = 1;
|
||||
int INTEGER_SIZE_OR_LENGTH_2 = 2;
|
||||
|
||||
int INDEX_0 = 0;
|
||||
int INDEX_1 = 1;
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* @author caikang
|
||||
* @date 2016/12/28
|
||||
*/
|
||||
public interface ObjectConstants {
|
||||
String METHOD_NAME_EQUALS = "equals";
|
||||
String METHOD_NAME_HASHCODE = "hashCode";
|
||||
String METHOD_NAME_ADD = "add";
|
||||
String METHOD_NAME_PUT = "put";
|
||||
String CLASS_LITERAL = "class";
|
||||
String INTERFACE_LITERAL = "interface";
|
||||
String ENUM_LITERAL = "enum";
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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 icons;
|
||||
|
||||
import javax.swing.Icon;
|
||||
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
|
||||
/**
|
||||
* @author caikang
|
||||
* @date 2016/12/28
|
||||
*/
|
||||
public interface P3cIcons {
|
||||
Icon ANALYSIS_ACTION = IconLoader.getIcon("/icons/ali-ide-run.png");
|
||||
|
||||
Icon PROJECT_INSPECTION_ON = IconLoader.getIcon("/icons/qiyong.png");
|
||||
Icon PROJECT_INSPECTION_OFF = IconLoader.getIcon("/icons/tingyong.png");
|
||||
Icon LANGUAGE = IconLoader.getIcon("/icons/language.png");
|
||||
Icon ALIBABA = IconLoader.getIcon("/icons/alibaba.png");
|
||||
}
|
@ -0,0 +1,193 @@
|
||||
/*
|
||||
* 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.action
|
||||
|
||||
import com.alibaba.p3c.idea.compatible.inspection.InspectionProfileService
|
||||
import com.alibaba.p3c.idea.compatible.inspection.Inspections
|
||||
import com.alibaba.p3c.idea.ep.InspectionActionExtensionPoint
|
||||
import com.alibaba.p3c.idea.i18n.P3cBundle
|
||||
import com.alibaba.p3c.idea.inspection.AliBaseInspection
|
||||
import com.beust.jcommander.internal.Lists
|
||||
import com.intellij.analysis.AnalysisScope
|
||||
import com.intellij.analysis.AnalysisUIOptions
|
||||
import com.intellij.analysis.BaseAnalysisActionDialog
|
||||
import com.intellij.codeInspection.InspectionManager
|
||||
import com.intellij.codeInspection.ex.GlobalInspectionContextImpl
|
||||
import com.intellij.codeInspection.ex.InspectionManagerEx
|
||||
import com.intellij.codeInspection.ex.InspectionToolWrapper
|
||||
import com.intellij.codeInspection.ui.InspectionResultsView
|
||||
import com.intellij.openapi.actionSystem.AnAction
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys
|
||||
import com.intellij.openapi.actionSystem.DataKeys
|
||||
import com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.module.ModuleUtilCore
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiManager
|
||||
import java.awt.event.KeyEvent
|
||||
|
||||
/**
|
||||
* @author caikang
|
||||
* @date 2016/12/11
|
||||
*/
|
||||
class AliInspectionAction : AnAction() {
|
||||
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val project = e.project ?: return
|
||||
val analysisUIOptions = ServiceManager.getService(project, AnalysisUIOptions::class.java)!!
|
||||
analysisUIOptions.GROUP_BY_SEVERITY = true
|
||||
|
||||
val managerEx = InspectionManager.getInstance(project) as InspectionManagerEx
|
||||
val toolWrappers = Inspections.aliInspections(project) {
|
||||
it.tool is AliBaseInspection
|
||||
}
|
||||
val psiElement = e.getData<PsiElement>(DataKeys.PSI_ELEMENT)
|
||||
val psiFile = e.getData<PsiFile>(DataKeys.PSI_FILE)
|
||||
val virtualFile = e.getData<VirtualFile>(DataKeys.VIRTUAL_FILE)
|
||||
val virtualFiles = e.getData<Array<VirtualFile>>(CommonDataKeys.VIRTUAL_FILE_ARRAY)
|
||||
var analysisScope: AnalysisScope? = null
|
||||
var projectDir = false
|
||||
if (psiFile != null) {
|
||||
analysisScope = AnalysisScope(psiFile)
|
||||
projectDir = isBaseDir(psiFile.virtualFile, project)
|
||||
} else if (virtualFiles != null && virtualFiles.size > com.alibaba.p3c.idea.NumberConstants.INTEGER_SIZE_OR_LENGTH_0) {
|
||||
analysisScope = AnalysisScope(project, Lists.newArrayList<VirtualFile>(*virtualFiles))
|
||||
projectDir = virtualFiles.any {
|
||||
isBaseDir(it, project)
|
||||
}
|
||||
} else {
|
||||
if (virtualFile != null && virtualFile.isDirectory) {
|
||||
val psiDirectory = PsiManager.getInstance(project).findDirectory(virtualFile)
|
||||
if (psiDirectory != null) {
|
||||
analysisScope = AnalysisScope(psiDirectory)
|
||||
projectDir = isBaseDir(virtualFile, project)
|
||||
}
|
||||
}
|
||||
if (analysisScope == null && virtualFile != null) {
|
||||
analysisScope = AnalysisScope(project, listOf(virtualFile))
|
||||
projectDir = isBaseDir(virtualFile, project)
|
||||
}
|
||||
if (analysisScope == null) {
|
||||
projectDir = true
|
||||
analysisScope = AnalysisScope(project)
|
||||
}
|
||||
}
|
||||
if (e.inputEvent is KeyEvent) {
|
||||
inspectForKeyEvent(project, managerEx, toolWrappers, psiElement, psiFile, virtualFile, analysisScope)
|
||||
return
|
||||
}
|
||||
val element = psiFile ?: psiElement
|
||||
analysisScope.isIncludeTestSource = false
|
||||
analysisScope.setSearchInLibraries(true)
|
||||
createContext(toolWrappers, managerEx, element,
|
||||
projectDir).doInspections(analysisScope)
|
||||
}
|
||||
|
||||
private fun isBaseDir(file: VirtualFile, project: Project): Boolean {
|
||||
if (file.canonicalPath == null || project.basePath == null) {
|
||||
return false
|
||||
}
|
||||
return project.basePath == file.canonicalPath
|
||||
}
|
||||
|
||||
private fun inspectForKeyEvent(project: Project, managerEx: InspectionManagerEx,
|
||||
toolWrappers: List<InspectionToolWrapper<*, *>>, psiElement: PsiElement?, psiFile: PsiFile?,
|
||||
virtualFile: VirtualFile?, analysisScope: AnalysisScope) {
|
||||
var module: Module? = null
|
||||
if (virtualFile != null && project.baseDir != virtualFile) {
|
||||
module = ModuleUtilCore.findModuleForFile(virtualFile, project)
|
||||
}
|
||||
|
||||
val uiOptions = AnalysisUIOptions.getInstance(project)
|
||||
uiOptions.ANALYZE_TEST_SOURCES = false
|
||||
val dialog = BaseAnalysisActionDialog("Select Analyze Scope", "Analyze Scope", project, analysisScope,
|
||||
if (module != null) module.name else null, true, uiOptions, psiElement)
|
||||
|
||||
if (!dialog.showAndGet()) {
|
||||
return
|
||||
}
|
||||
val scope = dialog.getScope(uiOptions, analysisScope, project, module)
|
||||
scope.setSearchInLibraries(true)
|
||||
val element = psiFile ?: psiElement
|
||||
createContext(toolWrappers, managerEx, element,
|
||||
dialog.isProjectScopeSelected).doInspections(scope)
|
||||
}
|
||||
|
||||
override fun update(e: AnActionEvent) {
|
||||
e.presentation.text = P3cBundle.getMessage("com.alibaba.p3c.idea.action.AliInspectionAction.text")
|
||||
}
|
||||
|
||||
companion object {
|
||||
val logger = Logger.getInstance(AliInspectionAction::class.java)
|
||||
|
||||
fun createContext(toolWrapperList: List<InspectionToolWrapper<*, *>>,
|
||||
managerEx: InspectionManagerEx, psiElement: PsiElement?, projectScopeSelected: Boolean):
|
||||
GlobalInspectionContextImpl {
|
||||
val model = InspectionProfileService.createSimpleProfile(toolWrapperList, managerEx, psiElement)
|
||||
val inspectionContext = createNewGlobalContext(
|
||||
managerEx, projectScopeSelected)
|
||||
InspectionProfileService.setExternalProfile(model, inspectionContext)
|
||||
return inspectionContext
|
||||
}
|
||||
|
||||
private fun createNewGlobalContext(managerEx: InspectionManagerEx,
|
||||
projectScopeSelected: Boolean): GlobalInspectionContextImpl {
|
||||
return object : GlobalInspectionContextImpl(managerEx.project, managerEx.contentManager) {
|
||||
override fun runTools(scope: AnalysisScope, runGlobalToolsOnly: Boolean,
|
||||
isOfflineInspections: Boolean) {
|
||||
super.runTools(scope, runGlobalToolsOnly, isOfflineInspections)
|
||||
if (myProgressIndicator.isCanceled) {
|
||||
return
|
||||
}
|
||||
InspectionActionExtensionPoint.extension.extensions.forEach {
|
||||
try {
|
||||
it.doOnInspectionFinished(this, projectScopeSelected)
|
||||
} catch(e: Exception) {
|
||||
logger.warn(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun close(noSuspiciousCodeFound: Boolean) {
|
||||
super.close(noSuspiciousCodeFound)
|
||||
InspectionActionExtensionPoint.extension.extensions.forEach {
|
||||
try {
|
||||
it.doOnClose(noSuspiciousCodeFound, project)
|
||||
} catch(e: Exception) {
|
||||
logger.warn(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun addView(view: InspectionResultsView) {
|
||||
super.addView(view)
|
||||
InspectionActionExtensionPoint.extension.extensions.forEach {
|
||||
try {
|
||||
it.doOnView(view)
|
||||
} catch(e: Exception) {
|
||||
logger.warn(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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.action
|
||||
|
||||
import com.alibaba.p3c.idea.config.P3cConfig
|
||||
import com.alibaba.p3c.idea.i18n.P3cBundle
|
||||
import com.alibaba.smartfox.idea.common.util.BalloonNotifications
|
||||
import com.alibaba.smartfox.idea.common.util.getService
|
||||
import com.intellij.notification.NotificationListener
|
||||
import com.intellij.openapi.actionSystem.AnAction
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.application.ex.ApplicationManagerEx
|
||||
import com.intellij.openapi.project.DumbAware
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author caikang
|
||||
* @date 2017/06/20
|
||||
*/
|
||||
class SwitchLanguageAction : AnAction(), DumbAware {
|
||||
val p3cConfig = P3cConfig::class.java.getService()
|
||||
|
||||
val textKey = "com.alibaba.p3c.action.switch_language.text"
|
||||
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
p3cConfig.locale = when (p3cConfig.locale) {
|
||||
P3cConfig.localeZh -> P3cConfig.localeEn
|
||||
else -> P3cConfig.localeZh
|
||||
}
|
||||
BalloonNotifications.showSuccessNotification(P3cBundle.getMessage("$textKey.success"), e.project,
|
||||
NotificationListener { notification, _ ->
|
||||
notification.expire()
|
||||
ApplicationManagerEx.getApplicationEx().restart(false)
|
||||
}, sticky = true)
|
||||
}
|
||||
|
||||
override fun update(e: AnActionEvent) {
|
||||
e.presentation.text = P3cBundle.getMessage("$textKey.cur_${p3cConfig.locale}")
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.action
|
||||
|
||||
import com.alibaba.p3c.idea.compatible.inspection.InspectionProfileService
|
||||
import com.alibaba.p3c.idea.compatible.inspection.Inspections
|
||||
import com.alibaba.p3c.idea.config.SmartFoxProjectConfig
|
||||
import com.alibaba.p3c.idea.i18n.P3cBundle
|
||||
import com.alibaba.p3c.idea.inspection.AliBaseInspection
|
||||
import com.intellij.openapi.actionSystem.AnAction
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.components.ServiceManager
|
||||
import icons.P3cIcons
|
||||
|
||||
/**
|
||||
*
|
||||
* Open or close inspections
|
||||
* @author caikang
|
||||
* @date 2017/03/14
|
||||
4
|
||||
*/
|
||||
class ToggleProjectInspectionAction : AnAction() {
|
||||
val textKey = "com.alibaba.p3c.idea.action.ToggleProjectInspectionAction.text"
|
||||
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val project = e.project ?: return
|
||||
val smartFoxConfig = ServiceManager.getService(project, SmartFoxProjectConfig::class.java)
|
||||
val tools = Inspections.aliInspections(project) {
|
||||
it.tool is AliBaseInspection
|
||||
}
|
||||
InspectionProfileService.toggleInspection(project, tools, smartFoxConfig.projectInspectionClosed)
|
||||
smartFoxConfig.projectInspectionClosed = !smartFoxConfig.projectInspectionClosed
|
||||
}
|
||||
|
||||
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
|
||||
P3cBundle.getMessage("$textKey.open")
|
||||
} else {
|
||||
e.presentation.icon = P3cIcons.PROJECT_INSPECTION_OFF
|
||||
P3cBundle.getMessage("$textKey.close")
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* 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.compatible.inspection
|
||||
|
||||
import com.alibaba.smartfox.idea.common.util.PluginVersions
|
||||
import com.google.common.collect.Sets
|
||||
import com.intellij.codeInspection.ex.GlobalInspectionContextImpl
|
||||
import com.intellij.codeInspection.ex.InspectionManagerEx
|
||||
import com.intellij.codeInspection.ex.InspectionProfileImpl
|
||||
import com.intellij.codeInspection.ex.InspectionToolWrapper
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.InvalidDataException
|
||||
import com.intellij.openapi.util.WriteExternalException
|
||||
import com.intellij.profile.codeInspection.InspectionProjectProfileManager
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jdom.Element
|
||||
import java.util.LinkedHashSet
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author caikang
|
||||
* @date 2017/03/01
|
||||
*/
|
||||
object InspectionProfileService {
|
||||
fun createSimpleProfile(toolWrapperList: List<InspectionToolWrapper<*, *>>,
|
||||
managerEx: InspectionManagerEx, psiElement: PsiElement?): InspectionProfileImpl {
|
||||
val profile = getProjectInspectionProfile(managerEx.project)
|
||||
val allWrappers: LinkedHashSet<InspectionToolWrapper<*, *>> = Sets.newLinkedHashSet()
|
||||
allWrappers.addAll(toolWrapperList)
|
||||
val forCompile = allWrappers
|
||||
for (toolWrapper in allWrappers) {
|
||||
profile.collectDependentInspections(toolWrapper, forCompile, managerEx.project)
|
||||
}
|
||||
val model = when (PluginVersions.baseVersion) {
|
||||
in PluginVersions.baseVersion171..Int.MAX_VALUE -> {
|
||||
val clz = Class.forName("com.intellij.codeInspection.ex.InspectionProfileKt")
|
||||
val method = clz.methods.first { it.name == "createSimple" }
|
||||
method.invoke(null, "Alibaba Coding Guidelines", managerEx.project, allWrappers.toList())
|
||||
as InspectionProfileImpl
|
||||
}
|
||||
PluginVersions.baseVersion163 -> {
|
||||
val method = profile.javaClass.methods.first {
|
||||
it.name == "createSimple"
|
||||
}
|
||||
method.invoke(null, "Alibaba Coding Guidelines", managerEx.project, allWrappers.toList())
|
||||
as InspectionProfileImpl
|
||||
}
|
||||
else -> {
|
||||
val method = profile.javaClass.methods.first {
|
||||
it.name == "createSimple"
|
||||
}
|
||||
method.invoke(null, "Alibaba Coding Guidelines", managerEx.project, allWrappers.toTypedArray())
|
||||
as InspectionProfileImpl
|
||||
}
|
||||
}
|
||||
try {
|
||||
val element = Element("toCopy")
|
||||
for (wrapper in allWrappers) {
|
||||
wrapper.tool.writeSettings(element)
|
||||
val tw = if (psiElement == null) {
|
||||
model.getInspectionTool(wrapper.shortName, managerEx.project)
|
||||
} else {
|
||||
model.getInspectionTool(wrapper.shortName, psiElement)
|
||||
}
|
||||
tw!!.tool.readSettings(element)
|
||||
}
|
||||
} catch (ignored: WriteExternalException) {
|
||||
} catch (ignored: InvalidDataException) {
|
||||
}
|
||||
return model
|
||||
}
|
||||
|
||||
fun toggleInspection(project: Project, aliInspections: List<InspectionToolWrapper<*, *>>, closed: Boolean) {
|
||||
val profile = getProjectInspectionProfile(project)
|
||||
val shortNames = aliInspections.map {
|
||||
it.tool.shortName
|
||||
}
|
||||
profile.removeScopes(shortNames, "AlibabaCodeAnalysis", project)
|
||||
val method = profile.javaClass.methods.first {
|
||||
it.name == if (closed) {
|
||||
"enableToolsByDefault"
|
||||
} else {
|
||||
"disableToolByDefault"
|
||||
}
|
||||
}
|
||||
method.invoke(profile, shortNames, project)
|
||||
profile.profileChanged()
|
||||
profile.scopesChanged()
|
||||
}
|
||||
|
||||
fun setExternalProfile(profile: InspectionProfileImpl,
|
||||
inspectionContext: GlobalInspectionContextImpl) {
|
||||
val method = inspectionContext.javaClass.methods.first {
|
||||
it.name == "setExternalProfile" && it.parameterTypes.size == 1 && it.parameterTypes.first().isAssignableFrom(InspectionProfileImpl::class.java)
|
||||
}
|
||||
method.invoke(inspectionContext, profile)
|
||||
}
|
||||
|
||||
fun getProjectInspectionProfile(project: Project): InspectionProfileImpl {
|
||||
return InspectionProjectProfileManager.getInstance(project).inspectionProfile as InspectionProfileImpl
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.compatible.inspection
|
||||
|
||||
import com.intellij.codeInspection.ex.InspectionProfileImpl
|
||||
import com.intellij.codeInspection.ex.InspectionToolWrapper
|
||||
import com.intellij.codeInspection.ex.ScopeToolState
|
||||
import com.intellij.openapi.project.Project
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author caikang
|
||||
* @date 2017/03/01
|
||||
*/
|
||||
object Inspections {
|
||||
fun aliInspections(project: Project, filter: (InspectionToolWrapper<*, *>) -> Boolean): List<InspectionToolWrapper<*, *>> {
|
||||
val profile = InspectionProfileService.getProjectInspectionProfile(project)
|
||||
return getAllTools(project, profile).filter(filter)
|
||||
}
|
||||
|
||||
private fun getAllTools(project: Project, profile: InspectionProfileImpl): List<InspectionToolWrapper<*, *>> {
|
||||
val method = InspectionProfileImpl::class.java.methods.first {
|
||||
it.name == "getAllTools"
|
||||
}
|
||||
|
||||
val result = if (method.parameterTypes.isNotEmpty()) {
|
||||
method.invoke(profile, project)
|
||||
} else {
|
||||
method.invoke(profile)
|
||||
}
|
||||
return (result as List<ScopeToolState>).map { it.tool }
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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.component
|
||||
|
||||
import com.alibaba.p3c.idea.config.P3cConfig
|
||||
import com.alibaba.p3c.idea.inspection.AliPmdInspectionInvoker
|
||||
import com.alibaba.p3c.idea.pmd.SourceCodeProcessor
|
||||
import com.alibaba.smartfox.idea.common.component.AliBaseProjectComponent
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFileAdapter
|
||||
import com.intellij.openapi.vfs.VirtualFileEvent
|
||||
import com.intellij.openapi.vfs.VirtualFileListener
|
||||
import com.intellij.openapi.vfs.VirtualFileManager
|
||||
import com.intellij.psi.PsiManager
|
||||
|
||||
/**
|
||||
* @author caikang
|
||||
* @date 2016/12/13
|
||||
*/
|
||||
class AliProjectComponent(private val project: Project,
|
||||
val p3cConfig: P3cConfig) : AliBaseProjectComponent {
|
||||
private val listener: VirtualFileListener
|
||||
private val javaExtension = ".java"
|
||||
private val velocityExtension = ".vm"
|
||||
|
||||
init {
|
||||
listener = object : VirtualFileAdapter() {
|
||||
override fun contentsChanged(event: VirtualFileEvent) {
|
||||
val path = event.file.canonicalPath
|
||||
if (path == null || !(path.endsWith(javaExtension) || path.endsWith(velocityExtension))) {
|
||||
return
|
||||
}
|
||||
PsiManager.getInstance(project).findFile(event.file) ?: return
|
||||
if (!p3cConfig.ruleCacheEnable) {
|
||||
AliPmdInspectionInvoker.refreshFileViolationsCache(event.file)
|
||||
}
|
||||
if (!p3cConfig.astCacheEnable) {
|
||||
SourceCodeProcessor.invalidateCache(path)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun projectOpened() {
|
||||
VirtualFileManager.getInstance().addVirtualFileListener(listener)
|
||||
}
|
||||
|
||||
override fun projectClosed() {
|
||||
VirtualFileManager.getInstance().removeVirtualFileListener(listener)
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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.component
|
||||
|
||||
import com.alibaba.p3c.idea.config.P3cConfig
|
||||
import com.alibaba.p3c.idea.i18n.P3cBundle
|
||||
import com.alibaba.p3c.idea.util.HighlightInfoTypes
|
||||
import com.alibaba.p3c.idea.util.HighlightSeverities
|
||||
import com.alibaba.p3c.pmd.I18nResources
|
||||
import com.alibaba.smartfox.idea.common.component.AliBaseApplicationComponent
|
||||
import com.intellij.codeInsight.daemon.impl.SeverityRegistrar
|
||||
import com.intellij.openapi.actionSystem.ActionManager
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author caikang
|
||||
* @date 2017/06/19
|
||||
*/
|
||||
class CommonSettingsApplicationComponent(private val p3cConfig: P3cConfig) : AliBaseApplicationComponent {
|
||||
override fun initComponent() {
|
||||
SeverityRegistrar.registerStandard(HighlightInfoTypes.BLOCKER, HighlightSeverities.BLOCKER)
|
||||
SeverityRegistrar.registerStandard(HighlightInfoTypes.CRITICAL, HighlightSeverities.CRITICAL)
|
||||
SeverityRegistrar.registerStandard(HighlightInfoTypes.MAJOR, HighlightSeverities.MAJOR)
|
||||
|
||||
I18nResources.changeLanguage(p3cConfig.locale)
|
||||
val analyticsGroup = ActionManager.getInstance().getAction(analyticsGroupId)
|
||||
analyticsGroup.templatePresentation.text = P3cBundle.getMessage(analyticsGroupText)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val analyticsGroupId = "com.alibaba.p3c.analytics.action_group"
|
||||
val analyticsGroupText = "$analyticsGroupId.text"
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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.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
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author caikang
|
||||
* @date 2017/06/19
|
||||
*/
|
||||
@State(name = "P3cConfig",
|
||||
storages = arrayOf(Storage(file = "${StoragePathMacros.APP_CONFIG}/smartfox/p3c.xml")))
|
||||
class P3cConfig : PersistentStateComponent<P3cConfig> {
|
||||
var astCacheTime = 1000L
|
||||
var astCacheEnable = true
|
||||
|
||||
var ruleCacheTime = 1000L
|
||||
var ruleCacheEnable = false
|
||||
|
||||
var analysisBeforeCheckin = false
|
||||
|
||||
var locale = localeZh
|
||||
|
||||
override fun getState(): P3cConfig {
|
||||
return this
|
||||
}
|
||||
|
||||
override fun loadState(state: P3cConfig?) {
|
||||
if (state == null) {
|
||||
return
|
||||
}
|
||||
XmlSerializerUtil.copyBean(state, this)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val localeEn = "en"
|
||||
val localeZh = "zh"
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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.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
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author caikang
|
||||
* @date 2017/03/01
|
||||
*/
|
||||
@State(name = "SmartFoxProjectConfig",
|
||||
storages = arrayOf(com.intellij.openapi.components.Storage(
|
||||
file = "${StoragePathMacros.PROJECT_CONFIG_DIR}/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
|
||||
}
|
||||
XmlSerializerUtil.copyBean(state, this)
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.ep
|
||||
|
||||
import com.alibaba.smartfox.idea.common.util.PluginVersions
|
||||
import com.intellij.codeInspection.ex.GlobalInspectionContextImpl
|
||||
import com.intellij.codeInspection.ui.InspectionResultsView
|
||||
import com.intellij.openapi.extensions.ExtensionPointName
|
||||
import com.intellij.openapi.project.Project
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author caikang
|
||||
* @date 2017/06/19
|
||||
*/
|
||||
interface InspectionActionExtensionPoint {
|
||||
fun doOnInspectionFinished(context: GlobalInspectionContextImpl, projectScopeSelected: Boolean) {}
|
||||
fun doOnClose(noSuspiciousCodeFound: Boolean, project: Project?) {}
|
||||
fun doOnView(view: InspectionResultsView) {}
|
||||
|
||||
companion object {
|
||||
val extension = ExtensionPointName.create<InspectionActionExtensionPoint>(
|
||||
"${PluginVersions.pluginId.idString}.inspectionAction")!!
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* extension point
|
||||
*
|
||||
* @author caikang
|
||||
* @date 2017/06/19
|
||||
*/
|
||||
package com.alibaba.p3c.idea.ep;
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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.i18n
|
||||
|
||||
import com.alibaba.p3c.idea.config.P3cConfig
|
||||
import com.alibaba.p3c.pmd.I18nResources
|
||||
import com.alibaba.smartfox.idea.common.util.getService
|
||||
import com.intellij.CommonBundle
|
||||
import java.util.Locale
|
||||
import java.util.ResourceBundle
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author caikang
|
||||
* @date 2017/06/20
|
||||
*/
|
||||
object P3cBundle {
|
||||
val p3cConfig = P3cConfig::class.java.getService()
|
||||
private val resourceBundle = ResourceBundle.getBundle("messages.P3cBundle",
|
||||
Locale(p3cConfig.locale), I18nResources.XmlControl())
|
||||
|
||||
fun getMessage(key: String): String {
|
||||
return resourceBundle.getString(key).trim()
|
||||
}
|
||||
|
||||
fun message(key: String, vararg params: Any): String {
|
||||
return CommonBundle.message(resourceBundle, key, *params).trim()
|
||||
}
|
||||
}
|