-
Notifications
You must be signed in to change notification settings - Fork 460
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
Allow configuration through .clang-format files #1759
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -20,11 +20,16 @@ | |||||||||||||||||
import java.io.Serializable; | ||||||||||||||||||
import java.nio.charset.StandardCharsets; | ||||||||||||||||||
import java.util.ArrayList; | ||||||||||||||||||
import java.util.Arrays; | ||||||||||||||||||
import java.util.HashSet; | ||||||||||||||||||
import java.util.List; | ||||||||||||||||||
import java.util.Objects; | ||||||||||||||||||
import java.util.Optional; | ||||||||||||||||||
import java.util.Set; | ||||||||||||||||||
|
||||||||||||||||||
import javax.annotation.Nullable; | ||||||||||||||||||
|
||||||||||||||||||
import com.diffplug.spotless.FileSignature; | ||||||||||||||||||
import com.diffplug.spotless.ForeignExe; | ||||||||||||||||||
import com.diffplug.spotless.FormatterFunc; | ||||||||||||||||||
import com.diffplug.spotless.FormatterStep; | ||||||||||||||||||
|
@@ -88,20 +93,66 @@ private State createState() throws IOException, InterruptedException { | |||||||||||||||||
@SuppressFBWarnings("SE_TRANSIENT_FIELD_NOT_RESTORED") | ||||||||||||||||||
static class State implements Serializable { | ||||||||||||||||||
private static final long serialVersionUID = -1825662356883926318L; | ||||||||||||||||||
private static final String DOT_FILE_NAME = ".clang-format"; | ||||||||||||||||||
// used for up-to-date checks and caching | ||||||||||||||||||
final String version; | ||||||||||||||||||
final @Nullable String style; | ||||||||||||||||||
final transient ForeignExe exe; | ||||||||||||||||||
final Set<File> dotFiles; | ||||||||||||||||||
FileSignature dotFileSig; | ||||||||||||||||||
// used for executing | ||||||||||||||||||
private transient @Nullable List<String> args; | ||||||||||||||||||
|
||||||||||||||||||
State(ClangFormatStep step, ForeignExe pathToExe) { | ||||||||||||||||||
State(ClangFormatStep step, ForeignExe pathToExe, @Nullable FileSignature sig) { | ||||||||||||||||||
this.version = step.version; | ||||||||||||||||||
this.style = step.style; | ||||||||||||||||||
this.exe = Objects.requireNonNull(pathToExe); | ||||||||||||||||||
this.dotFiles = new HashSet<>(); | ||||||||||||||||||
this.dotFileSig = sig; | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
State(ClangFormatStep step, ForeignExe pathToExe) { | ||||||||||||||||||
this(step, pathToExe, null); | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
/** | ||||||||||||||||||
* If relevant, locates the `.clang-format` file that will be used as config | ||||||||||||||||||
* for clang-format and stores its signature in dotFile. | ||||||||||||||||||
* @param targetFile file to be formatted. | ||||||||||||||||||
*/ | ||||||||||||||||||
private void resolveDotFile(File targetFile) throws IOException | ||||||||||||||||||
{ | ||||||||||||||||||
// The dot file is irrelevant if a specific style other than "file" is supplied. | ||||||||||||||||||
if (style != null && !style.equals("file")) { | ||||||||||||||||||
return; | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
File directory = targetFile.getParentFile(); | ||||||||||||||||||
Optional<File> dotFile = Optional.empty(); | ||||||||||||||||||
while (dotFile.isEmpty() && readableDirectory(directory)) { | ||||||||||||||||||
dotFile = Arrays.stream(directory.listFiles()).filter(file -> file.getName().equals(DOT_FILE_NAME)).findAny(); | ||||||||||||||||||
directory = directory.getParentFile(); | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
System.out.println("dotFile: " + dotFile); | ||||||||||||||||||
// Every target file can have a different .clang-format file (in theory). | ||||||||||||||||||
// Keep track of the ones we've covered and build the sig as we go. | ||||||||||||||||||
if (dotFile.isPresent() && !dotFiles.contains(dotFile.get())) { | ||||||||||||||||||
dotFiles.add(dotFile.get()); | ||||||||||||||||||
dotFileSig = FileSignature.signAsSet(dotFiles); | ||||||||||||||||||
} | ||||||||||||||||||
System.out.println("Signature" + dotFileSig); | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
|
||||||||||||||||||
private static boolean readableDirectory(File directory) | ||||||||||||||||||
{ | ||||||||||||||||||
return directory != null && directory.exists() && directory.isDirectory() && directory.canRead(); | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
|
||||||||||||||||||
String format(ProcessRunner runner, String input, File file) throws IOException, InterruptedException { | ||||||||||||||||||
resolveDotFile(file); | ||||||||||||||||||
if (args == null) { | ||||||||||||||||||
final List<String> tmpArgs = new ArrayList<>(); | ||||||||||||||||||
tmpArgs.add(exe.confirmVersionAndGetAbsolutePath()); | ||||||||||||||||||
|
@@ -111,7 +162,8 @@ String format(ProcessRunner runner, String input, File file) throws IOException, | |||||||||||||||||
args = tmpArgs; | ||||||||||||||||||
} | ||||||||||||||||||
final String[] processArgs = args.toArray(new String[args.size() + 1]); | ||||||||||||||||||
processArgs[processArgs.length - 1] = "--assume-filename=" + file.getName(); | ||||||||||||||||||
processArgs[processArgs.length - 1] = "--assume-filename=" + file.getAbsolutePath(); | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Interesting, this is all it takes for The only problem is that the content of the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the reply. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So looking into this, I learned 2 things so far: 🤓
That also means that for the devs who are currently using spotless without Two remaining questions for you:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If this
FileSignature dotFile then it will detect dotfile changes. Right now, without this PR, I believe it will not detect dotfile changes becuase it doesn't know where the files are, so it can't find them even if they are there.
In terms of what to merge/implement, the most important thing is that it works for you. If you need to bump the required clang, we can bump it, and if someone needs support for older versions, they can add it. Seems to me like a good compromise is |
||||||||||||||||||
System.out.println(String.join(", ", processArgs)); | ||||||||||||||||||
return runner.exec(input.getBytes(StandardCharsets.UTF_8), processArgs).assertExitZero(StandardCharsets.UTF_8); | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This does not seem sufficient to detect .clang-format changes