Skip to content

Commit

Permalink
generify SyntheticAccessRecorder
Browse files Browse the repository at this point in the history
... to allow fixing synthetic accesses for objects other than `RawAccessRecord`. We will now also need this for other raw import objects like `RawReferencedClassObject`, since these declarations can also take place within lambdas.

Signed-off-by: Peter Gafert <[email protected]>
  • Loading branch information
codecholeric committed Nov 21, 2022
1 parent 736ffb6 commit 710b565
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -245,9 +245,9 @@ private static class RawAccessRecordProcessed<TARGET extends AccessTarget> imple
RawAccessRecordProcessed(RawAccessRecord record, ImportedClasses classes, AccessTargetFactory<TARGET> accessTargetFactory) {
this.record = record;
this.classes = classes;
targetOwner = this.classes.getOrResolve(record.target.owner.getFullyQualifiedClassName());
targetOwner = this.classes.getOrResolve(record.getTarget().owner.getFullyQualifiedClassName());
this.accessTargetFactory = accessTargetFactory;
originSupplier = createOriginSupplier(record.caller, classes);
originSupplier = createOriginSupplier(record.getOrigin(), classes);
}

@Override
Expand All @@ -257,17 +257,17 @@ public JavaCodeUnit getOrigin() {

@Override
public TARGET getTarget() {
return accessTargetFactory.create(targetOwner, record.target, classes);
return accessTargetFactory.create(targetOwner, record.getTarget(), classes);
}

@Override
public int getLineNumber() {
return record.lineNumber;
return record.getLineNumber();
}

@Override
public boolean isDeclaredInLambda() {
return record.declaredInLambda;
return record.isDeclaredInLambda();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,13 +217,13 @@ Set<TryCatchBlockBuilder> getTryCatchBlockBuildersFor(JavaCodeUnit codeUnit) {
}

void registerFieldAccess(RawAccessRecord.ForField record) {
if (!isSyntheticEnumSwitchMapFieldName(record.target.name)) {
if (!isSyntheticEnumSwitchMapFieldName(record.getTarget().name)) {
rawFieldAccessRecords.add(record);
}
}

void registerMethodCall(RawAccessRecord record) {
if (isSyntheticAccessMethodName(record.target.name)) {
if (isSyntheticAccessMethodName(record.getTarget().name)) {
syntheticPrivateAccessRecorder.registerSyntheticMethodInvocation(record);
} else {
rawMethodCallRecords.add(record);
Expand Down Expand Up @@ -281,9 +281,9 @@ void forEachRawConstructorReferenceRecord(Consumer<RawAccessRecord> doWithRecord
).forEach(doWithRecord);
}

private <ACCESS extends RawAccessRecord> Stream<ACCESS> fixSyntheticOrigins(
private <ACCESS extends RawCodeUnitDependency<?>> Stream<ACCESS> fixSyntheticOrigins(
Set<ACCESS> rawAccessRecordsIncludingSyntheticAccesses,
Function<ACCESS, ? extends RawAccessRecord.BaseBuilder<ACCESS, ?>> createAccessWithNewOrigin,
Function<ACCESS, ? extends RawCodeUnitDependencyBuilder<ACCESS, ?>> createAccessWithNewOrigin,
SyntheticAccessRecorder... syntheticAccessRecorders
) {

Expand All @@ -303,33 +303,34 @@ Map<String, JavaClass> getClasses() {
}

private static final Function<RawAccessRecord, RawAccessRecord.Builder> COPY_RAW_ACCESS_RECORD =
access -> new RawAccessRecord.Builder()
.withCaller(access.caller)
.withTarget(access.target)
.withLineNumber(access.lineNumber)
.withDeclaredInLambda(access.declaredInLambda);
access -> copyInto(new RawAccessRecord.Builder(), access);

private static final Function<RawAccessRecord.ForField, RawAccessRecord.ForField.Builder> COPY_RAW_FIELD_ACCESS_RECORD =
access -> new RawAccessRecord.ForField.Builder()
.withCaller(access.caller)
.withAccessType(access.accessType)
.withTarget(access.target)
.withLineNumber(access.lineNumber)
.withDeclaredInLambda(access.declaredInLambda);
access -> copyInto(new RawAccessRecord.ForField.Builder(), access)
.withAccessType(access.accessType);

private static <TARGET, BUILDER extends RawCodeUnitDependencyBuilder<?, TARGET>> BUILDER copyInto(BUILDER builder, RawCodeUnitDependency<TARGET> referencedClassObject) {
builder
.withOrigin(referencedClassObject.getOrigin())
.withTarget(referencedClassObject.getTarget())
.withLineNumber(referencedClassObject.getLineNumber())
.withDeclaredInLambda(referencedClassObject.isDeclaredInLambda());
return builder;
}

private static SyntheticAccessRecorder createSyntheticLambdaAccessRecorder() {
return new SyntheticAccessRecorder(
codeUnit -> isLambdaMethodName(codeUnit.getName()),
(accessBuilder, newOrigin) -> accessBuilder
.withCaller(newOrigin)
.withOrigin(newOrigin)
.withDeclaredInLambda(true)
);
}

private static SyntheticAccessRecorder createSyntheticPrivateAccessRecorder() {
return new SyntheticAccessRecorder(
codeUnit -> isSyntheticAccessMethodName(codeUnit.getName()),
RawAccessRecord.BaseBuilder::withCaller
RawCodeUnitDependencyBuilder::withOrigin
);
}

Expand Down Expand Up @@ -377,54 +378,51 @@ Optional<CodeUnit> getEnclosingCodeUnit(String ownerName) {
private static class SyntheticAccessRecorder {
private final SetMultimap<String, RawAccessRecord> rawSyntheticMethodInvocationRecordsByTarget = HashMultimap.create();
private final Predicate<CodeUnit> isSyntheticOrigin;
private final BiConsumer<RawAccessRecord.BaseBuilder<?, ?>, CodeUnit> fixOrigin;
private final BiConsumer<RawCodeUnitDependencyBuilder<?, ?>, CodeUnit> fixOrigin;

SyntheticAccessRecorder(
Predicate<CodeUnit> isSyntheticOrigin,
BiConsumer<RawAccessRecord.BaseBuilder<?, ?>, CodeUnit> fixOrigin
BiConsumer<RawCodeUnitDependencyBuilder<?, ?>, CodeUnit> fixOrigin
) {
this.isSyntheticOrigin = isSyntheticOrigin;
this.fixOrigin = fixOrigin;
}

void registerSyntheticMethodInvocation(RawAccessRecord record) {
rawSyntheticMethodInvocationRecordsByTarget.put(getMemberKey(record.target), record);
rawSyntheticMethodInvocationRecordsByTarget.put(getMemberKey(record.getTarget()), record);
}

<ACCESS extends RawAccessRecord> Set<ACCESS> fixSyntheticAccess(
<ACCESS extends RawCodeUnitDependency<?>> Set<ACCESS> fixSyntheticAccess(
ACCESS access,
Function<ACCESS, ? extends RawAccessRecord.BaseBuilder<ACCESS, ?>> copyAccess
Function<ACCESS, ? extends RawCodeUnitDependencyBuilder<ACCESS, ?>> copyAccess
) {
return isSyntheticOrigin.test(access.caller)
return isSyntheticOrigin.test(access.getOrigin())
? replaceOriginByFixedOrigin(access, copyAccess)
: singleton(access);
}

private <ACCESS extends RawAccessRecord> Set<ACCESS> replaceOriginByFixedOrigin(
private <ACCESS extends RawCodeUnitDependency<?>> Set<ACCESS> replaceOriginByFixedOrigin(
ACCESS accessFromSyntheticMethod,
Function<ACCESS, ? extends RawAccessRecord.BaseBuilder<ACCESS, ?>> copyAccess
Function<ACCESS, ? extends RawCodeUnitDependencyBuilder<ACCESS, ?>> copyAccess
) {
Set<ACCESS> result = findNonSyntheticOriginOf(accessFromSyntheticMethod)
.map(accessWithCorrectOrigin -> {
RawAccessRecord.BaseBuilder<ACCESS, ?> copiedBuilder = copyAccess.apply(accessFromSyntheticMethod);
fixOrigin.accept(copiedBuilder, accessWithCorrectOrigin.caller);
RawCodeUnitDependencyBuilder<ACCESS, ?> copiedBuilder = copyAccess.apply(accessFromSyntheticMethod);
fixOrigin.accept(copiedBuilder, accessWithCorrectOrigin.getOrigin());
return copiedBuilder.build();
})
.collect(toSet());

if (result.isEmpty()) {
log.warn("Could not find matching origin for synthetic method {}.{}|{}",
accessFromSyntheticMethod.target.getDeclaringClassName(),
accessFromSyntheticMethod.target.name,
accessFromSyntheticMethod.target.getDescriptor());
log.warn("Could not find matching origin for synthetic method {}", accessFromSyntheticMethod);
}

return result;
}

private <ACCESS extends RawAccessRecord> Stream<RawAccessRecord> findNonSyntheticOriginOf(ACCESS access) {
return isSyntheticOrigin.test(access.caller)
? rawSyntheticMethodInvocationRecordsByTarget.get(getMemberKey(access.caller)).stream().flatMap(this::findNonSyntheticOriginOf)
private <ACCESS extends RawCodeUnitDependency<?>> Stream<RawCodeUnitDependency<?>> findNonSyntheticOriginOf(ACCESS access) {
return isSyntheticOrigin.test(access.getOrigin())
? rawSyntheticMethodInvocationRecordsByTarget.get(getMemberKey(access.getOrigin())).stream().flatMap(this::findNonSyntheticOriginOf)
: Stream.of(access);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ public void onTryCatchBlocksFinished(Set<TryCatchBlockBuilder> tryCatchBlocks) {

private <BUILDER extends RawAccessRecord.BaseBuilder<?, BUILDER>> BUILDER filled(BUILDER builder, TargetInfo target) {
return builder
.withCaller(codeUnit)
.withOrigin(codeUnit)
.withTarget(target)
.withLineNumber(lineNumber);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,26 +25,46 @@

import static com.google.common.base.Preconditions.checkNotNull;

class RawAccessRecord {
final CodeUnit caller;
final TargetInfo target;
final int lineNumber;
final boolean declaredInLambda;

RawAccessRecord(CodeUnit caller, TargetInfo target, int lineNumber, boolean declaredInLambda) {
this.caller = checkNotNull(caller);
class RawAccessRecord implements RawCodeUnitDependency<RawAccessRecord.TargetInfo> {
private final CodeUnit origin;
private final TargetInfo target;
private final int lineNumber;
private final boolean declaredInLambda;

RawAccessRecord(CodeUnit origin, TargetInfo target, int lineNumber, boolean declaredInLambda) {
this.origin = checkNotNull(origin);
this.target = checkNotNull(target);
this.lineNumber = lineNumber;
this.declaredInLambda = declaredInLambda;
}

@Override
public CodeUnit getOrigin() {
return origin;
}

@Override
public TargetInfo getTarget() {
return target;
}

@Override
public int getLineNumber() {
return lineNumber;
}

@Override
public boolean isDeclaredInLambda() {
return declaredInLambda;
}

@Override
public String toString() {
return getClass().getSimpleName() + "{" + fieldsAsString() + '}';
}

private String fieldsAsString() {
return "caller=" + caller + ", target=" + target + ", lineNumber=" + lineNumber;
return "origin=" + origin + ", target=" + target + ", lineNumber=" + lineNumber + ", declaredInLambda=" + declaredInLambda;
}

interface MemberSignature {
Expand Down Expand Up @@ -195,33 +215,37 @@ public String toString() {

static class Builder extends BaseBuilder<RawAccessRecord, Builder> {
@Override
RawAccessRecord build() {
return new RawAccessRecord(caller, target, lineNumber, declaredInLambda);
public RawAccessRecord build() {
return new RawAccessRecord(origin, target, lineNumber, declaredInLambda);
}
}

abstract static class BaseBuilder<ACCESS extends RawAccessRecord, SELF extends BaseBuilder<ACCESS, SELF>> {
CodeUnit caller;
abstract static class BaseBuilder<ACCESS extends RawAccessRecord, SELF extends BaseBuilder<ACCESS, SELF>> implements RawCodeUnitDependencyBuilder<ACCESS, TargetInfo> {
CodeUnit origin;
TargetInfo target;
int lineNumber = -1;
boolean declaredInLambda = false;

SELF withCaller(CodeUnit caller) {
this.caller = caller;
@Override
public SELF withOrigin(CodeUnit origin) {
this.origin = origin;
return self();
}

SELF withTarget(TargetInfo target) {
@Override
public SELF withTarget(TargetInfo target) {
this.target = target;
return self();
}

SELF withLineNumber(int lineNumber) {
@Override
public SELF withLineNumber(int lineNumber) {
this.lineNumber = lineNumber;
return self();
}

SELF withDeclaredInLambda(boolean declaredInLambda) {
@Override
public SELF withDeclaredInLambda(boolean declaredInLambda) {
this.declaredInLambda = declaredInLambda;
return self();
}
Expand All @@ -230,15 +254,13 @@ SELF withDeclaredInLambda(boolean declaredInLambda) {
SELF self() {
return (SELF) this;
}

abstract ACCESS build();
}

static class ForField extends RawAccessRecord {
final AccessType accessType;

private ForField(CodeUnit caller, TargetInfo target, int lineNumber, AccessType accessType, boolean declaredInLambda) {
super(caller, target, lineNumber, declaredInLambda);
private ForField(CodeUnit origin, TargetInfo target, int lineNumber, AccessType accessType, boolean declaredInLambda) {
super(origin, target, lineNumber, declaredInLambda);
this.accessType = accessType;
}

Expand All @@ -251,8 +273,8 @@ Builder withAccessType(AccessType accessType) {
}

@Override
ForField build() {
return new ForField(super.caller, super.target, super.lineNumber, accessType, declaredInLambda);
public ForField build() {
return new ForField(super.origin, super.target, super.lineNumber, accessType, declaredInLambda);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright 2014-2022 TNG Technology Consulting GmbH
*
* 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 com.tngtech.archunit.core.importer;

interface RawCodeUnitDependency<TARGET> {
RawAccessRecord.CodeUnit getOrigin();

TARGET getTarget();

int getLineNumber();

boolean isDeclaredInLambda();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright 2014-2022 TNG Technology Consulting GmbH
*
* 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 com.tngtech.archunit.core.importer;

import com.tngtech.archunit.core.importer.RawAccessRecord.CodeUnit;

interface RawCodeUnitDependencyBuilder<CODE_UNIT_DEPENDENCY extends RawCodeUnitDependency<TARGET>, TARGET> {
RawCodeUnitDependencyBuilder<CODE_UNIT_DEPENDENCY, TARGET> withOrigin(CodeUnit origin);

RawCodeUnitDependencyBuilder<CODE_UNIT_DEPENDENCY, TARGET> withTarget(TARGET target);

RawCodeUnitDependencyBuilder<CODE_UNIT_DEPENDENCY, TARGET> withLineNumber(int lineNumber);

RawCodeUnitDependencyBuilder<CODE_UNIT_DEPENDENCY, TARGET> withDeclaredInLambda(boolean declaredInLambda);

CODE_UNIT_DEPENDENCY build();
}

0 comments on commit 710b565

Please sign in to comment.