Merge ktlint 0.12.1
Test: None
diff --git a/.gitignore b/.gitignore
index 253761e..6e3b916 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
target
.gradle
build
+!ktlint/src/main/resources/config/.idea
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 812d3ed..41af543 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,26 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
+## [0.12.1] - 2017-11-13
+
+### Fixed
+- A conflict between `org.eclipse.aether:aether-*:1.1.0` and `org.eclipse.aether:aether-*:1.0.0.v20140518` ([#100](https://github.com/shyiko/ktlint/issues/100)).
+
+## [0.12.0] - 2017-11-10
+
+### Added
+- `--android` (`-a`) CLI option (turns on [Android Kotlin Style Guide](https://android.github.io/kotlin-guides/style.html) compatibility)
+(right now it's used only by `ktlint --apply-to-idea`).
+
+### Changed
+- `ktlint --apply-to-idea` to account for `indent_size` & `continuation_indent_size` in `.editorconfig` (if any).
+
+### Removed
+- `ktlint-intellij-idea-integration` binary (deprecated in [0.9.0](#090---2017-07-23)).
+
+### Fixed
+- "Unused import" false positive (`component1`..`component5`).
+
## [0.11.1] - 2017-10-26
### Fixed
@@ -223,6 +243,8 @@
## 0.1.0 - 2016-07-27
+[0.12.1]: https://github.com/shyiko/ktlint/compare/0.12.0...0.12.1
+[0.12.0]: https://github.com/shyiko/ktlint/compare/0.11.1...0.12.0
[0.11.1]: https://github.com/shyiko/ktlint/compare/0.11.0...0.11.1
[0.11.0]: https://github.com/shyiko/ktlint/compare/0.10.1...0.11.0
[0.10.2]: https://github.com/shyiko/ktlint/compare/0.10.1...0.10.2
diff --git a/README.md b/README.md
index 1bd0413..b8bd23c 100644
--- a/README.md
+++ b/README.md
@@ -16,23 +16,21 @@
Features:
- **No configuration.** Which means no decisions to make, nothing to argue about and no special files to manage.
-While this might sound extreme, keep in mind that `ktlint` tries to capture (reflect) **official code style** from [kotlinlang.org](https://kotlinlang.org/docs/reference/)
-(+ we respect you [.editorconfig](http://editorconfig.org/)\* and support additional [ruleset](#creating-a-ruleset)|s).
+While this might sound extreme, keep in mind that `ktlint` tries to capture (reflect) **official code style** from [kotlinlang.org](https://kotlinlang.org/docs/reference/coding-conventions.html) and [Android Kotlin Style Guide](https://android.github.io/kotlin-guides/style.html)
+(+ [we respect you .editorconfig](#editorconfig) and support additional [ruleset](#creating-a-ruleset)|s).
- **Built-in formatter.** So that you wouldn't have to fix all style violations by hand.
- **Customizable output.** `plain` (+ `plain?group_by_file`), `json` and `checkstyle` reporters are available out-of-the-box.
It's also [easy to create your own](#creating-a-reporter).
- **A single executable jar with all dependencies included.**
-> \* as of [0.9.0](https://github.com/shyiko/ktlint/releases/tag/0.9.0) ktlint recognizes `insert_final_newline`, `max_line_length` and `indent_size`
-(provided they are specified under `[*.{kt,kts}]`).
-
<p align="center">
<a href="#installation">Installation</a> | <a href="#usage">Usage</a> | <a href="#integration">Integration</a> with <a href="#-with-maven">Maven</a> / <a href="#-with-gradle">Gradle</a> / <a href="#-with-intellij-idea">IntelliJ IDEA</a> / <a href="#-with-emacs">Emacs</a> | Creating <a href="#creating-a-ruleset">a ruleset</a> | <a href="#creating-a-reporter">a reporter</a> | <a href="#badge">Badge</a> | <a href="#faq">FAQ</a>
</p>
## Standard rules
-- 4 spaces for indentation*;
+- 4 spaces for indentation
+(unless a different `indent_size` value is set in .editorconfig (see [EditorConfig](#editorconfig) section for more));
- No semicolons (unless used to separate multiple statements on the same line);
- No wildcard / unused `import`s;
- No consecutive blank lines;
@@ -42,21 +40,38 @@
- No empty (`{}`) class bodies;
- Consistent string templates (`$v` instead of `${v}`, `${p.v}` instead of `${p.v.toString()}`);
- Consistent order of modifiers;
-- Consistent spacing after keywords, commas; around colons, curly braces, infix operators, etc.
+- Consistent spacing after keywords, commas; around colons, curly braces, infix operators, etc;
+- Newline at the end of each file
+(unless `insert_final_newline` is set to false in .editorconfig (see [EditorConfig](#editorconfig) section for more)).
-> \* Starting from [0.8.0](https://github.com/shyiko/ktlint/releases/tag/0.8.0) value of `indent_size` specified under `[*{kt,kts}]` section in [.editorconfig](http://editorconfig.org/) takes precedence (if any). Official recommendation is to use 4 spaces, though. (see [#43](https://github.com/shyiko/ktlint/issues/43#issuecomment-304953280) for details)
+## EditorConfig
-> [More coming](https://github.com/shyiko/ktlint/labels/rule).
+ktlint recognizes the following [.editorconfig](http://editorconfig.org/) properties (provided they are specified under `[*.{kt,kts}]`):
+(values shown below are the defaults and do not need to be specified explicitly)
+```ini
+[*.{kt,kts}]
+# possible values: number (e.g. 2), "unset" (makes ktlint ignore indentation completely)
+indent_size=4
+continuation_indent_size=8
+insert_final_newline=true
+# possible values: number (e.g. 120) (package name, imports & comments are ignored), "off"
+max_line_length=off
+```
## Installation
> Skip all the way to the "Integration" section if you don't plan to use `ktlint`'s command line interface.
```sh
-curl -sSLO https://github.com/shyiko/ktlint/releases/download/0.11.1/ktlint &&
- chmod a+x ktlint
+curl -sSLO https://github.com/shyiko/ktlint/releases/download/0.12.1/ktlint &&
+ chmod a+x ktlint &&
+ sudo mv ktlint /usr/local/bin/
```
+... or just download `ktlint` from the [releases](https://github.com/shyiko/ktlint/releases) page (`ktlint.asc` contains PGP signature which you can verify with `curl -sS https://keybase.io/shyiko/pgp_keys.asc | gpg --import && gpg --verify ktlint.asc`).
+
+On macOS ([or Linux](http://linuxbrew.sh/)) you can also use [brew](http://brew.sh/) - `brew install shyiko/ktlint/ktlint`.
+
> If you don't have curl installed - replace `curl -sL` with `wget -qO-`.
> If you are behind a proxy see -
@@ -64,10 +79,6 @@
[wget](https://www.gnu.org/software/wget/manual/wget.html#Proxies) manpage.
Usually simple `http_proxy=http://proxy-server:port https_proxy=http://proxy-server:port curl -sL ...` is enough.
-... or just download `ktlint` from the ["release(s)"](https://github.com/shyiko/ktlint/releases) page (`ktlint.asc` contains PGP signature which you can verify with `curl -sS https://keybase.io/shyiko/pgp_keys.asc | gpg --import && gpg --verify ktlint.asc`).
-
-> On Mac OS X ([or Linux](http://linuxbrew.sh/)) one can also use [brew](http://brew.sh/) - `brew install shyiko/ktlint/ktlint`.
-
## Usage
```bash
@@ -146,7 +157,7 @@
<dependency>
<groupId>com.github.shyiko</groupId>
<artifactId>ktlint</artifactId>
- <version>0.11.1</version>
+ <version>0.12.1</version>
</dependency>
<!-- additional 3rd party ruleset(s) can be specified here -->
</dependencies>
@@ -173,7 +184,7 @@
}
dependencies {
- ktlint "com.github.shyiko:ktlint:0.11.1"
+ ktlint "com.github.shyiko:ktlint:0.12.1"
// additional 3rd party ruleset(s) can be specified here
// just add them to the classpath (ktlint 'groupId:artifactId:version') and
// ktlint will pick them up
@@ -218,9 +229,12 @@
##### Option #1 (recommended)
+> (inside project's root directory)
+
```sh
-# inside project's root directory
-ktlint --apply-to-idea
+ktlint --apply-to-idea
+# or if you want to be compliant with Android Kotlin Style Guide
+ktlint --apply-to-idea --android
```
##### Option #2
@@ -232,7 +246,8 @@
- open `Imports` tab, select all `Use single name import` options and remove `import java.util.*` from `Packages to Use Import with '*'`.
- open `Blank Lines` tab, change `Keep Maximum Blank Lines` -> `In declarations` & `In code` to 1 and `Before '}'` to 0.
- (optional but recommended) open `Wrapping and Braces` tab, uncheck `Method declaration parameters -> Align when multiline`.
- - (optional but recommended) open `Tabs and Indents` tab, change `Continuation indent` to 4.
+ - (optional but recommended) open `Tabs and Indents` tab, change `Continuation indent` to 4 (to be compliant with
+ [Android Kotlin Style Guide](https://android.github.io/kotlin-guides/style.html) value should stay equal 8).
- `Inspections`
- change `Severity` level of `Unused import directive`, `Redundant semicolon` and (optional but recommended) `Unused symbol` to `ERROR`.
@@ -278,8 +293,6 @@
## Badge
-If you use ktlint in your project, consider including a badge in your readme to let people know that your code is checked by ktlint.
-
[![ktlint](https://img.shields.io/badge/code%20style-%E2%9D%A4-FF4081.svg)](https://ktlint.github.io/)
```md
diff --git a/ktlint-core/src/main/kotlin/com/github/shyiko/ktlint/core/KtLint.kt b/ktlint-core/src/main/kotlin/com/github/shyiko/ktlint/core/KtLint.kt
index 84285c3..13c7ea4 100644
--- a/ktlint-core/src/main/kotlin/com/github/shyiko/ktlint/core/KtLint.kt
+++ b/ktlint-core/src/main/kotlin/com/github/shyiko/ktlint/core/KtLint.kt
@@ -32,6 +32,7 @@
object KtLint {
val EDITOR_CONFIG_USER_DATA_KEY = Key<EditorConfig>("EDITOR_CONFIG")
+ val ANDROID_USER_DATA_KEY = Key<Boolean>("ANDROID")
private val psiFileFactory: PsiFileFactory
private val nullSuppression = { _: Int, _: String -> false }
@@ -128,7 +129,8 @@
throw ParseException(line, col, errorElement.errorDescription)
}
val rootNode = psiFile.node
- rootNode.putUserData(EDITOR_CONFIG_USER_DATA_KEY, EditorConfig.fromMap(userData))
+ rootNode.putUserData(EDITOR_CONFIG_USER_DATA_KEY, EditorConfig.fromMap(userData - "android"))
+ rootNode.putUserData(ANDROID_USER_DATA_KEY, userData["android"]?.toBoolean() ?: false)
val isSuppressed = calculateSuppressedRegions(rootNode)
val r = flatten(ruleSets)
rootNode.visit { node ->
@@ -236,7 +238,8 @@
throw ParseException(line, col, errorElement.errorDescription)
}
val rootNode = psiFile.node
- rootNode.putUserData(EDITOR_CONFIG_USER_DATA_KEY, EditorConfig.fromMap(userData))
+ rootNode.putUserData(EDITOR_CONFIG_USER_DATA_KEY, EditorConfig.fromMap(userData - "android"))
+ rootNode.putUserData(ANDROID_USER_DATA_KEY, userData["android"]?.toBoolean() ?: false)
var isSuppressed = calculateSuppressedRegions(rootNode)
val r = flatten(ruleSets)
var autoCorrect = false
diff --git a/ktlint-intellij-idea-integration/pom.xml b/ktlint-intellij-idea-integration/pom.xml
deleted file mode 100644
index ef18886..0000000
--- a/ktlint-intellij-idea-integration/pom.xml
+++ /dev/null
@@ -1,206 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
-
- <parent>
- <groupId>com.github.shyiko.ktlint</groupId>
- <artifactId>pom</artifactId>
- <version>0.0.0-SNAPSHOT</version>
- </parent>
-
- <artifactId>ktlint-intellij-idea-integration</artifactId>
-
- <scm>
- <connection>scm:git:git@github.com:shyiko/ktlint.git</connection>
- <developerConnection>scm:git:git@github.com:shyiko/ktlint.git</developerConnection>
- <url>git@github.com:shyiko/ktlint.git</url>
- </scm>
-
- <dependencies>
- <dependency>
- <groupId>com.github.shyiko.klob</groupId>
- <artifactId>klob</artifactId>
- <version>0.2.0</version>
- <classifier>kalvanized</classifier>
- </dependency>
- </dependencies>
-
- <profiles>
- <profile>
- <id>release</id>
- <activation>
- <property>
- <name>deploy</name>
- <value>maven-central</value>
- </property>
- </activation>
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-source-plugin</artifactId>
- <version>3.0.1</version>
- <executions>
- <execution>
- <id>attach-sources</id>
- <phase>verify</phase>
- <goals>
- <goal>jar-no-fork</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-jar-plugin</artifactId>
- <version>3.0.2</version>
- <executions>
- <execution>
- <id>attach-javadocs</id>
- <phase>verify</phase>
- <goals>
- <goal>jar</goal>
- </goals>
- <configuration>
- <classifier>javadoc</classifier>
- <classesDirectory>${basedir}/javadoc</classesDirectory>
- </configuration>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
- </profile>
- <profile>
- <id>capsule</id>
- <activation>
- <property>
- <name>deploy</name>
- <value>github</value>
- </property>
- </activation>
- <build>
- <defaultGoal>clean deploy</defaultGoal>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-shade-plugin</artifactId>
- <version>3.0.0</version>
- <executions>
- <execution>
- <phase>package</phase>
- <goals>
- <goal>shade</goal>
- </goals>
- <configuration>
- <transformers>
- <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
- <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
- <mainClass>com.github.shyiko.ktlint.idea.Main</mainClass>
- </transformer>
- </transformers>
- <createDependencyReducedPom>false</createDependencyReducedPom>
- <filters>
- <filter>
- <artifact>*:*</artifact>
- <excludes>
- <exclude>META-INF/*.SF</exclude>
- <exclude>META-INF/*.DSA</exclude>
- <exclude>META-INF/*.RSA</exclude>
- </excludes>
- </filter>
- </filters>
- </configuration>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.skife.maven</groupId>
- <artifactId>really-executable-jar-maven-plugin</artifactId>
- <version>1.4.1</version>
- <configuration>
- <!--
- -XX:+TieredCompilation can be used to speed things up but it was reported to cause
- OOMs and all sort of problems depending on which version of jre6 is used
- -->
- <flags>-Xmx512m</flags>
- <programFile>ktlint-intellij-idea-integration</programFile>
- </configuration>
- <executions>
- <execution>
- <phase>package</phase>
- <goals>
- <goal>really-executable-jar</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
- </profile>
- <profile>
- <id>deploy-to-github</id>
- <activation>
- <property>
- <name>deploy</name>
- <value>github</value>
- </property>
- </activation>
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-antrun-plugin</artifactId>
- <version>1.7</version>
- <executions>
- <execution>
- <id>ktlint</id>
- <phase>verify</phase>
- <configuration>
- <target name="gpg-sign">
- <exec executable="gpg" dir="${basedir}" failonerror="true">
- <arg value="-ab"/>
- <arg value="${project.build.directory}/${project.artifactId}"/>
- </exec>
- </target>
- </configuration>
- <goals>
- <goal>run</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>de.jutzig</groupId>
- <artifactId>github-release-plugin</artifactId>
- <version>1.1.1</version>
- <configuration>
- <description>${project.version}</description>
- <releaseName>${project.version}</releaseName>
- <tag>${project.version}</tag>
- <artifact>${project.build.directory}/${project.artifactId}</artifact>
- <fileSets>
- <fileSet>
- <directory>${project.build.directory}</directory>
- <includes>
- <include>${project.artifactId}.asc</include>
- </includes>
- </fileSet>
- </fileSets>
- </configuration>
- <executions>
- <execution>
- <phase>deploy</phase>
- <goals>
- <goal>release</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
- </profile>
- </profiles>
-
-</project>
diff --git a/ktlint-intellij-idea-integration/src/main/java/com/github/shyiko/ktlint/idea/KtLintIntellijIDEAIntegration.java b/ktlint-intellij-idea-integration/src/main/java/com/github/shyiko/ktlint/idea/KtLintIntellijIDEAIntegration.java
deleted file mode 100644
index 0363a2d..0000000
--- a/ktlint-intellij-idea-integration/src/main/java/com/github/shyiko/ktlint/idea/KtLintIntellijIDEAIntegration.java
+++ /dev/null
@@ -1,142 +0,0 @@
-package com.github.shyiko.ktlint.idea;
-
-import com.github.shyiko.klob.Glob;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-import javax.xml.xpath.XPath;
-import javax.xml.xpath.XPathConstants;
-import javax.xml.xpath.XPathFactory;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.nio.file.Files;
-import java.nio.file.NoSuchFileException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Scanner;
-import java.util.function.BiConsumer;
-import java.util.function.Function;
-import java.util.function.Supplier;
-import java.util.stream.Stream;
-import java.util.stream.StreamSupport;
-
-public class KtLintIntellijIDEAIntegration {
-
- public static Path[] apply(final Path baseDir, final boolean dryRun) throws IOException {
- if (!Files.isDirectory(baseDir.resolve(".idea"))) {
- throw new ProjectNotFoundException();
- }
- final List<Path> result = new ArrayList<>();
- final BiConsumer<Path, Supplier<byte[]>> update = (path, contentSupplier) -> {
- result.add(path);
- if (!dryRun) {
- try {
- Files.createDirectories(path.getParent());
- Files.write(path, contentSupplier.get());
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
- };
- final Function<String, Supplier<byte[]>> overwriteWithResource = (resource) -> () -> {
- try {
- return getResourceText(resource).getBytes("UTF-8");
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- };
- final String home = System.getProperty("user.home");
- final Stream<String> paths = Stream.concat(
- // macOS
- StreamSupport.stream(((Iterable<Path>)() ->
- Glob.from("IntelliJIdea*", "IdeaIC*", "AndroidStudio*")
- .iterate(Paths.get(home, "Library", "Preferences"),
- Glob.IterationOption.SKIP_CHILDREN, Glob.IterationOption.DIRECTORY)
- ).spliterator(), false),
- // linux/windows
- StreamSupport.stream(((Iterable<Path>)() ->
- Glob.from(".IntelliJIdea*/config", ".IdeaIC*/config", ".AndroidStudio*/config")
- .iterate(Paths.get(home),
- Glob.IterationOption.SKIP_CHILDREN, Glob.IterationOption.DIRECTORY)
- ).spliterator(), false)
- ).map(Path::toString);
- for (final String dir : (Iterable<String>) paths::iterator) {
- update.accept(Paths.get(dir, "codestyles", "ktlint.xml"),
- overwriteWithResource.apply("/config/codestyles/ktlint.xml"));
- update.accept(Paths.get(dir, "inspection", "ktlint.xml"),
- overwriteWithResource.apply("/config/inspection/ktlint.xml"));
- update.accept(Paths.get(dir, "options", "code.style.schemes.xml"),
- overwriteWithResource.apply("/config/options/code.style.schemes.xml"));
- update.accept(Paths.get(dir, "options", "editor.codeinsight.xml"),
- () -> {
- byte[] in = "<application></application>".getBytes();
- try {
- in = Files.readAllBytes(Paths.get(dir, "options", "editor.codeinsight.xml"));
- } catch (IOException e) {
- if (!(e instanceof NoSuchFileException)) {
- throw new UncheckedIOException(e);
- }
- }
- try {
- return enableOptimizeImportsOnTheFly(in);
- } catch (Exception e) {
- throw new UncheckedIOException(new IOException(e));
- }
- });
- }
- update.accept(Paths.get(baseDir.toString(), ".idea", "inspectionProfiles", "profiles_settings.xml"),
- overwriteWithResource.apply("/config/.idea/inspectionProfiles/profiles_settings.xml"));
- return result.toArray(new Path[0]);
- }
-
- private static byte[] enableOptimizeImportsOnTheFly(final byte[] in) throws Exception {
- /*
- <application>
- <component name="CodeInsightSettings">
- <option name="OPTIMIZE_IMPORTS_ON_THE_FLY" value="true" />
- ...
- </component>
- ...
- </application>
- */
- Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new ByteArrayInputStream(in));
- XPath xpath = XPathFactory.newInstance().newXPath();
- Element cis = (Element) xpath.evaluate("//component[@name='CodeInsightSettings']",
- doc, XPathConstants.NODE);
- if (cis == null) {
- cis = doc.createElement("component");
- cis.setAttribute("name", "CodeInsightSettings");
- cis = (Element) doc.getDocumentElement().appendChild(cis);
- }
- Element oiotf = (Element) xpath.evaluate("//option[@name='OPTIMIZE_IMPORTS_ON_THE_FLY']",
- cis, XPathConstants.NODE);
- if (oiotf == null) {
- oiotf = doc.createElement("option");
- oiotf.setAttribute("name", "OPTIMIZE_IMPORTS_ON_THE_FLY");
- oiotf = (Element) cis.appendChild(oiotf);
- }
- oiotf.setAttribute("value", "true");
- Transformer transformer = TransformerFactory.newInstance().newTransformer();
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
- transformer.transform(new DOMSource(doc), new StreamResult(out));
- return out.toByteArray();
- }
-
- private static String getResourceText(final String name) {
- // https://community.oracle.com/blogs/pat/2004/10/23/stupid-scanner-tricks
- return new Scanner(Main.class.getResourceAsStream(name), "UTF-8").useDelimiter("\\A").next();
- }
-
- static class ProjectNotFoundException extends RuntimeException {}
-}
diff --git a/ktlint-intellij-idea-integration/src/main/java/com/github/shyiko/ktlint/idea/Main.java b/ktlint-intellij-idea-integration/src/main/java/com/github/shyiko/ktlint/idea/Main.java
deleted file mode 100644
index d5107ee..0000000
--- a/ktlint-intellij-idea-integration/src/main/java/com/github/shyiko/ktlint/idea/Main.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package com.github.shyiko.ktlint.idea;
-
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.Arrays;
-import java.util.NoSuchElementException;
-import java.util.Scanner;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-public class Main {
-
- private Main() {}
-
- public static void main(String[] args) throws Exception {
- Arrays.sort(args);
- final boolean help = Arrays.binarySearch(args, "--help") > -1;
- final boolean version = Arrays.binarySearch(args, "--version") > -1;
- final boolean apply = Arrays.binarySearch(args, "apply") > -1 && !help;
- final boolean forceApply = Arrays.binarySearch(args, "-y") > -1;
- if (version) {
- System.err.println(Main.class.getPackage().getImplementationVersion());
- System.exit(0);
- }
- if (apply) {
- try {
- final Path workDir = Paths.get(".");
- if (!forceApply) {
- final Path[] fileList = KtLintIntellijIDEAIntegration.apply(workDir, true);
- System.err.println("The following files are going to be updated:\n\n\t" +
- Arrays.stream(fileList).map(Path::toString).collect(Collectors.joining("\n\t")) +
- "\n\nDo you wish to proceed? [y/n]\n" +
- "(in future, use -y flag if you wish to skip confirmation)");
- final Scanner scanner = new Scanner(System.in);
- final String res = Stream.generate(() -> {
- try { return scanner.next(); } catch (NoSuchElementException e) { return "n"; }
- })
- .filter(line -> !line.trim().isEmpty())
- .findFirst()
- .get();
- if (!"y".equalsIgnoreCase(res)) {
- System.err.println("(update canceled)");
- System.exit(1);
- }
- }
- KtLintIntellijIDEAIntegration.apply(workDir, false);
- } catch (KtLintIntellijIDEAIntegration.ProjectNotFoundException e) {
- System.err.println(".idea directory not found. " +
- "Are you sure you are inside project root directory?");
- System.exit(1);
- }
- System.err.println("(updated)");
- System.err.println("\nPlease restart your IDE");
- System.err.println("(if you experience any issues please report them at https://github.com/shyiko/ktlint)");
- } else {
- System.err.println(
- "ktlint Intellij IDEA integration (https://github.com/shyiko/ktlint).\n" +
- "\n" +
- "Usage:\n" +
- " ktlint-intellij-idea-integration <flags> apply\n" +
- " java -jar ktlint-intellij-idea-integration <flags> apply\n" +
- "\n" +
- "Flags:\n" +
- " --version : Version\n"
- );
- if (!help) {
- System.exit(1);
- }
- }
- }
-}
diff --git a/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoUnusedImportsRule.kt b/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoUnusedImportsRule.kt
index 6916618..cbb8287 100644
--- a/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoUnusedImportsRule.kt
+++ b/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoUnusedImportsRule.kt
@@ -34,7 +34,9 @@
// iteration (https://github.com/shyiko/ktlint/issues/40)
"iterator",
// by (https://github.com/shyiko/ktlint/issues/54)
- "getValue", "setValue"
+ "getValue", "setValue",
+ // destructuring assignment
+ "component1", "component2", "component3", "component4", "component5"
)
private val ref = mutableSetOf("*")
private var packageName = ""
diff --git a/ktlint/pom.xml b/ktlint/pom.xml
index 4fbd083..a0f9509 100644
--- a/ktlint/pom.xml
+++ b/ktlint/pom.xml
@@ -52,17 +52,6 @@
<version>0.0.0-SNAPSHOT</version>
</dependency>
<dependency>
- <groupId>com.github.shyiko.ktlint</groupId>
- <artifactId>ktlint-intellij-idea-integration</artifactId>
- <version>0.0.0-SNAPSHOT</version>
- <exclusions>
- <exclusion>
- <groupId>com.github.shyiko.klob</groupId>
- <artifactId>klob</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
<groupId>com.github.shyiko.klob</groupId>
<artifactId>klob</artifactId>
<version>0.2.0</version>
@@ -76,6 +65,24 @@
<groupId>org.apache.maven</groupId>
<artifactId>maven-aether-provider</artifactId>
<version>${aether.maven.provider.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.eclipse.aether</groupId>
+ <artifactId>aether-api</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.eclipse.aether</groupId>
+ <artifactId>aether-spi</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.eclipse.aether</groupId>
+ <artifactId>aether-util</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.eclipse.aether</groupId>
+ <artifactId>aether-impl</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
<!-- maven-aether-provider's transitive dependency -->
<dependency>
@@ -286,13 +293,6 @@
<include>**</include>
</includes>
</filter>
- <filter>
- <artifact>com.github.shyiko.ktlint:ktlint-intellij-idea-integration</artifact>
- <includes>
- <include>com/github/shyiko/ktlint/idea/**</include>
- <include>config/**</include>
- </includes>
- </filter>
</filters>
</configuration>
</execution>
diff --git a/ktlint/src/main/kotlin/com/github/shyiko/ktlint/Main.kt b/ktlint/src/main/kotlin/com/github/shyiko/ktlint/Main.kt
index 035d577..ce80563 100644
--- a/ktlint/src/main/kotlin/com/github/shyiko/ktlint/Main.kt
+++ b/ktlint/src/main/kotlin/com/github/shyiko/ktlint/Main.kt
@@ -9,6 +9,8 @@
import com.github.shyiko.ktlint.core.RuleExecutionException
import com.github.shyiko.ktlint.core.RuleSet
import com.github.shyiko.ktlint.core.RuleSetProvider
+import com.github.shyiko.ktlint.internal.EditorConfig
+import com.github.shyiko.ktlint.internal.IntellijIDEAIntegration
import com.github.shyiko.ktlint.internal.MavenDependencyResolver
import org.eclipse.aether.RepositoryException
import org.eclipse.aether.artifact.DefaultArtifact
@@ -16,7 +18,6 @@
import org.eclipse.aether.repository.RepositoryPolicy
import org.eclipse.aether.repository.RepositoryPolicy.CHECKSUM_POLICY_IGNORE
import org.eclipse.aether.repository.RepositoryPolicy.UPDATE_POLICY_NEVER
-import org.ini4j.Wini
import org.jetbrains.kotlin.preprocessor.mkdirsOrFail
import org.kohsuke.args4j.Argument
import org.kohsuke.args4j.CmdLineException
@@ -38,7 +39,9 @@
import java.security.MessageDigest
import java.util.ArrayList
import java.util.Arrays
+import java.util.NoSuchElementException
import java.util.ResourceBundle
+import java.util.Scanner
import java.util.ServiceLoader
import java.util.concurrent.ArrayBlockingQueue
import java.util.concurrent.Callable
@@ -67,6 +70,9 @@
@Option(name="--format", aliases = arrayOf("-F"), usage = "Fix any deviations from the code style")
private var format: Boolean = false
+ @Option(name="--android", aliases = arrayOf("-a"), usage = "Turn on Android Kotlin Style Guide compatibility")
+ private var android: Boolean = false
+
@Option(name="--reporter",
usage = "A reporter to use (built-in: plain (default), plain?group_by_file, json, checkstyle). " +
"To use a third-party reporter specify either a path to a JAR file on the filesystem or a" +
@@ -154,8 +160,7 @@
.joinToString("\n")}
""".trimIndent()
- @JvmStatic
- fun main(args: Array<String>) {
+ fun parseCmdLine(args: Array<String>) {
args.forEach { arg ->
if (arg.startsWith("--") && arg.contains("=")) {
val flag = arg.substringBefore("=")
@@ -194,38 +199,25 @@
System.err.println("Error: ${err.message}\n\n${parser.usage()}")
exitProcess(1)
}
- if (version) { println(javaClass.`package`.implementationVersion); exitProcess(0) }
if (help) { println(parser.usage()); exitProcess(0) }
+ }
+
+ @JvmStatic
+ fun main(args: Array<String>) {
+ parseCmdLine(args)
+ if (version) {
+ println(javaClass.`package`.implementationVersion)
+ exitProcess(0)
+ }
if (installGitPreCommitHook) {
- if (!File(".git").isDirectory) {
- System.err.println(".git directory not found. " +
- "Are you sure you are inside project root directory?")
- System.exit(1)
- }
- val hooksDir = File(".git", "hooks")
- hooksDir.mkdirsOrFail()
- val preCommitHookFile = File(hooksDir, "pre-commit")
- val expectedPreCommitHook = ClassLoader.getSystemClassLoader()
- .getResourceAsStream("ktlint-git-pre-commit-hook.sh").readBytes()
- // backup existing hook (if any)
- val actualPreCommitHook = try { preCommitHookFile.readBytes() } catch (e: FileNotFoundException) { null }
- if (actualPreCommitHook != null && !actualPreCommitHook.isEmpty() && !Arrays.equals(actualPreCommitHook, expectedPreCommitHook)) {
- val backupFile = File(hooksDir, "pre-commit.ktlint-backup." + hex(actualPreCommitHook))
- System.err.println(".git/hooks/pre-commit -> $backupFile")
- preCommitHookFile.copyTo(backupFile, overwrite = true)
- }
- // > .git/hooks/pre-commit && chmod +x .git/hooks/pre-commit
- preCommitHookFile.writeBytes(expectedPreCommitHook)
- preCommitHookFile.setExecutable(true)
- System.err.println(".git/hooks/pre-commit installed")
+ installGitPreCommitHook()
if (!apply) {
exitProcess(0)
}
}
if (apply) {
- com.github.shyiko.ktlint.idea.Main.main(arrayOf("apply") +
- (if (forceApply) arrayOf("-y") else emptyArray()))
- return // process will be terminated before can reach this line
+ applyToIDEA()
+ exitProcess(0)
}
val workDir = File(".").canonicalPath
val start = System.currentTimeMillis()
@@ -290,15 +282,16 @@
}
}.toTypedArray())
// load .editorconfig
- val userData = locateEditorConfig(File(workDir))?.let { editoConfigFile ->
- if (debug) {
- System.err.println("[DEBUG] Discovered .editorconfig (${editoConfigFile.parent})")
- }
- loadEditorConfig(editoConfigFile)
- } ?: emptyMap()
- if (debug) {
- System.err.println("[DEBUG] ${userData.mapKeys { it.key }} loaded from .editorconfig")
- }
+ val userData = (
+ EditorConfig.of(workDir)
+ ?.also { editorConfig ->
+ if (debug) {
+ System.err.println("[DEBUG] Discovered .editorconfig (${editorConfig.path.parent})")
+ System.err.println("[DEBUG] ${editorConfig.mapKeys { it.key }} loaded from .editorconfig")
+ }
+ }
+ ?: emptyMap<String, String>()
+ ) + mapOf("android" to android.toString())
data class LintErrorWithCorrectionInfo(val err: LintError, val corrected: Boolean)
fun lintErrorFrom(e: Exception): LintError = when (e) {
is ParseException ->
@@ -400,6 +393,62 @@
}
}
+ fun installGitPreCommitHook() {
+ if (!File(".git").isDirectory) {
+ System.err.println(".git directory not found. " +
+ "Are you sure you are inside project root directory?")
+ exitProcess(1)
+ }
+ val hooksDir = File(".git", "hooks")
+ hooksDir.mkdirsOrFail()
+ val preCommitHookFile = File(hooksDir, "pre-commit")
+ val expectedPreCommitHook = ClassLoader.getSystemClassLoader()
+ .getResourceAsStream("ktlint-git-pre-commit-hook${if (android) "-android" else ""}.sh").readBytes()
+ // backup existing hook (if any)
+ val actualPreCommitHook = try { preCommitHookFile.readBytes() } catch (e: FileNotFoundException) { null }
+ if (actualPreCommitHook != null && !actualPreCommitHook.isEmpty() && !Arrays.equals(actualPreCommitHook, expectedPreCommitHook)) {
+ val backupFile = File(hooksDir, "pre-commit.ktlint-backup." + hex(actualPreCommitHook))
+ System.err.println(".git/hooks/pre-commit -> $backupFile")
+ preCommitHookFile.copyTo(backupFile, overwrite = true)
+ }
+ // > .git/hooks/pre-commit && chmod +x .git/hooks/pre-commit
+ preCommitHookFile.writeBytes(expectedPreCommitHook)
+ preCommitHookFile.setExecutable(true)
+ System.err.println(".git/hooks/pre-commit installed")
+ }
+
+ fun applyToIDEA() {
+ try {
+ val workDir = Paths.get(".")
+ if (!forceApply) {
+ val fileList = IntellijIDEAIntegration.apply(workDir, true, android)
+ System.err.println("The following files are going to be updated:\n\n\t" +
+ fileList.joinToString("\n\t") +
+ "\n\nDo you wish to proceed? [y/n]\n" +
+ "(in future, use -y flag if you wish to skip confirmation)")
+ val scanner = Scanner(System.`in`)
+
+ val res = generateSequence {
+ try { scanner.next() } catch (e: NoSuchElementException) { null }
+ }
+ .filter { line -> !line.trim().isEmpty() }
+ .first()
+ if (!"y".equals(res, ignoreCase = true)) {
+ System.err.println("(update canceled)")
+ exitProcess(1)
+ }
+ }
+ IntellijIDEAIntegration.apply(workDir, false, android)
+ } catch (e: IntellijIDEAIntegration.ProjectNotFoundException) {
+ System.err.println(".idea directory not found. " +
+ "Are you sure you are inside project root directory?")
+ exitProcess(1)
+ }
+ System.err.println("(updated)")
+ System.err.println("\nPlease restart your IDE")
+ System.err.println("(if you experience any issues please report them at https://github.com/shyiko/ktlint)")
+ }
+
fun hex(input: ByteArray) = BigInteger(MessageDigest.getInstance("SHA-256").digest(input)).toString(16)
// a complete solution would be to implement https://www.gnu.org/software/bash/manual/html_node/Tilde-Expansion.html
@@ -482,21 +531,6 @@
map
}
- fun locateEditorConfig(dir: File?): File? = when (dir) {
- null -> null
- else -> File(dir, ".editorconfig").let {
- if (it.exists()) it else locateEditorConfig(dir.parentFile)
- }
- }
-
- fun loadEditorConfig(file: File): Map<String, String> {
- val editorConfig = Wini(file)
- // right now ktlint requires explicit [*.{kt,kts}] section
- // (this way we can be sure that users want .editorconfig to be recognized by ktlint)
- val section = editorConfig["*.{kt,kts}"]
- return section?.toSortedMap() ?: emptyMap<String, String>()
- }
-
fun lint(fileName: String, text: String, ruleSets: Iterable<RuleSet>, userData: Map<String, String>,
cb: (e: LintError) -> Unit) =
if (fileName.endsWith(".kt", ignoreCase = true)) KtLint.lint(text, ruleSets, userData, cb) else
diff --git a/ktlint/src/main/kotlin/com/github/shyiko/ktlint/internal/EditorConfig.kt b/ktlint/src/main/kotlin/com/github/shyiko/ktlint/internal/EditorConfig.kt
new file mode 100644
index 0000000..519f6a5
--- /dev/null
+++ b/ktlint/src/main/kotlin/com/github/shyiko/ktlint/internal/EditorConfig.kt
@@ -0,0 +1,36 @@
+package com.github.shyiko.ktlint.internal
+
+import org.ini4j.Wini
+import java.io.ByteArrayInputStream
+import java.nio.file.Files
+import java.nio.file.Path
+import java.nio.file.Paths
+
+class EditorConfig private constructor (
+ val path: Path,
+ private val data: Map<String, String>
+) : Map<String, String> by data {
+
+ companion object {
+
+ fun of(dir: String) =
+ of(Paths.get(dir))
+ fun of(dir: Path) =
+ locate(dir)?.let { EditorConfig(it, load(it)) }
+
+ private fun locate(dir: Path?): Path? = when (dir) {
+ null -> null
+ else -> Paths.get(dir.toString(), ".editorconfig").let {
+ if (Files.exists(it)) it else locate(dir.parent)
+ }
+ }
+
+ private fun load(path: Path): Map<String, String> {
+ val editorConfig = Wini(ByteArrayInputStream(Files.readAllBytes(path)))
+ // right now ktlint requires explicit [*.{kt,kts}] section
+ // (this way we can be sure that users want .editorconfig to be recognized by ktlint)
+ val section = editorConfig["*.{kt,kts}"]
+ return section?.toSortedMap() ?: emptyMap()
+ }
+ }
+}
diff --git a/ktlint/src/main/kotlin/com/github/shyiko/ktlint/internal/IntellijIDEAIntegration.kt b/ktlint/src/main/kotlin/com/github/shyiko/ktlint/internal/IntellijIDEAIntegration.kt
new file mode 100644
index 0000000..7c7b23f
--- /dev/null
+++ b/ktlint/src/main/kotlin/com/github/shyiko/ktlint/internal/IntellijIDEAIntegration.kt
@@ -0,0 +1,140 @@
+package com.github.shyiko.ktlint.internal
+
+import com.github.shyiko.klob.Glob
+import org.w3c.dom.Element
+import java.io.ByteArrayInputStream
+import java.io.ByteArrayOutputStream
+import java.io.IOException
+import java.nio.charset.Charset
+import java.nio.file.Files
+import java.nio.file.NoSuchFileException
+import java.nio.file.Path
+import java.nio.file.Paths
+import javax.xml.parsers.DocumentBuilderFactory
+import javax.xml.transform.OutputKeys
+import javax.xml.transform.TransformerFactory
+import javax.xml.transform.dom.DOMSource
+import javax.xml.transform.stream.StreamResult
+import javax.xml.xpath.XPathConstants
+import javax.xml.xpath.XPathFactory
+
+object IntellijIDEAIntegration {
+
+ @Throws(IOException::class)
+ fun apply(workDir: Path, dryRun: Boolean, android: Boolean = false): Array<Path> {
+ if (!Files.isDirectory(workDir.resolve(".idea"))) {
+ throw ProjectNotFoundException()
+ }
+ val home = System.getProperty("user.home")
+ val editorConfig: Map<String, String> = EditorConfig.of(".") ?: emptyMap()
+ val continuationIndentSize = editorConfig["continuation_indent_size"]?.toIntOrNull() ?: if (android) 8 else 4
+ val indentSize = editorConfig["indent_size"]?.toIntOrNull() ?: 4
+ val codeStyleName = "ktlint${
+ if (continuationIndentSize == 4) "" else "-cis$continuationIndentSize"
+ }${
+ if (indentSize == 4) "" else "-is$indentSize"
+ }"
+ val paths =
+ // macOS
+ Glob.from("IntelliJIdea*", "IdeaIC*", "AndroidStudio*")
+ .iterate(Paths.get(home, "Library", "Preferences"),
+ Glob.IterationOption.SKIP_CHILDREN, Glob.IterationOption.DIRECTORY).asSequence() +
+ // linux/windows
+ Glob.from(".IntelliJIdea*/config", ".IdeaIC*/config", ".AndroidStudio*/config")
+ .iterate(Paths.get(home),
+ Glob.IterationOption.SKIP_CHILDREN, Glob.IterationOption.DIRECTORY).asSequence()
+ val updates = (paths.flatMap { dir ->
+ sequenceOf(
+ Paths.get(dir.toString(), "codestyles", "$codeStyleName.xml") to
+ overwriteWithResource("/config/codestyles/ktlint.xml") { resource ->
+ resource
+ .replace("code_scheme name=\"ktlint\"",
+ "code_scheme name=\"$codeStyleName\"")
+ .replace("option name=\"INDENT_SIZE\" value=\"4\"",
+ "option name=\"INDENT_SIZE\" value=\"$indentSize\"")
+ .replace("option name=\"CONTINUATION_INDENT_SIZE\" value=\"8\"",
+ "option name=\"CONTINUATION_INDENT_SIZE\" value=\"$continuationIndentSize\"")
+ },
+ Paths.get(dir.toString(), "options", "code.style.schemes.xml") to
+ overwriteWithResource("/config/options/code.style.schemes.xml") { content ->
+ content
+ .replace("option name=\"CURRENT_SCHEME_NAME\" value=\"ktlint\"",
+ "option name=\"CURRENT_SCHEME_NAME\" value=\"$codeStyleName\"")
+ },
+ Paths.get(dir.toString(), "inspection", "ktlint.xml") to
+ overwriteWithResource("/config/inspection/ktlint.xml"),
+ Paths.get(dir.toString(), "options", "editor.codeinsight.xml") to {
+ var arr = "<application></application>".toByteArray()
+ try {
+ arr = Files.readAllBytes(Paths.get(dir.toString(), "options", "editor.codeinsight.xml"))
+ } catch (e: IOException) {
+ if (e !is NoSuchFileException) {
+ throw e
+ }
+ }
+ enableOptimizeImportsOnTheFly(arr)
+ }
+ )
+ } + sequenceOf(
+ Paths.get(workDir.toString(), ".idea", "codeStyleSettings.xml") to
+ overwriteWithResource("/config/.idea/codeStyleSettings.xml") { content ->
+ content.replace(
+ "option name=\"PREFERRED_PROJECT_CODE_STYLE\" value=\"ktlint\"",
+ "option name=\"PREFERRED_PROJECT_CODE_STYLE\" value=\"$codeStyleName\""
+ )
+ },
+ Paths.get(workDir.toString(), ".idea", "inspectionProfiles", "profiles_settings.xml") to
+ overwriteWithResource("/config/.idea/inspectionProfiles/profiles_settings.xml")
+ )).toList()
+ if (!dryRun) {
+ updates.forEach { (path, contentSupplier) ->
+ Files.createDirectories(path.parent)
+ Files.write(path, contentSupplier())
+ }
+ }
+ return updates.map { (path) -> path }.toTypedArray()
+ }
+
+ private fun overwriteWithResource(resource: String, transformer: ((String) -> String) = { it }): () -> ByteArray = {
+ transformer(getResourceText(resource)).toByteArray(charset("UTF-8"))
+ }
+
+ private fun enableOptimizeImportsOnTheFly(arr: ByteArray): ByteArray {
+ /*
+ <application>
+ <component name="CodeInsightSettings">
+ <option name="OPTIMIZE_IMPORTS_ON_THE_FLY" value="true" />
+ ...
+ </component>
+ ...
+ </application>
+ */
+ val doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(ByteArrayInputStream(arr))
+ val xpath = XPathFactory.newInstance().newXPath()
+ var cis = xpath.evaluate("//component[@name='CodeInsightSettings']",
+ doc, XPathConstants.NODE) as Element?
+ if (cis == null) {
+ cis = doc.createElement("component")
+ cis.setAttribute("name", "CodeInsightSettings")
+ cis = doc.documentElement.appendChild(cis) as Element
+ }
+ var oiotf = xpath.evaluate("//option[@name='OPTIMIZE_IMPORTS_ON_THE_FLY']",
+ cis, XPathConstants.NODE) as Element?
+ if (oiotf == null) {
+ oiotf = doc.createElement("option")
+ oiotf.setAttribute("name", "OPTIMIZE_IMPORTS_ON_THE_FLY")
+ oiotf = cis.appendChild(oiotf) as Element
+ }
+ oiotf.setAttribute("value", "true")
+ val transformer = TransformerFactory.newInstance().newTransformer()
+ val out = ByteArrayOutputStream()
+ transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes")
+ transformer.transform(DOMSource(doc), StreamResult(out))
+ return out.toByteArray()
+ }
+
+ private fun getResourceText(name: String) =
+ this::class.java.getResourceAsStream(name).readBytes().toString(Charset.forName("UTF-8"))
+
+ class ProjectNotFoundException : RuntimeException()
+}
diff --git a/ktlint/src/main/resources/config/.idea/codeStyleSettings.xml b/ktlint/src/main/resources/config/.idea/codeStyleSettings.xml
new file mode 100644
index 0000000..64d0148
--- /dev/null
+++ b/ktlint/src/main/resources/config/.idea/codeStyleSettings.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectCodeStyleSettingsManager">
+ <option name="PER_PROJECT_SETTINGS">
+ <value />
+ </option>
+ <option name="PREFERRED_PROJECT_CODE_STYLE" value="ktlint" />
+ </component>
+</project>
diff --git a/ktlint-intellij-idea-integration/src/main/resources/config/.idea/inspectionProfiles/profiles_settings.xml b/ktlint/src/main/resources/config/.idea/inspectionProfiles/profiles_settings.xml
similarity index 100%
rename from ktlint-intellij-idea-integration/src/main/resources/config/.idea/inspectionProfiles/profiles_settings.xml
rename to ktlint/src/main/resources/config/.idea/inspectionProfiles/profiles_settings.xml
diff --git a/ktlint-intellij-idea-integration/src/main/resources/config/codestyles/ktlint.xml b/ktlint/src/main/resources/config/codestyles/ktlint.xml
similarity index 87%
rename from ktlint-intellij-idea-integration/src/main/resources/config/codestyles/ktlint.xml
rename to ktlint/src/main/resources/config/codestyles/ktlint.xml
index f7c94a7..213a17d 100644
--- a/ktlint-intellij-idea-integration/src/main/resources/config/codestyles/ktlint.xml
+++ b/ktlint/src/main/resources/config/codestyles/ktlint.xml
@@ -14,7 +14,8 @@
<option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="0" />
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
<indentOptions>
- <option name="CONTINUATION_INDENT_SIZE" value="4" />
+ <option name="INDENT_SIZE" value="4" />
+ <option name="CONTINUATION_INDENT_SIZE" value="8" />
</indentOptions>
</codeStyleSettings>
</code_scheme>
diff --git a/ktlint-intellij-idea-integration/src/main/resources/config/inspection/ktlint.xml b/ktlint/src/main/resources/config/inspection/ktlint.xml
similarity index 100%
rename from ktlint-intellij-idea-integration/src/main/resources/config/inspection/ktlint.xml
rename to ktlint/src/main/resources/config/inspection/ktlint.xml
diff --git a/ktlint-intellij-idea-integration/src/main/resources/config/options/code.style.schemes.xml b/ktlint/src/main/resources/config/options/code.style.schemes.xml
similarity index 100%
rename from ktlint-intellij-idea-integration/src/main/resources/config/options/code.style.schemes.xml
rename to ktlint/src/main/resources/config/options/code.style.schemes.xml
diff --git a/ktlint/src/main/resources/ktlint-git-pre-commit-hook-android.sh b/ktlint/src/main/resources/ktlint-git-pre-commit-hook-android.sh
new file mode 100755
index 0000000..3d8432c
--- /dev/null
+++ b/ktlint/src/main/resources/ktlint-git-pre-commit-hook-android.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+# https://github.com/shyiko/ktlint pre-commit hook
+git diff --name-only --cached --relative | grep '\.kts\?$' | xargs ktlint --android --relative .
+if [ $? -ne 0 ]; then exit 1; fi
diff --git a/pom.xml b/pom.xml
index 2a9d26b..0113e4c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -55,7 +55,6 @@
<module>ktlint-reporter-plain</module>
<module>ktlint-reporter-json</module>
<module>ktlint-reporter-checkstyle</module>
- <module>ktlint-intellij-idea-integration</module>
<module>ktlint</module>
</modules>