Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Java importOrder support for sorting wildcards last #954

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ This document is intended for Spotless developers.
We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`).

## [Unreleased]
* Added `wildcardsLast` option for Java `ImportOrderStep` ([#954](https://github.com/diffplug/spotless/pull/954))

## [2.18.0] - 2021-09-30
### Added
Expand Down
24 changes: 17 additions & 7 deletions lib/src/main/java/com/diffplug/spotless/java/ImportOrderStep.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,28 @@ private ImportOrderStep(String lineFormat) {
}

public FormatterStep createFrom(String... importOrder) {
return createFrom(false, importOrder);
hakanai marked this conversation as resolved.
Show resolved Hide resolved
}

public FormatterStep createFrom(boolean wildcardsLast, String... importOrder) {
// defensive copying and null checking
List<String> importOrderList = requireElementsNonNull(Arrays.asList(importOrder));
return createFrom(() -> importOrderList);
return createFrom(wildcardsLast, () -> importOrderList);
}

public FormatterStep createFrom(File importsFile) {
return createFrom(false, importsFile);
hakanai marked this conversation as resolved.
Show resolved Hide resolved
}

public FormatterStep createFrom(boolean wildcardsLast, File importsFile) {
Objects.requireNonNull(importsFile);
return createFrom(() -> getImportOrder(importsFile));
return createFrom(wildcardsLast, () -> getImportOrder(importsFile));
}

private FormatterStep createFrom(Supplier<List<String>> importOrder) {
private FormatterStep createFrom(boolean wildcardsLast, Supplier<List<String>> importOrder) {
return FormatterStep.createLazy("importOrder",
() -> new State(importOrder.get(), lineFormat),
State::toFormatter);
() -> new State(importOrder.get(), lineFormat, wildcardsLast),
State::toFormatter);
}

private static List<String> getImportOrder(File importsFile) {
Expand Down Expand Up @@ -92,14 +100,16 @@ private static final class State implements Serializable {

private final List<String> importOrder;
private final String lineFormat;
private final boolean wildcardsLast;

State(List<String> importOrder, String lineFormat) {
State(List<String> importOrder, String lineFormat, boolean wildcardsLast) {
this.importOrder = importOrder;
this.lineFormat = lineFormat;
this.wildcardsLast = wildcardsLast;
}

FormatterFunc toFormatter() {
return raw -> new ImportSorter(importOrder).format(raw, lineFormat);
return raw -> new ImportSorter(importOrder, wildcardsLast).format(raw, lineFormat);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,11 @@ final class ImportSorter {
static final String N = "\n";

private final List<String> importsOrder;
private final boolean wildcardsLast;

ImportSorter(List<String> importsOrder) {
ImportSorter(List<String> importsOrder, boolean wildcardsLast) {
this.importsOrder = new ArrayList<>(importsOrder);
this.wildcardsLast = wildcardsLast;
}

String format(String raw, String lineFormat) {
Expand Down Expand Up @@ -79,7 +81,7 @@ String format(String raw, String lineFormat) {
}
scanner.close();

List<String> sortedImports = ImportSorterImpl.sort(imports, importsOrder, lineFormat);
List<String> sortedImports = ImportSorterImpl.sort(imports, importsOrder, wildcardsLast, lineFormat);
return applyImportsToDocument(raw, firstImportLine, lastImportLine, sortedImports);
}

Expand Down
48 changes: 36 additions & 12 deletions lib/src/main/java/com/diffplug/spotless/java/ImportSorterImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,7 @@
*/
package com.diffplug.spotless.java;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;

import javax.annotation.Nullable;

Expand All @@ -34,9 +28,10 @@ final class ImportSorterImpl {
private final Map<String, List<String>> matchingImports = new HashMap<>();
private final List<String> notMatching = new ArrayList<>();
private final Set<String> allImportOrderItems = new HashSet<>();
private final Comparator<String> ordering;

static List<String> sort(List<String> imports, List<String> importsOrder, String lineFormat) {
ImportSorterImpl importsSorter = new ImportSorterImpl(importsOrder);
static List<String> sort(List<String> imports, List<String> importsOrder, boolean wildcardsLast, String lineFormat) {
ImportSorterImpl importsSorter = new ImportSorterImpl(importsOrder, wildcardsLast);
return importsSorter.sort(imports, lineFormat);
}

Expand All @@ -49,11 +44,12 @@ private List<String> sort(List<String> imports, String lineFormat) {
return getResult(lineFormat);
}

private ImportSorterImpl(List<String> importOrder) {
private ImportSorterImpl(List<String> importOrder, boolean wildcardsLast) {
List<String> importOrderCopy = new ArrayList<>(importOrder);
normalizeStaticOrderItems(importOrderCopy);
putStaticItemIfNotExists(importOrderCopy);
template.addAll(importOrderCopy);
ordering = new OrderingComparator(wildcardsLast);
this.allImportOrderItems.addAll(importOrderCopy);
}

Expand Down Expand Up @@ -119,7 +115,7 @@ private void filterMatchingImports(List<String> imports) {
* not matching means it does not match any order item, so it will be appended before or after order items
*/
private void mergeNotMatchingItems(boolean staticItems) {
Collections.sort(notMatching);
sort(notMatching);

int firstIndexOfOrderItem = getFirstIndexOfOrderItem(notMatching, staticItems);
int indexOfOrderItem = 0;
Expand Down Expand Up @@ -192,7 +188,7 @@ private void mergeMatchingItems() {
continue;
}
List<String> matchingItems = new ArrayList<>(strings);
Collections.sort(matchingItems);
sort(matchingItems);

// replace order item by matching import statements
// this is a mess and it is only a luck that it works :-]
Expand All @@ -218,6 +214,10 @@ private void mergeMatchingItems() {
}
}

private void sort(List<String> items) {
items.sort(ordering);
}

private List<String> getResult(String lineFormat) {
List<String> strings = new ArrayList<>();

Expand Down Expand Up @@ -256,4 +256,28 @@ private List<String> getResult(String lineFormat) {
return null;
}

private static class OrderingComparator implements Comparator<String> {
private final boolean wildcardsLast;

private OrderingComparator(boolean wildcardsLast) {
this.wildcardsLast = wildcardsLast;
}

@Override
public int compare(String string1, String string2) {
int string1WildcardIndex = string1.indexOf('*');
int string2WildcardIndex = string2.indexOf('*');
boolean string1IsWildcard = string1WildcardIndex >= 0;
boolean string2IsWildcard = string2WildcardIndex >= 0;
if (string1IsWildcard == string2IsWildcard) {
return string1.compareTo(string2);
}
int prefixLength = string1IsWildcard ? string1WildcardIndex : string2WildcardIndex;
boolean samePrefix = string1.regionMatches(0, string2, 0, prefixLength);
if (!samePrefix) {
return string1.compareTo(string2);
}
return (string1IsWildcard == wildcardsLast) ? 1 : -1;
}
}
}
1 change: 1 addition & 0 deletions plugin-gradle/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `3.27.0`).

## [Unreleased]
* Added `wildcardsLast()` option for Java `importOrder` ([#954](https://github.com/diffplug/spotless/pull/954))

## [5.15.2] - 2021-09-27
### Changed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import static com.diffplug.gradle.spotless.PluginGradlePreconditions.requireElementsNonNull;

import java.io.File;
import java.util.Objects;

import javax.inject.Inject;
Expand Down Expand Up @@ -57,13 +58,47 @@ public LicenseHeaderConfig licenseHeaderFile(Object licenseHeaderFile) {
return licenseHeaderFile(licenseHeaderFile, LICENSE_HEADER_DELIMITER);
}

public void importOrder(String... importOrder) {
addStep(ImportOrderStep.forJava().createFrom(importOrder));
public ImportOrderConfig importOrder(String... importOrder) {
return new ImportOrderConfig(importOrder);
}

public void importOrderFile(Object importOrderFile) {
public ImportOrderConfig importOrderFile(Object importOrderFile) {
Objects.requireNonNull(importOrderFile);
addStep(ImportOrderStep.forJava().createFrom(getProject().file(importOrderFile)));
return new ImportOrderConfig(getProject().file(importOrderFile));
}

public class ImportOrderConfig {
final String[] importOrder;
final File importOrderFile;

boolean wildcardsLast = false;

ImportOrderConfig(String[] importOrder) {
this.importOrder = importOrder;
importOrderFile = null;
addStep(createStep());
}

ImportOrderConfig(File importOrderFile) {
importOrder = null;
this.importOrderFile = importOrderFile;
addStep(createStep());
}

/** Sorts wildcard imports after non-wildcard imports, instead of before. */
public ImportOrderConfig wildcardsLast() {
hakanai marked this conversation as resolved.
Show resolved Hide resolved
wildcardsLast = true;
replaceStep(createStep());
return this;
}

private FormatterStep createStep() {
ImportOrderStep importOrderStep = ImportOrderStep.forJava();

return importOrderFile != null
? importOrderStep.createFrom(wildcardsLast, getProject().file(importOrderFile))
: importOrderStep.createFrom(wildcardsLast, importOrder);
}
}

/** Removes any unused imports. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,14 @@ import java.lang.Runnable;
import org.comments.be
import org.comments.removed
*/
import static java.lang.Runnable.*;
import static java.lang.Runnable.*;
/*
import other.multiline.comments
import will.be.removed.too */
import will.be.removed.too */
import static com.foo.Bar
import java.awt.*;
import java.util.*;
import java.util.List;
import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
import static org.hamcrest.Matchers.*;
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import java.awt.*;
import java.lang.Runnable;
import java.lang.Thread;
import java.util.*;
import java.util.List;

import org.dooda.Didoo;

import static java.lang.Exception.*;
import static java.lang.Runnable.*;
import static org.hamcrest.Matchers.*;

import static com.foo.Bar;
import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import static com.foo.Bar;
import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
import static java.lang.Exception.*;
import static java.lang.Runnable.*;
import static org.hamcrest.Matchers.*;

import java.awt.*;
import java.lang.Runnable;
import java.lang.Thread;
import java.util.*;
import java.util.List;
import org.dooda.Didoo;
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import static com.foo.Bar;
import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static java.lang.Exception.*;
import static java.lang.Runnable.*;
import static org.hamcrest.Matchers.*;

import java.awt.*;
import java.lang.Runnable;
import java.lang.Thread;
import java.util.List;
import java.util.*;
import org.dooda.Didoo;
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import static java.lang.Exception.*;
import static com.github.tomakehurst.wiremock.client.WireMock.*;
import org.dooda.Didoo;
import java.util.List;
import java.lang.Thread;
import java.util.*;
import java.lang.Runnable;
import static org.hamcrest.Matchers.*;

import static java.lang.Runnable.*;
import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
import static com.foo.Bar
import java.awt.*;
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ void sortImportsUnmatched() throws Throwable {
assertOnResources(step, "java/importsorter/JavaCodeUnsortedImportsUnmatched.test", "java/importsorter/JavaCodeSortedImportsUnmatched.test");
}

@Test
void sortImportsWildcardsLast() throws Throwable {
FormatterStep step = ImportOrderStep.forJava().createFrom(true);
assertOnResources(step, "java/importsorter/JavaCodeUnsortedImports.test", "java/importsorter/JavaCodeSortedImportsWildcardsLast.test");
}

@Test
void removeDuplicates() throws Throwable {
FormatterStep step = ImportOrderStep.forJava().createFrom(createTestFile("java/importsorter/import_unmatched.properties"));
Expand Down