Skip to content
Closed
Show file tree
Hide file tree
Changes from all 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
3 changes: 2 additions & 1 deletion src/main/java/net/fabricmc/mappingio/FlatMappingVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,11 @@ default void visitMetadata(String key, String value) throws IOException { }

/**
* Determine whether the mapping content (classes and anything below, metadata if not part of the header) should be visited.
* Lazy callers, which don't know beforehand how many elements they're going to have (e.g. mapping readers), must pass -1.
*
* @return true if content is to be visited, false otherwise
*/
default boolean visitContent() throws IOException {
default boolean visitContent(int classCount, int fieldCount, int methodCount, int methodArgCount, int methodVarCount, int commentCount, int metadataCount) throws IOException {
return true;
}

Expand Down
28 changes: 14 additions & 14 deletions src/main/java/net/fabricmc/mappingio/MappingReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -135,24 +135,24 @@ public static List<String> getNamespaces(Reader reader, MappingFormat format) th
}
}

public static void read(Path file, MappingVisitor visitor) throws IOException {
read(file, null, visitor);
public static void read(Path file, MappingVisitor visitor, ProgressListener progressListener) throws IOException {
read(file, null, visitor, progressListener);
}

public static void read(Path file, MappingFormat format, MappingVisitor visitor) throws IOException {
public static void read(Path file, MappingFormat format, MappingVisitor visitor, ProgressListener progressListener) throws IOException {
if (format == null) {
format = detectFormat(file);
if (format == null) throw new IOException("invalid/unsupported mapping format");
}

if (format.hasSingleFile()) {
try (Reader reader = Files.newBufferedReader(file)) {
read(reader, format, visitor);
read(reader, format, visitor, progressListener);
}
} else {
switch (format) {
case ENIGMA_DIR:
EnigmaDirReader.read(file, visitor);
EnigmaDirReader.read(file, visitor, progressListener);
break;
case MCP_DIR:
throw new UnsupportedOperationException(); // TODO: implement
Expand All @@ -162,11 +162,11 @@ public static void read(Path file, MappingFormat format, MappingVisitor visitor)
}
}

public static void read(Reader reader, MappingVisitor visitor) throws IOException {
read(reader, null, visitor);
public static void read(Reader reader, MappingVisitor visitor, ProgressListener progressListener) throws IOException {
read(reader, null, visitor, progressListener);
}

public static void read(Reader reader, MappingFormat format, MappingVisitor visitor) throws IOException {
public static void read(Reader reader, MappingFormat format, MappingVisitor visitor, ProgressListener progressListener) throws IOException {
if (format == null) {
if (!reader.markSupported()) reader = new BufferedReader(reader);
reader.mark(DETECT_HEADER_LEN);
Expand All @@ -179,23 +179,23 @@ public static void read(Reader reader, MappingFormat format, MappingVisitor visi

switch (format) {
case TINY_FILE:
Tiny1FileReader.read(reader, visitor);
Tiny1FileReader.read(reader, visitor, progressListener);
break;
case TINY_2_FILE:
Tiny2FileReader.read(reader, visitor);
Tiny2FileReader.read(reader, visitor, progressListener);
break;
case ENIGMA_FILE:
EnigmaFileReader.read(reader, visitor);
EnigmaFileReader.read(reader, visitor, progressListener);
break;
case SRG_FILE:
SrgFileReader.read(reader, visitor);
SrgFileReader.read(reader, visitor, progressListener);
break;
case TSRG_FILE:
case TSRG_2_FILE:
TsrgFileReader.read(reader, visitor);
TsrgFileReader.read(reader, visitor, progressListener);
break;
case PROGUARD_FILE:
ProGuardFileReader.read(reader, visitor);
ProGuardFileReader.read(reader, visitor, progressListener);
break;
default:
throw new IllegalStateException();
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/net/fabricmc/mappingio/MappingVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,11 @@ default void visitMetadata(String key, String value) throws IOException { }

/**
* Determine whether the mapping content (classes and anything below, metadata if not part of the header) should be visited.
* Lazy callers, which don't know beforehand how many elements they're going to have (e.g. mapping readers), must pass -1.
*
* @return true if content is to be visited, false otherwise
*/
default boolean visitContent() throws IOException {
default boolean visitContent(int classCount, int fieldCount, int methodCount, int methodArgCount, int methodVarCount, int commentCount, int metadataCount) throws IOException {
return true;
}

Expand Down
16 changes: 8 additions & 8 deletions src/main/java/net/fabricmc/mappingio/MappingWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,25 +30,25 @@
import net.fabricmc.mappingio.format.tiny.Tiny2FileWriter;

public interface MappingWriter extends Closeable, MappingVisitor {
static MappingWriter create(Path file, MappingFormat format) throws IOException {
static MappingWriter create(Path file, MappingFormat format, ProgressListener progressListener) throws IOException {
if (format.hasSingleFile()) {
return create(Files.newBufferedWriter(file), format);
return create(Files.newBufferedWriter(file), format, progressListener);
} else {
switch (format) {
case ENIGMA_DIR: return new EnigmaDirWriter(file, true);
case ENIGMA_DIR: return new EnigmaDirWriter(file, true, progressListener);
default: throw new UnsupportedOperationException("format "+format+" is not implemented");
}
}
}

static MappingWriter create(Writer writer, MappingFormat format) throws IOException {
static MappingWriter create(Writer writer, MappingFormat format, ProgressListener progressListener) throws IOException {
if (!format.hasSingleFile()) throw new IllegalArgumentException("format "+format+" is not applicable to a single writer");

switch (format) {
case TINY_FILE: return new Tiny1FileWriter(writer);
case TINY_2_FILE: return new Tiny2FileWriter(writer, false);
case ENIGMA_FILE: return new EnigmaFileWriter(writer);
case PROGUARD_FILE: return new ProGuardFileWriter(writer);
case TINY_FILE: return new Tiny1FileWriter(writer, progressListener);
case TINY_2_FILE: return new Tiny2FileWriter(writer, false, progressListener);
case ENIGMA_FILE: return new EnigmaFileWriter(writer, progressListener);
case PROGUARD_FILE: return new ProGuardFileWriter(writer, progressListener);
default: throw new UnsupportedOperationException("format "+format+" is not implemented");
}
}
Expand Down
161 changes: 161 additions & 0 deletions src/main/java/net/fabricmc/mappingio/ProgressListener.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/*
* Copyright (c) 2023 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.fabricmc.mappingio;

import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;

public abstract class ProgressListener {
protected ProgressListener(LogLevel logLevel) {
this.logLevel = logLevel;
this.forwarder = this instanceof Forwarder ? (Forwarder) this : new Forwarder(logLevel, this);
}

/**
* Sets the progress listener's total amount of steps and provides a name for the job.
* If the total amount of steps isn't known beforehand, {@code totalWork} must be set to -1.
* Can only be called once.
*/
protected abstract void init(int totalWork, String title);

/**
* Indicates the start of a new step being processed, and optionally gives it a name.
*/
protected abstract void startStep(LogLevel logLevel, @Nullable String stepName);

/**
* Updates the name of the current step.
*/
protected abstract void updateMessage(LogLevel logLevel, @Nullable String stepName);

/**
* Indicates that all steps have finished processing.
* After that point, further method invocations are illegal.
*/
protected abstract void finish();

/**
* Determines the granularity of progress reports the progress listener wishes to receive.
*/
public enum LogLevel {
FILES,
CLASSES,
MEMBERS;

public boolean allows(LogLevel logLevel) {
if (logLevel.compareTo(this) <= 0) {
return true;
}

return false;
}
}

/**
* Class which forwards only applicable log levels to the passed receiver,
* and automatically checks for illegal calls.
*/
@ApiStatus.Internal
public final class Forwarder extends ProgressListener {
private Forwarder(LogLevel logLevel, ProgressListener receiver) {
super(logLevel);

this.receiver = receiver;
}

@Override
public void init(int totalWork, String title) {
assertNotFinished();

if (initialized && receiver != NOP) {
throw new RuntimeException("Progress listener can only be initialized once!");
}

receiver.init(totalWork, title);
initialized = true;
}

@Override
public void startStep(LogLevel logLevel, @Nullable String stepName) {
assertNotFinished();

if (this.logLevel.allows(logLevel)) {
receiver.startStep(logLevel, stepName);
}
}

@Override
public void updateMessage(LogLevel logLevel, @Nullable String stepName) {
assertNotFinished();

if (this.logLevel.allows(logLevel)) {
receiver.updateMessage(logLevel, stepName);
}
}

@Override
public void finish() {
assertNotFinished();
receiver.finish();
finished = true;
}

private void assertNotFinished() {
if (finished && receiver != NOP) {
throw new RuntimeException("Illegal method invocation, progress listener has already finished!");
}
}

private final ProgressListener receiver;
private boolean initialized;
private boolean finished;
}

/**
* No-op progress listener that ignores all events.
*/
public static final ProgressListener NOP = new ProgressListener(LogLevel.FILES) {
@Override
public void init(int totalWork, String title) {
}

@Override
public void startStep(LogLevel logLevel, @Nullable String stepName) {
}

@Override
public void updateMessage(LogLevel logLevel, @Nullable String stepName) {
}

@Override
public void finish() {
}
};

/**
* Finest log level the progress listener accepts.
*/
public final LogLevel logLevel;

/**
* Public-facing progress listener interface for progress passers to interact with,
* which automatically checks for illegal calls and only forwards the applicable
* log levels to the actual {@link ProgressListener}.
*/
@ApiStatus.Internal
public final Forwarder forwarder;
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ public void visitMetadata(String key, String value) throws IOException {
}

@Override
public boolean visitContent() throws IOException {
return next.visitContent();
public boolean visitContent(int classCount, int fieldCount, int methodCount, int methodArgCount, int methodVarCount, int commentCount, int metadataCount) throws IOException {
return next.visitContent(classCount, fieldCount, methodCount, methodArgCount, methodVarCount, commentCount, metadataCount);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ public void visitMetadata(String key, String value) throws IOException {
}

@Override
public boolean visitContent() throws IOException {
return next.visitContent();
public boolean visitContent(int classCount, int fieldCount, int methodCount, int methodArgCount, int methodVarCount, int commentCount, int metadataCount) throws IOException {
return next.visitContent(classCount, fieldCount, methodCount, methodArgCount, methodVarCount, commentCount, metadataCount);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,10 @@ public void visitMetadata(String key, String value) throws IOException {
}

@Override
public boolean visitContent() throws IOException {
public boolean visitContent(int classCount, int fieldCount, int methodCount, int methodArgCount, int methodVarCount, int commentCount, int metadataCount) throws IOException {
relayHeaderOrMetadata = true; // for in-content metadata

return next.visitContent();
return next.visitContent(classCount, fieldCount, methodCount, methodArgCount, methodVarCount, commentCount, metadataCount);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,16 @@ public void visitMetadata(String key, String value) throws IOException {
}

@Override
public boolean visitContent() throws IOException {
public boolean visitContent(int classCount, int fieldCount, int methodCount, int methodArgCount, int methodVarCount, int commentCount, int metadataCount) throws IOException {
if (!classMapReady) return true;

relayHeaderOrMetadata = true; // for in-content metadata

return next.visitContent();
if (dropMissingNewSrcName) {
return next.visitContent(-1, -1, -1, -1, -1, -1, -1);
} else {
return next.visitContent(classCount, fieldCount, methodCount, methodArgCount, methodVarCount, commentCount, metadataCount);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ public void visitMetadata(String key, String value) throws IOException {
}

@Override
public boolean visitContent() throws IOException {
return next.visitContent();
public boolean visitContent(int classCount, int fieldCount, int methodCount, int methodArgCount, int methodVarCount, int commentCount, int metadataCount) throws IOException {
return next.visitContent(classCount, fieldCount, methodCount, methodArgCount, methodVarCount, commentCount, metadataCount);
}

@Override
Expand Down
Loading