Java源码示例:org.benf.cfr.reader.bytecode.analysis.parse.utils.Pair
示例1
private Pair< List<StatementContainer<StructuredStatement>>, StatementContainer<StructuredStatement>> getBestScopeFor(
LValue lValue,
Collection<StatementContainer<StructuredStatement>> nestedScope,
StatementContainer<StructuredStatement> exactStatement) {
if (nestedScope == null) return Pair.make(null, exactStatement);
List<StatementContainer<StructuredStatement>> scope = ListFactory.newList(nestedScope);
if (exactStatement != null && exactStatement.getStatement().alwaysDefines(lValue)) return Pair.make(scope, exactStatement);
if (scope.isEmpty()) return Pair.make(scope, exactStatement);
for (int x=scope.size()-1;x>=0;--x) {
StatementContainer<StructuredStatement> scopeTest = scope.get(x);
if (scopeTest.getStatement().canDefine(lValue, factCache)) break;
scope.remove(x);
}
if (scope.size() == nestedScope.size()) return Pair.make(scope, exactStatement);
if (scope.isEmpty()) return Pair.make(null, exactStatement);
exactStatement = scope.get(scope.size()-1);
return Pair.make(scope, exactStatement);
}
示例2
public static void main(String[] args) {
GetOptParser getOptParser = new GetOptParser();
Options options = null;
List<String> files = null;
try {
Pair<List<String>, Options> processedArgs = getOptParser.parse(args, OptionsImpl.getFactory());
files = processedArgs.getFirst();
options = processedArgs.getSecond();
if (files.size() == 0) {
throw new IllegalArgumentException("Insufficient unqualified parameters - provide at least one filename.");
}
} catch (Exception e) {
getOptParser.showHelp(e);
System.exit(1);
}
if (options.optionIsSet(OptionsImpl.HELP) || files.isEmpty()) {
getOptParser.showOptionHelp(OptionsImpl.getFactory(), options, OptionsImpl.HELP);
return;
}
CfrDriver cfrDriver = new CfrDriver.Builder().withBuiltOptions(options).build();
cfrDriver.analyse(files);
}
示例3
public Pair<JavaRefTypeInstance, JavaRefTypeInstance> getRefClassForInnerOuterPair(String rawInnerName, String rawOuterName) {
String innerName = ClassNameUtils.convertFromPath(rawInnerName);
String outerName = ClassNameUtils.convertFromPath(rawOuterName);
JavaRefTypeInstance inner = refClassTypeCache.get(innerName);
JavaRefTypeInstance outer = refClassTypeCache.get(outerName);
if (inner != null && outer != null) return Pair.make(inner, outer);
Pair<JavaRefTypeInstance, JavaRefTypeInstance> pair = JavaRefTypeInstance.createKnownInnerOuter(innerName, outerName, outer, dcCommonState);
if (inner == null) {
add(innerName, pair.getFirst());
inner = pair.getFirst();
}
if (outer == null) {
add(outerName, pair.getSecond());
outer = pair.getSecond();
}
return Pair.make(inner, outer);
}
示例4
private void initialiseFrom(Set<JavaRefTypeInstance> usedRefTypes) {
List<JavaRefTypeInstance> usedRefs = ListFactory.newList(usedRefTypes);
Collections.sort(usedRefs, new Comparator<JavaRefTypeInstance>() {
@Override
public int compare(JavaRefTypeInstance a, JavaRefTypeInstance b) {
return a.getRawName(iid).compareTo(b.getRawName(iid));
}
});
this.usedRefTypes.addAll(usedRefs);
Pair<List<JavaRefTypeInstance>, List<JavaRefTypeInstance>> types = Functional.partition(usedRefs, new Predicate<JavaRefTypeInstance>() {
@Override
public boolean test(JavaRefTypeInstance in) {
return in.getInnerClassHereInfo().isTransitiveInnerClassOf(analysisType);
}
});
this.usedLocalInnerTypes.addAll(types.getFirst());
addDisplayNames(usedRefTypes);
}
示例5
public void dumpNamedInnerClasses(Dumper d) {
if (innerClassesByTypeInfo == null || innerClassesByTypeInfo.isEmpty()) return;
for (Pair<InnerClassAttributeInfo, ClassFile> innerClassEntry : innerClassesByTypeInfo.values()) {
// catchy!
InnerClassInfo innerClassInfo = innerClassEntry.getFirst().getInnerClassInfo().getInnerClassHereInfo();
if (innerClassInfo.isSyntheticFriendClass()) {
continue;
}
if (innerClassInfo.isMethodScopedClass()) {
continue;
}
ClassFile classFile = innerClassEntry.getSecond();
if (classFile.hiddenInnerClass) {
continue;
}
TypeUsageInformation typeUsageInformation = d.getTypeUsageInformation();
TypeUsageInformation innerclassTypeUsageInformation = new InnerClassTypeUsageInformation(typeUsageInformation, (JavaRefTypeInstance) classFile.getClassType());
d.newln();
Dumper d2 = d.withTypeUsageInformation(innerclassTypeUsageInformation);
classFile.dumpHelper.dump(classFile, ClassFileDumper.InnerClassDumpType.INNER_CLASS, d2);
}
}
示例6
public void dumpReceiverClassIdentity(List<AnnotationTableTypeEntry> recieverAnnotations, Dumper d) {
Pair<List<AnnotationTableTypeEntry>, List<AnnotationTableTypeEntry>> split = Functional.partition(recieverAnnotations, new Predicate<AnnotationTableTypeEntry>() {
@Override
public boolean test(AnnotationTableTypeEntry in) {
return in.getTypePath().segments.isEmpty();
}
});
List<AnnotationTableTypeEntry> pre = split.getFirst();
List<AnnotationTableTypeEntry> type = split.getSecond();
if (!pre.isEmpty()) {
pre.get(0).dump(d);
d.print(" ");
}
JavaTypeInstance t = classSignature.getThisGeneralTypeClass(this.getClassType(), constantPool);
JavaAnnotatedTypeInstance jat = t.getAnnotatedInstance();
DecompilerComments comments = new DecompilerComments();
TypeAnnotationHelper.apply(jat, type, comments);
d.dump(comments);
d.dump(jat);
}
示例7
private static void dumpEntry(Dumper d, Pair<StaticVariable, AbstractConstructorInvokation> entry, boolean last, JavaTypeInstance classType) {
StaticVariable staticVariable = entry.getFirst();
AbstractConstructorInvokation constructorInvokation = entry.getSecond();
d.fieldName(staticVariable.getFieldName(), classType, false, true, true);
if (constructorInvokation instanceof ConstructorInvokationSimple) {
List<Expression> args = constructorInvokation.getArgs();
if (args.size() > 2) {
d.separator("(");
for (int x = 2, len = args.size(); x < len; ++x) {
if (x > 2) d.print(", ");
d.dump(args.get(x));
}
d.separator(")");
}
} else if (constructorInvokation instanceof ConstructorInvokationAnonymousInner) {
((ConstructorInvokationAnonymousInner) constructorInvokation).dumpForEnum(d);
} else {
MiscUtils.handyBreakPoint();
}
if (last) {
d.endCodeln();
} else {
d.print(",").newln();
}
}
示例8
AttributeTypeAnnotations(ByteData raw, ConstantPool cp) {
this.length = raw.getS4At(OFFSET_OF_ATTRIBUTE_LENGTH);
int numAnnotations = raw.getU2At(OFFSET_OF_NUMBER_OF_ANNOTATIONS);
long offset = OFFSET_OF_ANNOTATION_TABLE;
Map<TypeAnnotationEntryValue, List<AnnotationTableTypeEntry>> entryData = MapFactory.newLazyMap(annotationTableEntryData, new UnaryFunction<TypeAnnotationEntryValue, List<AnnotationTableTypeEntry>>() {
@Override
public List<AnnotationTableTypeEntry> invoke(TypeAnnotationEntryValue arg) {
return ListFactory.newList();
}
});
for (int x = 0; x < numAnnotations; ++x) {
Pair<Long, AnnotationTableTypeEntry> ape = AnnotationHelpers.getTypeAnnotation(raw, offset, cp);
offset = ape.getFirst();
AnnotationTableTypeEntry entry = ape.getSecond();
entryData.get(entry.getValue()).add(entry);
}
}
示例9
private static Pair<Long, TypeAnnotationTargetInfo> readTypeAnnotationTargetInfo(TypeAnnotationEntryKind kind, ByteData raw, long offset) {
switch (kind) {
case type_parameter_target:
return TypeAnnotationTargetInfo.TypeAnnotationParameterTarget.Read(raw, offset);
case supertype_target:
return TypeAnnotationTargetInfo.TypeAnnotationSupertypeTarget.Read(raw, offset);
case type_parameter_bound_target:
return TypeAnnotationTargetInfo.TypeAnnotationParameterBoundTarget.Read(raw, offset);
case empty_target:
return TypeAnnotationTargetInfo.TypeAnnotationEmptyTarget.Read(raw, offset);
case method_formal_parameter_target:
return TypeAnnotationTargetInfo.TypeAnnotationFormalParameterTarget.Read(raw, offset);
case throws_target:
return TypeAnnotationTargetInfo.TypeAnnotationThrowsTarget.Read(raw, offset);
case localvar_target:
return TypeAnnotationTargetInfo.TypeAnnotationLocalVarTarget.Read(raw, offset);
case catch_target:
return TypeAnnotationTargetInfo.TypeAnnotationCatchTarget.Read(raw, offset);
case offset_target:
return TypeAnnotationTargetInfo.TypeAnnotationOffsetTarget.Read(raw, offset);
case type_argument_target:
return TypeAnnotationTargetInfo.TypeAnnotationTypeArgumentTarget.Read(raw, offset);
default:
throw new BadAttributeException();
}
}
示例10
private static Pair<Integer, List<FormalTypeParameter>> parseFormalTypeParameters(String proto, ConstantPool cp, int curridx) {
List<FormalTypeParameter> formalTypeParameters = null;
FormalTypeParameter last = null;
if (proto.charAt(curridx) == '<') {
formalTypeParameters = ListFactory.newList();
curridx++;
while (proto.charAt(curridx) != '>') {
String formalTypeTok = getNextFormalTypeTok(proto, curridx);
FormalTypeParameter typeTok = decodeFormalTypeTok(formalTypeTok, cp);
if (typeTok.getName().equals("")) {
// previous type was an intersection type!
if (last != null) {
last.add(typeTok);
} // else no idea - have to skip.
} else {
formalTypeParameters.add(typeTok);
last = typeTok;
}
curridx += formalTypeTok.length();
}
curridx++;
}
return Pair.make(curridx, formalTypeParameters);
}
示例11
private static NavigableMap<Integer, JavaTypeInstance> assignIdentsAndGetMissingMap(SSAIdentifierFactory<Slot, StackType> ssaIdentifierFactory, Method method, List<Op02WithProcessedDataAndRefs> statements, BytecodeMeta bytecodeMeta, boolean useProtoArgs) {
assignSSAIdentifiersInner(ssaIdentifierFactory, method, statements, bytecodeMeta, useProtoArgs);
/*
* We can walk all the reads to see if there are any reads of 'uninitialised' slots.
* These are masking hidden parameters. (usually synthetic ones?).
*/
NavigableMap<Integer, JavaTypeInstance> missing = MapFactory.newTreeMap();
for (Op02WithProcessedDataAndRefs op02 : statements) {
Pair<JavaTypeInstance, Integer> load = op02.getRetrieveType();
if (load == null) continue;
SSAIdent ident = op02.ssaIdentifiers.getSSAIdentOnExit(new Slot(load.getFirst(), load.getSecond()));
if (ident == null) {
missing.put(load.getSecond(), load.getFirst());
}
}
return missing;
}
示例12
@Override
@SuppressWarnings("deprecation")
public Pair<byte[], String> getClassFileContent(String inputPath) {
String className = inputPath.substring(0, inputPath.indexOf(".class"));
byte[] code = controller.getWorkspace().getRawClass(className);
// Strip debug if config says so
if (controller.config().decompile().stripDebug)
code = ClassUtil.stripDebugForDecompile(code);
// Fetch code from runtime if not in workspace
if (code == null) {
code = Objects.requireNonNull(ClassUtil.fromRuntime(className),
"Failed to load class from runtime: " + className).b;
}
return new Pair<>(code, inputPath);
}
示例13
protected Pair<byte[], String> getSystemClass(String name, String path) throws IOException {
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream(path);
if (is != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
int n;
while ((n = is.read(buffer)) > 0) {
baos.write(buffer, 0, n);
}
return Pair.make(baos.toByteArray(), name);
}
return null;
}
示例14
@Override
public String decompileClassNode(FileContainer container, ClassNode cn) {
try {
byte[] bytes = JDA.getClassBytes(container, cn);
GetOptParser getOptParser = new GetOptParser();
Pair processedArgs = getOptParser.parse(generateMainMethod(), OptionsImpl.getFactory());
List files = (List)processedArgs.getFirst();
Options options = (Options)processedArgs.getSecond();
ClassFileSourceImpl classFileSource = new ClassFileSourceImpl(options);
DCCommonState dcCommonState = new DCCommonState(options, classFileSource);
return doClass(dcCommonState, bytes);
} catch (Exception e) {
return parseException(e);
}
}
示例15
public ClassFile loadClassFileAtPath(final String path) {
try {
Pair<byte[], String> content = classFileSource.getClassFileContent(path);
ByteData data = new BaseByteData(content.getFirst());
return new ClassFile(data, content.getSecond(), this);
} catch (Exception e) {
couldNotLoadClasses.add(path);
throw new CannotLoadClassException(path, e);
}
}
示例16
public static Pair<JavaRefTypeInstance, JavaRefTypeInstance> createKnownInnerOuter(String inner, String outer, JavaRefTypeInstance outerType, DCCommonState dcCommonState) {
if (outerType == null) outerType = new JavaRefTypeInstance(outer, dcCommonState);
JavaRefTypeInstance innerType;
if (!inner.startsWith(outer)) {
// Handle the illegal inner/outer combo.
innerType = new JavaRefTypeInstance(inner, dcCommonState);
} else {
innerType = new JavaRefTypeInstance(inner, outerType, dcCommonState);
}
return Pair.make(innerType, outerType);
}
示例17
private void analyseInnerClassesPass1(DCCommonState state) {
if (innerClassesByTypeInfo == null) return;
for (Pair<InnerClassAttributeInfo, ClassFile> innerClassInfoClassFilePair : innerClassesByTypeInfo.values()) {
ClassFile classFile = innerClassInfoClassFilePair.getSecond();
classFile.analyseMid(state);
}
}
示例18
private void analysePassOuterFirst(UnaryProcedure<ClassFile> fn) {
try {
fn.call(this);
} catch (RuntimeException e) {
addComment("Exception performing whole class analysis ignored.", e);
}
if (innerClassesByTypeInfo == null) return;
for (Pair<InnerClassAttributeInfo, ClassFile> innerClassInfoClassFilePair : innerClassesByTypeInfo.values()) {
ClassFile classFile = innerClassInfoClassFilePair.getSecond();
classFile.analysePassOuterFirst(fn);
}
}
示例19
private void collapseTypeClash(boolean force) {
if (resolved) return;
List<JavaTypeInstance> clashTypes = ListFactory.newList();
int arraySize = clashes.get(0).getJavaTypeInstance().getNumArrayDimensions();
for (IJTInternal clash : clashes) {
JavaTypeInstance clashType = clash.getJavaTypeInstance();
if (clashType.getNumArrayDimensions() != arraySize) arraySize = -1;
clashTypes.add(clashType);
}
if (arraySize == 1) {
for (int x=0;x<clashTypes.size();++x) {
clashTypes.set(x, clashTypes.get(x).removeAnArrayIndirection());
}
}
Pair<Boolean, JavaTypeInstance> newlyResolved = collapseTypeClash2(clashTypes);
//noinspection ConstantConditions
if (newlyResolved == null) return;
// Ignore the first part of the pair - we have to resolve here, so do our best.
if (!newlyResolved.getFirst() && !force) return;
resolved = true;
type = newlyResolved.getSecond();
if (arraySize == 1) {
type = new JavaArrayTypeInstance(1, type);
}
}
示例20
@Override
public void collectTypeUsages(TypeUsageCollector collector) {
for (Pair<StaticVariable, AbstractConstructorInvokation> entry : entries) {
collector.collectFrom(entry.getFirst());
collector.collectFrom(entry.getSecond());
}
}
示例21
private Dumper SinkSourceClassDumper(final OutputSinkFactory.Sink<SinkReturns.Decompiled> sink, JavaTypeInstance classType, MethodErrorCollector methodErrorCollector, TypeUsageInformation typeUsageInformation, IllegalIdentifierDump illegalIdentifierDump) {
final StringBuilder sb = new StringBuilder();
final Pair<String, String> names = ClassNameUtils.getPackageAndClassNames(classType);
return new StringStreamDumper(methodErrorCollector, sb, typeUsageInformation, options, illegalIdentifierDump, new MovableDumperContext()) {
@Override
public void close() {
final String java = sb.toString();
SinkReturns.Decompiled res = new SinkReturns.Decompiled() {
@Override
public String getPackageName() {
return names.getFirst();
}
@Override
public String getClassName() {
return names.getSecond();
}
@Override
public String getJava() {
return java;
}
};
sink.write(res);
}
};
}
示例22
AttributeAnnotations(ByteData raw, ConstantPool cp) {
this.length = raw.getS4At(OFFSET_OF_ATTRIBUTE_LENGTH);
int numAnnotations = raw.getU2At(OFFSET_OF_NUMBER_OF_ANNOTATIONS);
long offset = OFFSET_OF_ANNOTATION_TABLE;
for (int x = 0; x < numAnnotations; ++x) {
Pair<Long, AnnotationTableEntry> ape = AnnotationHelpers.getAnnotation(raw, offset, cp);
offset = ape.getFirst();
annotationTableEntryList.add(ape.getSecond());
}
}
示例23
static Pair<Long, TypeAnnotationTargetInfo> Read(ByteData raw, long offset) {
int count = raw.getU2At(offset);
offset += 2;
List<LocalVarTarget> targetList = ListFactory.newList();
for (int x=0;x<count;++x) {
int start = raw.getU2At(offset);
offset += 2;
int length = raw.getU2At(offset);
offset += 2;
int index = raw.getU2At(offset);
offset += 2;
targetList.add(new LocalVarTarget(start, length, index));
}
return Pair.<Long, TypeAnnotationTargetInfo>make(offset, new TypeAnnotationLocalVarTarget(targetList));
}
示例24
private static Pair<JavaTypeInstance, JavaTypeInstance> getInnerOuter(int idxinner, int idxouter, ConstantPool cp) {
if (idxinner == 0 || idxouter == 0) {
return Pair.make(getOptClass(idxinner, cp), getOptClass(idxouter, cp));
}
ConstantPoolEntryClass cpecInner = cp.getClassEntry(idxinner);
ConstantPoolEntryClass cpecOuter = cp.getClassEntry(idxouter);
JavaTypeInstance innerType = cpecInner.getTypeInstanceKnownOuter(cpecOuter);
JavaTypeInstance outerType = cpecOuter.getTypeInstanceKnownInner(cpecInner);
return Pair.make(innerType, outerType);
}
示例25
public AttributeInnerClasses(ByteData raw, ConstantPool cp) {
Boolean forbidMethodScopedClasses = cp.getDCCommonState().getOptions().getOption(OptionsImpl.FORBID_METHOD_SCOPED_CLASSES);
Boolean forbidAnonymousClasses = cp.getDCCommonState().getOptions().getOption(OptionsImpl.FORBID_ANONYMOUS_CLASSES);
this.length = raw.getS4At(OFFSET_OF_ATTRIBUTE_LENGTH);
int numberInnerClasses = raw.getU2At(OFFSET_OF_NUMBER_OF_CLASSES);
long offset = OFFSET_OF_CLASS_ARRAY;
for (int x = 0; x < numberInnerClasses; ++x) {
int innerClassInfoIdx = raw.getU2At(offset);
offset += 2;
int outerClassInfoIdx = raw.getU2At(offset);
offset += 2;
int innerNameIdx = raw.getU2At(offset);
offset += 2;
int innerAccessFlags = raw.getU2At(offset);
offset += 2;
Pair<JavaTypeInstance, JavaTypeInstance> innerOuter = getInnerOuter(innerClassInfoIdx, outerClassInfoIdx, cp);
JavaTypeInstance innerClassType = innerOuter.getFirst();
JavaTypeInstance outerClassType = innerOuter.getSecond();
// MarkAnonymous feels like a bit of a hack, but otherwise we need to propagate this information
// the whole way down the type creation path, and this is the only place we care about it.
// May add that in later.
if (outerClassType == null) {
// This option has to be set manually, because it affects state generated
// which is shared between fallback passes.
if (forbidMethodScopedClasses) {
outerClassType = innerClassType.getInnerClassHereInfo().getOuterClass();
} else {
boolean isAnonymous = !forbidAnonymousClasses && innerNameIdx == 0;
innerClassType.getInnerClassHereInfo().markMethodScoped(isAnonymous);
}
}
innerClassAttributeInfoList.add(new InnerClassAttributeInfo(
innerClassType,
outerClassType,
getOptName(innerNameIdx, cp),
AccessFlag.build(innerAccessFlags)
));
}
}
示例26
static Pair<Long, AnnotationTableEntry> getAnnotation(ByteData raw, long offset, ConstantPool cp) {
ConstantPoolEntryUTF8 typeName = cp.getUTF8Entry(raw.getU2At(offset));
offset += 2;
int numElementPairs = raw.getU2At(offset);
offset += 2;
Map<String, ElementValue> elementValueMap = MapFactory.newOrderedMap();
for (int x = 0; x < numElementPairs; ++x) {
offset = getElementValuePair(raw, offset, cp, elementValueMap);
}
return new Pair<Long, AnnotationTableEntry>(offset, new AnnotationTableEntry(ConstantPoolUtils.decodeTypeTok(typeName.getValue(), cp), elementValueMap));
}
示例27
private static long getElementValuePair(ByteData raw, long offset, ConstantPool cp, Map<String, ElementValue> res) {
ConstantPoolEntryUTF8 elementName = cp.getUTF8Entry(raw.getU2At(offset));
offset += 2;
Pair<Long, ElementValue> elementValueP = getElementValue(raw, offset, cp);
offset = elementValueP.getFirst();
res.put(elementName.getValue(), elementValueP.getSecond());
return offset;
}
示例28
private String mkFilename(String dir, Pair<String, String> names, SummaryDumper summaryDumper) {
String packageName = names.getFirst();
String className = names.getSecond();
if (className.length() > MAX_FILE_LEN_MINUS_EXT) {
/*
* Have to try to find a replacement name.
*/
className = className.substring(0, TRUNC_PREFIX_LEN) + "_cfr_" + (truncCount++);
summaryDumper.notify("Class name " + names.getSecond() + " was shortened to " + className + " due to filesystem limitations.");
}
return dir + File.separator + packageName.replace(".", File.separator) +
((packageName.length() == 0) ? "" : File.separator) +
className + ".java";
}
示例29
public static ClassSignature parseClassSignature(ConstantPoolEntryUTF8 signature, ConstantPool cp) {
final String sig = signature.getValue();
int curridx = 0;
/*
* Optional formal type parameters
*/
Pair<Integer, List<FormalTypeParameter>> formalTypeParametersRes = parseFormalTypeParameters(sig, cp, curridx);
curridx = formalTypeParametersRes.getFirst();
List<FormalTypeParameter> formalTypeParameters = formalTypeParametersRes.getSecond();
/*
* Superclass signature.
*/
String superClassSignatureTok = getNextTypeTok(sig, curridx);
curridx += superClassSignatureTok.length();
JavaTypeInstance superClassSignature = decodeTypeTok(superClassSignatureTok, cp);
List<JavaTypeInstance> interfaceClassSignatures = ListFactory.newList();
while (curridx < sig.length()) {
String interfaceSignatureTok = getNextTypeTok(sig, curridx);
curridx += interfaceSignatureTok.length();
interfaceClassSignatures.add(decodeTypeTok(interfaceSignatureTok, cp));
}
return new ClassSignature(formalTypeParameters, superClassSignature, interfaceClassSignatures);
}
示例30
public Dumper getNewTopLevelDumper(JavaTypeInstance classType, SummaryDumper summaryDumper, TypeUsageInformation typeUsageInformation, IllegalIdentifierDump illegalIdentifierDump) {
Pair<String, Boolean> targetInfo = getPathAndClobber();
if (targetInfo == null) return new StdIODumper(typeUsageInformation, options, illegalIdentifierDump, new MovableDumperContext());
FileDumper res = new FileDumper(targetInfo.getFirst() + prefix, targetInfo.getSecond(), classType, summaryDumper, typeUsageInformation, options, illegalIdentifierDump);
if (checkDupes) {
if (!seen.add(res.getFileName().toLowerCase())) {
seenCaseDupe = true;
}
}
return res;
}