├── src
├── test
│ ├── resources
│ │ ├── emptyFile1.xml
│ │ ├── emptyFile2.xml
│ │ ├── cpstab
│ │ │ ├── readme.txt
│ │ │ ├── lib1.jar
│ │ │ ├── libs
│ │ │ │ ├── lib1.jar
│ │ │ │ └── lib2.jar
│ │ │ ├── hashed
│ │ │ │ └── lib1.jar
│ │ │ ├── mmmfkoez3kxcsqlrrqbfbcxo5e4k6gq4
│ │ │ │ └── lib1.jar
│ │ │ └── a_long_folder
│ │ │ │ └── path_more_than_50_characters
│ │ │ │ └── in_total
│ │ │ │ └── lib1.jar
│ │ ├── checkstyle-idea.broken2.properties
│ │ ├── checkstyle-idea.broken1.properties
│ │ └── org
│ │ │ └── infernus
│ │ │ └── idea
│ │ │ └── checkstyle
│ │ │ ├── SourceFile.java
│ │ │ └── config-ok.xml
│ └── java
│ │ └── org
│ │ └── infernus
│ │ └── idea
│ │ └── checkstyle
│ │ ├── StringConfigurationLocation.java
│ │ ├── TestHelper.java
│ │ ├── VersionComparatorTest.java
│ │ ├── CheckstyleProjectServiceTest.java
│ │ ├── VersionListReaderTest.java
│ │ └── csapi
│ │ └── ProcessResultsThreadTest.java
├── main
│ ├── resources
│ │ ├── org
│ │ │ └── infernus
│ │ │ │ └── idea
│ │ │ │ └── checkstyle
│ │ │ │ ├── images
│ │ │ │ ├── checkstyle.pxd
│ │ │ │ ├── checkstyle.svg
│ │ │ │ ├── checkstyle_dark.svg
│ │ │ │ ├── checkstyle@20x20.svg
│ │ │ │ └── checkstyle@20x20_dark.svg
│ │ │ │ └── util
│ │ │ │ └── copylibs-readme.template.txt
│ │ ├── dtd
│ │ │ ├── packages_1_0.dtd
│ │ │ ├── configuration_1_0.dtd
│ │ │ ├── suppressions_1_0.dtd
│ │ │ ├── suppressions_1_2.dtd
│ │ │ ├── suppressions_1_1.dtd
│ │ │ ├── suppressions_1_1_xpath_experimental.dtd
│ │ │ ├── suppressions_1_2_xpath_experimental.dtd
│ │ │ ├── configuration_1_1.dtd
│ │ │ ├── configuration_1_2.dtd
│ │ │ ├── configuration_1_3.dtd
│ │ │ ├── import_control_1_0.dtd
│ │ │ ├── import_control_1_1.dtd
│ │ │ └── import_control_1_2.dtd
│ │ └── inspectionDescriptions
│ │ │ └── CheckStyle.html
│ └── java
│ │ └── org
│ │ └── infernus
│ │ └── idea
│ │ └── checkstyle
│ │ ├── doc-files
│ │ ├── CheckstyleClassLoader-1.png
│ │ └── CheckstyleClassLoader-2.png
│ │ ├── config
│ │ ├── ConfigurationListener.java
│ │ ├── ConfigurationLocationSource.java
│ │ └── PluginConfigurationManager.java
│ │ ├── checker
│ │ ├── ConfigurationLocationStatus.java
│ │ ├── ScannerListener.java
│ │ ├── SuppressForCheckstyleFix.java
│ │ ├── ConfigurationLocationResult.java
│ │ ├── CachedChecker.java
│ │ ├── CheckerFactoryCacheKey.java
│ │ ├── CheckerFactoryWorker.java
│ │ ├── ListPropertyResolver.java
│ │ └── CreateScannableFileAction.java
│ │ ├── csapi
│ │ ├── SeverityLevel.java
│ │ ├── TabWidthAndBaseDirProvider.java
│ │ ├── ConfigVisitor.java
│ │ ├── Issue.java
│ │ ├── CheckstyleInternalObject.java
│ │ ├── KnownTokenTypes.java
│ │ ├── BundledConfigProvider.java
│ │ └── ConfigurationModule.java
│ │ ├── toolwindow
│ │ ├── ResultGrouping.java
│ │ ├── FileGroupTreeInfo.java
│ │ ├── PackageGroupTreeInfo.java
│ │ ├── ConfigurationLocationGroupTreeInfo.java
│ │ ├── SeverityGroupTreeInfo.java
│ │ ├── CheckStyleToolWindowFactory.java
│ │ ├── GroupTreeInfo.java
│ │ ├── ResultProblem.java
│ │ ├── ResultTreeNode.java
│ │ ├── ProblemResultTreeInfo.java
│ │ └── ToggleableTreeNode.java
│ │ ├── util
│ │ ├── Strings.java
│ │ ├── Exceptions.java
│ │ ├── OS.java
│ │ ├── FileTypes.java
│ │ ├── Objects.java
│ │ ├── DisplayFormats.java
│ │ ├── ProjectPaths.java
│ │ ├── Streams.java
│ │ ├── ClassLoaderDumper.java
│ │ ├── Async.java
│ │ └── ModulePaths.java
│ │ ├── actions
│ │ ├── GroupByFile.java
│ │ ├── GroupByPackage.java
│ │ ├── GroupBySeverity.java
│ │ ├── GroupBySourceCheck.java
│ │ ├── GroupByConfigurationLocation.java
│ │ ├── Close.java
│ │ ├── JumpToSource.java
│ │ ├── NextResult.java
│ │ ├── PreviousResult.java
│ │ ├── ExpandAll.java
│ │ ├── CollapseAll.java
│ │ ├── ScanAllGivenFilesTask.java
│ │ ├── ScanAllFilesInProjectTask.java
│ │ ├── ScanAllFilesInModuleTask.java
│ │ ├── AnalyseCurrentFile.java
│ │ ├── ResetLoadedRulesFiles.java
│ │ ├── ScrollToSource.java
│ │ ├── DisplayErrors.java
│ │ ├── DisplayInfo.java
│ │ ├── DisplayWarnings.java
│ │ ├── GroupingAction.java
│ │ ├── StopCheck.java
│ │ ├── ScanAllFilesTask.java
│ │ ├── ScanModifiedFiles.java
│ │ ├── ToolWindowAccess.java
│ │ └── ScanCurrentChangeList.java
│ │ ├── exception
│ │ ├── CheckStylePluginParseException.java
│ │ ├── CheckStylePluginException.java
│ │ ├── CheckstyleToolException.java
│ │ └── CheckstyleServiceException.java
│ │ ├── model
│ │ ├── ScanResult.java
│ │ ├── ConfigurationType.java
│ │ ├── RelativeFileConfigurationLocation.java
│ │ ├── ScanScope.java
│ │ ├── BundledConfigurationLocation.java
│ │ ├── InsecureHTTPURLConfigurationLocation.java
│ │ ├── NamedScopeHelper.java
│ │ └── ClasspathConfigurationLocation.java
│ │ ├── CheckstyleModuleConfigurationEditorProvider.java
│ │ ├── CheckStyleBundle.java
│ │ ├── ui
│ │ ├── CompletePanel.java
│ │ ├── CheckStyleInspectionPanel.java
│ │ ├── PropertiesDialogue.java
│ │ └── ErrorPanel.java
│ │ ├── handlers
│ │ └── ScanFilesBeforeCheckinHandlerFactory.java
│ │ ├── CheckStylePlugin.java
│ │ ├── checks
│ │ ├── Check.java
│ │ ├── CheckFactory.java
│ │ └── PackageHtmlCheck.java
│ │ ├── importer
│ │ ├── modules
│ │ │ ├── NoWhitespaceBeforeImporter.java
│ │ │ ├── WhitespaceAfterImporter.java
│ │ │ ├── NeedBracesImporter.java
│ │ │ ├── FileTabCharacterImporter.java
│ │ │ ├── EmptyLineSeparatorImporter.java
│ │ │ ├── LineLengthImporter.java
│ │ │ ├── IndentationImporter.java
│ │ │ └── AvoidStarImportImporter.java
│ │ ├── ModuleImporterFactory.java
│ │ └── ModuleImporter.java
│ │ ├── startup
│ │ └── DisableCheckstyleLogging.java
│ │ ├── ConfigurationInvalidator.java
│ │ └── CheckstylePluginApi.java
├── csaccessTest
│ ├── resources
│ │ └── org
│ │ │ └── infernus
│ │ │ └── idea
│ │ │ └── checkstyle
│ │ │ └── service
│ │ │ ├── SourceFile.java
│ │ │ ├── cmd
│ │ │ └── config-ok.xml
│ │ │ └── config-file-contents-holder.xml
│ └── java
│ │ └── org
│ │ └── infernus
│ │ └── idea
│ │ └── checkstyle
│ │ └── service
│ │ ├── FileUtil.java
│ │ ├── TestHelper.java
│ │ ├── SimpleResolverTest.java
│ │ ├── cmd
│ │ ├── OpScanTest.java
│ │ ├── OpDestroyCheckerTest.java
│ │ └── OpPeruseConfigurationTest.java
│ │ ├── ConfigurationBuilder.java
│ │ ├── StringConfigurationLocation.java
│ │ └── CsVersionInfo.java
└── csaccess
│ └── java
│ └── org
│ └── infernus
│ └── idea
│ └── checkstyle
│ └── service
│ ├── entities
│ ├── HasCsConfig.java
│ ├── HasChecker.java
│ ├── CsConfigObject.java
│ └── CheckerWithConfig.java
│ ├── package-info.java
│ ├── cmd
│ ├── CheckstyleCommand.java
│ ├── CheckstyleBridge.java
│ └── OpDestroyChecker.java
│ └── SimpleResolver.java
├── mise.toml
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── settings.gradle.kts
├── .gitignore
├── .github
└── workflows
│ ├── ci.yml
│ └── release.yml
└── LICENCE
/src/test/resources/emptyFile1.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/test/resources/emptyFile2.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/mise.toml:
--------------------------------------------------------------------------------
1 | [tools]
2 | java = "liberica-17"
3 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.configuration-cache=true
2 |
--------------------------------------------------------------------------------
/src/test/resources/cpstab/readme.txt:
--------------------------------------------------------------------------------
1 | This file should be named as in TempDirProvider.README_FILE.
2 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jshiell/checkstyle-idea/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/src/test/resources/cpstab/lib1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jshiell/checkstyle-idea/HEAD/src/test/resources/cpstab/lib1.jar
--------------------------------------------------------------------------------
/src/test/resources/cpstab/libs/lib1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jshiell/checkstyle-idea/HEAD/src/test/resources/cpstab/libs/lib1.jar
--------------------------------------------------------------------------------
/src/test/resources/cpstab/libs/lib2.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jshiell/checkstyle-idea/HEAD/src/test/resources/cpstab/libs/lib2.jar
--------------------------------------------------------------------------------
/src/test/resources/cpstab/hashed/lib1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jshiell/checkstyle-idea/HEAD/src/test/resources/cpstab/hashed/lib1.jar
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | rootProject.name = "checkstyle-idea"
2 |
3 | dependencyResolutionManagement {
4 | repositories {
5 | mavenCentral()
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/test/resources/cpstab/mmmfkoez3kxcsqlrrqbfbcxo5e4k6gq4/lib1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jshiell/checkstyle-idea/HEAD/src/test/resources/cpstab/mmmfkoez3kxcsqlrrqbfbcxo5e4k6gq4/lib1.jar
--------------------------------------------------------------------------------
/src/main/resources/org/infernus/idea/checkstyle/images/checkstyle.pxd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jshiell/checkstyle-idea/HEAD/src/main/resources/org/infernus/idea/checkstyle/images/checkstyle.pxd
--------------------------------------------------------------------------------
/src/main/resources/dtd/packages_1_0.dtd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/doc-files/CheckstyleClassLoader-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jshiell/checkstyle-idea/HEAD/src/main/java/org/infernus/idea/checkstyle/doc-files/CheckstyleClassLoader-1.png
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/doc-files/CheckstyleClassLoader-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jshiell/checkstyle-idea/HEAD/src/main/java/org/infernus/idea/checkstyle/doc-files/CheckstyleClassLoader-2.png
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/config/ConfigurationListener.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.config;
2 |
3 | public interface ConfigurationListener {
4 |
5 | void configurationChanged();
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/src/test/resources/cpstab/a_long_folder/path_more_than_50_characters/in_total/lib1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jshiell/checkstyle-idea/HEAD/src/test/resources/cpstab/a_long_folder/path_more_than_50_characters/in_total/lib1.jar
--------------------------------------------------------------------------------
/src/main/resources/inspectionDescriptions/CheckStyle.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | This inspection integrates CheckStyle and reports in real-time
4 | on problems against the current CheckStyle profile.
5 |
6 |
7 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/checker/ConfigurationLocationStatus.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.checker;
2 |
3 | public enum ConfigurationLocationStatus {
4 |
5 | PRESENT,
6 | NOT_PRESENT,
7 | BLOCKED
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/csapi/SeverityLevel.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.csapi;
2 |
3 | /**
4 | * Checkstyle violation severity levels supported by this plugin.
5 | */
6 | public enum SeverityLevel {
7 | Ignore, Info, Warning, Error
8 | }
9 |
--------------------------------------------------------------------------------
/src/test/resources/checkstyle-idea.broken2.properties:
--------------------------------------------------------------------------------
1 | # Broken Checkstyle-IDEA plugin configuration for unit tests
2 |
3 |
4 | checkstyle.versions.supported = 7.1, 7.2, 7.3
5 | baseVersion = 7.1
6 |
7 | # Error: 7.1.1 does not exist
8 | checkstyle.versions.map = 7.0 -> 7.1.1
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | CheckStyle-IDEA.zip
2 | .DS_Store
3 | *.iws
4 | *.ipr
5 | *.iml
6 | .idea/
7 | /build/
8 | /buildSrc/build/
9 | /buildSrc/out/
10 | /test-configs/
11 | .gradle/
12 | gradle-app.setting
13 | /.gradletasknamecache
14 | _support/
15 | /out/
16 | .intellijPlatform/
17 |
--------------------------------------------------------------------------------
/src/test/resources/checkstyle-idea.broken1.properties:
--------------------------------------------------------------------------------
1 | # Broken Checkstyle-IDEA plugin configuration for unit tests
2 |
3 |
4 | checkstyle.versions.supported = 7.1, 7.2, 7.3
5 | baseVersion = 7.1
6 |
7 | # Error: 7.1 is in fact supported
8 | checkstyle.versions.map = 7.0 -> 7.1, 7.1 -> 7.2
9 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/csapi/TabWidthAndBaseDirProvider.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.csapi;
2 |
3 | import java.util.Optional;
4 |
5 |
6 | public interface TabWidthAndBaseDirProvider {
7 |
8 | int tabWidth();
9 |
10 | Optional baseDir();
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/toolwindow/ResultGrouping.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.toolwindow;
2 |
3 | public enum ResultGrouping {
4 |
5 | BY_FILE,
6 | BY_PACKAGE,
7 | BY_SEVERITY,
8 | BY_CONFIGURATION_LOCATION,
9 | BY_SOURCE_CHECK
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip
4 | networkTimeout=10000
5 | validateDistributionUrl=true
6 | zipStoreBase=GRADLE_USER_HOME
7 | zipStorePath=wrapper/dists
8 |
--------------------------------------------------------------------------------
/src/test/resources/org/infernus/idea/checkstyle/SourceFile.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.service;
2 |
3 | /**
4 | * An example source file used for triggering Checkstyle scans in unit tests.
5 | */
6 | public class SourceFile {
7 | public void method() {
8 | // does not matter
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/util/Strings.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.util;
2 |
3 | public final class Strings {
4 |
5 | private Strings() {
6 | }
7 |
8 | public static boolean isBlank(final String value) {
9 | return value == null || value.trim().isEmpty();
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/src/csaccessTest/resources/org/infernus/idea/checkstyle/service/SourceFile.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.service;
2 |
3 | /**
4 | * An example source file used for triggering Checkstyle scans in unit tests.
5 | */
6 | public class SourceFile {
7 | public void method() {
8 | // does not matter
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/actions/GroupByFile.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.actions;
2 |
3 | import org.infernus.idea.checkstyle.toolwindow.ResultGrouping;
4 |
5 | public class GroupByFile extends GroupingAction {
6 |
7 | public GroupByFile() {
8 | super(ResultGrouping.BY_FILE);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/actions/GroupByPackage.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.actions;
2 |
3 | import org.infernus.idea.checkstyle.toolwindow.ResultGrouping;
4 |
5 | public class GroupByPackage extends GroupingAction {
6 |
7 | public GroupByPackage() {
8 | super(ResultGrouping.BY_PACKAGE);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/actions/GroupBySeverity.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.actions;
2 |
3 | import org.infernus.idea.checkstyle.toolwindow.ResultGrouping;
4 |
5 | public class GroupBySeverity extends GroupingAction {
6 |
7 | public GroupBySeverity() {
8 | super(ResultGrouping.BY_SEVERITY);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/csapi/ConfigVisitor.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.csapi;
2 |
3 | import org.jetbrains.annotations.NotNull;
4 |
5 |
6 | /**
7 | * Visitor called by the PeruseConfiguration command.
8 | */
9 | public interface ConfigVisitor {
10 |
11 | void visit(@NotNull ConfigurationModule module);
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/actions/GroupBySourceCheck.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.actions;
2 |
3 | import org.infernus.idea.checkstyle.toolwindow.ResultGrouping;
4 |
5 | public class GroupBySourceCheck extends GroupingAction {
6 |
7 | public GroupBySourceCheck() {
8 | super(ResultGrouping.BY_SOURCE_CHECK);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/actions/GroupByConfigurationLocation.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.actions;
2 |
3 | import org.infernus.idea.checkstyle.toolwindow.ResultGrouping;
4 |
5 | public class GroupByConfigurationLocation extends GroupingAction {
6 |
7 | public GroupByConfigurationLocation() {
8 | super(ResultGrouping.BY_CONFIGURATION_LOCATION);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/csaccess/java/org/infernus/idea/checkstyle/service/entities/HasCsConfig.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.service.entities;
2 |
3 | import com.puppycrawl.tools.checkstyle.api.Configuration;
4 | import org.infernus.idea.checkstyle.csapi.CheckstyleInternalObject;
5 |
6 |
7 | public interface HasCsConfig extends CheckstyleInternalObject {
8 |
9 | Configuration getConfiguration();
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/util/Exceptions.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.util;
2 |
3 | public final class Exceptions {
4 |
5 | private Exceptions() {
6 | }
7 |
8 | public static Throwable rootCauseOf(final Throwable t) {
9 | if (t.getCause() != null && t.getCause() != t) {
10 | return rootCauseOf(t.getCause());
11 | }
12 | return t;
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/util/OS.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.util;
2 |
3 | import java.util.Locale;
4 |
5 | public final class OS {
6 |
7 | private static final String OPERATING_SYSTEM = System.getProperty("os.name").toLowerCase(Locale.ENGLISH);
8 |
9 | private OS() {
10 | }
11 |
12 | public static boolean isWindows() {
13 | return OPERATING_SYSTEM.contains("win");
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/util/FileTypes.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.util;
2 |
3 | import com.intellij.ide.highlighter.JavaFileType;
4 | import com.intellij.openapi.fileTypes.FileType;
5 |
6 | public final class FileTypes {
7 |
8 | private FileTypes() {
9 | }
10 |
11 | public static boolean isJava(final FileType fileType) {
12 | return JavaFileType.INSTANCE.equals(fileType);
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/csaccess/java/org/infernus/idea/checkstyle/service/entities/HasChecker.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.service.entities;
2 |
3 | import com.puppycrawl.tools.checkstyle.Checker;
4 | import org.infernus.idea.checkstyle.csapi.CheckstyleInternalObject;
5 |
6 | import java.util.concurrent.locks.Lock;
7 |
8 |
9 | public interface HasChecker extends CheckstyleInternalObject {
10 |
11 | Checker getChecker();
12 |
13 | Lock getCheckerLock();
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: Build
2 |
3 | on:
4 | push:
5 | branches: [ main ]
6 | pull_request:
7 | branches: [ main ]
8 |
9 | jobs:
10 | build:
11 | runs-on: ubuntu-latest
12 |
13 | steps:
14 | - uses: actions/checkout@v4
15 |
16 | - name: Set up Java 17
17 | uses: actions/setup-java@v4
18 | with:
19 | java-version: 17
20 | distribution: liberica
21 |
22 | - name: Build
23 | run: ./gradlew build
24 |
--------------------------------------------------------------------------------
/src/main/resources/org/infernus/idea/checkstyle/util/copylibs-readme.template.txt:
--------------------------------------------------------------------------------
1 | This folder contains libraries copied from the "{0}" project.
2 | It is managed by the {1} IDE plugin.
3 | Do not modify this folder while the IDE is running.
4 | When the IDE is stopped, you may delete this folder at any time. It will be recreated as needed.
5 | In order to prevent the {1} IDE plugin from creating this folder,
6 | uncheck the "Copy libraries from project directory" option in the {1} settings dialog.
7 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/exception/CheckStylePluginParseException.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.exception;
2 |
3 | import java.io.Serial;
4 |
5 | public class CheckStylePluginParseException extends CheckStylePluginException {
6 | @Serial
7 | private static final long serialVersionUID = -2138216104879079892L;
8 |
9 | public CheckStylePluginParseException(final String message, final Throwable cause) {
10 | super(message, cause);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/csaccess/java/org/infernus/idea/checkstyle/service/entities/CsConfigObject.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.service.entities;
2 |
3 | import com.puppycrawl.tools.checkstyle.api.Configuration;
4 |
5 |
6 | public class CsConfigObject implements HasCsConfig {
7 |
8 | private final Configuration configuration;
9 |
10 | public CsConfigObject(final Configuration configuration) {
11 | this.configuration = configuration;
12 | }
13 |
14 | public Configuration getConfiguration() {
15 | return configuration;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/util/Objects.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.util;
2 |
3 | public final class Objects {
4 |
5 | private Objects() {
6 | }
7 |
8 | public static > int compare(final T obj1, final T obj2) {
9 | if (obj1 == null && obj2 == null) {
10 | return 0;
11 | } else if (obj1 == null) {
12 | return -1;
13 | } else if (obj2 == null) {
14 | return 1;
15 | }
16 | return obj1.compareTo(obj2);
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/resources/dtd/configuration_1_0.dtd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/toolwindow/FileGroupTreeInfo.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.toolwindow;
2 |
3 | import com.intellij.icons.AllIcons;
4 |
5 | class FileGroupTreeInfo extends GroupTreeInfo {
6 |
7 | /**
8 | * Construct a file node.
9 | *
10 | * @param fileName the name of the file.
11 | * @param problemCount the number of problems in the file.
12 | */
13 | FileGroupTreeInfo(final String fileName, final int problemCount) {
14 | super(fileName, "file", AllIcons.FileTypes.Java, problemCount);
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/util/DisplayFormats.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.util;
2 |
3 | public final class DisplayFormats {
4 |
5 | private DisplayFormats() {
6 | }
7 |
8 | public static String shortenClassName(final String className) {
9 | final int lastPackageIndex = className.lastIndexOf(".");
10 | if (lastPackageIndex >= 0) {
11 | return className
12 | .substring(lastPackageIndex + 1)
13 | .replaceFirst("Check$", "");
14 | }
15 | return className;
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/resources/dtd/suppressions_1_0.dtd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 |
12 |
13 |
17 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/actions/Close.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.actions;
2 |
3 | import com.intellij.openapi.actionSystem.AnActionEvent;
4 | import org.jetbrains.annotations.NotNull;
5 |
6 | import static org.infernus.idea.checkstyle.actions.ToolWindowAccess.toolWindow;
7 |
8 | /**
9 | * Action to close the tool window.
10 | */
11 | public class Close extends BaseAction {
12 |
13 | @Override
14 | public void actionPerformed(final @NotNull AnActionEvent event) {
15 | project(event).ifPresent(project -> toolWindow(project).hide(null));
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/toolwindow/PackageGroupTreeInfo.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.toolwindow;
2 |
3 | import com.intellij.icons.AllIcons;
4 |
5 | class PackageGroupTreeInfo extends GroupTreeInfo {
6 |
7 | /**
8 | * Construct a package node.
9 | *
10 | * @param packageName the name of the package.
11 | * @param problemCount the number of problems in the file.
12 | */
13 | PackageGroupTreeInfo(final String packageName, final int problemCount) {
14 | super(packageName, "package", AllIcons.Nodes.Package, problemCount);
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/resources/dtd/suppressions_1_2.dtd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 |
12 |
13 |
19 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/checker/ScannerListener.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.checker;
2 |
3 | import com.intellij.psi.PsiFile;
4 | import org.infernus.idea.checkstyle.exception.CheckStylePluginException;
5 | import org.infernus.idea.checkstyle.model.ScanResult;
6 |
7 | import java.util.List;
8 |
9 | public interface ScannerListener {
10 |
11 | void scanStarting(List filesToScan);
12 |
13 | void filesScanned(int count);
14 |
15 | void scanCompletedSuccessfully(List scanResults);
16 |
17 | void scanFailedWithError(CheckStylePluginException error);
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/exception/CheckStylePluginException.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.exception;
2 |
3 |
4 | import java.io.Serial;
5 |
6 | /**
7 | * Common exception thrown anywhere in this plugin.
8 | */
9 | public class CheckStylePluginException extends RuntimeException {
10 |
11 | @Serial
12 | private static final long serialVersionUID = 2L;
13 |
14 | public CheckStylePluginException(final String message) {
15 | super(message);
16 | }
17 |
18 | public CheckStylePluginException(final String message, final Throwable cause) {
19 | super(message, cause);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/resources/dtd/suppressions_1_1.dtd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 |
12 |
13 |
18 |
--------------------------------------------------------------------------------
/src/test/resources/org/infernus/idea/checkstyle/config-ok.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/exception/CheckstyleToolException.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.exception;
2 |
3 | /**
4 | * Wrapper for an exception that occurred in the Checkstyle tool itself.
5 | * Important: Be sure to throw it only from the 'csaccess' sourceset!
6 | */
7 | public class CheckstyleToolException extends CheckstyleServiceException {
8 |
9 | /**
10 | * Constructor which copies the given cause's message into this instance.
11 | *
12 | * @param pCause the cause
13 | */
14 | public CheckstyleToolException(final Throwable pCause) {
15 | super(pCause.getMessage(), pCause);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/csaccessTest/resources/org/infernus/idea/checkstyle/service/cmd/config-ok.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/checker/SuppressForCheckstyleFix.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.checker;
2 |
3 | import com.intellij.codeInsight.daemon.impl.actions.SuppressFix;
4 | import org.infernus.idea.checkstyle.CheckStyleBundle;
5 | import org.jetbrains.annotations.NotNull;
6 |
7 | public class SuppressForCheckstyleFix extends SuppressFix {
8 | SuppressForCheckstyleFix(@NotNull final String sourceCheckName) {
9 | super("checkstyle:" + sourceCheckName);
10 | }
11 |
12 | @NotNull
13 | @Override
14 | public String getText() {
15 | return CheckStyleBundle.message("inspection.fix.suppress-for-checkstyle");
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/model/ScanResult.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.model;
2 |
3 | import com.intellij.openapi.module.Module;
4 | import com.intellij.psi.PsiFile;
5 | import org.infernus.idea.checkstyle.checker.ConfigurationLocationResult;
6 | import org.infernus.idea.checkstyle.checker.Problem;
7 |
8 | import java.util.Collections;
9 | import java.util.List;
10 | import java.util.Map;
11 |
12 | public record ScanResult(ConfigurationLocationResult configurationLocationResult,
13 | Module module,
14 | Map> problems) {
15 |
16 | public static final ScanResult EMPTY = new ScanResult(null, null, Collections.emptyMap());
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/CheckstyleModuleConfigurationEditorProvider.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle;
2 |
3 | import com.intellij.openapi.module.ModuleConfigurationEditor;
4 | import com.intellij.openapi.roots.ui.configuration.ModuleConfigurationEditorProvider;
5 | import com.intellij.openapi.roots.ui.configuration.ModuleConfigurationState;
6 |
7 | public class CheckstyleModuleConfigurationEditorProvider implements ModuleConfigurationEditorProvider {
8 | @Override
9 | public ModuleConfigurationEditor[] createEditors(final ModuleConfigurationState state) {
10 | return new ModuleConfigurationEditor[] {new CheckStyleModuleConfigurationEditor(state.getCurrentRootModel().getModule())};
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/exception/CheckstyleServiceException.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.exception;
2 |
3 | /**
4 | * An exception that originates with the Checkstyle access layer (aka Checkstyle plugin service), but is not
5 | * a native CheckstyleException.
6 | * Important: Be sure to throw it only from the 'csaccess' sourceset!
7 | */
8 | public class CheckstyleServiceException extends CheckStylePluginException {
9 |
10 | public CheckstyleServiceException(final String message) {
11 | super(message);
12 | }
13 |
14 | public CheckstyleServiceException(final String message, final Throwable cause) {
15 | super(message, cause);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/CheckStyleBundle.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle;
2 |
3 | import com.intellij.AbstractBundle;
4 | import org.jetbrains.annotations.NonNls;
5 | import org.jetbrains.annotations.PropertyKey;
6 |
7 | public final class CheckStyleBundle extends AbstractBundle {
8 |
9 | @NonNls
10 | private static final String BUNDLE = "org.infernus.idea.checkstyle.CheckStyleBundle";
11 | private static final CheckStyleBundle INSTANCE = new CheckStyleBundle();
12 |
13 | private CheckStyleBundle() {
14 | super(BUNDLE);
15 | }
16 |
17 | public static String message(@PropertyKey(resourceBundle = BUNDLE) final String key, final Object... params) {
18 | return INSTANCE.getMessage(key, params);
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/toolwindow/ConfigurationLocationGroupTreeInfo.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.toolwindow;
2 |
3 | import com.intellij.icons.AllIcons;
4 |
5 | class ConfigurationLocationGroupTreeInfo extends GroupTreeInfo {
6 |
7 | /**
8 | * Construct a configuration location node.
9 | *
10 | * @param configurationLocationDescription the name of the configuration location.
11 | * @param problemCount the number of problems in the file.
12 | */
13 | ConfigurationLocationGroupTreeInfo(final String configurationLocationDescription, final int problemCount) {
14 | super(configurationLocationDescription, "configuration-location", AllIcons.FileTypes.Properties, problemCount);
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/actions/JumpToSource.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.actions;
2 |
3 | import com.intellij.openapi.actionSystem.AnActionEvent;
4 | import org.infernus.idea.checkstyle.toolwindow.CheckStyleToolWindowPanel;
5 | import org.jetbrains.annotations.NotNull;
6 |
7 | import static org.infernus.idea.checkstyle.actions.ToolWindowAccess.*;
8 |
9 | public class JumpToSource extends BaseAction {
10 |
11 | @Override
12 | public void actionPerformed(@NotNull final AnActionEvent event) {
13 | project(event).ifPresent(project -> {
14 | if (isFocusInToolWindow(project)) {
15 | actOnToolWindowPanel(toolWindow(project), CheckStyleToolWindowPanel::jumpToSource);
16 | }
17 | });
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/actions/NextResult.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.actions;
2 |
3 | import com.intellij.openapi.actionSystem.AnActionEvent;
4 | import org.infernus.idea.checkstyle.toolwindow.CheckStyleToolWindowPanel;
5 | import org.jetbrains.annotations.NotNull;
6 |
7 | import static org.infernus.idea.checkstyle.actions.ToolWindowAccess.*;
8 |
9 | public class NextResult extends BaseAction {
10 |
11 | @Override
12 | public void actionPerformed(@NotNull final AnActionEvent event) {
13 | project(event).ifPresent(project -> {
14 | if (isFocusInToolWindow(project)) {
15 | actOnToolWindowPanel(toolWindow(project), CheckStyleToolWindowPanel::selectNextResult);
16 | }
17 | });
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/resources/org/infernus/idea/checkstyle/images/checkstyle.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/csaccess/java/org/infernus/idea/checkstyle/service/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * The Checkstyle Service Layer, or just the "service layer". The Checkstyle tool itself, which means the classes in
3 | * {@code com.puppycrawl}, are available in this package and its subpackages only. All classes of the service layer
4 | * are loaded by a custom classloader which is discarded and rebuilt whenever the user of the Checkstyle-IDEA plugin
5 | * selects a new Checkstyle version. This is required so that the plugin can support multiple Checkstyle versions.
6 | * This layer must be kept as thin as absolutely possible. Test coverage must be very high in order to make sure
7 | * that breaking changes in the Checkstyle API are detected and handled.
8 | */
9 | package org.infernus.idea.checkstyle.service;
10 |
--------------------------------------------------------------------------------
/src/main/resources/org/infernus/idea/checkstyle/images/checkstyle_dark.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/actions/PreviousResult.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.actions;
2 |
3 | import com.intellij.openapi.actionSystem.AnActionEvent;
4 | import org.infernus.idea.checkstyle.toolwindow.CheckStyleToolWindowPanel;
5 | import org.jetbrains.annotations.NotNull;
6 |
7 | import static org.infernus.idea.checkstyle.actions.ToolWindowAccess.*;
8 |
9 | public class PreviousResult extends BaseAction {
10 |
11 | @Override
12 | public void actionPerformed(@NotNull final AnActionEvent event) {
13 | project(event).ifPresent(project -> {
14 | if (isFocusInToolWindow(project)) {
15 | actOnToolWindowPanel(toolWindow(project), CheckStyleToolWindowPanel::selectPreviousResult);
16 | }
17 | });
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/csaccess/java/org/infernus/idea/checkstyle/service/cmd/CheckstyleCommand.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.service.cmd;
2 |
3 | import com.intellij.openapi.project.Project;
4 | import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
5 | import org.jetbrains.annotations.NotNull;
6 |
7 | /**
8 | * Describes commands of the Checkstyle access layer.
9 | *
10 | * @param result type
11 | */
12 | public interface CheckstyleCommand {
13 | /**
14 | * Execute the command.
15 | *
16 | * @param project the IntelliJ project in whose context we are executing
17 | * @return the result of the command
18 | * @throws CheckstyleException if an exception was thrown from the Checkstyle tool
19 | */
20 | R execute(@NotNull Project project) throws CheckstyleException;
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/ui/CompletePanel.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.ui;
2 |
3 | import com.intellij.util.ui.JBUI;
4 | import org.infernus.idea.checkstyle.CheckStyleBundle;
5 |
6 | import javax.swing.*;
7 | import java.awt.*;
8 |
9 | public class CompletePanel extends JPanel {
10 |
11 | public CompletePanel() {
12 | super(new GridBagLayout());
13 |
14 | initialise();
15 | }
16 |
17 | private void initialise() {
18 | final JLabel infoLabel = new JLabel(CheckStyleBundle.message("config.file.complete.text"));
19 |
20 | setBorder(JBUI.Borders.empty(4));
21 |
22 | add(infoLabel, new GridBagConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.NORTHWEST,
23 | GridBagConstraints.NONE, JBUI.insets(8), 0, 0));
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/handlers/ScanFilesBeforeCheckinHandlerFactory.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.handlers;
2 |
3 | import com.intellij.openapi.vcs.CheckinProjectPanel;
4 | import com.intellij.openapi.vcs.changes.CommitContext;
5 | import com.intellij.openapi.vcs.checkin.CheckinHandler;
6 | import com.intellij.openapi.vcs.checkin.CheckinHandlerFactory;
7 | import org.jetbrains.annotations.NotNull;
8 |
9 | public class ScanFilesBeforeCheckinHandlerFactory extends CheckinHandlerFactory {
10 |
11 | @NotNull
12 | @Override
13 | public CheckinHandler createHandler(@NotNull final CheckinProjectPanel checkinProjectPanel,
14 | @NotNull final CommitContext commitContext) {
15 | return new ScanFilesBeforeCheckinHandler(checkinProjectPanel);
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/csaccess/java/org/infernus/idea/checkstyle/service/SimpleResolver.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.service;
2 |
3 | import java.util.Map;
4 |
5 | import com.puppycrawl.tools.checkstyle.PropertyResolver;
6 | import org.jetbrains.annotations.NotNull;
7 | import org.jetbrains.annotations.Nullable;
8 |
9 |
10 | public class SimpleResolver implements PropertyResolver {
11 |
12 | private final Map properties;
13 |
14 | public SimpleResolver(@NotNull final Map properties) {
15 | this.properties = properties;
16 | }
17 |
18 | @Override
19 | @Nullable
20 | public String resolve(@Nullable final String name) {
21 | String result = null;
22 | if (name != null) {
23 | result = properties.get(name);
24 | }
25 | return result;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/actions/ExpandAll.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.actions;
2 |
3 | import com.intellij.openapi.actionSystem.AnActionEvent;
4 | import org.infernus.idea.checkstyle.toolwindow.CheckStyleToolWindowPanel;
5 | import org.jetbrains.annotations.NotNull;
6 |
7 | import static org.infernus.idea.checkstyle.actions.ToolWindowAccess.actOnToolWindowPanel;
8 | import static org.infernus.idea.checkstyle.actions.ToolWindowAccess.toolWindow;
9 |
10 | /**
11 | * Action to expand all nodes in the results window.
12 | */
13 | public class ExpandAll extends BaseAction {
14 |
15 | @Override
16 | public void actionPerformed(final @NotNull AnActionEvent event) {
17 | project(event).ifPresent(project -> actOnToolWindowPanel(toolWindow(project), CheckStyleToolWindowPanel::expandTree));
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/util/ProjectPaths.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.util;
2 |
3 | import com.intellij.openapi.module.Module;
4 | import com.intellij.openapi.project.Project;
5 | import com.intellij.openapi.project.ProjectUtil;
6 | import com.intellij.openapi.vfs.VirtualFile;
7 | import org.jetbrains.annotations.NotNull;
8 | import org.jetbrains.annotations.Nullable;
9 |
10 | public class ProjectPaths {
11 |
12 | @Nullable
13 | public VirtualFile projectPath(@NotNull final Project project) {
14 | // workaround to allow testing with Jetbrain's love of static shite
15 | return ProjectUtil.guessProjectDir(project);
16 | }
17 |
18 | @Nullable
19 | public VirtualFile modulePath(@NotNull final Module module) {
20 | return ProjectUtil.guessModuleDir(module);
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/actions/CollapseAll.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.actions;
2 |
3 | import com.intellij.openapi.actionSystem.AnActionEvent;
4 | import org.infernus.idea.checkstyle.toolwindow.CheckStyleToolWindowPanel;
5 | import org.jetbrains.annotations.NotNull;
6 |
7 | import static org.infernus.idea.checkstyle.actions.ToolWindowAccess.actOnToolWindowPanel;
8 | import static org.infernus.idea.checkstyle.actions.ToolWindowAccess.toolWindow;
9 |
10 | /**
11 | * Action to collapse all nodes in the results window.
12 | */
13 | public class CollapseAll extends BaseAction {
14 |
15 | @Override
16 | public void actionPerformed(final @NotNull AnActionEvent event) {
17 | project(event).ifPresent(project -> actOnToolWindowPanel(toolWindow(project), CheckStyleToolWindowPanel::collapseTree));
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/resources/org/infernus/idea/checkstyle/images/checkstyle@20x20.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/main/resources/org/infernus/idea/checkstyle/images/checkstyle@20x20_dark.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/actions/ScanAllGivenFilesTask.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.actions;
2 |
3 | import com.intellij.openapi.project.Project;
4 | import com.intellij.openapi.vfs.VirtualFile;
5 | import org.infernus.idea.checkstyle.model.ConfigurationLocation;
6 | import org.jetbrains.annotations.NotNull;
7 |
8 | class ScanAllGivenFilesTask extends ScanAllFilesTask {
9 | private final VirtualFile[] filesToScan;
10 |
11 | ScanAllGivenFilesTask(@NotNull final Project project,
12 | @NotNull final VirtualFile[] filesToScan,
13 | final ConfigurationLocation selectedOverride) {
14 | super(project, selectedOverride);
15 | this.filesToScan = filesToScan;
16 | }
17 |
18 | @Override
19 | protected VirtualFile[] files() {
20 | return filesToScan;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/resources/dtd/suppressions_1_1_xpath_experimental.dtd:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
16 |
17 |
18 |
22 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/checker/ConfigurationLocationResult.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.checker;
2 |
3 | import org.infernus.idea.checkstyle.model.ConfigurationLocation;
4 | import org.jetbrains.annotations.NotNull;
5 | import org.jetbrains.annotations.Nullable;
6 |
7 | public record ConfigurationLocationResult(ConfigurationLocation location, ConfigurationLocationStatus status) {
8 |
9 | public static final ConfigurationLocationResult NOT_PRESENT = new ConfigurationLocationResult(null, ConfigurationLocationStatus.NOT_PRESENT);
10 |
11 | public static ConfigurationLocationResult of(@Nullable final ConfigurationLocation configurationLocation,
12 | @NotNull final ConfigurationLocationStatus status) {
13 | return new ConfigurationLocationResult(configurationLocation, status);
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/actions/ScanAllFilesInProjectTask.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.actions;
2 |
3 | import com.intellij.openapi.project.Project;
4 | import com.intellij.openapi.roots.ProjectRootManager;
5 | import com.intellij.openapi.vfs.VirtualFile;
6 | import org.infernus.idea.checkstyle.model.ConfigurationLocation;
7 | import org.jetbrains.annotations.NotNull;
8 |
9 | public class ScanAllFilesInProjectTask extends ScanAllFilesTask {
10 |
11 | private final Project project;
12 |
13 | ScanAllFilesInProjectTask(@NotNull final Project project,
14 | final ConfigurationLocation selectedOverride) {
15 | super(project, selectedOverride);
16 | this.project = project;
17 | }
18 | @Override
19 | protected VirtualFile[] files() {
20 | return ProjectRootManager.getInstance(project).getContentRoots();
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/actions/ScanAllFilesInModuleTask.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.actions;
2 |
3 | import com.intellij.openapi.module.Module;
4 | import com.intellij.openapi.roots.ModuleRootManager;
5 | import com.intellij.openapi.vfs.VirtualFile;
6 | import org.infernus.idea.checkstyle.model.ConfigurationLocation;
7 | import org.jetbrains.annotations.NotNull;
8 |
9 | public class ScanAllFilesInModuleTask extends ScanAllFilesTask {
10 |
11 | private final Module module;
12 |
13 | ScanAllFilesInModuleTask(@NotNull final Module module,
14 | final ConfigurationLocation selectedOverride) {
15 | super(module.getProject(), selectedOverride);
16 | this.module = module;
17 | }
18 |
19 | @Override
20 | protected VirtualFile[] files() {
21 | return ModuleRootManager.getInstance(module).getContentRoots();
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/csaccessTest/java/org/infernus/idea/checkstyle/service/FileUtil.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.service;
2 |
3 | import org.jetbrains.annotations.NotNull;
4 | import org.junit.Assert;
5 |
6 | import java.io.IOException;
7 | import java.net.URISyntaxException;
8 | import java.net.URL;
9 | import java.nio.file.Files;
10 | import java.nio.file.Paths;
11 |
12 |
13 | public final class FileUtil {
14 |
15 | private FileUtil() {
16 | super();
17 | }
18 |
19 |
20 | public static String readFile(@NotNull final String filename) throws IOException, URISyntaxException {
21 | URL url = FileUtil.class.getResource(filename);
22 | if (url == null) {
23 | url = Thread.currentThread().getContextClassLoader().getResource(filename);
24 | }
25 | Assert.assertNotNull("File not found: " + filename, url);
26 | return Files.readString(Paths.get(url.toURI()));
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/resources/dtd/suppressions_1_2_xpath_experimental.dtd:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
17 |
18 |
19 |
24 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/csapi/Issue.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.csapi;
2 |
3 |
4 | /**
5 | * An issue as reported by the Checkstyle tool.
6 | */
7 | public class Issue {
8 |
9 | public final String fileName;
10 | public final int lineNumber;
11 | public final int columnNumber;
12 | public final String message;
13 | public final SeverityLevel severityLevel;
14 | public final String sourceName;
15 |
16 | public Issue(final String fileName,
17 | final int lineNumber,
18 | final int columnNumber,
19 | final String message,
20 | final SeverityLevel severityLevel,
21 | final String sourceName) {
22 | this.fileName = fileName;
23 | this.lineNumber = lineNumber;
24 | this.columnNumber = columnNumber;
25 | this.message = message;
26 | this.severityLevel = severityLevel;
27 | this.sourceName = sourceName;
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/CheckStylePlugin.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle;
2 |
3 | import com.intellij.ide.plugins.IdeaPluginDescriptor;
4 | import com.intellij.ide.plugins.PluginManagerCore;
5 | import com.intellij.openapi.extensions.PluginId;
6 |
7 | public final class CheckStylePlugin {
8 |
9 | private CheckStylePlugin() {
10 | }
11 |
12 | /**
13 | * The plugin ID. Caution: It must be identical to the String set in build.gradle at intellij.pluginName
14 | */
15 | public static final String ID_PLUGIN = "CheckStyle-IDEA";
16 |
17 | public static String version() {
18 | try {
19 | final IdeaPluginDescriptor plugin = PluginManagerCore.getPlugin(PluginId.getId(ID_PLUGIN));
20 | if (plugin != null) {
21 | return plugin.getVersion();
22 | }
23 | } catch (Throwable ignored) {
24 | // thrown if plugin isn't initialised, e.g. during tests
25 | }
26 | return "unknown";
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/toolwindow/SeverityGroupTreeInfo.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.toolwindow;
2 |
3 | import com.intellij.icons.AllIcons;
4 | import org.infernus.idea.checkstyle.csapi.SeverityLevel;
5 |
6 | import javax.swing.*;
7 |
8 | class SeverityGroupTreeInfo extends GroupTreeInfo {
9 |
10 | /**
11 | * Construct a severity node.
12 | *
13 | * @param severityLevel the severity level.
14 | * @param problemCount the number of problems at this severity.
15 | */
16 | SeverityGroupTreeInfo(final SeverityLevel severityLevel, final int problemCount) {
17 | super(severityLevel.name(), "file", iconForSeverity(severityLevel), problemCount);
18 | }
19 |
20 | private static Icon iconForSeverity(final SeverityLevel severityLevel) {
21 | return switch (severityLevel) {
22 | case Error -> AllIcons.General.Error;
23 | case Warning -> AllIcons.General.Warning;
24 | default -> AllIcons.General.Information;
25 | };
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/csaccess/java/org/infernus/idea/checkstyle/service/entities/CheckerWithConfig.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.service.entities;
2 |
3 | import com.puppycrawl.tools.checkstyle.Checker;
4 | import com.puppycrawl.tools.checkstyle.api.Configuration;
5 |
6 | import java.util.concurrent.locks.Lock;
7 | import java.util.concurrent.locks.ReentrantLock;
8 |
9 |
10 | public class CheckerWithConfig implements HasChecker, HasCsConfig {
11 |
12 | private final Checker checker;
13 | private final Lock lock = new ReentrantLock();
14 | private final Configuration configuration;
15 |
16 | public CheckerWithConfig(final Checker checker, final Configuration configuration) {
17 | this.checker = checker;
18 | this.configuration = configuration;
19 | }
20 |
21 | @Override
22 | public Checker getChecker() {
23 | return checker;
24 | }
25 |
26 | @Override
27 | public Lock getCheckerLock() {
28 | return lock;
29 | }
30 |
31 | public Configuration getConfiguration() {
32 | return configuration;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/util/Streams.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.util;
2 |
3 | import org.jetbrains.annotations.NotNull;
4 |
5 | import java.io.*;
6 |
7 | public final class Streams {
8 |
9 | private static final int BUFFER_SIZE = 4096;
10 |
11 | private Streams() {
12 |
13 | }
14 |
15 | public static InputStream inMemoryCopyOf(@NotNull final InputStream sourceStream) throws IOException {
16 | try (BufferedInputStream bis = new BufferedInputStream(sourceStream)) {
17 | return new ByteArrayInputStream(readContentOf(bis));
18 | }
19 | }
20 |
21 | public static byte[] readContentOf(final InputStream source) throws IOException {
22 | final ByteArrayOutputStream destination = new ByteArrayOutputStream();
23 | final byte[] readBuffer = new byte[BUFFER_SIZE];
24 | int count;
25 | while ((count = source.read(readBuffer, 0, BUFFER_SIZE)) != -1) {
26 | destination.write(readBuffer, 0, count);
27 | }
28 | return destination.toByteArray();
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/csapi/CheckstyleInternalObject.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.csapi;
2 |
3 |
4 | /**
5 | * Objects which implement this interface are keepers of objects internal to the Checkstyle tool, so from within the
6 | * normal plugin code we cannot know what they are. They are to be used from within the 'csaccess' source set only.
7 | * In this way, we can store objects from the Checkstyle tool itself in other parts of the plugin, although we
8 | * cannot use these objects.
9 | * It is important to make sure that these objects do not outlive the classloader that loaded them (at least not by
10 | * much). When the Checkstyle version is changed in the configuration, all objects which implement this interface
11 | * must be discarded. The new classloader with the new Checkstyle version would not be able to use them and
12 | * {@link org.infernus.idea.checkstyle.exception.CheckstyleVersionMixException CheckstyleVersionMixException}s would
13 | * result.
14 | */
15 | public interface CheckstyleInternalObject {
16 | // tagging interface
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/checks/Check.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.checks;
2 |
3 | import com.intellij.psi.PsiFile;
4 | import org.infernus.idea.checkstyle.csapi.CheckstyleInternalObject;
5 | import org.jetbrains.annotations.NotNull;
6 |
7 | /**
8 | * Allows extra logic for a certain Check.
9 | *
10 | * Not a lot of extra logic at present, but it's a start.
11 | */
12 | public interface Check {
13 |
14 | String getShortName();
15 |
16 | // TODO This may not be enough, because Checkstyle accepts more forms (e.g. FQCN without "Check" postfix).
17 | String getFullyQualifiedName();
18 |
19 | /**
20 | * Configure the check given the CheckStyle configuration.
21 | *
22 | * @param config the configuration.
23 | */
24 | void configure(@NotNull CheckstyleInternalObject config);
25 |
26 | /**
27 | * Process a file.
28 | *
29 | * @param file the file
30 | * @param pEventSourceName sourceName of the audit event
31 | * @return true to continue processing, false to cancel
32 | */
33 | boolean process(@NotNull PsiFile file, @NotNull String pEventSourceName);
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/importer/modules/NoWhitespaceBeforeImporter.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.importer.modules;
2 |
3 | import com.intellij.psi.codeStyle.CodeStyleSettings;
4 | import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
5 | import org.infernus.idea.checkstyle.csapi.KnownTokenTypes;
6 | import org.infernus.idea.checkstyle.importer.ModuleImporter;
7 | import org.jetbrains.annotations.NotNull;
8 |
9 | @SuppressWarnings("unused")
10 | public class NoWhitespaceBeforeImporter extends ModuleImporter {
11 |
12 | @Override
13 | protected void handleAttribute(@NotNull final String attrName, @NotNull final String attrValue) {
14 | // nothing to do
15 | }
16 |
17 |
18 | @Override
19 | public void importTo(@NotNull final CodeStyleSettings settings) {
20 | CommonCodeStyleSettings commonSettings = getCommonSettings(settings);
21 | if (appliesTo(KnownTokenTypes.COMMA)) {
22 | commonSettings.SPACE_BEFORE_COMMA = false;
23 | }
24 | if (appliesTo(KnownTokenTypes.SEMI)) {
25 | commonSettings.SPACE_BEFORE_SEMICOLON = false;
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/csaccessTest/java/org/infernus/idea/checkstyle/service/TestHelper.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.service;
2 |
3 | import com.intellij.openapi.project.Project;
4 | import com.intellij.packageDependencies.DependencyValidationManager;
5 | import com.intellij.psi.search.scope.packageSet.NamedScopeManager;
6 | import org.infernus.idea.checkstyle.checker.CheckerFactoryCache;
7 | import org.jetbrains.annotations.NotNull;
8 |
9 | import static org.mockito.Mockito.mock;
10 | import static org.mockito.Mockito.when;
11 |
12 | public final class TestHelper {
13 |
14 | private TestHelper() {
15 | }
16 |
17 | @NotNull
18 | public static Project mockProject() {
19 | final Project project = mock(Project.class);
20 | final CheckerFactoryCache checkerFactoryCache = new CheckerFactoryCache();
21 | when(project.getService(CheckerFactoryCache.class)).thenReturn(checkerFactoryCache);
22 | when(project.getService(NamedScopeManager.class)).thenReturn(new NamedScopeManager(project));
23 | when(project.getService(DependencyValidationManager.class)).thenReturn(mock(DependencyValidationManager.class));
24 | return project;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/csaccessTest/resources/org/infernus/idea/checkstyle/service/config-file-contents-holder.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/src/main/resources/dtd/configuration_1_1.dtd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 |
12 |
13 |
14 |
18 |
19 |
32 |
33 |
34 |
38 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/checker/CachedChecker.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.checker;
2 |
3 | import org.jetbrains.annotations.NotNull;
4 |
5 | /**
6 | * Value for checker cache.
7 | */
8 | class CachedChecker {
9 |
10 | /**
11 | * We cache purely to ignore repeated requests in a multi-file scan. Hence we'll treat the cached
12 | * value as valid for time in ms.
13 | */
14 | private static final int CACHE_VALID_TIME = 60000;
15 |
16 | private final CheckStyleChecker checkStyleChecker;
17 |
18 | private long timeStamp;
19 |
20 | CachedChecker(@NotNull final CheckStyleChecker checkStyleChecker) {
21 | this.checkStyleChecker = checkStyleChecker;
22 | this.timeStamp = System.currentTimeMillis();
23 | }
24 |
25 | public CheckStyleChecker getCheckStyleChecker() {
26 | this.timeStamp = System.currentTimeMillis();
27 | return checkStyleChecker;
28 | }
29 |
30 | private long getTimeStamp() {
31 | return timeStamp;
32 | }
33 |
34 | public boolean isValid() {
35 | return (getTimeStamp() + CACHE_VALID_TIME) >= System.currentTimeMillis();
36 | }
37 |
38 | public void destroy() {
39 | checkStyleChecker.destroy();
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/resources/dtd/configuration_1_2.dtd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 |
12 |
13 |
14 |
19 |
20 |
33 |
34 |
35 |
39 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/toolwindow/CheckStyleToolWindowFactory.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.toolwindow;
2 |
3 | import com.intellij.openapi.project.DumbAware;
4 | import com.intellij.openapi.project.Project;
5 | import com.intellij.openapi.wm.ToolWindow;
6 | import com.intellij.openapi.wm.ToolWindowFactory;
7 | import com.intellij.openapi.wm.ToolWindowType;
8 | import com.intellij.ui.content.Content;
9 | import org.infernus.idea.checkstyle.CheckStyleBundle;
10 | import org.jetbrains.annotations.NotNull;
11 |
12 | public class CheckStyleToolWindowFactory implements ToolWindowFactory, DumbAware {
13 |
14 | @Override
15 | public void createToolWindowContent(@NotNull final Project project, @NotNull final ToolWindow toolWindow) {
16 | final Content toolContent = toolWindow.getContentManager().getFactory().createContent(
17 | new CheckStyleToolWindowPanel(toolWindow, project),
18 | CheckStyleBundle.message("plugin.toolwindow.action"),
19 | false);
20 | toolWindow.getContentManager().addContent(toolContent);
21 |
22 | toolWindow.setTitle(CheckStyleBundle.message("plugin.toolwindow.name"));
23 | toolWindow.setType(ToolWindowType.DOCKED, null);
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/importer/modules/WhitespaceAfterImporter.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.importer.modules;
2 |
3 | import com.intellij.psi.codeStyle.CodeStyleSettings;
4 | import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
5 | import org.infernus.idea.checkstyle.csapi.KnownTokenTypes;
6 | import org.infernus.idea.checkstyle.importer.ModuleImporter;
7 | import org.jetbrains.annotations.NotNull;
8 |
9 | @SuppressWarnings("unused")
10 | public class WhitespaceAfterImporter extends ModuleImporter {
11 |
12 | @Override
13 | protected void handleAttribute(@NotNull final String attrName, @NotNull final String attrValue) {
14 | // nothing to do
15 | }
16 |
17 | @Override
18 | public void importTo(@NotNull final CodeStyleSettings settings) {
19 | CommonCodeStyleSettings commonSettings = getCommonSettings(settings);
20 | if (appliesTo(KnownTokenTypes.COMMA)) {
21 | commonSettings.SPACE_AFTER_COMMA = true;
22 | }
23 | if (appliesTo(KnownTokenTypes.SEMI)) {
24 | commonSettings.SPACE_AFTER_SEMICOLON = true;
25 | }
26 | if (appliesTo(KnownTokenTypes.TYPECAST)) {
27 | commonSettings.SPACE_AFTER_TYPE_CAST = true;
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/csaccessTest/java/org/infernus/idea/checkstyle/service/SimpleResolverTest.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.service;
2 |
3 | import org.junit.Before;
4 | import org.junit.Test;
5 |
6 | import java.util.HashMap;
7 | import java.util.Map;
8 |
9 | import static java.util.Collections.emptyMap;
10 | import static org.junit.Assert.assertEquals;
11 | import static org.junit.Assert.assertNull;
12 |
13 |
14 | public class SimpleResolverTest {
15 | private Map props;
16 |
17 | @Before
18 | public void beforeTest() {
19 | props = new HashMap<>();
20 | props.put("key1", "value1");
21 | props.put("key2", "value2");
22 | }
23 |
24 | @Test
25 | public void testResolve1() {
26 | assertEquals("value1", new SimpleResolver(props).resolve("key1"));
27 | assertEquals("value2", new SimpleResolver(props).resolve("key2"));
28 | }
29 |
30 | @Test
31 | public void testNotFound() {
32 | assertNull(new SimpleResolver(props).resolve("unknownKey"));
33 | assertNull(new SimpleResolver(props).resolve(null));
34 | }
35 |
36 | @Test
37 | public void testNoProps() {
38 | assertNull(new SimpleResolver(emptyMap()).resolve("key1"));
39 | assertNull(new SimpleResolver(emptyMap()).resolve(null));
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 |
3 | on:
4 | push:
5 | tags:
6 | - '*'
7 |
8 | jobs:
9 | build:
10 | runs-on: ubuntu-latest
11 |
12 | steps:
13 | - uses: actions/checkout@v4
14 |
15 | - name: Build info
16 | id: build_info
17 | run: |
18 | BUILD_TAG=${GITHUB_REF#refs/tags/}
19 | cat ./CHANGELOG.md | grep "$BUILD_TAG" | sed 's%^\*[[:space:]]*\*\*[0-9.]*\*\*[[:space:]]*%%g' > ${{ github.workspace }}-CHANGELOG.txt
20 | echo "build_tag=${BUILD_TAG}" >> $GITHUB_OUTPUT
21 |
22 | - name: Set up Java 17
23 | uses: actions/setup-java@v4
24 | with:
25 | java-version: 17
26 | distribution: liberica
27 |
28 | - name: Build
29 | run: ./gradlew build buildPlugin
30 |
31 | - name: Release
32 | uses: softprops/action-gh-release@v2
33 | with:
34 | body_path: ${{ github.workspace }}-CHANGELOG.txt
35 | fail_on_unmatched_files: true
36 | draft: false
37 | prerelease: false
38 | files:
39 | build/distributions/checkstyle-idea-${{ steps.build_info.outputs.build_tag }}.zip
40 |
41 | - name: Publish to Jetbrains Plugin Repo
42 | run: ./gradlew publishPlugin
43 | env:
44 | JETBRAINS_PLUGIN_REPO_TOKEN: ${{ secrets.JETBRAINS_PLUGIN_REPO_TOKEN }}
45 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/csapi/KnownTokenTypes.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.csapi;
2 |
3 | /**
4 | * TokenTypes which we use in this plugin somehow, a subset of the TokenTypes defined by Checkstyle.
5 | */
6 | //@formatter:off
7 | public enum KnownTokenTypes {
8 | ASSIGN,
9 | BAND,
10 | BAND_ASSIGN,
11 | BOR,
12 | BOR_ASSIGN,
13 | BSR,
14 | BSR_ASSIGN,
15 | BXOR,
16 | BXOR_ASSIGN,
17 | CLASS_DEF,
18 | COLON,
19 | COMMA,
20 | CTOR_DEF,
21 | DIV,
22 | DIV_ASSIGN,
23 | DO_WHILE,
24 | EQUAL,
25 | GE,
26 | GT,
27 | IMPORT,
28 | INTERFACE_DEF,
29 | LAND,
30 | LCURLY,
31 | LE,
32 | LITERAL_CASE,
33 | LITERAL_CATCH,
34 | LITERAL_DEFAULT,
35 | LITERAL_DO,
36 | LITERAL_ELSE,
37 | LITERAL_FINALLY,
38 | LITERAL_FOR,
39 | LITERAL_IF,
40 | LITERAL_SWITCH,
41 | LITERAL_SYNCHRONIZED,
42 | LITERAL_TRY,
43 | LITERAL_WHILE,
44 | LOR,
45 | LT,
46 | METHOD_DEF,
47 | MINUS,
48 | MINUS_ASSIGN,
49 | MOD,
50 | MOD_ASSIGN,
51 | NOT_EQUAL,
52 | PACKAGE_DEF,
53 | PLUS,
54 | PLUS_ASSIGN,
55 | QUESTION,
56 | SEMI,
57 | SL,
58 | SL_ASSIGN,
59 | SR,
60 | SR_ASSIGN,
61 | STAR,
62 | STAR_ASSIGN,
63 | TYPECAST,
64 | VARIABLE_DEF
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/startup/DisableCheckstyleLogging.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.startup;
2 |
3 | import com.intellij.openapi.diagnostic.Logger;
4 | import com.intellij.openapi.project.Project;
5 | import com.intellij.openapi.startup.ProjectActivity;
6 | import kotlin.Unit;
7 | import kotlin.coroutines.Continuation;
8 | import org.apache.log4j.Level;
9 | import org.jetbrains.annotations.NotNull;
10 | import org.jetbrains.annotations.Nullable;
11 |
12 | public class DisableCheckstyleLogging implements ProjectActivity {
13 |
14 | private static final Logger LOG = Logger.getInstance(DisableCheckstyleLogging.class);
15 |
16 | @Nullable
17 | @Override
18 | public Object execute(@NotNull final Project project,
19 | @NotNull final Continuation super Unit> continuation) {
20 | try {
21 | // This is a nasty hack to get around IDEA's DialogAppender sending any errors to the Event Log,
22 | // which would result in CheckStyle parse errors spamming the Event Log.
23 | org.apache.log4j.Logger.getLogger("com.puppycrawl.tools.checkstyle.TreeWalker").setLevel(Level.OFF);
24 | } catch (Exception e) {
25 | LOG.warn("Unable to suppress logging from CheckStyle's TreeWalker", e);
26 | }
27 |
28 | return null;
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/csaccess/java/org/infernus/idea/checkstyle/service/cmd/CheckstyleBridge.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.service.cmd;
2 |
3 | import com.puppycrawl.tools.checkstyle.api.Configuration;
4 | import org.jetbrains.annotations.NotNull;
5 |
6 | import java.lang.reflect.InvocationTargetException;
7 | import java.lang.reflect.Method;
8 | import java.util.Map;
9 |
10 | public final class CheckstyleBridge {
11 |
12 | private CheckstyleBridge() {
13 | }
14 |
15 | @SuppressWarnings("unchecked")
16 | public static Map messagesFrom(@NotNull final Configuration source) {
17 | // Checkstyle 8.7 changes the return type of Configuration.getMessages()
18 | Method getMessagesMethod = null;
19 | try {
20 | getMessagesMethod = Configuration.class.getDeclaredMethod("getMessages");
21 | } catch (NoSuchMethodException ignored) {
22 | }
23 |
24 | if (getMessagesMethod == null) {
25 | throw new RuntimeException("Unable to find usable getMessages method on configuration");
26 | }
27 |
28 | try {
29 | return (Map) getMessagesMethod.invoke(source);
30 | } catch (IllegalAccessException | InvocationTargetException e) {
31 | throw new RuntimeException("Unable to invoke getMessages method on configuration", e);
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/actions/AnalyseCurrentFile.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.actions;
2 |
3 | import com.intellij.openapi.actionSystem.AnActionEvent;
4 | import com.intellij.openapi.actionSystem.Presentation;
5 | import com.intellij.openapi.project.Project;
6 | import com.intellij.openapi.vfs.VirtualFile;
7 | import org.jetbrains.annotations.NotNull;
8 | import org.jetbrains.annotations.Nullable;
9 |
10 | import static com.intellij.openapi.actionSystem.CommonDataKeys.VIRTUAL_FILE;
11 |
12 | /**
13 | * Action to execute a CheckStyle scan on the current editor file.
14 | */
15 | public class AnalyseCurrentFile extends ScanCurrentFile {
16 |
17 | @Override
18 | protected @Nullable VirtualFile selectedFile(@NotNull final Project project,
19 | @NotNull final AnActionEvent event) {
20 | return event.getDataContext().getData(VIRTUAL_FILE);
21 | }
22 |
23 | @Override
24 | public void update(@NotNull final AnActionEvent event) {
25 | // update event does not expose selected file, so we always enable
26 | final Presentation presentation = event.getPresentation();
27 | project(event).ifPresentOrElse(
28 | project -> presentation.setEnabled(!staticScanner(project).isScanInProgress()),
29 | () -> presentation.setEnabled(false));
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/csaccessTest/java/org/infernus/idea/checkstyle/service/cmd/OpScanTest.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.service.cmd;
2 |
3 | import java.util.Collections;
4 | import java.util.Optional;
5 |
6 | import com.intellij.openapi.project.Project;
7 | import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
8 | import org.infernus.idea.checkstyle.csapi.CheckstyleInternalObject;
9 | import org.infernus.idea.checkstyle.exception.CheckstyleVersionMixException;
10 | import org.infernus.idea.checkstyle.service.entities.CheckerWithConfig;
11 | import org.junit.Assert;
12 | import org.junit.Test;
13 | import org.mockito.Mockito;
14 |
15 |
16 | public class OpScanTest {
17 | private static final Project PROJECT = Mockito.mock(Project.class);
18 |
19 | private static final class InvalidObject
20 | implements CheckstyleInternalObject {
21 | // does not matter
22 | }
23 |
24 |
25 | @Test(expected = CheckstyleVersionMixException.class)
26 | public void testWrongCheckerClass() {
27 | new OpScan(new InvalidObject(), Collections.emptyList(), false, 2, Optional.empty());
28 | }
29 |
30 |
31 | @Test
32 | public void testEmptyListOfFiles() throws CheckstyleException {
33 | OpScan cmd = new OpScan(new CheckerWithConfig(null, null), Collections.emptyList(), false, 2, Optional.empty());
34 | Assert.assertEquals(Collections.emptyMap(), cmd.execute(PROJECT));
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/actions/ResetLoadedRulesFiles.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.actions;
2 |
3 | import com.intellij.openapi.actionSystem.AnActionEvent;
4 | import com.intellij.openapi.application.ApplicationManager;
5 | import com.intellij.openapi.editor.Document;
6 | import com.intellij.openapi.fileEditor.FileDocumentManager;
7 | import org.infernus.idea.checkstyle.ConfigurationInvalidator;
8 | import org.jetbrains.annotations.NotNull;
9 |
10 | /**
11 | * Clear the Checker cache and blocks, forcing reloading of rules files.
12 | */
13 | public class ResetLoadedRulesFiles extends BaseAction {
14 |
15 | @Override
16 | public void actionPerformed(@NotNull final AnActionEvent event) {
17 | if (FileDocumentManager.getInstance().getUnsavedDocuments().length > 0) {
18 | // If there is an unsaved file, this could be the changed rules file or a dependent file.
19 | // Save them first, then continue.
20 | ApplicationManager.getApplication().runWriteAction(() -> {
21 | for (Document unsavedDocument : FileDocumentManager.getInstance().getUnsavedDocuments()) {
22 | FileDocumentManager.getInstance().saveDocument(unsavedDocument);
23 | }
24 | });
25 | }
26 |
27 | project(event).ifPresent(project -> project.getService(ConfigurationInvalidator.class).invalidateCachedResources());
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/model/ConfigurationType.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.model;
2 |
3 |
4 | public enum ConfigurationType {
5 | /**
6 | * one of the configurations bundled with the Checkstyle tool, chosen from the
7 | * {@link org.infernus.idea.checkstyle.csapi.BundledConfig} enum
8 | */
9 | BUNDLED,
10 |
11 | HTTP_URL,
12 |
13 | /**
14 | * Located on a HTTP URL where the SSL context is naughtily ignored.
15 | */
16 | INSECURE_HTTP_URL,
17 |
18 | LOCAL_FILE,
19 |
20 | /**
21 | * Located in a local file where the path is project relative.
22 | */
23 | PROJECT_RELATIVE,
24 |
25 | PLUGIN_CLASSPATH,
26 |
27 | LEGACY_CLASSPATH; // legacy
28 |
29 |
30 | /**
31 | * Parse a case-insensitive type string.
32 | *
33 | * @param typeAsString the type, as a string.
34 | * @return the type.
35 | */
36 | public static ConfigurationType parse(final String typeAsString) {
37 | if (typeAsString == null) {
38 | return null;
39 | }
40 |
41 | final String processedType = typeAsString.toUpperCase().replace(' ', '_');
42 | if ("FILE".equals(processedType)) {
43 | return LOCAL_FILE;
44 | } else if ("CLASSPATH".equals(processedType)) {
45 | return LEGACY_CLASSPATH;
46 | }
47 |
48 | return valueOf(processedType);
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/csaccessTest/java/org/infernus/idea/checkstyle/service/ConfigurationBuilder.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.service;
2 |
3 | import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
4 | import com.puppycrawl.tools.checkstyle.api.Configuration;
5 |
6 | public final class ConfigurationBuilder {
7 |
8 | private final DefaultConfiguration configuration;
9 |
10 | private ConfigurationBuilder(final DefaultConfiguration configuration) {
11 | this.configuration = configuration;
12 | }
13 |
14 | public static ConfigurationBuilder checker() {
15 | return new ConfigurationBuilder(new DefaultConfiguration("Checker"));
16 | }
17 |
18 | public static ConfigurationBuilder config(final String name) {
19 | return new ConfigurationBuilder(new DefaultConfiguration(name));
20 | }
21 |
22 | public ConfigurationBuilder withChild(final ConfigurationBuilder child) {
23 | configuration.addChild(child.build());
24 | return this;
25 | }
26 |
27 | public ConfigurationBuilder withAttribute(final String name, final String value) {
28 | configuration.addProperty(name, value);
29 | return this;
30 | }
31 |
32 | public ConfigurationBuilder withMessage(final String key, final String value) {
33 | configuration.addMessage(key, value);
34 | return this;
35 | }
36 |
37 | public Configuration build() {
38 | return configuration;
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/model/RelativeFileConfigurationLocation.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.model;
2 |
3 | import com.intellij.openapi.project.Project;
4 | import org.infernus.idea.checkstyle.util.Strings;
5 | import org.jetbrains.annotations.NotNull;
6 |
7 | /**
8 | * A configuration file on a mounted file system which will always be referred to
9 | * by a path relative to the project path.
10 | */
11 | public class RelativeFileConfigurationLocation extends FileConfigurationLocation {
12 |
13 | RelativeFileConfigurationLocation(@NotNull final Project project,
14 | @NotNull final String id) {
15 | super(project, id, ConfigurationType.PROJECT_RELATIVE);
16 | }
17 |
18 | @Override
19 | public boolean canBeResolvedInDefaultProject() {
20 | return false;
21 | }
22 |
23 | @Override
24 | public void setLocation(final String location) {
25 | if (Strings.isBlank(location)) {
26 | throw new IllegalArgumentException("A non-blank location is required");
27 | }
28 |
29 | super.setLocation(projectFilePaths().tokenise(
30 | projectFilePaths().makeProjectRelative(
31 | projectFilePaths().detokenise(location))));
32 | }
33 |
34 | @Override
35 | public Object clone() {
36 | return cloneCommonPropertiesTo(new RelativeFileConfigurationLocation(getProject(), getId()));
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/test/java/org/infernus/idea/checkstyle/StringConfigurationLocation.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle;
2 |
3 | import java.io.ByteArrayInputStream;
4 | import java.io.InputStream;
5 | import java.nio.charset.StandardCharsets;
6 | import java.util.UUID;
7 |
8 | import com.intellij.openapi.project.Project;
9 | import org.infernus.idea.checkstyle.model.ConfigurationLocation;
10 | import org.infernus.idea.checkstyle.model.ConfigurationType;
11 | import org.jetbrains.annotations.NotNull;
12 |
13 |
14 | public class StringConfigurationLocation
15 | extends ConfigurationLocation {
16 | private final String configurationXml;
17 |
18 | public StringConfigurationLocation(@NotNull final String configurationXml,
19 | @NotNull final Project project) {
20 | super(UUID.randomUUID().toString(), ConfigurationType.LOCAL_FILE, project);
21 | setDescription("In-memory String-based configuration: "
22 | + configurationXml.substring(0, Math.min(100, configurationXml.length())) + " ...");
23 | this.configurationXml = configurationXml;
24 | }
25 |
26 | @NotNull
27 | @Override
28 | protected InputStream resolveFile(@NotNull final ClassLoader checkstyleClassLoader) {
29 | return new ByteArrayInputStream(configurationXml.getBytes(StandardCharsets.UTF_8));
30 | }
31 |
32 | @Override
33 | public StringConfigurationLocation clone() {
34 | return new StringConfigurationLocation(configurationXml, getProject());
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/csapi/BundledConfigProvider.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.csapi;
2 |
3 | import org.apache.commons.lang3.StringUtils;
4 | import org.jetbrains.annotations.NotNull;
5 |
6 | import java.util.Collection;
7 |
8 | /**
9 | * Provider that providers the additional bundled checkstyle configs
10 | */
11 | public interface BundledConfigProvider {
12 |
13 | /**
14 | * @return the configs
15 | */
16 | @NotNull
17 | Collection getConfigs();
18 |
19 | class BasicConfig {
20 | private final String id;
21 | private final String path;
22 | private final String description;
23 |
24 | public BasicConfig(final String id, final String description, final String path) {
25 | this.id = requiredNotBlank(id, "id");
26 | this.path = requiredNotBlank(path, "path");
27 | this.description = requiredNotBlank(description, "description");
28 | }
29 |
30 | static String requiredNotBlank(final String val, final String name) {
31 | if (StringUtils.isBlank(val)) {
32 | throw new IllegalArgumentException(name + " must not be blank");
33 | }
34 | return val;
35 | }
36 |
37 | public String getId() {
38 | return id;
39 | }
40 |
41 | public String getPath() {
42 | return path;
43 | }
44 |
45 | public String getDescription() {
46 | return description;
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/csapi/ConfigurationModule.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.csapi;
2 |
3 |
4 | import java.util.Collections;
5 | import java.util.Map;
6 | import java.util.Set;
7 |
8 | import org.jetbrains.annotations.NotNull;
9 | import org.jetbrains.annotations.Nullable;
10 |
11 |
12 | public class ConfigurationModule {
13 |
14 | private final String name;
15 |
16 | private final Map properties;
17 |
18 | private final Set knownTokenTypes;
19 |
20 | public ConfigurationModule(@NotNull final String name,
21 | @Nullable final Map properties,
22 | @Nullable final Set knownTokenTypes) {
23 | this.name = name;
24 |
25 | if (properties != null) {
26 | this.properties = Collections.unmodifiableMap(properties);
27 | } else {
28 | this.properties = Collections.emptyMap();
29 | }
30 |
31 | if (knownTokenTypes != null) {
32 | this.knownTokenTypes = Collections.unmodifiableSet(knownTokenTypes);
33 | } else {
34 | this.knownTokenTypes = Collections.emptySet();
35 | }
36 | }
37 |
38 |
39 | @NotNull
40 | public String getName() {
41 | return name;
42 | }
43 |
44 | @NotNull
45 | public Map getProperties() {
46 | return properties;
47 | }
48 |
49 | @NotNull
50 | public Set getKnownTokenTypes() {
51 | return knownTokenTypes;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/LICENCE:
--------------------------------------------------------------------------------
1 | CheckStyle-IDEA
2 | ---------------
3 | (c) Copyright 2006-2022 CheckStyle-IDEA Contributors
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above copyright notice, this
13 | list of conditions and the following disclaimer in the documentation and/or
14 | other materials provided with the distribution.
15 |
16 | * Neither the name of the author nor the names of its contributors may
17 | be used to endorse or promote products derived from this software without
18 | specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 | POSSIBILITY OF SUCH DAMAGE.
31 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/ui/CheckStyleInspectionPanel.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.ui;
2 |
3 | import com.intellij.util.ui.JBUI;
4 | import org.infernus.idea.checkstyle.CheckStyleBundle;
5 |
6 | import javax.swing.*;
7 | import java.awt.*;
8 |
9 | /**
10 | * Provides a dummy panel for the inspection configuration.
11 | */
12 | public final class CheckStyleInspectionPanel extends JPanel {
13 |
14 | /**
15 | * A text label for a description blurb.
16 | */
17 | private final JTextArea descriptionLabel = new JTextArea();
18 |
19 | /**
20 | * Create a new panel.
21 | */
22 | public CheckStyleInspectionPanel() {
23 | super(new GridBagLayout());
24 |
25 | initialise();
26 | }
27 |
28 | /**
29 | * Initialise the view.
30 | */
31 | private void initialise() {
32 | // fake a multi-line label with a text area
33 | descriptionLabel.setText(CheckStyleBundle.message("config.inspection.description"));
34 | descriptionLabel.setEditable(false);
35 | descriptionLabel.setEnabled(false);
36 | descriptionLabel.setWrapStyleWord(true);
37 | descriptionLabel.setLineWrap(true);
38 | descriptionLabel.setOpaque(false);
39 | descriptionLabel.setDisabledTextColor(descriptionLabel.getForeground());
40 |
41 | final GridBagConstraints descLabelConstraints = new GridBagConstraints(
42 | 0, 0, 3, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST,
43 | GridBagConstraints.BOTH, JBUI.insets(4), 0, 0);
44 | add(descriptionLabel, descLabelConstraints);
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/src/csaccessTest/java/org/infernus/idea/checkstyle/service/StringConfigurationLocation.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.service;
2 |
3 | import com.intellij.openapi.project.Project;
4 | import org.infernus.idea.checkstyle.model.ConfigurationLocation;
5 | import org.infernus.idea.checkstyle.model.ConfigurationType;
6 | import org.jetbrains.annotations.NotNull;
7 |
8 | import java.io.ByteArrayInputStream;
9 | import java.io.InputStream;
10 | import java.nio.charset.StandardCharsets;
11 | import java.util.UUID;
12 |
13 |
14 | public class StringConfigurationLocation
15 | extends ConfigurationLocation {
16 |
17 | private static final int MAX_TRIMMED_LENGTH = 100;
18 |
19 | private final String configurationXml;
20 |
21 | public StringConfigurationLocation(@NotNull final String configurationXml,
22 | @NotNull final Project project) {
23 | super(UUID.randomUUID().toString(), ConfigurationType.LOCAL_FILE, project);
24 | setDescription("In-memory String-based configuration: "
25 | + configurationXml.substring(0, Math.min(MAX_TRIMMED_LENGTH, configurationXml.length())) + " ...");
26 | this.configurationXml = configurationXml;
27 | }
28 |
29 | @NotNull
30 | @Override
31 | protected InputStream resolveFile(@NotNull final ClassLoader checkstyleClassLoader) {
32 | return new ByteArrayInputStream(configurationXml.getBytes(StandardCharsets.UTF_8));
33 | }
34 |
35 | @Override
36 | public StringConfigurationLocation clone() {
37 | return new StringConfigurationLocation(configurationXml, getProject());
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/checks/CheckFactory.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.checks;
2 |
3 | import com.intellij.openapi.diagnostic.Logger;
4 | import com.intellij.openapi.project.Project;
5 | import org.infernus.idea.checkstyle.CheckstyleProjectService;
6 | import org.infernus.idea.checkstyle.csapi.CheckstyleInternalObject;
7 | import org.jetbrains.annotations.NotNull;
8 |
9 | import java.util.ArrayList;
10 | import java.util.Arrays;
11 | import java.util.List;
12 | import java.util.function.Function;
13 |
14 |
15 | /**
16 | * Factory for producing various check modifications.
17 | */
18 | public final class CheckFactory {
19 |
20 | private static final Logger LOG = Logger.getInstance(CheckFactory.class);
21 |
22 | private static final List> CHECKS = Arrays.asList(
23 | (project) -> new JavadocPackageCheck(project.getService(CheckstyleProjectService.class)),
24 | (project) -> new PackageHtmlCheck());
25 |
26 | private CheckFactory() {
27 | }
28 |
29 | @NotNull
30 | public static List getChecks(final Project project, final CheckstyleInternalObject config) {
31 | final List checks = new ArrayList<>();
32 |
33 | for (final Function checkFactory : CHECKS) {
34 | try {
35 | final Check check = checkFactory.apply(project);
36 | check.configure(config);
37 | checks.add(check);
38 | } catch (Exception e) {
39 | LOG.warn("Couldn't instantiate check", e);
40 | }
41 | }
42 |
43 | return checks;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/test/java/org/infernus/idea/checkstyle/TestHelper.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle;
2 |
3 | import com.intellij.openapi.project.Project;
4 | import com.intellij.packageDependencies.DependencyValidationManager;
5 | import com.intellij.psi.search.scope.packageSet.InvalidPackageSet;
6 | import com.intellij.psi.search.scope.packageSet.NamedScope;
7 | import com.intellij.psi.search.scope.packageSet.NamedScopeManager;
8 | import org.infernus.idea.checkstyle.checker.CheckerFactoryCache;
9 | import org.jetbrains.annotations.NotNull;
10 |
11 | import static org.infernus.idea.checkstyle.model.NamedScopeHelper.DEFAULT_SCOPE_ID;
12 | import static org.mockito.Mockito.mock;
13 | import static org.mockito.Mockito.when;
14 |
15 | public final class TestHelper {
16 | public static final NamedScope NAMED_SCOPE = new NamedScope("test", new InvalidPackageSet("asdf"));
17 |
18 | private TestHelper() {
19 | }
20 |
21 | @NotNull
22 | public static Project mockProject() {
23 | DependencyValidationManager dependencyValidationManager = mock(DependencyValidationManager.class);
24 | when(dependencyValidationManager.getScope(DEFAULT_SCOPE_ID)).thenReturn(NAMED_SCOPE);
25 |
26 | final CheckerFactoryCache checkerFactoryCache = new CheckerFactoryCache();
27 |
28 | final Project project = mock(Project.class);
29 | when(project.getService(CheckerFactoryCache.class)).thenReturn(checkerFactoryCache);
30 | when(project.getService(NamedScopeManager.class)).thenReturn(new NamedScopeManager(project));
31 | when(project.getService(DependencyValidationManager.class)).thenReturn(dependencyValidationManager);
32 | return project;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/csaccessTest/java/org/infernus/idea/checkstyle/service/cmd/OpDestroyCheckerTest.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.service.cmd;
2 |
3 | import com.intellij.openapi.project.Project;
4 | import com.puppycrawl.tools.checkstyle.Checker;
5 | import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
6 | import org.infernus.idea.checkstyle.CheckstyleProjectService;
7 | import org.infernus.idea.checkstyle.csapi.CheckstyleInternalObject;
8 | import org.infernus.idea.checkstyle.exception.CheckstyleVersionMixException;
9 | import org.infernus.idea.checkstyle.service.CheckstyleActionsImpl;
10 | import org.infernus.idea.checkstyle.service.entities.CheckerWithConfig;
11 | import org.junit.Test;
12 |
13 | import static org.mockito.Mockito.mock;
14 |
15 |
16 | public class OpDestroyCheckerTest {
17 | private static final Project PROJECT = mock(Project.class);
18 |
19 | private static final class WrongObject implements CheckstyleInternalObject {
20 | // does not matter
21 | }
22 |
23 | @Test
24 | public void testDestroyChecker() {
25 | CheckerWithConfig checkerWithConfig = new CheckerWithConfig(new Checker(), new DefaultConfiguration("testConfig"));
26 | new CheckstyleActionsImpl(PROJECT, mock(CheckstyleProjectService.class)).destroyChecker(checkerWithConfig);
27 | }
28 |
29 | @Test(expected = CheckstyleVersionMixException.class)
30 | public void testMixExceptionInInit() {
31 | new OpDestroyChecker(new WrongObject());
32 | }
33 |
34 |
35 | @Test(expected = CheckstyleVersionMixException.class)
36 | public void testCheckerNull() {
37 | //noinspection ConstantConditions
38 | new OpDestroyChecker(null);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/actions/ScrollToSource.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.actions;
2 |
3 | import com.intellij.openapi.actionSystem.ActionUpdateThread;
4 | import com.intellij.openapi.actionSystem.AnActionEvent;
5 | import com.intellij.openapi.project.DumbAwareToggleAction;
6 | import com.intellij.openapi.project.Project;
7 | import org.infernus.idea.checkstyle.toolwindow.CheckStyleToolWindowPanel;
8 | import org.jetbrains.annotations.NotNull;
9 |
10 | import static org.infernus.idea.checkstyle.actions.ToolWindowAccess.*;
11 |
12 | /**
13 | * Toggle the scroll to source setting.
14 | */
15 | public final class ScrollToSource extends DumbAwareToggleAction {
16 |
17 | @Override
18 | public boolean isSelected(final @NotNull AnActionEvent event) {
19 | final Project project = getEventProject(event);
20 | if (project == null) {
21 | return false;
22 | }
23 |
24 | Boolean scrollToSource = getFromToolWindowPanel(toolWindow(project), CheckStyleToolWindowPanel::isScrollToSource);
25 | if (scrollToSource != null) {
26 | return scrollToSource;
27 | }
28 | return false;
29 | }
30 |
31 | @Override
32 | public void setSelected(final @NotNull AnActionEvent event, final boolean selected) {
33 | final Project project = getEventProject(event);
34 | if (project == null) {
35 | return;
36 | }
37 |
38 | actOnToolWindowPanel(toolWindow(project), panel -> panel.setScrollToSource(selected));
39 | }
40 |
41 | @Override
42 | public @NotNull ActionUpdateThread getActionUpdateThread() {
43 | return ActionUpdateThread.EDT;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/csaccessTest/java/org/infernus/idea/checkstyle/service/cmd/OpPeruseConfigurationTest.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.service.cmd;
2 |
3 |
4 | import com.intellij.openapi.project.Project;
5 | import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
6 | import org.infernus.idea.checkstyle.csapi.CheckstyleInternalObject;
7 | import org.infernus.idea.checkstyle.csapi.ConfigVisitor;
8 | import org.infernus.idea.checkstyle.csapi.ConfigurationModule;
9 | import org.infernus.idea.checkstyle.exception.CheckstyleVersionMixException;
10 | import org.infernus.idea.checkstyle.service.entities.CsConfigObject;
11 | import org.jetbrains.annotations.NotNull;
12 | import org.junit.Test;
13 | import org.mockito.Mockito;
14 |
15 | import static org.junit.Assert.assertNull;
16 |
17 | public class OpPeruseConfigurationTest {
18 | private static final Project PROJECT = Mockito.mock(Project.class);
19 |
20 | private static final class InvalidObject implements CheckstyleInternalObject {
21 | // does not matter
22 | }
23 |
24 | @Test(expected = CheckstyleVersionMixException.class)
25 | public void testWrongConfigurationClass() {
26 | new OpPeruseConfiguration(new InvalidObject(), new StubVisitor());
27 | }
28 |
29 | @Test
30 | public void testNullConfig() throws CheckstyleException {
31 | final OpPeruseConfiguration cmd = new OpPeruseConfiguration(new CsConfigObject(null), new StubVisitor());
32 | assertNull(cmd.execute(PROJECT));
33 | }
34 |
35 | private static final class StubVisitor implements ConfigVisitor {
36 | @Override
37 | public void visit(@NotNull final ConfigurationModule module) {
38 |
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/importer/ModuleImporterFactory.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.importer;
2 |
3 | import org.infernus.idea.checkstyle.csapi.ConfigurationModule;
4 | import org.jetbrains.annotations.NotNull;
5 | import org.jetbrains.annotations.Nullable;
6 |
7 | import java.lang.reflect.InvocationTargetException;
8 |
9 | final class ModuleImporterFactory {
10 |
11 | private ModuleImporterFactory() {
12 | }
13 |
14 | @Nullable
15 | static ModuleImporter getModuleImporter(@NotNull final ConfigurationModule configuration)
16 | throws InstantiationException, IllegalAccessException {
17 | String name = configuration.getName();
18 | ModuleImporter moduleImporter = createImporter(name);
19 | if (moduleImporter != null) {
20 | moduleImporter.setFrom(configuration);
21 | }
22 | return moduleImporter;
23 | }
24 |
25 | @Nullable
26 | private static ModuleImporter createImporter(@NotNull final String name)
27 | throws IllegalAccessException, InstantiationException {
28 | String fqn = getFullyQualifiedClassName(name);
29 | try {
30 | Class> c = Class.forName(fqn);
31 | Object o = c.getDeclaredConstructor().newInstance();
32 | return o instanceof ModuleImporter ? (ModuleImporter) o : null;
33 | } catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException e) {
34 | return null;
35 | }
36 | }
37 |
38 | private static String getFullyQualifiedClassName(@NotNull final String moduleName) {
39 | return ModuleImporterFactory.class.getPackage().getName() + ".modules." + moduleName + "Importer";
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/actions/DisplayErrors.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.actions;
2 |
3 | import com.intellij.openapi.actionSystem.ActionUpdateThread;
4 | import com.intellij.openapi.actionSystem.AnActionEvent;
5 | import com.intellij.openapi.project.DumbAwareToggleAction;
6 | import com.intellij.openapi.project.Project;
7 | import org.infernus.idea.checkstyle.toolwindow.CheckStyleToolWindowPanel;
8 | import org.jetbrains.annotations.NotNull;
9 |
10 | import java.util.Objects;
11 |
12 | import static org.infernus.idea.checkstyle.actions.ToolWindowAccess.*;
13 |
14 | /**
15 | * Action to toggle error display in tool window.
16 | */
17 | public class DisplayErrors extends DumbAwareToggleAction {
18 |
19 | @Override
20 | public boolean isSelected(final @NotNull AnActionEvent event) {
21 | final Project project = getEventProject(event);
22 | if (project == null) {
23 | return false;
24 | }
25 |
26 | Boolean displayingErrors = getFromToolWindowPanel(toolWindow(project), CheckStyleToolWindowPanel::isDisplayingErrors);
27 | return Objects.requireNonNullElse(displayingErrors, false);
28 | }
29 |
30 | @Override
31 | public void setSelected(final @NotNull AnActionEvent event, final boolean selected) {
32 | final Project project = getEventProject(event);
33 | if (project == null) {
34 | return;
35 | }
36 |
37 | actOnToolWindowPanel(toolWindow(project), panel -> {
38 | panel.setDisplayingErrors(selected);
39 | panel.filterDisplayedResults();
40 | });
41 | }
42 |
43 | @Override
44 | public @NotNull ActionUpdateThread getActionUpdateThread() {
45 | return ActionUpdateThread.EDT;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/ConfigurationInvalidator.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle;
2 |
3 | import com.intellij.openapi.project.Project;
4 | import org.infernus.idea.checkstyle.checker.CheckerFactoryCache;
5 | import org.infernus.idea.checkstyle.config.PluginConfiguration;
6 | import org.infernus.idea.checkstyle.config.PluginConfigurationManager;
7 | import org.infernus.idea.checkstyle.model.ConfigurationLocation;
8 | import org.infernus.idea.checkstyle.util.TempDirProvider;
9 | import org.jetbrains.annotations.NotNull;
10 |
11 | public class ConfigurationInvalidator {
12 |
13 | private final Project project;
14 | private final CheckstyleProjectService checkstyleProjectService;
15 | private final PluginConfigurationManager pluginConfigurationManager;
16 | private final CheckerFactoryCache checkerFactoryCache;
17 |
18 | ConfigurationInvalidator(@NotNull final Project project) {
19 | this.project = project;
20 | this.checkstyleProjectService = project.getService(CheckstyleProjectService.class);
21 | this.checkerFactoryCache = project.getService(CheckerFactoryCache.class);
22 | this.pluginConfigurationManager = project.getService(PluginConfigurationManager.class);
23 | }
24 |
25 | public void invalidateCachedResources() {
26 | checkerFactoryCache.invalidate();
27 |
28 | PluginConfiguration config = pluginConfigurationManager.getCurrent();
29 | config.getLocations().forEach(ConfigurationLocation::reset);
30 |
31 | checkstyleProjectService.activateCheckstyleVersion(config.getCheckstyleVersion(), config.getThirdPartyClasspath());
32 | if (!config.isCopyLibs()) {
33 | new TempDirProvider().deleteCopiedLibrariesDir(project);
34 | }
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/actions/DisplayInfo.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.actions;
2 |
3 | import com.intellij.openapi.actionSystem.ActionUpdateThread;
4 | import com.intellij.openapi.actionSystem.AnActionEvent;
5 | import com.intellij.openapi.project.DumbAwareToggleAction;
6 | import com.intellij.openapi.project.Project;
7 | import org.infernus.idea.checkstyle.toolwindow.CheckStyleToolWindowPanel;
8 | import org.jetbrains.annotations.NotNull;
9 |
10 | import static org.infernus.idea.checkstyle.actions.ToolWindowAccess.*;
11 |
12 | /**
13 | * Action to toggle error display in tool window.
14 | */
15 | public class DisplayInfo extends DumbAwareToggleAction {
16 |
17 | @Override
18 | public boolean isSelected(final @NotNull AnActionEvent event) {
19 | final Project project = getEventProject(event);
20 | if (project == null) {
21 | return false;
22 | }
23 |
24 | Boolean displayingInfo = getFromToolWindowPanel(toolWindow(project), CheckStyleToolWindowPanel::isDisplayingInfo);
25 | if (displayingInfo != null) {
26 | return displayingInfo;
27 | }
28 | return false;
29 | }
30 |
31 | @Override
32 | public void setSelected(final @NotNull AnActionEvent event, final boolean selected) {
33 | final Project project = getEventProject(event);
34 | if (project == null) {
35 | return;
36 | }
37 |
38 | actOnToolWindowPanel(toolWindow(project), panel -> {
39 | panel.setDisplayingInfo(selected);
40 | panel.filterDisplayedResults();
41 | });
42 | }
43 |
44 | @Override
45 | public @NotNull ActionUpdateThread getActionUpdateThread() {
46 | return ActionUpdateThread.EDT;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/actions/DisplayWarnings.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.actions;
2 |
3 | import com.intellij.openapi.actionSystem.ActionUpdateThread;
4 | import com.intellij.openapi.actionSystem.AnActionEvent;
5 | import com.intellij.openapi.project.DumbAwareToggleAction;
6 | import com.intellij.openapi.project.Project;
7 | import org.infernus.idea.checkstyle.toolwindow.CheckStyleToolWindowPanel;
8 | import org.jetbrains.annotations.NotNull;
9 |
10 | import java.util.Objects;
11 |
12 | import static org.infernus.idea.checkstyle.actions.ToolWindowAccess.*;
13 |
14 | /**
15 | * Action to toggle error display in tool window.
16 | */
17 | public class DisplayWarnings extends DumbAwareToggleAction {
18 |
19 | @Override
20 | public boolean isSelected(final @NotNull AnActionEvent event) {
21 | final Project project = getEventProject(event);
22 | if (project == null) {
23 | return false;
24 | }
25 |
26 | Boolean displayingWarnings = getFromToolWindowPanel(toolWindow(project), CheckStyleToolWindowPanel::isDisplayingWarnings);
27 | return Objects.requireNonNullElse(displayingWarnings, false);
28 | }
29 |
30 | @Override
31 | public void setSelected(final @NotNull AnActionEvent event, final boolean selected) {
32 | final Project project = getEventProject(event);
33 | if (project == null) {
34 | return;
35 | }
36 |
37 | actOnToolWindowPanel(toolWindow(project), panel -> {
38 | panel.setDisplayingWarnings(selected);
39 | panel.filterDisplayedResults();
40 | });
41 | }
42 |
43 | @Override
44 | public @NotNull ActionUpdateThread getActionUpdateThread() {
45 | return ActionUpdateThread.EDT;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/actions/GroupingAction.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.actions;
2 |
3 | import com.intellij.openapi.actionSystem.ActionUpdateThread;
4 | import com.intellij.openapi.actionSystem.AnActionEvent;
5 | import com.intellij.openapi.project.DumbAwareToggleAction;
6 | import com.intellij.openapi.project.Project;
7 | import org.infernus.idea.checkstyle.toolwindow.ResultGrouping;
8 | import org.jetbrains.annotations.NotNull;
9 |
10 | import java.util.Objects;
11 |
12 | import static org.infernus.idea.checkstyle.actions.ToolWindowAccess.*;
13 |
14 | abstract class GroupingAction extends DumbAwareToggleAction {
15 |
16 | private final ResultGrouping grouping;
17 |
18 | GroupingAction(@NotNull final ResultGrouping grouping) {
19 | this.grouping = grouping;
20 | }
21 |
22 | @Override
23 | public boolean isSelected(final @NotNull AnActionEvent event) {
24 | final Project project = getEventProject(event);
25 | if (project == null) {
26 | return false;
27 | }
28 |
29 | Boolean selected = getFromToolWindowPanel(toolWindow(project), panel -> panel.groupedBy() == grouping);
30 | return Objects.requireNonNullElse(selected, false);
31 | }
32 |
33 | @Override
34 | public void setSelected(final @NotNull AnActionEvent event, final boolean selected) {
35 | final Project project = getEventProject(event);
36 | if (project == null) {
37 | return;
38 | }
39 |
40 | actOnToolWindowPanel(toolWindow(project), panel -> {
41 | panel.groupBy(grouping);
42 | });
43 | }
44 |
45 | @Override
46 | public @NotNull ActionUpdateThread getActionUpdateThread() {
47 | return ActionUpdateThread.EDT;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/checker/CheckerFactoryCacheKey.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.checker;
2 |
3 | import java.util.Objects;
4 |
5 | import com.intellij.openapi.module.Module;
6 | import org.infernus.idea.checkstyle.model.ConfigurationLocation;
7 | import org.jetbrains.annotations.NotNull;
8 | import org.jetbrains.annotations.Nullable;
9 |
10 |
11 | class CheckerFactoryCacheKey {
12 |
13 | private final String projectName;
14 | private final String moduleName;
15 | private final ConfigurationLocation location;
16 |
17 | // We can disregard Checkstyle version and third party jars as elements of the cache key, because the cache
18 | // must be invalidated when any of these properties change anyway.
19 |
20 |
21 | CheckerFactoryCacheKey(@NotNull final ConfigurationLocation location, @Nullable final Module module) {
22 | this.projectName = module != null ? module.getProject().getName() : "noProject";
23 | this.moduleName = module != null ? module.getName() : "noModule";
24 | this.location = location;
25 | }
26 |
27 |
28 | @Override
29 | public boolean equals(final Object pOther) {
30 | if (this == pOther) {
31 | return true;
32 | }
33 | if (pOther == null || getClass() != pOther.getClass()) {
34 | return false;
35 | }
36 | final CheckerFactoryCacheKey other = (CheckerFactoryCacheKey) pOther;
37 | return Objects.equals(projectName, other.projectName)
38 | && Objects.equals(moduleName, other.moduleName)
39 | && Objects.equals(location, other.location);
40 | }
41 |
42 |
43 | @Override
44 | public int hashCode() {
45 | return Objects.hash(projectName, moduleName, location);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/checker/CheckerFactoryWorker.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.checker;
2 |
3 | import com.intellij.openapi.module.Module;
4 | import org.infernus.idea.checkstyle.CheckstyleProjectService;
5 | import org.infernus.idea.checkstyle.model.ConfigurationLocation;
6 | import org.jetbrains.annotations.NotNull;
7 | import org.jetbrains.annotations.Nullable;
8 |
9 | import java.util.Map;
10 |
11 |
12 | class CheckerFactoryWorker extends Thread {
13 | private final ConfigurationLocation location;
14 | private final Map properties;
15 | private final Module module;
16 | private final CheckstyleProjectService checkstyleProjectService;
17 |
18 | private Object threadReturn = null;
19 |
20 | CheckerFactoryWorker(@NotNull final ConfigurationLocation location,
21 | @Nullable final Map properties,
22 | @Nullable final Module module,
23 | @NotNull final CheckstyleProjectService checkstyleProjectService) {
24 | this.location = location;
25 | this.properties = properties;
26 | this.module = module;
27 | this.checkstyleProjectService = checkstyleProjectService;
28 | }
29 |
30 | @Override
31 | public void run() {
32 | super.run();
33 |
34 | try {
35 | final CheckStyleChecker checker = checkstyleProjectService
36 | .getCheckstyleInstance()
37 | .createChecker(module, location, properties);
38 | threadReturn = new CachedChecker(checker);
39 | } catch (RuntimeException e) {
40 | threadReturn = e;
41 | }
42 | }
43 |
44 | public Object getResult() {
45 | return threadReturn;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/util/ClassLoaderDumper.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.util;
2 |
3 | import com.intellij.util.lang.UrlClassLoader;
4 |
5 | import java.net.URL;
6 | import java.net.URLClassLoader;
7 |
8 | public final class ClassLoaderDumper {
9 |
10 | private ClassLoaderDumper() {
11 | }
12 |
13 | public static String dumpClassLoader(final ClassLoader classLoader) {
14 | StringBuilder dump = new StringBuilder();
15 |
16 | if (classLoader != null) {
17 | ClassLoader currentLoader = classLoader;
18 | while (currentLoader != null) {
19 | if (currentLoader instanceof URLClassLoader) {
20 | dump.append("URLClassLoader: ")
21 | .append(currentLoader.getClass().getName())
22 | .append('\n');
23 | for (final URL url : ((URLClassLoader) currentLoader).getURLs()) {
24 | dump.append("- url=").append(url).append('\n');
25 | }
26 | } else if (currentLoader instanceof UrlClassLoader) {
27 | dump.append("UrlClassLoader: ")
28 | .append(currentLoader.getClass().getName())
29 | .append('\n');
30 | for (final URL url : ((UrlClassLoader) currentLoader).getUrls()) {
31 | dump.append("- url=").append(url).append('\n');
32 | }
33 | } else {
34 | dump.append("ClassLoader: ").append(currentLoader.getClass().getName());
35 | }
36 |
37 | currentLoader = currentLoader.getParent();
38 | }
39 | }
40 |
41 | return dump.toString();
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/importer/modules/NeedBracesImporter.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.importer.modules;
2 |
3 | import com.intellij.psi.codeStyle.CodeStyleSettings;
4 | import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
5 | import org.infernus.idea.checkstyle.csapi.KnownTokenTypes;
6 | import org.infernus.idea.checkstyle.importer.ModuleImporter;
7 | import org.jetbrains.annotations.NotNull;
8 |
9 | @SuppressWarnings("unused")
10 | public class NeedBracesImporter extends ModuleImporter {
11 |
12 | private static final String ALLOW_SINGLE_LINE_STATEMENT_PROP = "allowSingleLineStatement";
13 |
14 | private int forceBraces = CommonCodeStyleSettings.FORCE_BRACES_ALWAYS;
15 |
16 | @Override
17 | protected void handleAttribute(@NotNull final String attrName, @NotNull final String attrValue) {
18 | if (ALLOW_SINGLE_LINE_STATEMENT_PROP.equals(attrName)) {
19 | if (Boolean.parseBoolean(attrValue)) {
20 | forceBraces = CommonCodeStyleSettings.FORCE_BRACES_IF_MULTILINE;
21 | }
22 | }
23 | }
24 |
25 | @Override
26 | public void importTo(@NotNull final CodeStyleSettings settings) {
27 | CommonCodeStyleSettings commonSettings = getCommonSettings(settings);
28 | if (appliesTo(KnownTokenTypes.LITERAL_DO)) {
29 | commonSettings.DOWHILE_BRACE_FORCE = forceBraces;
30 | }
31 | if (appliesTo(KnownTokenTypes.LITERAL_FOR)) {
32 | commonSettings.FOR_BRACE_FORCE = forceBraces;
33 | }
34 | if (appliesTo(KnownTokenTypes.LITERAL_IF)) {
35 | commonSettings.IF_BRACE_FORCE = forceBraces;
36 | }
37 | if (appliesTo(KnownTokenTypes.LITERAL_WHILE)) {
38 | commonSettings.WHILE_BRACE_FORCE = forceBraces;
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/test/java/org/infernus/idea/checkstyle/VersionComparatorTest.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 |
8 | /**
9 | * Unit tests of {@link VersionComparator}.
10 | */
11 | public class VersionComparatorTest {
12 | @Test
13 | public void testComp() {
14 | VersionComparator testee = new VersionComparator();
15 |
16 | assertTrue(testee.compare("8.1", "8.1.2") < 0);
17 | assertTrue(testee.compare("8.1.2", "8.1") > 0);
18 | assertTrue(testee.compare("8.2", "8.1.2") > 0);
19 | assertTrue(testee.compare("8.1.2", "8.2") < 0);
20 | assertTrue(testee.compare("8.1", "9.1") < 0);
21 | assertTrue(testee.compare("9.1", "8.1") > 0);
22 | assertTrue(testee.compare("8.1.3", "8.1.2") > 0);
23 | assertTrue(testee.compare("8.1.2", "8.1.3") < 0);
24 | assertTrue(testee.compare("8.1", "foo") < 0);
25 | assertTrue(testee.compare("foo", "8.1") > 0);
26 | assertTrue(testee.compare("foo", "FOO") > 0);
27 | assertTrue(testee.compare("FOO", "foo") < 0);
28 | assertTrue(testee.compare("8.1", null) < 0);
29 | assertTrue(testee.compare(null, "8.1") > 0);
30 | assertEquals(0, testee.compare(null, null));
31 | assertEquals(0, testee.compare("8.1.2", "8.1.2"));
32 | assertEquals(0, testee.compare("8.1", "8.1"));
33 | assertEquals(0, testee.compare("foo", "foo"));
34 | assertTrue(testee.compare("8", "0815") > 0); // lex. order b/c "6" does not match version pattern
35 | assertTrue(testee.compare("8.1", "8.x") < 0);
36 | assertTrue(testee.compare("8.x", "8.1") > 0);
37 | assertTrue(testee.compare("8.1.8", "8.1.x") < 0);
38 | assertTrue(testee.compare("8.1.x", "8.1.8") > 0);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/csaccess/java/org/infernus/idea/checkstyle/service/cmd/OpDestroyChecker.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.service.cmd;
2 |
3 | import com.intellij.openapi.diagnostic.Logger;
4 | import com.intellij.openapi.project.Project;
5 | import org.infernus.idea.checkstyle.csapi.CheckstyleInternalObject;
6 | import org.infernus.idea.checkstyle.exception.CheckstyleVersionMixException;
7 | import org.infernus.idea.checkstyle.service.entities.HasChecker;
8 | import org.jetbrains.annotations.NotNull;
9 | import org.jetbrains.annotations.Nullable;
10 |
11 | import java.util.concurrent.TimeUnit;
12 |
13 | /**
14 | * Destroy a checker instance.
15 | */
16 | public class OpDestroyChecker
17 | implements CheckstyleCommand {
18 |
19 | private static final Logger LOG = Logger.getInstance(OpDestroyChecker.class);
20 |
21 | private final HasChecker hasChecker;
22 |
23 | public OpDestroyChecker(@NotNull final CheckstyleInternalObject checker) {
24 | if (!(checker instanceof HasChecker)) {
25 | throw new CheckstyleVersionMixException(HasChecker.class, checker);
26 | }
27 | this.hasChecker = (HasChecker) checker;
28 | }
29 |
30 | @Nullable
31 | @Override
32 | public Void execute(@NotNull final Project project) {
33 | try {
34 | if (hasChecker.getCheckerLock().tryLock(1, TimeUnit.SECONDS)) {
35 | try {
36 | hasChecker.getChecker().destroy();
37 | } finally {
38 | hasChecker.getCheckerLock().unlock();
39 | }
40 | }
41 | } catch (InterruptedException e) {
42 | LOG.debug("Checker will not be destroyed as we couldn't lock the checker", e);
43 | Thread.currentThread().interrupt();
44 | }
45 | return null;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/checker/ListPropertyResolver.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.checker;
2 |
3 | import java.util.ArrayList;
4 | import java.util.HashMap;
5 | import java.util.List;
6 | import java.util.Map;
7 |
8 | import static org.infernus.idea.checkstyle.util.Strings.isBlank;
9 |
10 | class ListPropertyResolver {
11 |
12 | private final Map propertyNamesToValues = new HashMap<>();
13 |
14 | private final List propertyNames = new ArrayList<>();
15 |
16 | ListPropertyResolver(final Map properties) {
17 | setProperties(properties);
18 | }
19 |
20 | public Map getPropertyNamesToValues() {
21 | return propertyNamesToValues;
22 | }
23 |
24 | public String resolve(final String propertyName) {
25 | // collect properties that are referenced in the config file
26 | if (!propertyNames.contains(propertyName)) {
27 | propertyNames.add(propertyName);
28 | }
29 |
30 | final String propertyValue = propertyNamesToValues.get(propertyName);
31 | if (isBlank(propertyValue)) {
32 | return null;
33 | }
34 | return propertyValue;
35 | }
36 |
37 | public void setProperty(final String name, final String value) {
38 | if (!propertyNames.contains(name)) {
39 | propertyNames.add(name);
40 | }
41 |
42 | propertyNamesToValues.put(name, value);
43 | }
44 |
45 | public void setProperties(final Map properties) {
46 | if (properties == null) {
47 | return;
48 | }
49 |
50 | for (final Map.Entry propertyEntry : properties.entrySet()) {
51 | setProperty(propertyEntry.getKey(), propertyEntry.getValue());
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/actions/StopCheck.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.actions;
2 |
3 | import com.intellij.openapi.actionSystem.AnActionEvent;
4 | import com.intellij.openapi.actionSystem.Presentation;
5 | import com.intellij.openapi.diagnostic.Logger;
6 | import com.intellij.openapi.wm.ToolWindow;
7 | import org.jetbrains.annotations.NotNull;
8 |
9 | import static org.infernus.idea.checkstyle.actions.ToolWindowAccess.toolWindow;
10 |
11 | /**
12 | * Action to stop a check in progress.
13 | */
14 | public class StopCheck extends BaseAction {
15 | private static final Logger LOG = Logger.getInstance(StopCheck.class);
16 |
17 | @Override
18 | public void actionPerformed(final @NotNull AnActionEvent event) {
19 | project(event).ifPresent(project -> {
20 | try {
21 | final ToolWindow toolWindow = toolWindow(project);
22 | toolWindow.activate(() -> {
23 | setProgressText(toolWindow, "plugin.status.in-progress.current");
24 |
25 | staticScanner(project).stopChecks();
26 |
27 | setProgressText(toolWindow, "plugin.status.aborted");
28 | });
29 |
30 | } catch (Throwable e) {
31 | LOG.warn("Abort Scan failed", e);
32 | }
33 | });
34 | }
35 |
36 | @Override
37 | public void update(final @NotNull AnActionEvent event) {
38 | final Presentation presentation = event.getPresentation();
39 | project(event).ifPresentOrElse(project -> {
40 | try {
41 | presentation.setEnabled(staticScanner(project).isScanInProgress());
42 |
43 | } catch (Throwable e) {
44 | LOG.warn("Abort button update failed", e);
45 | }
46 | }, () -> presentation.setEnabled(false));
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/resources/dtd/configuration_1_3.dtd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 |
12 |
13 |
14 |
19 |
20 |
33 |
34 |
35 |
39 |
40 |
52 |
53 |
57 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/importer/modules/FileTabCharacterImporter.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.importer.modules;
2 |
3 | import com.intellij.openapi.fileTypes.FileType;
4 | import com.intellij.openapi.fileTypes.FileTypeManager;
5 | import com.intellij.psi.codeStyle.CodeStyleSettings;
6 | import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
7 | import org.infernus.idea.checkstyle.importer.ModuleImporter;
8 | import org.jetbrains.annotations.NotNull;
9 |
10 | @SuppressWarnings("unused")
11 | public class FileTabCharacterImporter extends ModuleImporter {
12 |
13 | private static final String FILE_EXTENSIONS_PROP = "fileExtensions";
14 | private String[] extensions;
15 |
16 | @Override
17 | protected void handleAttribute(@NotNull final String attrName, @NotNull final String attrValue) {
18 | if (FILE_EXTENSIONS_PROP.equals(attrName)) {
19 | extensions = attrValue.split("\\s*,\\s*");
20 | }
21 | }
22 |
23 | @Override
24 | public void importTo(@NotNull final CodeStyleSettings settings) {
25 | if (extensions != null) {
26 | for (String extension : extensions) {
27 | if (!extension.isEmpty()) {
28 | FileType fileType = FileTypeManager.getInstance().getFileTypeByExtension(extension);
29 | setNoTabChar(settings, fileType);
30 | }
31 | }
32 | } else {
33 | for (FileType fileType : FileTypeManager.getInstance().getRegisteredFileTypes()) {
34 | setNoTabChar(settings, fileType);
35 | }
36 | }
37 | }
38 |
39 | private void setNoTabChar(@NotNull final CodeStyleSettings settings, final FileType fileType) {
40 | CommonCodeStyleSettings.IndentOptions indentOptions = settings.getIndentOptions(fileType);
41 | indentOptions.USE_TAB_CHARACTER = false;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/importer/modules/EmptyLineSeparatorImporter.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.importer.modules;
2 |
3 | import com.intellij.psi.codeStyle.CodeStyleSettings;
4 | import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
5 | import org.infernus.idea.checkstyle.csapi.KnownTokenTypes;
6 | import org.infernus.idea.checkstyle.importer.ModuleImporter;
7 | import org.jetbrains.annotations.NotNull;
8 |
9 | @SuppressWarnings("unused")
10 | public class EmptyLineSeparatorImporter extends ModuleImporter {
11 |
12 | private boolean noEmptyLinesBetweenFields = false;
13 | private static final String NO_EMPTY_LINES_BETWEEN_FIELDS_PROP = "allowNoEmptyLineBetweenFields";
14 |
15 | @Override
16 | protected void handleAttribute(@NotNull final String attrName, @NotNull final String attrValue) {
17 | if (NO_EMPTY_LINES_BETWEEN_FIELDS_PROP.equals(attrName)) {
18 | noEmptyLinesBetweenFields = Boolean.parseBoolean(attrValue);
19 | }
20 | }
21 |
22 | @Override
23 | public void importTo(@NotNull final CodeStyleSettings settings) {
24 | CommonCodeStyleSettings commonSettings = getCommonSettings(settings);
25 |
26 | if (noEmptyLinesBetweenFields) {
27 | commonSettings.BLANK_LINES_AROUND_FIELD = 0;
28 | } else if (appliesTo(KnownTokenTypes.VARIABLE_DEF)) {
29 | commonSettings.BLANK_LINES_AROUND_FIELD = 1;
30 | }
31 | if (appliesTo(KnownTokenTypes.PACKAGE_DEF)) {
32 | commonSettings.BLANK_LINES_AFTER_PACKAGE = 1;
33 | commonSettings.BLANK_LINES_BEFORE_PACKAGE = 1;
34 | }
35 | if (appliesTo(KnownTokenTypes.IMPORT)) {
36 | commonSettings.BLANK_LINES_AFTER_IMPORTS = 1;
37 | }
38 | if (appliesTo(KnownTokenTypes.METHOD_DEF)) {
39 | commonSettings.BLANK_LINES_AROUND_METHOD = 1;
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/checker/CreateScannableFileAction.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.checker;
2 |
3 | import com.intellij.openapi.module.Module;
4 | import com.intellij.psi.PsiFile;
5 | import com.intellij.util.ThrowableRunnable;
6 | import org.jetbrains.annotations.NotNull;
7 | import org.jetbrains.annotations.Nullable;
8 |
9 | import java.io.IOException;
10 |
11 | /**
12 | * Action to read the file to a temporary file.
13 | */
14 | class CreateScannableFileAction implements ThrowableRunnable {
15 |
16 | /**
17 | * Any failure that occurred on the thread.
18 | */
19 | private IOException failure;
20 |
21 | private final PsiFile psiFile;
22 | private final Module module;
23 |
24 | /**
25 | * The created temporary file.
26 | */
27 | private ScannableFile file;
28 |
29 | /**
30 | * Create a thread to read the given file to a temporary file.
31 | *
32 | * @param psiFile the file to read.
33 | * @param module the module the file belongs to.
34 | */
35 | CreateScannableFileAction(@NotNull final PsiFile psiFile,
36 | @Nullable final Module module) {
37 | this.psiFile = psiFile;
38 | this.module = module;
39 | }
40 |
41 | /**
42 | * Get any failure that occurred in this thread.
43 | *
44 | * @return the failure, if any.
45 | */
46 | public IOException getFailure() {
47 | return failure;
48 | }
49 |
50 | /**
51 | * Get the scannable file.
52 | *
53 | * @return the scannable file.
54 | */
55 | public ScannableFile getFile() {
56 | return file;
57 | }
58 |
59 | @Override
60 | public void run() {
61 | try {
62 | file = new ScannableFile(psiFile, module);
63 |
64 | } catch (IOException e) {
65 | failure = e;
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/toolwindow/GroupTreeInfo.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.toolwindow;
2 |
3 | import org.infernus.idea.checkstyle.CheckStyleBundle;
4 | import org.jetbrains.annotations.NotNull;
5 |
6 | import javax.swing.*;
7 |
8 | abstract class GroupTreeInfo extends ResultTreeNode {
9 |
10 | private final String name;
11 | private final String groupId;
12 | private final int totalProblems;
13 | private int visibleProblems;
14 |
15 | /**
16 | * Construct a group node.
17 | *
18 | * @param name the name of the group.
19 | * @param groupId the ID used as part of message lookup.
20 | * @param icon the icon of the group.
21 | * @param problemCount the number of problems in the group.
22 | */
23 | public GroupTreeInfo(@NotNull final String name,
24 | @NotNull final String groupId,
25 | @NotNull final Icon icon,
26 | final int problemCount) {
27 | super(CheckStyleBundle.message("plugin.results.scan-" + groupId + "-result", name, problemCount));
28 |
29 | this.name = name;
30 | this.groupId = groupId;
31 | this.totalProblems = problemCount;
32 | this.visibleProblems = problemCount;
33 |
34 | updateDisplayText();
35 | setIcon(icon);
36 | }
37 |
38 | private void updateDisplayText() {
39 | if (totalProblems == visibleProblems) {
40 | setText(CheckStyleBundle.message("plugin.results.scan-" + groupId + "-result", name, totalProblems));
41 | } else {
42 | setText(CheckStyleBundle.message("plugin.results.scan-" + groupId + "-result.filtered", name, visibleProblems, totalProblems - visibleProblems));
43 | }
44 | }
45 |
46 | void setVisibleProblems(final int visibleProblems) {
47 | this.visibleProblems = visibleProblems;
48 |
49 | updateDisplayText();
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/toolwindow/ResultProblem.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.toolwindow;
2 |
3 | import com.intellij.openapi.module.Module;
4 | import com.intellij.psi.PsiElement;
5 | import org.infernus.idea.checkstyle.CheckStyleBundle;
6 | import org.infernus.idea.checkstyle.checker.ConfigurationLocationResult;
7 | import org.infernus.idea.checkstyle.checker.Problem;
8 | import org.infernus.idea.checkstyle.csapi.SeverityLevel;
9 | import org.infernus.idea.checkstyle.util.DisplayFormats;
10 | import org.jetbrains.annotations.NotNull;
11 |
12 | record ResultProblem(
13 | ConfigurationLocationResult configurationLocationResult,
14 | Module module,
15 | PsiElement target,
16 | SeverityLevel severityLevel,
17 | int line,
18 | int column,
19 | String sourceName,
20 | String message,
21 | boolean afterEndOfLine,
22 | boolean suppressErrors) {
23 |
24 | ResultProblem(@NotNull final ConfigurationLocationResult configurationLocationResult,
25 | @NotNull final Module module,
26 | @NotNull final Problem csProblem) {
27 | this(configurationLocationResult, module, csProblem.target(), csProblem.severityLevel(), csProblem.line(),
28 | csProblem.column(), csProblem.sourceName(), csProblem.message(), csProblem.afterEndOfLine(),
29 | csProblem.suppressErrors());
30 | }
31 |
32 | @NotNull
33 | public String sourceCheck() {
34 | if (sourceName != null) {
35 | return DisplayFormats.shortenClassName(sourceName);
36 | }
37 | return CheckStyleBundle.message("plugin.results.unknown-source");
38 | }
39 |
40 | public String locationDescription() {
41 | if (configurationLocationResult.location() != null) {
42 | return configurationLocationResult().location().getDescription();
43 | }
44 | return CheckStyleBundle.message("plugin.results.unknown-location");
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/checks/PackageHtmlCheck.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.checks;
2 |
3 | import com.intellij.psi.PsiElement;
4 | import com.intellij.psi.PsiFile;
5 | import org.infernus.idea.checkstyle.csapi.CheckstyleInternalObject;
6 | import org.jetbrains.annotations.NotNull;
7 |
8 |
9 | /**
10 | * Extra logic for the PackageHtmlCheck check.
11 | */
12 | public class PackageHtmlCheck implements Check {
13 |
14 | private static final String CHECK_PACKAGE_HTML = "com.puppycrawl.tools.checkstyle.checks.javadoc.PackageHtmlCheck";
15 | private static final String PACKAGE_HTML_FILE = "package.html";
16 |
17 | @Override
18 | public String getShortName() {
19 | return "PackageHtml";
20 | }
21 |
22 | @Override
23 | public String getFullyQualifiedName() {
24 | return CHECK_PACKAGE_HTML;
25 | }
26 |
27 |
28 | public void configure(@NotNull final CheckstyleInternalObject config) {
29 | }
30 |
31 |
32 | public boolean process(@NotNull final PsiFile file, @NotNull final String pEventSourceName) {
33 | if (!CHECK_PACKAGE_HTML.equals(pEventSourceName)) {
34 | return true;
35 | }
36 |
37 | PsiElement currentSibling = findFirstSibling(file);
38 |
39 | while (currentSibling != null) {
40 | if (currentSibling.isPhysical() && currentSibling.isValid()
41 | && currentSibling instanceof PsiFile
42 | && PACKAGE_HTML_FILE.equals(((PsiFile) currentSibling).getName())) {
43 | return false;
44 | }
45 |
46 | currentSibling = currentSibling.getNextSibling();
47 | }
48 |
49 | return true;
50 | }
51 |
52 |
53 | private PsiElement findFirstSibling(@NotNull final PsiFile psiFile) {
54 | PsiElement currentSibling = psiFile;
55 | while (currentSibling.getPrevSibling() != null) {
56 | currentSibling = currentSibling.getPrevSibling();
57 | }
58 | return currentSibling;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/ui/PropertiesDialogue.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.ui;
2 |
3 | import com.intellij.openapi.project.Project;
4 | import com.intellij.openapi.ui.DialogWrapper;
5 | import org.infernus.idea.checkstyle.CheckStyleBundle;
6 | import org.infernus.idea.checkstyle.CheckstyleProjectService;
7 | import org.infernus.idea.checkstyle.model.ConfigurationLocation;
8 | import org.jetbrains.annotations.NotNull;
9 | import org.jetbrains.annotations.Nullable;
10 |
11 | import javax.swing.*;
12 | import java.awt.*;
13 |
14 | /**
15 | * Allows setting of file properties.
16 | */
17 | public class PropertiesDialogue extends DialogWrapper {
18 |
19 | private final PropertiesPanel propertiesPanel;
20 |
21 |
22 | public PropertiesDialogue(@Nullable final Dialog parent,
23 | @NotNull final Project project,
24 | @NotNull final CheckstyleProjectService checkstyleProjectService) {
25 | super(project, parent, false, IdeModalityType.IDE);
26 |
27 | this.propertiesPanel = new PropertiesPanel(project, checkstyleProjectService);
28 |
29 | setTitle(CheckStyleBundle.message("config.file.properties.title"));
30 | init();
31 | }
32 |
33 | @Override
34 | protected @Nullable JComponent createCenterPanel() {
35 | return propertiesPanel;
36 | }
37 |
38 | /**
39 | * Get the configuration location entered in the dialogue, or null if no valid location was entered.
40 | *
41 | * @return the location or null if no valid location entered.
42 | */
43 | public ConfigurationLocation getConfigurationLocation() {
44 | return propertiesPanel.getConfigurationLocation();
45 | }
46 |
47 | /**
48 | * Set the configuration location.
49 | *
50 | * @param configurationLocation the location.
51 | */
52 | public void setConfigurationLocation(final ConfigurationLocation configurationLocation) {
53 | propertiesPanel.setConfigurationLocation(configurationLocation);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/toolwindow/ResultTreeNode.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.toolwindow;
2 |
3 | import com.intellij.icons.AllIcons;
4 |
5 | import javax.swing.*;
6 |
7 | import static org.infernus.idea.checkstyle.util.Strings.isBlank;
8 |
9 |
10 | /**
11 | * The user object for meta-data on tree nodes in the tool window.
12 | */
13 | public class ResultTreeNode {
14 |
15 | private String text;
16 | private Icon icon = AllIcons.General.Information;
17 |
18 | /**
19 | * Construct an informational node.
20 | *
21 | * @param text the information text.
22 | */
23 | public ResultTreeNode(final String text) {
24 | if (text == null) {
25 | throw new IllegalArgumentException("Text may not be null");
26 | }
27 |
28 | this.text = text;
29 | }
30 |
31 | /**
32 | * Get the node's icon when in an expanded state.
33 | *
34 | * @return the node's icon when in an expanded state.
35 | */
36 | public Icon getExpandedIcon() {
37 | return icon;
38 | }
39 |
40 | /**
41 | * Get the node's icon when in a collapsed state.
42 | *
43 | * @return the node's icon when in a collapsed state.
44 | */
45 | public Icon getCollapsedIcon() {
46 | return icon;
47 | }
48 |
49 | /**
50 | * Get the file the node represents.
51 | *
52 | * @return the file the node represents.
53 | */
54 | public String getText() {
55 | return text;
56 | }
57 |
58 | /**
59 | * Set the file the node represents.
60 | *
61 | * @param text the file the node represents.
62 | */
63 | void setText(final String text) {
64 | if (isBlank(text)) {
65 | throw new IllegalArgumentException("Text may not be null/empty");
66 | }
67 | this.text = text;
68 | }
69 |
70 | protected void setIcon(final Icon icon) {
71 | this.icon = icon;
72 | }
73 |
74 | @Override
75 | public String toString() {
76 | return text;
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/ui/ErrorPanel.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.ui;
2 |
3 | import com.intellij.ui.components.JBScrollPane;
4 | import com.intellij.util.ui.JBUI;
5 | import org.infernus.idea.checkstyle.CheckStyleBundle;
6 |
7 | import javax.swing.*;
8 | import java.awt.*;
9 | import java.io.PrintWriter;
10 | import java.io.StringWriter;
11 |
12 | import static javax.swing.JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS;
13 | import static javax.swing.JScrollPane.VERTICAL_SCROLLBAR_ALWAYS;
14 |
15 | public class ErrorPanel extends JPanel {
16 | private final JTextArea errorField = new JTextArea();
17 |
18 | public ErrorPanel() {
19 | super(new BorderLayout());
20 |
21 | initialise();
22 |
23 | setError(new RuntimeException());
24 | }
25 |
26 | private void initialise() {
27 | setBorder(JBUI.Borders.empty(8));
28 |
29 | final JLabel infoLabel = new JLabel(CheckStyleBundle.message("config.file.error.caption"));
30 | infoLabel.setBorder(JBUI.Borders.emptyBottom(8));
31 | add(infoLabel, BorderLayout.NORTH);
32 |
33 | errorField.setEditable(false);
34 | errorField.setTabSize(2);
35 | errorField.setWrapStyleWord(true);
36 | errorField.setLineWrap(true);
37 |
38 | final JScrollPane errorScrollPane = new JBScrollPane(errorField, VERTICAL_SCROLLBAR_ALWAYS, HORIZONTAL_SCROLLBAR_ALWAYS);
39 | add(errorScrollPane, BorderLayout.CENTER);
40 | }
41 |
42 | public void setError(final Throwable t) {
43 | final StringWriter errorWriter = new StringWriter();
44 | causeOf(t).printStackTrace(new PrintWriter(errorWriter));
45 |
46 | errorField.setText(errorWriter.getBuffer().toString());
47 | errorField.setCaretPosition(0);
48 | invalidate();
49 | }
50 |
51 | private Throwable causeOf(final Throwable t) {
52 | if (t.getCause() != null && t.getCause() != t
53 | && !t.getClass().getPackage().getName().startsWith("com.puppycrawl")) {
54 | return causeOf(t.getCause());
55 | }
56 | return t;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/model/ScanScope.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.model;
2 |
3 | import org.infernus.idea.checkstyle.CheckStyleBundle;
4 | import org.jetbrains.annotations.NotNull;
5 |
6 | /**
7 | * Possible values of the 'scope' configuration item.
8 | */
9 | public enum ScanScope {
10 | /**
11 | * Scan only Java files which reside in source folders (main only)
12 | */
13 | JavaOnly,
14 |
15 | /**
16 | * Scan only Java files which reside in source folders (main and test)
17 | */
18 | JavaOnlyWithTests,
19 |
20 | /**
21 | * Scan all files which reside in source folders (main only)
22 | */
23 | AllSources,
24 |
25 | /**
26 | * Scan all files which reside in source folders (main and test)
27 | */
28 | AllSourcesWithTests,
29 |
30 | /**
31 | * Scan all files in the project, regardless of their location
32 | */
33 | Everything;
34 |
35 | private final String dropdownBoxEntry;
36 |
37 | ScanScope() {
38 | dropdownBoxEntry = CheckStyleBundle.message("config.scanscope." + this.name());
39 | }
40 |
41 | public boolean includeTestClasses() {
42 | return this == JavaOnlyWithTests || this == AllSourcesWithTests || this == Everything;
43 | }
44 |
45 | public boolean includeNonJavaSources() {
46 | return this == AllSources || this == AllSourcesWithTests || this == Everything;
47 | }
48 |
49 | @NotNull
50 | public static ScanScope fromFlags(final boolean pIncludeTests, final boolean pIncludeNonJava) {
51 | ScanScope result = getDefaultValue();
52 | if (pIncludeTests) {
53 | if (pIncludeNonJava) {
54 | result = AllSourcesWithTests;
55 | } else {
56 | result = JavaOnlyWithTests;
57 | }
58 | } else if (pIncludeNonJava) {
59 | result = AllSources;
60 | }
61 | return result;
62 | }
63 |
64 | @NotNull
65 | public static ScanScope getDefaultValue() {
66 | return JavaOnly;
67 | }
68 |
69 | @Override
70 | public String toString() {
71 | return dropdownBoxEntry;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/test/java/org/infernus/idea/checkstyle/CheckstyleProjectServiceTest.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle;
2 |
3 | import com.intellij.openapi.project.Project;
4 | import org.infernus.idea.checkstyle.config.PluginConfigurationBuilder;
5 | import org.infernus.idea.checkstyle.config.PluginConfigurationManager;
6 | import org.junit.Before;
7 | import org.junit.Test;
8 |
9 | import java.util.SortedSet;
10 |
11 | import static org.hamcrest.Matchers.*;
12 | import static org.hamcrest.MatcherAssert.assertThat;
13 | import static org.mockito.Mockito.mock;
14 | import static org.mockito.Mockito.when;
15 |
16 |
17 | public class CheckstyleProjectServiceTest {
18 | private static final String CHECKSTYLE_VERSION = "9.0.1";
19 |
20 | private CheckstyleProjectService underTest;
21 |
22 | @Before
23 | public void setUp() {
24 | Project project = mock(Project.class);
25 |
26 | PluginConfigurationManager pluginConfigManager = mock(PluginConfigurationManager.class);
27 | when(pluginConfigManager.getCurrent())
28 | .thenReturn(PluginConfigurationBuilder.testInstance(CHECKSTYLE_VERSION).build());
29 | when(project.getService(PluginConfigurationManager.class)).thenReturn(pluginConfigManager);
30 |
31 | underTest = new CheckstyleProjectService(project);
32 | }
33 |
34 | @Test
35 | public void readingSupportedVersionsReturnsASetOfVersions() {
36 | SortedSet versions = underTest.getSupportedVersions();
37 | assertThat(versions, hasItem(CHECKSTYLE_VERSION));
38 | assertThat(versions.comparator(), is(instanceOf(VersionComparator.class)));
39 | }
40 |
41 | @Test
42 | public void classLoaderCanBeRetrievedByExternalTools() {
43 | underTest.activateCheckstyleVersion(CHECKSTYLE_VERSION, null);
44 | assertThat(underTest.underlyingClassLoader(), is(not(nullValue())));
45 | }
46 |
47 | @Test
48 | public void classLoaderCanLoadCheckStyleInternalClasses() throws ClassNotFoundException {
49 | underTest.activateCheckstyleVersion(CHECKSTYLE_VERSION, null);
50 | assertThat(underTest.underlyingClassLoader().loadClass("com.puppycrawl.tools.checkstyle.Checker"),
51 | is(not(nullValue())));
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/importer/ModuleImporter.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.importer;
2 |
3 | import java.util.Collections;
4 | import java.util.Map;
5 | import java.util.Set;
6 |
7 | import com.intellij.lang.java.JavaLanguage;
8 | import com.intellij.psi.codeStyle.CodeStyleSettings;
9 | import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
10 | import com.intellij.psi.codeStyle.JavaCodeStyleSettings;
11 | import org.infernus.idea.checkstyle.csapi.ConfigurationModule;
12 | import org.infernus.idea.checkstyle.csapi.KnownTokenTypes;
13 | import org.jetbrains.annotations.NotNull;
14 |
15 | public abstract class ModuleImporter {
16 |
17 | private Set tokens;
18 |
19 | @NotNull
20 | protected CommonCodeStyleSettings getCommonSettings(@NotNull final CodeStyleSettings settings) {
21 | return settings.getCommonSettings(JavaLanguage.INSTANCE);
22 | }
23 | @NotNull
24 | protected JavaCodeStyleSettings getJavaSettings(@NotNull final CodeStyleSettings settings) {
25 | return settings.getCustomSettings(JavaCodeStyleSettings.class);
26 | }
27 |
28 | public void setFrom(@NotNull final ConfigurationModule moduleConfig) {
29 | tokens = moduleConfig.getKnownTokenTypes();
30 | for (Map.Entry entry : moduleConfig.getProperties().entrySet()) {
31 | handleAttribute(entry.getKey(), entry.getValue());
32 | }
33 | }
34 |
35 | protected abstract void handleAttribute(@NotNull String attrName, @NotNull String attrValue);
36 |
37 |
38 | protected boolean appliesTo(final KnownTokenTypes token) {
39 | return tokens == null || tokens.isEmpty() || tokens.contains(token);
40 | }
41 |
42 | protected boolean appliesToOneOf(final Set tokenSet) {
43 | return tokens == null || tokens.isEmpty() || !Collections.disjoint(tokens, tokenSet);
44 | }
45 |
46 |
47 | public abstract void importTo(@NotNull CodeStyleSettings settings);
48 |
49 |
50 | protected int getIntOrDefault(@NotNull final String intStr, final int defaultValue) {
51 | try {
52 | return Integer.parseInt(intStr);
53 | } catch (NumberFormatException e) {
54 | return defaultValue;
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/main/resources/dtd/import_control_1_0.dtd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
13 |
14 |
15 |
18 |
20 |
21 |
24 |
25 |
26 |
31 |
33 |
34 |
54 |
59 |
60 |
63 |
64 |
66 |
67 |
70 |
71 |
73 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/util/Async.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.util;
2 |
3 | import java.util.concurrent.Callable;
4 | import java.util.concurrent.Future;
5 |
6 | import com.intellij.openapi.application.ApplicationManager;
7 | import com.intellij.openapi.diagnostic.Logger;
8 | import com.intellij.openapi.progress.ProcessCanceledException;
9 | import com.intellij.openapi.progress.ProgressManager;
10 | import org.jetbrains.annotations.NotNull;
11 | import org.jetbrains.annotations.Nullable;
12 |
13 | public final class Async {
14 | private static final Logger LOG = Logger.getInstance(Async.class);
15 |
16 | private static final int FIFTY_MS = 50;
17 |
18 | private Async() {
19 | }
20 |
21 | @Nullable
22 | public static T asyncResultOf(@NotNull final Callable callable,
23 | @Nullable final T defaultValue,
24 | final long timeoutInMs) {
25 | try {
26 | return whenFinished(executeOnPooledThread(callable), timeoutInMs).get();
27 |
28 | } catch (Exception e) {
29 | return defaultValue;
30 | }
31 | }
32 |
33 | public static Future executeOnPooledThread(final Callable callable) {
34 | return ApplicationManager.getApplication().executeOnPooledThread(callable);
35 | }
36 |
37 | public static Future whenFinished(final Future future,
38 | final long timeoutInMs) {
39 | long elapsedTime = 0;
40 | while (!future.isDone() && !future.isCancelled()) {
41 | ProgressManager.checkCanceled();
42 | elapsedTime += waitFor(FIFTY_MS);
43 |
44 | if (timeoutInMs > 0 && elapsedTime >= timeoutInMs) {
45 | LOG.debug("Async task exhausted timeout of " + timeoutInMs + "ms, cancelling.");
46 | future.cancel(true);
47 | throw new ProcessCanceledException();
48 | }
49 | }
50 | return future;
51 | }
52 |
53 | private static long waitFor(final int millis) {
54 | try {
55 | Thread.sleep(millis);
56 | } catch (InterruptedException ignored) {
57 | Thread.currentThread().interrupt();
58 | }
59 | return millis;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/actions/ScanAllFilesTask.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.actions;
2 |
3 | import com.intellij.openapi.application.ReadAction;
4 | import com.intellij.openapi.project.Project;
5 | import com.intellij.openapi.vfs.VfsUtilCore;
6 | import com.intellij.openapi.vfs.VirtualFile;
7 | import com.intellij.openapi.vfs.VirtualFileVisitor;
8 | import org.infernus.idea.checkstyle.StaticScanner;
9 | import org.infernus.idea.checkstyle.model.ConfigurationLocation;
10 | import org.jetbrains.annotations.NotNull;
11 |
12 | import java.util.ArrayList;
13 | import java.util.List;
14 | import java.util.concurrent.Callable;
15 |
16 |
17 | abstract class ScanAllFilesTask implements Callable {
18 |
19 | private final Project project;
20 | private final ConfigurationLocation selectedOverride;
21 |
22 | ScanAllFilesTask(@NotNull final Project project,
23 | final ConfigurationLocation selectedOverride) {
24 | this.project = project;
25 | this.selectedOverride = selectedOverride;
26 | }
27 |
28 | @Override
29 | public Void call() {
30 | project.getService(StaticScanner.class)
31 | .asyncScanFiles(flattenFiles(files()), selectedOverride);
32 | return null;
33 | }
34 |
35 | protected abstract VirtualFile[] files();
36 |
37 | private List flattenFiles(final VirtualFile[] files) {
38 | final List flattened = new ArrayList<>();
39 | if (files != null) {
40 | for (final VirtualFile file : files) {
41 | flattened.add(file);
42 | flattened.addAll(ReadAction.compute(() -> {
43 | final List flattenedChildren = new ArrayList<>();
44 | VfsUtilCore.visitChildrenRecursively(file, new VirtualFileVisitor<>() {
45 | @Override
46 | @NotNull
47 | public Result visitFileEx(@NotNull final VirtualFile file) {
48 | flattenedChildren.add(file);
49 | return CONTINUE;
50 | }
51 | });
52 | return flattenedChildren;
53 | }));
54 | }
55 | }
56 | return flattened;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/CheckstylePluginApi.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle;
2 |
3 | import com.intellij.openapi.project.Project;
4 | import org.infernus.idea.checkstyle.config.PluginConfigurationManager;
5 | import org.infernus.idea.checkstyle.csapi.CheckstyleActions;
6 | import org.infernus.idea.checkstyle.csapi.ConfigurationModule;
7 | import org.infernus.idea.checkstyle.model.ConfigurationLocation;
8 | import org.jetbrains.annotations.NotNull;
9 | import org.jetbrains.annotations.Nullable;
10 |
11 | import java.util.HashMap;
12 | import java.util.SortedSet;
13 | import java.util.function.BiConsumer;
14 |
15 | /**
16 | * This class contains methods known to be used by external dependencies.
17 | *
18 | * We guarantee nothing, but try to keep compatibility :-)
19 | */
20 | @SuppressWarnings("unused")
21 | public class CheckstylePluginApi {
22 | private final Project project;
23 |
24 | public CheckstylePluginApi(final Project project) {
25 | this.project = project;
26 | }
27 |
28 | @Nullable
29 | public ClassLoader currentCheckstyleClassLoader() {
30 | return checkstyleProjectService().underlyingClassLoader();
31 | }
32 |
33 | public void visitCurrentConfiguration(@NotNull final ConfigurationVisitor visitor) {
34 | SortedSet activeLocations = pluginConfigurationManager().getCurrent().getActiveLocations();
35 |
36 | activeLocations.forEach(it -> {
37 | CheckstyleActions checkstyleInstance = checkstyleProjectService().getCheckstyleInstance();
38 | checkstyleInstance.peruseConfiguration(
39 | checkstyleInstance.loadConfiguration(
40 | it,
41 | new HashMap<>()),
42 | module -> visitor.accept(it.getDescription(), module));
43 | });
44 | }
45 |
46 | @SuppressWarnings("WeakerAccess")
47 | public interface ConfigurationVisitor extends BiConsumer {
48 |
49 | }
50 |
51 | private PluginConfigurationManager pluginConfigurationManager() {
52 | return project.getService(PluginConfigurationManager.class);
53 | }
54 |
55 | private CheckstyleProjectService checkstyleProjectService() {
56 | return project.getService(CheckstyleProjectService.class);
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/actions/ScanModifiedFiles.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.actions;
2 |
3 | import com.intellij.openapi.actionSystem.AnActionEvent;
4 | import com.intellij.openapi.actionSystem.Presentation;
5 | import com.intellij.openapi.diagnostic.Logger;
6 | import com.intellij.openapi.vcs.changes.ChangeListManager;
7 | import com.intellij.openapi.vfs.VirtualFile;
8 | import org.infernus.idea.checkstyle.toolwindow.CheckStyleToolWindowPanel;
9 | import org.jetbrains.annotations.NotNull;
10 |
11 | import java.util.List;
12 |
13 | import static org.infernus.idea.checkstyle.actions.ToolWindowAccess.toolWindow;
14 |
15 | /**
16 | * Scan modified files.
17 | *
18 | * If the project is not setup to use VCS then no files will be scanned.
19 | */
20 | public class ScanModifiedFiles extends BaseAction {
21 |
22 | private static final Logger LOG = Logger.getInstance(ScanModifiedFiles.class);
23 |
24 | @Override
25 | public final void actionPerformed(final @NotNull AnActionEvent event) {
26 | project(event).ifPresent(project -> {
27 | try {
28 | List affectedFiles = ChangeListManager.getInstance(project).getAffectedFiles();
29 | if (affectedFiles.isEmpty()) {
30 | CheckStyleToolWindowPanel checkStyleToolWindowPanel = CheckStyleToolWindowPanel.panelFor(project);
31 | if (checkStyleToolWindowPanel != null) {
32 | checkStyleToolWindowPanel.displayWarningResult("plugin.status.in-progress.no-modified-files");
33 | }
34 | } else {
35 | staticScanner(project).asyncScanFiles(
36 | affectedFiles,
37 | getSelectedOverride(toolWindow(project)));
38 | }
39 | } catch (Throwable e) {
40 | LOG.warn("Modified files scan failed", e);
41 | }
42 | });
43 | }
44 |
45 | @Override
46 | public void update(final @NotNull AnActionEvent event) {
47 | final Presentation presentation = event.getPresentation();
48 |
49 | project(event).ifPresentOrElse(
50 | project -> presentation.setEnabled(!staticScanner(project).isScanInProgress()),
51 | () -> presentation.setEnabled(false));
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/resources/dtd/import_control_1_1.dtd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
13 |
14 |
15 |
18 |
20 |
21 |
24 |
25 |
26 |
31 |
33 |
34 |
56 |
62 |
63 |
66 |
67 |
69 |
70 |
73 |
74 |
76 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/config/ConfigurationLocationSource.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.config;
2 |
3 | import com.intellij.openapi.module.Module;
4 | import com.intellij.openapi.project.Project;
5 | import org.infernus.idea.checkstyle.model.ConfigurationLocation;
6 | import org.jetbrains.annotations.NotNull;
7 | import org.jetbrains.annotations.Nullable;
8 |
9 | import java.util.Collections;
10 | import java.util.Objects;
11 | import java.util.SortedSet;
12 | import java.util.TreeSet;
13 | import java.util.stream.Collectors;
14 |
15 | public class ConfigurationLocationSource {
16 |
17 | private final Project project;
18 |
19 | public ConfigurationLocationSource(@NotNull final Project project) {
20 | this.project = project;
21 | }
22 |
23 | public SortedSet getConfigurationLocations(@Nullable final Module module,
24 | @Nullable final ConfigurationLocation override) {
25 | if (override != null) {
26 | return new TreeSet<>(Collections.singleton(override));
27 | }
28 |
29 | if (module != null) {
30 | ModuleConfigurationState moduleConfiguration = checkstyleModuleConfiguration(module);
31 | if (moduleConfiguration.isExcluded()) {
32 | return Collections.emptySortedSet();
33 | }
34 |
35 | PluginConfiguration configuration = configurationManager().getCurrent();
36 | TreeSet moduleActiveConfigurations = moduleConfiguration.getActiveLocationIds().stream()
37 | .map(id -> configuration.getLocationById(id).orElse(null))
38 | .filter(Objects::nonNull)
39 | .collect(Collectors.toCollection(TreeSet::new));
40 | if (!moduleActiveConfigurations.isEmpty()) {
41 | return moduleActiveConfigurations;
42 | }
43 | }
44 |
45 | return configurationManager().getCurrent().getActiveLocations();
46 | }
47 |
48 | private PluginConfigurationManager configurationManager() {
49 | return project.getService(PluginConfigurationManager.class);
50 | }
51 |
52 | private ModuleConfigurationState checkstyleModuleConfiguration(final Module module) {
53 | return module.getService(ModuleConfigurationState.class);
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/model/BundledConfigurationLocation.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.model;
2 |
3 | import com.intellij.openapi.project.Project;
4 | import org.infernus.idea.checkstyle.csapi.BundledConfig;
5 | import org.jetbrains.annotations.NotNull;
6 | import org.jetbrains.annotations.Nullable;
7 |
8 | import java.io.IOException;
9 | import java.io.InputStream;
10 |
11 | import static org.infernus.idea.checkstyle.util.Streams.inMemoryCopyOf;
12 |
13 |
14 | public class BundledConfigurationLocation extends ConfigurationLocation {
15 | @NotNull
16 | private final BundledConfig bundledConfig;
17 |
18 | BundledConfigurationLocation(@NotNull final BundledConfig bundledConfig,
19 | @NotNull final Project project) {
20 | super(bundledConfig.getId(), ConfigurationType.BUNDLED, project);
21 | super.setLocation(bundledConfig.getLocation());
22 | super.setDescription(bundledConfig.getDescription());
23 |
24 | this.bundledConfig = bundledConfig;
25 | }
26 |
27 | @NotNull
28 | public BundledConfig getBundledConfig() {
29 | return bundledConfig;
30 | }
31 |
32 | @Override
33 | public void setLocation(final String location) {
34 | // do nothing, we always use the hard-coded location
35 | }
36 |
37 | @Override
38 | public void setDescription(@Nullable final String description) {
39 | // do nothing, we always use the hard-coded description
40 | }
41 |
42 | @Override
43 | @NotNull
44 | protected InputStream resolveFile(@NotNull final ClassLoader checkstyleClassLoader) throws IOException {
45 | try {
46 | InputStream source = checkstyleClassLoader.loadClass("com.puppycrawl.tools.checkstyle.Checker").getResourceAsStream(bundledConfig.getPath());
47 | if (source == null) {
48 | throw new IOException("Could not read " + bundledConfig.getPath() + " from classpath");
49 | }
50 | return inMemoryCopyOf(source);
51 | } catch (ClassNotFoundException e) {
52 | throw new IOException("Couldn't find Checkstyle on classpath", e);
53 | }
54 | }
55 |
56 | public boolean isRemovable() {
57 | return false;
58 | }
59 |
60 |
61 | @Override
62 | @NotNull
63 | public BundledConfigurationLocation clone() {
64 | return new BundledConfigurationLocation(bundledConfig, getProject());
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/actions/ToolWindowAccess.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.actions;
2 |
3 | import com.intellij.openapi.project.Project;
4 | import com.intellij.openapi.wm.ToolWindow;
5 | import com.intellij.openapi.wm.ToolWindowManager;
6 | import com.intellij.ui.content.Content;
7 | import org.infernus.idea.checkstyle.toolwindow.CheckStyleToolWindowPanel;
8 | import org.jetbrains.annotations.NotNull;
9 |
10 | import javax.swing.*;
11 | import java.awt.*;
12 | import java.util.function.Consumer;
13 | import java.util.function.Function;
14 |
15 | public final class ToolWindowAccess {
16 | private ToolWindowAccess() {
17 | }
18 |
19 | static void actOnToolWindowPanel(final ToolWindow toolWindow, final Consumer action) {
20 | final Content content = toolWindow.getContentManager().getContent(0);
21 | // the content instance will be a JLabel while the component initialises
22 | if (content != null && content.getComponent() instanceof CheckStyleToolWindowPanel) {
23 | action.accept((CheckStyleToolWindowPanel) content.getComponent());
24 | }
25 | }
26 |
27 | static R getFromToolWindowPanel(final ToolWindow toolWindow, final Function action) {
28 | final Content content = toolWindow.getContentManager().getContent(0);
29 | // the content instance will be a JLabel while the component initialises
30 | if (content != null && content.getComponent() instanceof CheckStyleToolWindowPanel) {
31 | return action.apply((CheckStyleToolWindowPanel) content.getComponent());
32 | }
33 | return null;
34 | }
35 |
36 | static ToolWindow toolWindow(final Project project) {
37 | return ToolWindowManager
38 | .getInstance(project)
39 | .getToolWindow(CheckStyleToolWindowPanel.ID_TOOLWINDOW);
40 | }
41 |
42 | static boolean isFocusInToolWindow(@NotNull final Project project) {
43 | final ToolWindow toolWindow = ToolWindowManager.getInstance(project).getToolWindow(CheckStyleToolWindowPanel.ID_TOOLWINDOW);
44 | if (toolWindow == null || !toolWindow.isVisible()) {
45 | return false;
46 | }
47 | final Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
48 | return focusOwner != null && SwingUtilities.isDescendingFrom(focusOwner, toolWindow.getComponent());
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/config/PluginConfigurationManager.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.config;
2 |
3 | import com.intellij.openapi.project.Project;
4 | import org.jetbrains.annotations.NotNull;
5 |
6 | import java.util.ArrayList;
7 | import java.util.Collections;
8 | import java.util.List;
9 | import java.util.TreeSet;
10 |
11 | public class PluginConfigurationManager {
12 |
13 | private final List configurationListeners = Collections.synchronizedList(new ArrayList<>());
14 |
15 | private final Project project;
16 |
17 | private volatile PluginConfiguration cachedConfiguration;
18 |
19 | public PluginConfigurationManager(@NotNull final Project project) {
20 | this.project = project;
21 | }
22 |
23 | public void addConfigurationListener(final ConfigurationListener configurationListener) {
24 | if (configurationListener != null) {
25 | configurationListeners.add(configurationListener);
26 | }
27 | }
28 |
29 | private void fireConfigurationChanged() {
30 | synchronized (configurationListeners) {
31 | for (ConfigurationListener configurationListener : configurationListeners) {
32 | configurationListener.configurationChanged();
33 | }
34 | }
35 | }
36 |
37 | public synchronized void disableActiveConfiguration() {
38 | setCurrent(PluginConfigurationBuilder.from(getCurrent())
39 | .withActiveLocationIds(new TreeSet<>())
40 | .build(), true);
41 | }
42 |
43 | @NotNull
44 | public synchronized PluginConfiguration getCurrent() {
45 | if (cachedConfiguration != null) {
46 | return cachedConfiguration;
47 | }
48 |
49 | cachedConfiguration = projectConfigurationState()
50 | .populate(PluginConfigurationBuilder.defaultConfiguration(project))
51 | .build();
52 | return cachedConfiguration;
53 | }
54 |
55 | public synchronized void setCurrent(@NotNull final PluginConfiguration updatedConfiguration, final boolean fireEvents) {
56 | cachedConfiguration = null;
57 |
58 | projectConfigurationState().setCurrentConfig(updatedConfiguration);
59 | if (fireEvents) {
60 | fireConfigurationChanged();
61 | }
62 | }
63 |
64 | private ProjectConfigurationState projectConfigurationState() {
65 | return project.getService(ProjectConfigurationState.class);
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/test/java/org/infernus/idea/checkstyle/VersionListReaderTest.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle;
2 |
3 |
4 | import org.infernus.idea.checkstyle.exception.CheckStylePluginException;
5 | import org.junit.Assert;
6 | import org.junit.Test;
7 |
8 |
9 | public class VersionListReaderTest {
10 | @Test
11 | public void testNormalLoading() {
12 | VersionListReader underTest = new VersionListReader();
13 | Assert.assertNotNull(underTest.getSupportedVersions());
14 | Assert.assertTrue(underTest.getSupportedVersions().size() > 1);
15 | Assert.assertNotNull(underTest.getDefaultVersion());
16 | Assert.assertNotNull(underTest.getReplacementMap());
17 | Assert.assertTrue(underTest.getReplacementMap().size() > 1);
18 | }
19 |
20 |
21 | @Test
22 | public void testNonExistingFile() {
23 | try {
24 | new VersionListReader("non-existent.file");
25 | Assert.fail("expected exception was not thrown");
26 | } catch (CheckStylePluginException e) {
27 | // expected
28 | Assert.assertTrue(e.getMessage().startsWith("Internal error: Could not read internal configuration file"));
29 | }
30 | }
31 |
32 |
33 | @Test
34 | public void testSupportedVersionMustNotBeMapped() {
35 | try {
36 | new VersionListReader("checkstyle-idea.broken1.properties");
37 | Assert.fail("expected exception was not thrown");
38 | } catch (CheckStylePluginException e) {
39 | // expected
40 | Assert.assertEquals("Internal error: Property 'checkstyle.versions.map' contains "
41 | + "invalid mapping '7.1 -> 7.2'. Checkstyle version 7.1 is in fact supported "
42 | + "in configuration file 'checkstyle-idea.broken1.properties'", e.getMessage());
43 | }
44 | }
45 |
46 |
47 | @Test
48 | public void testTargetVersionMustExist() {
49 | try {
50 | new VersionListReader("checkstyle-idea.broken2.properties");
51 | Assert.fail("expected exception was not thrown");
52 | } catch (CheckStylePluginException e) {
53 | // expected
54 | Assert.assertEquals("Internal error: Property 'checkstyle.versions.map' contains "
55 | + "invalid mapping '7.0 -> 7.1.1'. Target version 7.1.1 is not a supported "
56 | + "version in configuration file 'checkstyle-idea.broken2.properties'", e.getMessage());
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/importer/modules/LineLengthImporter.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.importer.modules;
2 |
3 | import com.intellij.lang.java.JavaLanguage;
4 | import com.intellij.psi.codeStyle.CodeStyleSettings;
5 | import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
6 | import org.infernus.idea.checkstyle.importer.ModuleImporter;
7 | import org.jetbrains.annotations.NotNull;
8 |
9 | import static com.intellij.psi.codeStyle.CommonCodeStyleSettings.WRAP_AS_NEEDED;
10 |
11 | @SuppressWarnings("unused")
12 | public class LineLengthImporter extends ModuleImporter {
13 |
14 | private static final int DEFAULT_MAX_COLUMNS = 80;
15 | private static final String MAX_PROP = "max";
16 | private int maxColumns = DEFAULT_MAX_COLUMNS;
17 |
18 | @Override
19 | protected void handleAttribute(@NotNull final String attrName, @NotNull final String attrValue) {
20 | if (MAX_PROP.equals(attrName)) {
21 | try {
22 | maxColumns = Integer.parseInt(attrValue);
23 | } catch (NumberFormatException nfe) {
24 | // ignore
25 | }
26 | }
27 | }
28 |
29 | @Override
30 | public void importTo(@NotNull final CodeStyleSettings settings) {
31 | settings.setRightMargin(JavaLanguage.INSTANCE, maxColumns);
32 | CommonCodeStyleSettings commonSettings = settings.getCommonSettings(JavaLanguage.INSTANCE);
33 |
34 | commonSettings.CALL_PARAMETERS_WRAP = WRAP_AS_NEEDED;
35 | commonSettings.METHOD_PARAMETERS_WRAP = WRAP_AS_NEEDED;
36 | commonSettings.RESOURCE_LIST_WRAP = WRAP_AS_NEEDED;
37 | commonSettings.EXTENDS_LIST_WRAP = WRAP_AS_NEEDED;
38 | commonSettings.THROWS_LIST_WRAP = WRAP_AS_NEEDED;
39 | commonSettings.EXTENDS_KEYWORD_WRAP = WRAP_AS_NEEDED;
40 | commonSettings.THROWS_KEYWORD_WRAP = WRAP_AS_NEEDED;
41 | commonSettings.METHOD_CALL_CHAIN_WRAP = WRAP_AS_NEEDED;
42 | commonSettings.BINARY_OPERATION_WRAP = WRAP_AS_NEEDED;
43 | commonSettings.TERNARY_OPERATION_WRAP = WRAP_AS_NEEDED;
44 | commonSettings.FOR_STATEMENT_WRAP = WRAP_AS_NEEDED;
45 | commonSettings.ARRAY_INITIALIZER_WRAP = WRAP_AS_NEEDED;
46 | commonSettings.ASSIGNMENT_WRAP = WRAP_AS_NEEDED;
47 | commonSettings.ASSERT_STATEMENT_WRAP = WRAP_AS_NEEDED;
48 | commonSettings.PARAMETER_ANNOTATION_WRAP = WRAP_AS_NEEDED;
49 | commonSettings.VARIABLE_ANNOTATION_WRAP = WRAP_AS_NEEDED;
50 | commonSettings.ENUM_CONSTANTS_WRAP = WRAP_AS_NEEDED;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/toolwindow/ProblemResultTreeInfo.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.toolwindow;
2 |
3 | import com.intellij.icons.AllIcons;
4 | import com.intellij.psi.PsiFile;
5 | import org.infernus.idea.checkstyle.CheckStyleBundle;
6 | import org.infernus.idea.checkstyle.csapi.SeverityLevel;
7 | import org.jetbrains.annotations.NotNull;
8 |
9 | public class ProblemResultTreeInfo extends ResultTreeNode {
10 |
11 | private final PsiFile file;
12 | private final ResultProblem problem;
13 | private final SeverityLevel severity;
14 |
15 | /**
16 | * Construct a node for a given problem.
17 | *
18 | * @param file the file the problem exists in.
19 | * @param problem the problem.
20 | */
21 | ProblemResultTreeInfo(@NotNull final PsiFile file,
22 | @NotNull final ResultProblem problem) {
23 | super(CheckStyleBundle.message("plugin.results.file-result",
24 | file.getName(),
25 | problem.message(),
26 | problem.line(),
27 | Integer.toString(problem.column()),
28 | problem.sourceCheck(),
29 | problem.locationDescription()));
30 |
31 | this.file = file;
32 | this.problem = problem;
33 |
34 | severity = problem.severityLevel();
35 |
36 | updateIconsForProblem();
37 | }
38 |
39 | private void updateIconsForProblem() {
40 | if (SeverityLevel.Ignore.equals(severity)) {
41 | setIcon(AllIcons.General.Note);
42 | } else if (SeverityLevel.Warning.equals(severity)) {
43 | setIcon(AllIcons.General.Warning);
44 | } else if (SeverityLevel.Info.equals(severity)) {
45 | setIcon(AllIcons.General.Information);
46 | } else {
47 | setIcon(AllIcons.General.Error);
48 | }
49 | }
50 |
51 | /**
52 | * Get the file associated with this node.
53 | *
54 | * @return the file associated with this node.
55 | */
56 | public PsiFile getFile() {
57 | return file;
58 | }
59 |
60 | /**
61 | * Get the problem associated with this node.
62 | *
63 | * @return the problem associated with this node.
64 | */
65 | ResultProblem getProblem() {
66 | return problem;
67 | }
68 |
69 | /**
70 | * Get the severity of the problem.
71 | *
72 | * @return the severity, or null if not applicable.
73 | */
74 | public SeverityLevel getSeverity() {
75 | return severity;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/main/resources/dtd/import_control_1_2.dtd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
13 |
14 |
15 |
18 |
21 |
22 |
25 |
26 |
27 |
33 |
36 |
37 |
59 |
65 |
66 |
69 |
70 |
72 |
73 |
76 |
77 |
79 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/importer/modules/IndentationImporter.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.importer.modules;
2 |
3 | import com.intellij.openapi.diagnostic.Logger;
4 | import com.intellij.psi.codeStyle.CodeStyleSettings;
5 | import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
6 | import org.infernus.idea.checkstyle.importer.ModuleImporter;
7 | import org.jetbrains.annotations.NotNull;
8 |
9 | @SuppressWarnings("unused")
10 | public class IndentationImporter extends ModuleImporter {
11 |
12 | private static final Logger LOG = Logger.getInstance(IndentationImporter.class);
13 |
14 | private static final String BASIC_OFFSET_PROP = "basicOffset";
15 | private static final String CASE_INDENT_PROP = "caseIndent";
16 | private static final String LINE_WRAP_INDENT_PROP = "lineWrappingIndentation";
17 |
18 | private static final int DEFAULT_BASIC_OFFSET = 4;
19 | private static final int DEFAULT_LINE_WRAP_INDENT = 4;
20 | private static final boolean DEFAULT_INDENT_CASE = true;
21 |
22 | private int basicIndent = DEFAULT_BASIC_OFFSET;
23 | private int continuationIndent = DEFAULT_LINE_WRAP_INDENT;
24 | private boolean indentCase = DEFAULT_INDENT_CASE;
25 |
26 | @Override
27 | protected void handleAttribute(@NotNull final String attrName, @NotNull final String attrValue) {
28 | switch (attrName) {
29 | case BASIC_OFFSET_PROP:
30 | basicIndent = getIntOrDefault(attrValue, DEFAULT_BASIC_OFFSET);
31 | break;
32 | case CASE_INDENT_PROP:
33 | int caseIndent = getIntOrDefault(attrValue, 0);
34 | indentCase = caseIndent > 0;
35 | break;
36 | case LINE_WRAP_INDENT_PROP:
37 | continuationIndent = getIntOrDefault(attrValue, DEFAULT_LINE_WRAP_INDENT);
38 | break;
39 |
40 | default:
41 | // uncharted territory - https://checkstyle.org/property_types.html#LeftCurlyOption
42 | LOG.warn("Unexpected indentation policy: " + attrValue);
43 | break;
44 | }
45 | }
46 |
47 | @Override
48 | public void importTo(@NotNull final CodeStyleSettings settings) {
49 | CommonCodeStyleSettings commonSettings = getCommonSettings(settings);
50 | CommonCodeStyleSettings.IndentOptions indentOptions = commonSettings.getIndentOptions();
51 | if (indentOptions != null) {
52 | indentOptions.INDENT_SIZE = basicIndent;
53 | indentOptions.CONTINUATION_INDENT_SIZE = continuationIndent;
54 | }
55 | commonSettings.INDENT_CASE_FROM_SWITCH = indentCase;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/model/InsecureHTTPURLConfigurationLocation.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.model;
2 |
3 | import com.intellij.openapi.project.Project;
4 | import org.jetbrains.annotations.NotNull;
5 |
6 | import javax.net.ssl.HttpsURLConnection;
7 | import javax.net.ssl.SSLContext;
8 | import javax.net.ssl.TrustManager;
9 | import javax.net.ssl.X509TrustManager;
10 | import java.io.IOException;
11 | import java.net.URLConnection;
12 | import java.security.KeyManagementException;
13 | import java.security.NoSuchAlgorithmException;
14 | import java.security.cert.X509Certificate;
15 |
16 | /**
17 | * A configuration location located on a HTTP server for which we wish to ignore any SSL
18 | * errors. Caveat emptor.
19 | */
20 | public class InsecureHTTPURLConfigurationLocation extends HTTPURLConfigurationLocation {
21 |
22 | public InsecureHTTPURLConfigurationLocation(@NotNull final Project project,
23 | @NotNull final String id) {
24 | super(id, ConfigurationType.INSECURE_HTTP_URL, project);
25 | }
26 |
27 | @Override
28 | @NotNull URLConnection connectionTo(final String location) throws IOException {
29 | final URLConnection urlConnection = super.connectionTo(location);
30 |
31 | if (urlConnection instanceof HttpsURLConnection httpsURLConnection) {
32 | try {
33 | final TrustManager[] trustAllCerts = new TrustManager[]{new AllTrustingTrustManager()};
34 | final SSLContext sc = SSLContext.getInstance("TLSv1.3");
35 | sc.init(null, trustAllCerts, new java.security.SecureRandom());
36 | httpsURLConnection.setSSLSocketFactory(sc.getSocketFactory());
37 | } catch (NoSuchAlgorithmException | KeyManagementException e) {
38 | throw new IOException("Failed to set an insecure SSL socket factory", e);
39 | }
40 | }
41 |
42 | return urlConnection;
43 | }
44 |
45 | private static final class AllTrustingTrustManager implements X509TrustManager {
46 | @Override
47 | public X509Certificate[] getAcceptedIssuers() {
48 | return new X509Certificate[] {};
49 | }
50 |
51 | @Override
52 | public void checkClientTrusted(final X509Certificate[] certs, final String authType) {
53 | }
54 |
55 | @Override
56 | public void checkServerTrusted(final X509Certificate[] certs, final String authType) {
57 | }
58 | }
59 |
60 | @Override
61 | public Object clone() {
62 | return cloneCommonPropertiesTo(new InsecureHTTPURLConfigurationLocation(getProject(), getId()));
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/model/NamedScopeHelper.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.model;
2 |
3 | import com.intellij.openapi.application.ReadAction;
4 | import com.intellij.openapi.project.Project;
5 | import com.intellij.packageDependencies.DependencyValidationManager;
6 | import com.intellij.psi.PsiFile;
7 | import com.intellij.psi.search.scope.packageSet.NamedScope;
8 | import com.intellij.psi.search.scope.packageSet.NamedScopeManager;
9 | import com.intellij.psi.search.scope.packageSet.PackageSet;
10 | import org.jetbrains.annotations.NotNull;
11 |
12 | import java.util.Arrays;
13 | import java.util.stream.Stream;
14 |
15 | public final class NamedScopeHelper {
16 |
17 | private NamedScopeHelper() {
18 | }
19 |
20 | public static final String DEFAULT_SCOPE_ID = "All";
21 |
22 | /**
23 | * Returns the scope with the given id.
24 | * If no scope with this ID exists, the Scope with the {@link #DEFAULT_SCOPE_ID} is being returned.
25 | */
26 | @NotNull
27 | public static NamedScope getScopeByIdWithDefaultFallback(@NotNull final Project project,
28 | @NotNull final String id) {
29 | final NamedScope localScopeOrNull = NamedScopeManager.getInstance(project).getScope(id);
30 | if (localScopeOrNull != null) {
31 | return localScopeOrNull;
32 | }
33 | final NamedScope sharedScopeOrNull = DependencyValidationManager.getInstance(project).getScope(id);
34 | if (sharedScopeOrNull != null) {
35 | return sharedScopeOrNull;
36 | }
37 |
38 | return getDefaultScope(project);
39 | }
40 |
41 | public static Stream getAllScopes(@NotNull final Project project) {
42 | return Stream.concat(
43 | Arrays.stream(NamedScopeManager.getInstance(project).getScopes()),
44 | Arrays.stream(DependencyValidationManager.getInstance(project).getScopes()));
45 | }
46 |
47 | public static NamedScope getDefaultScope(@NotNull final Project project) {
48 | return DependencyValidationManager.getInstance(project).getScope(DEFAULT_SCOPE_ID);
49 | }
50 |
51 | public static boolean isFileInScope(final PsiFile psiFile, @NotNull final NamedScope namedScope) {
52 | return ReadAction.compute(() -> {
53 | final PackageSet packageSet = namedScope.getValue();
54 | if (packageSet == null) {
55 | return true;
56 | }
57 |
58 | return packageSet.contains(
59 | psiFile,
60 | DependencyValidationManager.getInstance(psiFile.getProject()));
61 | });
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/util/ModulePaths.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.util;
2 |
3 | import com.intellij.openapi.diagnostic.Logger;
4 | import com.intellij.openapi.module.Module;
5 | import com.intellij.openapi.roots.CompilerModuleExtension;
6 | import com.intellij.openapi.roots.libraries.LibraryUtil;
7 | import com.intellij.openapi.vfs.VirtualFile;
8 | import org.jetbrains.annotations.NotNull;
9 |
10 | import java.io.File;
11 | import java.net.MalformedURLException;
12 | import java.net.URL;
13 | import java.util.ArrayList;
14 | import java.util.List;
15 |
16 | import static java.util.Collections.emptyList;
17 |
18 | public final class ModulePaths {
19 |
20 | private static final Logger LOG = Logger.getInstance(ModulePaths.class);
21 |
22 | private ModulePaths() {
23 | // utility class
24 | }
25 |
26 | public static List libraryPathsFor(final Module moduleInScope) {
27 | return pathsOf(libraryRootsFor(moduleInScope));
28 | }
29 |
30 | private static VirtualFile[] libraryRootsFor(final Module module) {
31 | return LibraryUtil.getLibraryRoots(new Module[]{module}, false, false);
32 | }
33 |
34 | public static List compilerOutputPathsFor(final Module module) {
35 | final CompilerModuleExtension compilerModule = CompilerModuleExtension.getInstance(module);
36 | if (compilerModule != null) {
37 | return pathsOf(compilerModule.getOutputRoots(true));
38 | }
39 | return emptyList();
40 | }
41 |
42 | private static List pathsOf(final VirtualFile[] files) {
43 | final List outputPaths = new ArrayList<>();
44 | for (final VirtualFile file : files) {
45 | try {
46 | outputPaths.add(urlFor(pathOf(file)));
47 | } catch (MalformedURLException e) {
48 | LOG.warn("Malformed virtual file URL: " + file, e);
49 | }
50 | }
51 | return outputPaths;
52 | }
53 |
54 | @NotNull
55 | private static URL urlFor(final String filePath) throws MalformedURLException {
56 | // toURI().toURL() escapes, whereas toURL() doesn't.
57 | return new File(filePath).toURI().toURL();
58 | }
59 |
60 | @NotNull
61 | private static String pathOf(final VirtualFile file) {
62 | return stripJarFileSuffix(file);
63 | }
64 |
65 | @NotNull
66 | private static String stripJarFileSuffix(final VirtualFile file) {
67 | final String filePath = file.getPath();
68 | if (filePath.endsWith("!/")) { // filter JAR suffix
69 | return filePath.substring(0, filePath.length() - 2);
70 | }
71 | return filePath;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/importer/modules/AvoidStarImportImporter.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.importer.modules;
2 |
3 | import com.intellij.openapi.diagnostic.Logger;
4 | import com.intellij.psi.codeStyle.CodeStyleSettings;
5 | import com.intellij.psi.codeStyle.JavaCodeStyleSettings;
6 | import com.intellij.psi.codeStyle.PackageEntry;
7 | import com.intellij.psi.codeStyle.PackageEntryTable;
8 | import org.infernus.idea.checkstyle.importer.ModuleImporter;
9 | import org.jetbrains.annotations.NotNull;
10 |
11 | @SuppressWarnings("unused")
12 | public class AvoidStarImportImporter extends ModuleImporter {
13 | private static final Logger LOG = Logger.getInstance(AvoidStarImportImporter.class);
14 |
15 | private static final String EXCLUDES = "excludes";
16 | private static final String ALLOW_CLASS_STAR_IMPORT = "allowClassImports";
17 | private static final String ALLOW_STATIC_STAR_IMPORT = "allowStaticMemberImports";
18 | private static final int MAXIMUM_INPUTS = 999;
19 |
20 | private boolean allowClassStarImports;
21 | private boolean allowStaticStarImports;
22 | private String[] excludes;
23 |
24 | @Override
25 | protected void handleAttribute(@NotNull final String attrName, @NotNull final String attrValue) {
26 | switch (attrName) {
27 | case EXCLUDES:
28 | excludes = attrValue.split(",");
29 | break;
30 | case ALLOW_CLASS_STAR_IMPORT:
31 | allowClassStarImports = Boolean.parseBoolean(attrValue);
32 | break;
33 | case ALLOW_STATIC_STAR_IMPORT:
34 | allowStaticStarImports = Boolean.parseBoolean(attrValue);
35 | break;
36 | default:
37 | LOG.warn("Unexpected avoid star import policy: " + attrValue);
38 | break;
39 | }
40 |
41 | }
42 |
43 | @Override
44 | public void importTo(@NotNull final CodeStyleSettings settings) {
45 | JavaCodeStyleSettings javaSettings = getJavaSettings(settings);
46 | if (!allowClassStarImports) {
47 | javaSettings.CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND = MAXIMUM_INPUTS;
48 | }
49 |
50 | if (!allowStaticStarImports) {
51 | javaSettings.NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND = MAXIMUM_INPUTS;
52 | }
53 |
54 | PackageEntryTable excludeTable = new PackageEntryTable();
55 | if (excludes != null) {
56 | for (String exclude : excludes) {
57 | excludeTable.addEntry(new PackageEntry(false, exclude, false));
58 | }
59 | }
60 | javaSettings.PACKAGES_TO_USE_IMPORT_ON_DEMAND.copyFrom(excludeTable);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/toolwindow/ToggleableTreeNode.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.toolwindow;
2 |
3 | import org.jetbrains.annotations.NotNull;
4 |
5 | import javax.swing.tree.DefaultMutableTreeNode;
6 | import javax.swing.tree.TreeNode;
7 | import java.io.Serial;
8 | import java.util.Collections;
9 | import java.util.List;
10 | import java.util.stream.Collectors;
11 |
12 | /**
13 | * Tree node with toggleable visibility.
14 | */
15 | public class ToggleableTreeNode extends DefaultMutableTreeNode {
16 | @Serial
17 | private static final long serialVersionUID = -4490734768175672868L;
18 |
19 | private boolean visible = true;
20 |
21 | public ToggleableTreeNode() {
22 | }
23 |
24 | public ToggleableTreeNode(final Object userObject) {
25 | super(userObject);
26 | }
27 |
28 | public boolean isVisible() {
29 | return visible;
30 | }
31 |
32 | public void setVisible(final boolean visible) {
33 | this.visible = visible;
34 | }
35 |
36 | @NotNull
37 | List getAllChildren() {
38 | if (children != null) {
39 | return children.stream()
40 | .map(child -> (ToggleableTreeNode) child)
41 | .collect(Collectors.toList());
42 | }
43 | return Collections.emptyList();
44 | }
45 |
46 | @Override
47 | public void removeAllChildren() {
48 | if (children != null) {
49 | children.clear();
50 | }
51 | }
52 |
53 | @Override
54 | public TreeNode getChildAt(final int index) {
55 | if (children == null) {
56 | throw new ArrayIndexOutOfBoundsException("Invalid index: " + index + " (no children)");
57 | }
58 |
59 | int realIndex = -1;
60 | int visibleIndex = -1;
61 |
62 | for (final Object child : children) {
63 | final ToggleableTreeNode node = (ToggleableTreeNode) child;
64 | if (node.isVisible()) {
65 | ++visibleIndex;
66 | }
67 | ++realIndex;
68 | if (visibleIndex == index) {
69 | return children.get(realIndex);
70 | }
71 | }
72 |
73 | throw new ArrayIndexOutOfBoundsException("Invalid index: " + index);
74 | }
75 |
76 | @Override
77 | public int getChildCount() {
78 | if (children == null) {
79 | return 0;
80 | }
81 |
82 | int count = 0;
83 | for (final Object child : children) {
84 | final ToggleableTreeNode node = (ToggleableTreeNode) child;
85 | if (node.isVisible()) {
86 | ++count;
87 | }
88 | }
89 |
90 | return count;
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/csaccessTest/java/org/infernus/idea/checkstyle/service/CsVersionInfo.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.service;
2 |
3 | import org.hamcrest.Description;
4 | import org.hamcrest.Matcher;
5 | import org.hamcrest.TypeSafeMatcher;
6 | import org.infernus.idea.checkstyle.VersionComparator;
7 | import org.infernus.idea.checkstyle.exception.CheckStylePluginException;
8 | import org.jetbrains.annotations.NotNull;
9 | import org.junit.Assert;
10 |
11 | import java.io.IOException;
12 | import java.io.InputStream;
13 | import java.util.Properties;
14 |
15 | import static org.junit.Assert.assertNotNull;
16 |
17 |
18 | /**
19 | * Utility class for unit tests in 'csaccessTest' to query the currently used Checkstyle runtime.
20 | */
21 | public final class CsVersionInfo {
22 | private static final String PROPS_FILE_NAME = "/checkstyle-idea.properties";
23 | private static final String BASE_VERSION = readBaseVersion();
24 |
25 | public static final String CSVERSION_SYSPROP_NAME = "org.infernus.idea.checkstyle.version";
26 |
27 | private CsVersionInfo() {
28 | }
29 |
30 | @NotNull
31 | private static String readBaseVersion() {
32 | String result;
33 | try (InputStream is = CsVersionInfo.class.getResourceAsStream(PROPS_FILE_NAME)) {
34 | Properties props = new Properties();
35 | props.load(is);
36 | result = props.getProperty("baseVersion");
37 | } catch (IOException e) {
38 | throw new CheckStylePluginException("internal error - Failed to read property file: " + PROPS_FILE_NAME, e);
39 | }
40 | assertNotNull(result);
41 | return result;
42 | }
43 |
44 | @NotNull
45 | public static String currentCsVersion() {
46 | final String sysPropValue = System.getProperty(CSVERSION_SYSPROP_NAME);
47 | if (sysPropValue == null) {
48 | return BASE_VERSION;
49 | } else {
50 | Assert.assertTrue("System property \"" + CSVERSION_SYSPROP_NAME //
51 | + "\" does not contain a valid Checkstyle version: " + sysPropValue, //
52 | VersionComparator.isValidVersion(System.getProperty(CSVERSION_SYSPROP_NAME)));
53 | return sysPropValue;
54 | }
55 | }
56 |
57 | public static Matcher isGreaterThanOrEqualTo(@NotNull final String expectedCsVersion) {
58 | return new TypeSafeMatcher<>() {
59 | @Override
60 | protected boolean matchesSafely(final String actualCsVersion) {
61 | return new VersionComparator().compare(actualCsVersion, expectedCsVersion) >= 0;
62 | }
63 |
64 | @Override
65 | public void describeTo(final Description description) {
66 | description.appendText("is greater than").appendValue(expectedCsVersion);
67 | }
68 | };
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/actions/ScanCurrentChangeList.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.actions;
2 |
3 | import com.intellij.openapi.actionSystem.AnActionEvent;
4 | import com.intellij.openapi.actionSystem.Presentation;
5 | import com.intellij.openapi.diagnostic.Logger;
6 | import com.intellij.openapi.vcs.changes.Change;
7 | import com.intellij.openapi.vcs.changes.ChangeListManager;
8 | import com.intellij.openapi.vcs.changes.LocalChangeList;
9 | import com.intellij.openapi.vfs.VirtualFile;
10 | import org.jetbrains.annotations.NotNull;
11 |
12 | import java.util.*;
13 |
14 | import static org.infernus.idea.checkstyle.actions.ToolWindowAccess.toolWindow;
15 |
16 | /**
17 | * Scan files in the current change-list.
18 | */
19 | public class ScanCurrentChangeList extends BaseAction {
20 |
21 | private static final Logger LOG = Logger.getInstance(ScanCurrentChangeList.class);
22 |
23 | @Override
24 | public final void actionPerformed(final @NotNull AnActionEvent event) {
25 | project(event).ifPresent(project -> {
26 | try {
27 | final ChangeListManager changeListManager = ChangeListManager.getInstance(project);
28 | staticScanner(project).asyncScanFiles(filesFor(changeListManager.getDefaultChangeList()), getSelectedOverride(toolWindow(project)));
29 | } catch (Throwable e) {
30 | LOG.warn("Modified files scan failed", e);
31 | }
32 | });
33 | }
34 |
35 | private List filesFor(final LocalChangeList changeList) {
36 | if (changeList == null || changeList.getChanges() == null) {
37 | return Collections.emptyList();
38 | }
39 |
40 | final Collection filesInChanges = new HashSet<>();
41 | for (Change change : changeList.getChanges()) {
42 | if (change.getVirtualFile() != null) {
43 | filesInChanges.add(change.getVirtualFile());
44 | }
45 | }
46 |
47 | return new ArrayList<>(filesInChanges);
48 | }
49 |
50 | @Override
51 | public void update(final @NotNull AnActionEvent event) {
52 | final Presentation presentation = event.getPresentation();
53 |
54 | project(event).ifPresentOrElse(project -> {
55 | try {
56 | final LocalChangeList changeList = ChangeListManager.getInstance(project).getDefaultChangeList();
57 | if (changeList.getChanges() == null || changeList.getChanges().isEmpty()) {
58 | presentation.setEnabled(false);
59 | } else {
60 | presentation.setEnabled(!staticScanner(project).isScanInProgress());
61 | }
62 |
63 | } catch (Throwable e) {
64 | LOG.warn("Button update failed.", e);
65 | }
66 | }, () -> presentation.setEnabled(false));
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/main/java/org/infernus/idea/checkstyle/model/ClasspathConfigurationLocation.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.model;
2 |
3 | import com.intellij.openapi.diagnostic.Logger;
4 | import com.intellij.openapi.project.Project;
5 | import org.infernus.idea.checkstyle.CheckstyleProjectService;
6 | import org.jetbrains.annotations.NotNull;
7 |
8 | import java.io.ByteArrayInputStream;
9 | import java.io.FileNotFoundException;
10 | import java.io.IOException;
11 | import java.io.InputStream;
12 |
13 | import static org.infernus.idea.checkstyle.util.Streams.readContentOf;
14 |
15 | public class ClasspathConfigurationLocation extends ConfigurationLocation {
16 |
17 | private static final Logger LOG = Logger.getInstance(ClasspathConfigurationLocation.class);
18 |
19 | private static final int CONTENT_CACHE_SECONDS = 2;
20 | private static final int ONE_SECOND = 1000;
21 |
22 | private byte[] cachedContent;
23 | private long cacheExpiry;
24 |
25 | ClasspathConfigurationLocation(@NotNull final Project project,
26 | @NotNull final String id) {
27 | super(id, ConfigurationType.PLUGIN_CLASSPATH, project);
28 | }
29 |
30 | @NotNull
31 | protected InputStream resolveFile(@NotNull final ClassLoader checkstyleClassLoader) throws IOException {
32 | if (cachedContent != null && cacheExpiry > System.currentTimeMillis()) {
33 | return new ByteArrayInputStream(cachedContent);
34 | }
35 |
36 | try {
37 | cachedContent = readContentOf(streamOf(getLocation()));
38 | cacheExpiry = System.currentTimeMillis() + (CONTENT_CACHE_SECONDS * ONE_SECOND);
39 | return new ByteArrayInputStream(cachedContent);
40 |
41 | } catch (IOException e) {
42 | LOG.info("Couldn't read file from classpath: " + getLocation(), e);
43 | cachedContent = null;
44 | cacheExpiry = 0;
45 | throw e;
46 | }
47 | }
48 |
49 | private InputStream streamOf(final String classpathLocation) throws IOException {
50 | InputStream resourceStream = checkstyleClassLoader().getResourceAsStream(classpathLocation);
51 | if (resourceStream == null) {
52 | throw new FileNotFoundException("Couldn't read classpath resource: " + classpathLocation);
53 | }
54 | return resourceStream;
55 | }
56 |
57 | private ClassLoader checkstyleClassLoader() {
58 | return checkstyleProjectService(getProject()).underlyingClassLoader();
59 | }
60 |
61 | private CheckstyleProjectService checkstyleProjectService(@NotNull final Project project) {
62 | // we can't bring this in at construction time due to a cyclic dep
63 | return project.getService(CheckstyleProjectService.class);
64 | }
65 |
66 | @Override
67 | public Object clone() {
68 | return cloneCommonPropertiesTo(new ClasspathConfigurationLocation(getProject(), getId()));
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/test/java/org/infernus/idea/checkstyle/csapi/ProcessResultsThreadTest.java:
--------------------------------------------------------------------------------
1 | package org.infernus.idea.checkstyle.csapi;
2 |
3 | import com.intellij.psi.PsiElement;
4 | import com.intellij.psi.PsiFile;
5 | import org.infernus.idea.checkstyle.checker.Problem;
6 | import org.junit.Test;
7 |
8 | import java.util.*;
9 |
10 | import static java.util.Collections.singletonList;
11 | import static org.hamcrest.Matchers.hasEntry;
12 | import static org.hamcrest.MatcherAssert.assertThat;
13 | import static org.mockito.Mockito.mock;
14 | import static org.mockito.Mockito.when;
15 |
16 | public class ProcessResultsThreadTest {
17 |
18 | @Test
19 | public void fileWithMatchingPathIsLinked() {
20 | PsiFile expectedFile = aPsiFile();
21 | Map fileNamesToPsiFiles = new HashMap<>();
22 | fileNamesToPsiFiles.put("aFileName", expectedFile);
23 | fileNamesToPsiFiles.put("anotherFileName", mock(PsiFile.class));
24 |
25 | ProcessResultsThread underTest = underTest(fileNamesToPsiFiles, singletonList(anIssueFor("aFileName")));
26 | underTest.run();
27 |
28 | assertThat(underTest.getProblems(),
29 | hasEntry(expectedFile, singletonList(aProblemFor(expectedFile))));
30 | }
31 |
32 | @Test
33 | public void fileWithMatchingButDenormalisedPathIsLinked() {
34 | PsiFile expectedFile = aPsiFile();
35 |
36 | Map fileNamesToPsiFiles = new HashMap<>();
37 | fileNamesToPsiFiles.put("aFileName", expectedFile);
38 | fileNamesToPsiFiles.put("anotherFileName", mock(PsiFile.class));
39 |
40 | List events = singletonList(anIssueFor("foo/bar/../../aFileName"));
41 |
42 | ProcessResultsThread underTest = underTest(fileNamesToPsiFiles, events);
43 |
44 | underTest.run();
45 |
46 | assertThat(underTest.getProblems(),
47 | hasEntry(expectedFile, singletonList(aProblemFor(expectedFile))));
48 | }
49 |
50 | private ProcessResultsThread underTest(final Map fileNamesToPsiFiles, final List events) {
51 | return new ProcessResultsThread(
52 | false, Collections.emptyList(), 4, Optional.empty(), events, fileNamesToPsiFiles);
53 | }
54 |
55 | private PsiFile aPsiFile() {
56 | PsiFile expectedFile = mock(PsiFile.class);
57 | when(expectedFile.textToCharArray()).thenReturn("import boo.*;".toCharArray());
58 | when(expectedFile.findElementAt(6)).thenReturn(mock(PsiElement.class));
59 | return expectedFile;
60 | }
61 |
62 | private Issue anIssueFor(final String aFileName) {
63 | return new Issue(aFileName, 1, 7, "aMessage", SeverityLevel.Error, "com.checkstyle.rules.aCheck");
64 | }
65 |
66 | private Problem aProblemFor(final PsiFile expectedFile) {
67 | return new Problem(expectedFile, "aMessage", SeverityLevel.Error, 1, 7, "com.checkstyle.rules.aCheck", false, false);
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------