-
Notifications
You must be signed in to change notification settings - Fork 21
Create cross-format StandardProperties
class
#29
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
base: dev
Are you sure you want to change the base?
Changes from all commits
c87e3ba
ee30d57
ad0c724
0910fa9
3cc9283
bc4ce09
45783f0
5341ecf
b8673c7
bd7ecc2
f0a2376
da53284
52852bd
6f4aa42
0a46ede
fd19740
4633d7f
273e481
26e608f
5eaf880
782469d
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 |
---|---|---|
@@ -0,0 +1,109 @@ | ||
/* | ||
* 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.format; | ||
|
||
import java.util.AbstractMap; | ||
import java.util.Collection; | ||
import java.util.Collections; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
import org.jetbrains.annotations.ApiStatus; | ||
import org.jetbrains.annotations.Nullable; | ||
|
||
public final class StandardProperties { | ||
private StandardProperties() { | ||
} | ||
|
||
public static Collection<StandardProperty> values() { | ||
return Collections.unmodifiableCollection(valuesById.values()); | ||
} | ||
|
||
@Nullable | ||
public static StandardProperty getByName(MappingFormat format, String name) { | ||
return valuesByFormatAndName.get(new AbstractMap.SimpleEntry<>(format, name)); | ||
} | ||
|
||
@Nullable | ||
@ApiStatus.Internal | ||
public static StandardProperty getById(String id) { | ||
return valuesById.get(id); | ||
} | ||
|
||
public static final StandardProperty NEXT_INTERMEDIARY_CLASS; | ||
public static final StandardProperty NEXT_INTERMEDIARY_FIELD; | ||
public static final StandardProperty NEXT_INTERMEDIARY_METHOD; | ||
public static final StandardProperty NEXT_INTERMEDIARY_COMPONENT; | ||
Comment on lines
+47
to
+50
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. Im not sure these should exist in mio, they are specific to intermediary and are generated by matcher. They arent part of the tiny format, and I dont think we actually read them anymore? 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. happy to discuss this if you think otherwise. 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. I'd say this is a bit of an edge-case, since the counters have been special-cased until now and consequently behaved as de-facto standard properties. I could remove it, so we end up using 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. In the long run we might need an API letting consumers register their own standard properties |
||
public static final StandardProperty MISSING_LVT_INDICES; | ||
public static final StandardProperty ESCAPED_NAMES; | ||
private static final Map<Map.Entry<MappingFormat, String>, StandardProperty> valuesByFormatAndName = new HashMap<>(); | ||
private static final Map<String, StandardProperty> valuesById = new HashMap<>(); | ||
|
||
static { | ||
NEXT_INTERMEDIARY_CLASS = register("next-intermediary-class") | ||
.addMapping(MappingFormat.TINY_FILE, "INTERMEDIARY_COUNTER class") | ||
.addMapping(MappingFormat.TINY_2_FILE, "next-intermediary-class"); | ||
NEXT_INTERMEDIARY_FIELD = register("next-intermediary-field") | ||
.addMapping(MappingFormat.TINY_FILE, "INTERMEDIARY_COUNTER field") | ||
.addMapping(MappingFormat.TINY_2_FILE, "next-intermediary-field"); | ||
NEXT_INTERMEDIARY_METHOD = register("next-intermediary-method") | ||
.addMapping(MappingFormat.TINY_FILE, "INTERMEDIARY_COUNTER method") | ||
.addMapping(MappingFormat.TINY_2_FILE, "next-intermediary-method"); | ||
NEXT_INTERMEDIARY_COMPONENT = register("next-intermediary-component") | ||
.addMapping(MappingFormat.TINY_FILE, "INTERMEDIARY_COUNTER component") | ||
.addMapping(MappingFormat.TINY_2_FILE, "next-intermediary-component"); | ||
MISSING_LVT_INDICES = register("missing-lvt-indices") | ||
.addMapping(MappingFormat.TINY_2_FILE, "missing-lvt-indices"); | ||
ESCAPED_NAMES = register("escaped-names") | ||
.addMapping(MappingFormat.TINY_2_FILE, "escaped-names"); | ||
} | ||
|
||
private static StandardPropertyImpl register(String id) { | ||
return new StandardPropertyImpl(id); | ||
} | ||
|
||
private static class StandardPropertyImpl implements StandardProperty { | ||
StandardPropertyImpl(String id) { | ||
this.id = id; | ||
valuesById.put(id, this); | ||
} | ||
|
||
private StandardPropertyImpl addMapping(MappingFormat format, String name) { | ||
nameByFormat.put(format, name); | ||
valuesByFormatAndName.put(new AbstractMap.SimpleEntry<>(format, name), this); | ||
return this; | ||
} | ||
|
||
@Override | ||
public boolean isApplicableTo(MappingFormat format) { | ||
return nameByFormat.containsKey(format); | ||
} | ||
|
||
@Override | ||
public String getNameFor(MappingFormat format) { | ||
return nameByFormat.get(format); | ||
} | ||
|
||
@Override | ||
public String getId() { | ||
return id; | ||
} | ||
|
||
private final String id; | ||
private final Map<MappingFormat, String> nameByFormat = new HashMap<>(4); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
/* | ||
* 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.format; | ||
|
||
import org.jetbrains.annotations.ApiStatus; | ||
import org.jetbrains.annotations.Nullable; | ||
|
||
@ApiStatus.NonExtendable | ||
public interface StandardProperty { | ||
NebelNidas marked this conversation as resolved.
Show resolved
Hide resolved
|
||
boolean isApplicableTo(MappingFormat format); | ||
NebelNidas marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
@Nullable | ||
String getNameFor(MappingFormat format); | ||
|
||
/** | ||
* Used internally by MappingTrees, consistency between JVM sessions or library versions isn't guaranteed! | ||
*/ | ||
@ApiStatus.Internal | ||
String getId(); | ||
} |
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 design is bad: malicious actors can fake an id and pollute the metadata detection. You should just keep a
Map<MappingFormat, Map<String, StandardProperty>>
instead.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.
Not sure what you mean, the internal maps are all private anyway
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.
Say if you have a
next-intermediary-method
read from tiny v1, you would incorrectly interpret it as an intermediary counter while it isn't.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.
I've already added a sanity check preventing this: 5341ecf
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.
The issue why I need a simple String ID instead of a
Map<MappingFormat, Map<String, StandardProperty>>
is intermediate operations, sayMemoryMappingTree.accept(MemoryMappingTree)
, where none of the participants know which mapping format the former tree was originally constructed from. I could generate a random ID per session, but IMO that's overcomplicating things without much reason. Maybe prepending the existing ID withmio:
would do?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.
Can we just add a new
default void visitStandardProperty(StandardProperty prop, String value)
inMappingVisitor
andFlatMappingVisitor
, which fabric's builtin visitors will override? And we can choose to feed these standard properties back as String key-values in visit options.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.
Hmm, not a huge fan of this, since up until this point the visitor- and tree-based APIs have always been cleanly separated.
Edit: On the other hand,
StandardProperty
isn't really part of the tree-api, so maybe it'd work? But it still duplicates the metadata visit methods, which pollute theFlatMappingVisitor
interface, especially considering #41 will add even more.