Last active
August 14, 2023 17:08
-
-
Save techyourchance/dc764f11ee7af6ce823a18fe5b340df9 to your computer and use it in GitHub Desktop.
Script that refactors Java and Kotlin files from mHungarianNotation to camelCase
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.BufferedReader; | |
import java.io.File; | |
import java.io.FileReader; | |
import java.io.FileWriter; | |
import java.nio.file.Files; | |
import java.nio.file.Path; | |
import java.nio.file.Paths; | |
import java.util.regex.*; | |
import java.util.Arrays; | |
import java.util.Collection; | |
import java.util.HashSet; | |
import java.util.List; | |
import java.util.Set; | |
import java.util.stream.Collectors; | |
public class HungarianRemover { | |
private enum SupportedLanguage { | |
JAVA, KOTLIN | |
} | |
private static final String IDENTIFIER_CHAR_REGEXP = "[a-zA-Z0-9_]"; // intentionally omitted $ | |
private static final String HUNGARIAN_FIRST_CHAR_REGEXP = "[ms]"; | |
private static final String HUNGARIAN_IDENTIFIER_REGEXP = "" | |
+ "(?<!" + IDENTIFIER_CHAR_REGEXP + ")" // not preceeded by a valid identifier char | |
+ HUNGARIAN_FIRST_CHAR_REGEXP // one of "hungarian" first chars | |
+ "([A-Z])" // followed by a capital letter | |
+ "(" + IDENTIFIER_CHAR_REGEXP + "{2,})"; // followed by at least two more chars | |
private static final String JAVA_SIMPLE_ASSIGNMENT_REGEXP = "" | |
+ "^(\\s*)" // only preceeding whitespaces | |
+ "(" + IDENTIFIER_CHAR_REGEXP + "+)" // identifier | |
+ "(\\s*=\\s*)" // equals | |
+ "(" + IDENTIFIER_CHAR_REGEXP + "+)" // identifier | |
+ "(\\s*;)"; // trailing semicolon | |
public static void main(String[] args) { | |
File targetDir; | |
try { | |
targetDir = extractTargetDirFromArgs(args); | |
} catch (Exception e) { | |
error(e.getMessage()); | |
return; | |
} | |
print("Target directory: " + targetDir.toString()); | |
HungarianRemover remover = new HungarianRemover(); | |
try { | |
remover.removeHungarianNotationInDir(targetDir); | |
} catch (Exception e) { | |
throw new RuntimeException(e); | |
} | |
} | |
private static File extractTargetDirFromArgs(String[] args) throws Exception { | |
Path path; | |
if (args.length == 0) { | |
path = Paths.get(".").toAbsolutePath(); | |
} else { | |
path = Paths.get(args[0]).toAbsolutePath(); | |
} | |
if (Files.exists(path) && Files.isDirectory(path)) { | |
return path.toFile(); | |
} else { | |
throw new Exception("Directory doesn't exist: " + path.toString()); | |
} | |
} | |
private static void print(String message) { | |
System.out.println(message); | |
} | |
private static void error(String message) { | |
System.out.println("Error! " + message); | |
} | |
private int linesChanged = 0; | |
private int identifiersChanged = 0; | |
public void removeHungarianNotationInDir(File targetDir) throws Exception { | |
Collection<File> files = getAllRelevantFilesInDir(targetDir); | |
for (File file : files) { | |
removeHungarianNotationInFile(file); | |
} | |
print("Done"); | |
print("Lines changed: " + linesChanged); | |
print("Identifiers changed: " + identifiersChanged); | |
} | |
public Collection<File> getAllRelevantFilesInDir(File dir) { | |
Collection<File> fileTree = getAllFilesInDir(dir); | |
return fileTree.stream() | |
.filter(file -> { | |
String absolutePath = file.getAbsolutePath(); | |
return (absolutePath.endsWith(".java") || absolutePath.endsWith(".kt")) | |
&& !absolutePath.contains(".git") | |
&& !absolutePath.contains(".orig"); | |
}) | |
.collect(Collectors.toList()); | |
} | |
public Collection<File> getAllFilesInDir(File dir) { | |
Set<File> fileTree = new HashSet<>(); | |
if (dir == null || dir.listFiles() == null) { | |
return fileTree; | |
} | |
for (File entry : dir.listFiles()) { | |
if (entry.isFile()) { | |
fileTree.add(entry); | |
} else { | |
fileTree.addAll(getAllRelevantFilesInDir(entry)); | |
} | |
} | |
return fileTree; | |
} | |
public void removeHungarianNotationInFile(File file) throws Exception { | |
SupportedLanguage language = deriveLanguageFromExtension(file); | |
BufferedReader bufferedReader = new BufferedReader(new FileReader(file)); | |
StringBuilder editedLines = new StringBuilder(); | |
String originalLine; | |
String editedLine; | |
while ((originalLine = bufferedReader.readLine()) != null) { | |
editedLine = removeHungarianNotationInLine(originalLine); | |
if (language == SupportedLanguage.JAVA) { | |
editedLine = correctSameNameClassFieldAssignmentsInJava(editedLine); | |
} | |
if (!editedLine.equals(originalLine)) { | |
linesChanged++; | |
} | |
editedLines.append(editedLine); | |
editedLines.append("\n"); | |
} | |
FileWriter fw = new FileWriter(file, false); | |
fw.append(editedLines.toString()); | |
fw.close(); | |
} | |
public SupportedLanguage deriveLanguageFromExtension(File file) { | |
if (file.getName().endsWith(".java")) { | |
return SupportedLanguage.JAVA; | |
} else if (file.getName().endsWith(".kt")) { | |
return SupportedLanguage.KOTLIN; | |
} else { | |
throw new RuntimeException("Unsupported file extension: " + file.getName()); | |
} | |
} | |
public String removeHungarianNotationInLine(String line) { | |
return Pattern.compile(HUNGARIAN_IDENTIFIER_REGEXP) | |
.matcher(line) | |
.replaceAll(m -> { | |
identifiersChanged++; | |
return m.group(1).toLowerCase() + m.group(2); | |
}); | |
} | |
public String correctSameNameClassFieldAssignmentsInJava(String line) { | |
return Pattern.compile(JAVA_SIMPLE_ASSIGNMENT_REGEXP) | |
.matcher(line) | |
.replaceAll(m -> { | |
if (m.group(2).equals(m.group(4))) { // if identifiers on both sides of "=" are the same | |
return m.group(1) + "this." + m.group(2) + m.group(3) + m.group(4) + m.group(5); | |
} else { | |
return m.group(0); // no change | |
} | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment