Skip to content

Commit

Permalink
almost works
Browse files Browse the repository at this point in the history
  • Loading branch information
ramidzkh committed Nov 21, 2023
1 parent ee40ec1 commit 9a6206b
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 58 deletions.
4 changes: 1 addition & 3 deletions src/main/java/io/github/astrarre/sfu/SourceFixerUpper.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,11 @@ static SourceFixerUpper create() {

SourceFixerUpper mappings(MappingTreeView tree, int srcNamespace, int dstNamespace);

SourceFixerUpper input(Path root);
SourceFixerUpper input(Path input, Path output);

SourceFixerUpper sourcepath(Path root);

SourceFixerUpper classpath(Path root);

SourceFixerUpper output(Path output);

void process() throws IOException;
}
168 changes: 131 additions & 37 deletions src/main/java/io/github/astrarre/sfu/impl/SFUImpl.java
Original file line number Diff line number Diff line change
@@ -1,32 +1,49 @@
package io.github.astrarre.sfu.impl;

import io.github.astrarre.sfu.SourceFixerUpper;
import java.io.IOException;
import java.io.*;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.net.URI;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import javax.tools.JavaFileObject;
import java.util.*;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.NestingKind;
import javax.tools.*;
import net.fabricmc.mappingio.tree.MappingTreeView;
import sfu_rpkg.com.sun.source.tree.CompilationUnitTree;
import sfu_rpkg.com.sun.source.util.JavacTask;
import sfu_rpkg.com.sun.source.util.Trees;
import sfu_rpkg.com.sun.tools.javac.api.ClientCodeWrapper;
import sfu_rpkg.com.sun.tools.javac.api.JavacTaskImpl;
import sfu_rpkg.com.sun.tools.javac.api.JavacTool;
import sfu_rpkg.com.sun.tools.javac.file.JavacFileManager;
import sfu_rpkg.com.sun.tools.javac.util.Context;

public class SFUImpl implements SourceFixerUpper {

private static final MethodHandle UNWRAP;

static {
try {
UNWRAP = MethodHandles.privateLookupIn(ClientCodeWrapper.class, MethodHandles.lookup())
.findVirtual(ClientCodeWrapper.class, "unwrap",
MethodType.methodType(JavaFileObject.class, JavaFileObject.class));
} catch (NoSuchMethodException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}

private Charset charset = Charset.defaultCharset();
private MappingTreeView tree;
private int srcNamespace, dstNamespace;
private Path output;

private final List<Path> inputs, sourcepath, classpath;
private final Map<Path, Path> inputs;
private final List<Path> sourcepath;
private final List<Path> classpath;

public SFUImpl() {
this.inputs = new ArrayList<>();
this.inputs = new LinkedHashMap<>();
this.sourcepath = new ArrayList<>();
this.classpath = new ArrayList<>();
}
Expand All @@ -46,8 +63,8 @@ public SourceFixerUpper mappings(MappingTreeView tree, int srcNamespace, int dst
}

@Override
public SourceFixerUpper input(Path root) {
this.inputs.add(root);
public SourceFixerUpper input(Path input, Path output) {
this.inputs.put(input, output);
return this;
}

Expand All @@ -63,39 +80,116 @@ public SourceFixerUpper classpath(Path root) {
return this;
}

@Override
public SourceFixerUpper output(Path output) {
this.output = output;
return this;
}

@Override
public void process() throws IOException {
Context context = new Context();
JavacFileManager jcFileManager = new JavacFileManager(context, true, charset);
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, charset);
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
JavacTool javac = JavacTool.create();

Path filePath = Files.list(inputs.get(0)).filter(Files::isRegularFile).findAny().get();

Iterable<? extends JavaFileObject> javaFiles = jcFileManager.getJavaFileObjects(filePath);
JavacTask jcTask = javac.getTask(null,
jcFileManager,
JavacTaskImpl task = (JavacTaskImpl) javac.getTask(null,
fileManager,
diagnostics,
List.of("-proc:none"),
null,
List.of(),
null,
javaFiles);
Trees trees = Trees.instance(jcTask);

Iterable<? extends CompilationUnitTree> codeResult = jcTask.parse();
jcTask.analyze();
inputs.entrySet().stream().map(path -> {
Iterator<? extends JavaFileObject> iterable = fileManager
.getJavaFileObjectsFromPaths(List.of(path.getKey())).iterator();
JavaFileObject object = iterable.next();
assert !iterable.hasNext();
return new WJavaFileObject(object, path.getValue());
}).toList());
ClientCodeWrapper wrapper = ClientCodeWrapper.instance(task.getContext());
Trees trees = Trees.instance(task);

Iterable<? extends CompilationUnitTree> codeResult = task.parse();
task.analyze();

for (CompilationUnitTree codeTree : codeResult) {
var jsv = new RangeCollectingVisitor(trees);
codeTree.accept(jsv, null);
StringBuilder builder = new StringBuilder(Files.readString(filePath));
Remapper remapper = new Remapper(builder, jsv.members, jsv.types, tree, srcNamespace, dstNamespace);
var collector = new RangeCollectingVisitor(trees);
codeTree.accept(collector, null);

WJavaFileObject sourceFile;

try {
sourceFile = (WJavaFileObject) (JavaFileObject) UNWRAP.invokeExact(wrapper, codeTree.getSourceFile());
} catch (Throwable e) {
throw new RuntimeException(e);
}

StringBuilder builder = new StringBuilder(sourceFile.getCharContent(false));
Remapper remapper = new Remapper(builder, collector.members, collector.types, tree, srcNamespace,
dstNamespace);
remapper.apply();
System.out.println(builder);
Files.createDirectories(sourceFile.output.getParent());
Files.writeString(sourceFile.output, builder.toString(), charset);
}
}

record WJavaFileObject(JavaFileObject object, Path output) implements JavaFileObject {
@Override
public Kind getKind() {
return object.getKind();
}

@Override
public boolean isNameCompatible(String simpleName, Kind kind) {
return object.isNameCompatible(simpleName, kind);
}

@Override
public NestingKind getNestingKind() {
return object.getNestingKind();
}

@Override
public Modifier getAccessLevel() {
return object.getAccessLevel();
}

@Override
public URI toUri() {
return object.toUri();
}

@Override
public String getName() {
return object.getName();
}

@Override
public InputStream openInputStream() throws IOException {
return object.openInputStream();
}

@Override
public OutputStream openOutputStream() throws IOException {
return object.openOutputStream();
}

@Override
public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
return object.openReader(ignoreEncodingErrors);
}

@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
return object.getCharContent(ignoreEncodingErrors);
}

@Override
public Writer openWriter() throws IOException {
return object.openWriter();
}

@Override
public long getLastModified() {
return object.getLastModified();
}

@Override
public boolean delete() {
return object.delete();
}
}
}
37 changes: 19 additions & 18 deletions src/test/java/io/github/astrarre/sfu/test/RemappingTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Arrays;
import net.fabricmc.mappingio.format.Tiny2Reader;
import net.fabricmc.mappingio.tree.MemoryMappingTree;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.opentest4j.AssertionFailedError;

public class RemappingTests {

Expand All @@ -35,31 +34,33 @@ public void remap() throws IOException {
Tiny2Reader.read(reader, tree);
}

SourceFixerUpper.create()
.mappings(tree, tree.getNamespaceId("a"), tree.getNamespaceId("b"))
.input(original)
.output(output)
.process();
SourceFixerUpper sfu = SourceFixerUpper.create()
.mappings(tree, tree.getNamespaceId("a"), tree.getNamespaceId("b"));

verifyDirsAreEqual(output, test);
verifyDirsAreEqual(test, output);
Files.walk(original).forEach(path -> {
if (Files.isRegularFile(path)) {
sfu.input(path, output.resolve(original.relativize(path)));
}
});

sfu.process();

verifyDirsAreEqual(output, test, false);
verifyDirsAreEqual(test, output, true);
}
}

private static void verifyDirsAreEqual(Path one, Path other) throws IOException {
private static void verifyDirsAreEqual(Path one, Path other, boolean flip) throws IOException {
Files.walkFileTree(one, new SimpleFileVisitor<>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
FileVisitResult result = super.visitFile(file, attrs);
Path fileInOther = other.resolve(one.relativize(file));

Path relativize = one.relativize(file);
Path fileInOther = other.resolve(relativize);

byte[] otherBytes = Files.readAllBytes(fileInOther);
byte[] theseBytes = Files.readAllBytes(file);

if (!Arrays.equals(otherBytes, theseBytes)) {
throw new AssertionFailedError(file + " is not equal to " + fileInOther);
if (flip) {
Assertions.assertEquals(Files.readString(file), Files.readString(fileInOther));
} else {
Assertions.assertEquals(Files.readString(fileInOther), Files.readString(file));
}

return result;
Expand Down

0 comments on commit 9a6206b

Please sign in to comment.