boolean (final DiffState state, final ClassRepr.Diff diff, final ClassRepr classRepr) { final Collection<FieldRepr> added = diff.fields().added(); if (added.isEmpty()) { return true; } debug("Processing added fields"); assert myFuture != null; assert myPresent != null; assert myCompiledFiles != null; assert myAffectedFiles != null; if (classRepr.isEnum()) { debug("Constants added to enum, affecting class usages ", classRepr.name); final UsageRepr.Usage usage = classRepr.createUsage(); state.myAffectedUsages.add(usage); // only mark synthetic classes used to implement switch statements: this will limit the number of recompiled classes to those where switch statements on changed enum are used state.myUsageConstraints.put(usage, residence -> { for (ClassRepr candidate : myPresent.reprsByName(residence, ClassRepr.class)) { if (candidate.isSynthetic()) { return true; } } return false; }); } for (final FieldRepr addedField : added) { debug("Field: ", addedField.name); if (!addedField.isPrivate()) { IntSet changedClassWithSubclasses = myFuture.propagateFieldAccess(addedField.name, classRepr.name); changedClassWithSubclasses.add(classRepr.name); changedClassWithSubclasses.forEach(subClass -> { final Iterable<ClassRepr> reprs = Iterators.collect(myFuture.reprsByName(subClass, ClassRepr.class), new SmartList<>()); if (!Iterators.isEmpty(reprs)) { final Iterable<File> sourceFileNames = classToSourceFileGet(subClass); if (sourceFileNames != null && !containsAll(myCompiledFiles, sourceFileNames)) { for (ClassRepr r : reprs) { if (r.isLocal()) { for (File sourceFileName : sourceFileNames) { debug("Affecting local subclass (introduced field can potentially hide surrounding method parameters/local variables): ", sourceFileName); myAffectedFiles.add(sourceFileName); } break; } else { final int outerClass = r.getOuterClassName(); if (!isEmpty(outerClass) && myFuture.isFieldVisible(outerClass, addedField)) { for (File sourceFileName : sourceFileNames) { debug("Affecting inner subclass (introduced field can potentially hide surrounding class fields): ", sourceFileName); myAffectedFiles.add(sourceFileName); } break; } } } } } debug("Affecting field usages referenced from subclass ", subClass); myFuture.affectFieldUsages(addedField, IntSet.of(), addedField.createUsage(myContext, subClass), state.myAffectedUsages, state.myDependants); if (addedField.isStatic()) { myFuture.affectStaticMemberOnDemandUsages(subClass, IntSet.of(), state.myAffectedUsages, state.myDependants); } myFuture.appendDependents(subClass, state.myDependants); }); } final Collection<Pair<FieldRepr, ClassRepr>> overriddenFields = new HashSet<>(); myFuture.addOverriddenFields(addedField, classRepr, overriddenFields, null, classRepr); for (final Pair<FieldRepr, ClassRepr> p : overriddenFields) { final FieldRepr overridden = p.first; final ClassRepr cc = p.second; if (!overridden.isPrivate()) { debug("Affecting usages of overridden field in class ", cc.name); myFuture.affectFieldUsages(overridden, myPresent.propagateFieldAccess(overridden.name, cc.name), overridden.createUsage(myContext, cc.name), state.myAffectedUsages, state.myDependants); } } } debug("End of added fields processing"); return true; }