support of "constant search" callbacks on the build-process side

This commit is contained in:
Eugene Zhuravlev
2012-05-03 17:42:23 +02:00
parent 8fef46c346
commit 5342890aa5
20 changed files with 1700 additions and 125 deletions
@@ -553,7 +553,7 @@ public class CompileDriver {
}
@Override
public void handleFailure(CmdlineRemoteProto.Message.Failure failure) {
public void handleFailure(UUID sessionId, CmdlineRemoteProto.Message.Failure failure) {
compileContext.addMessage(CompilerMessageCategory.ERROR, failure.getDescription(), null, -1, -1);
final String trace = failure.getStacktrace();
if (trace != null) {
@@ -279,7 +279,8 @@ public class ChangedConstantsDependencyProcessor {
}
*/
private PsiField getOwnerField(PsiElement element) {
@Nullable
private static PsiField getOwnerField(PsiElement element) {
while (!(element instanceof PsiFile)) {
if (element instanceof PsiClass) {
break;
@@ -292,6 +293,7 @@ public class ChangedConstantsDependencyProcessor {
return null;
}
@Nullable
private FieldChangeInfo findChangeInfo(PsiField field) throws CacheCorruptedException {
String name = field.getName();
for (final FieldChangeInfo changeInfo : myChangedFields) {
@@ -29,6 +29,7 @@ import com.intellij.problems.WolfTheProblemSolver;
import org.jetbrains.jps.api.CmdlineRemoteProto;
import java.util.Collections;
import java.util.UUID;
/**
* @author Eugene Zhuravlev
@@ -83,7 +84,7 @@ class AutoMakeMessageHandler extends DefaultMessageHandler {
}
@Override
public void handleFailure(CmdlineRemoteProto.Message.Failure failure) {
public void handleFailure(UUID sessionId, CmdlineRemoteProto.Message.Failure failure) {
CompilerManager.NOTIFICATION_GROUP.createNotification("Auto make failure: " + failure.getDescription(), MessageType.INFO);
}
@@ -369,7 +369,7 @@ public class BuildManager implements ApplicationComponent{
}
catch (Exception e) {
myMessageDispatcher.unregisterBuildMessageHandler(sessionId);
handler.handleFailure(CmdlineProtoUtil.createFailure(e.getMessage(), null));
handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure(e.getMessage(), null));
handler.sessionTerminated();
return null;
}
@@ -421,7 +421,7 @@ public class BuildManager implements ApplicationComponent{
}
catch (ExecutionException e) {
myMessageDispatcher.unregisterBuildMessageHandler(sessionId);
future.getMessageHandler().handleFailure(CmdlineProtoUtil.createFailure(e.getMessage(), e));
future.getMessageHandler().handleFailure(sessionId, CmdlineProtoUtil.createFailure(e.getMessage(), e));
future.getMessageHandler().sessionTerminated();
}
finally {
@@ -107,7 +107,7 @@ class BuildMessageDispatcher extends SimpleChannelHandler {
final CmdlineRemoteProto.Message.Type messageType = message.getType();
switch (messageType) {
case FAILURE:
handler.handleFailure(message.getFailure());
handler.handleFailure(sessionId, message.getFailure());
break;
case BUILDER_MESSAGE:
@@ -124,7 +124,7 @@ class BuildMessageDispatcher extends SimpleChannelHandler {
}
}
else {
handler.handleBuildMessage(builderMessage);
handler.handleBuildMessage(ctx.getChannel(), sessionId, builderMessage);
}
break;
@@ -15,16 +15,19 @@
*/
package com.intellij.compiler.server;
import org.jboss.netty.channel.Channel;
import org.jetbrains.jps.api.CmdlineRemoteProto;
import java.util.UUID;
/**
* @author Eugene Zhuravlev
* Date: 4/25/12
*/
public interface BuilderMessageHandler {
void handleBuildMessage(CmdlineRemoteProto.Message.BuilderMessage msg);
void handleBuildMessage(Channel channel, UUID sessionId, CmdlineRemoteProto.Message.BuilderMessage msg);
void handleFailure(CmdlineRemoteProto.Message.Failure failure);
void handleFailure(UUID sessionId, CmdlineRemoteProto.Message.Failure failure);
void sessionTerminated();
}
@@ -15,15 +15,20 @@
*/
package com.intellij.compiler.server;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.Channels;
import org.jetbrains.jps.api.CmdlineProtoUtil;
import org.jetbrains.jps.api.CmdlineRemoteProto;
import java.util.UUID;
/**
* @author Eugene Zhuravlev
* Date: 4/18/12
*/
public abstract class DefaultMessageHandler implements BuilderMessageHandler {
@Override
public final void handleBuildMessage(CmdlineRemoteProto.Message.BuilderMessage msg) {
public final void handleBuildMessage(Channel channel, UUID sessionId, CmdlineRemoteProto.Message.BuilderMessage msg) {
switch (msg.getType()) {
case BUILD_EVENT:
handleBuildEvent(msg.getBuildEvent());
@@ -31,9 +36,23 @@ public abstract class DefaultMessageHandler implements BuilderMessageHandler {
case COMPILE_MESSAGE:
handleCompileMessage(msg.getCompileMessage());
break;
case CONSTANT_SEARCH_TASK:
handleConstantSearchTask(channel, sessionId, msg.getConstantSearchTask());
}
}
protected void handleConstantSearchTask(Channel channel, UUID sessionId, CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask task) {
// todo: complete impl
final CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult.Builder builder =
CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult.newBuilder();
builder.setOwnerClassName(task.getOwnerClassName());
builder.setFieldName(task.getFieldName());
builder.setIsSuccess(false); // todo
Channels.write(channel, CmdlineProtoUtil.toMessage(sessionId, CmdlineRemoteProto.Message.ControllerMessage.newBuilder().setType(
CmdlineRemoteProto.Message.ControllerMessage.Type.CONSTANT_SEARCH_RESULT).setConstantSearchResult(builder.build()).build()
));
}
protected abstract void handleCompileMessage(CmdlineRemoteProto.Message.BuilderMessage.CompileMessage message);
protected abstract void handleBuildEvent(CmdlineRemoteProto.Message.BuilderMessage.BuildEvent event);
@@ -32,6 +32,7 @@ message Message {
BUILD_PARAMETERS = 1;
CANCEL_BUILD_COMMAND = 2;
FS_EVENT = 3;
CONSTANT_SEARCH_RESULT = 4;
}
message FSEvent {
@@ -74,9 +75,17 @@ message Message {
repeated KeyValuePair builder_parameter = 7;
}
message ConstantSearchResult {
required string owner_class_name = 1;
required string field_name = 2;
required bool is_success = 3;
repeated string path = 4;
}
required Type type = 1;
optional ParametersMessage params_message = 2;
optional FSEvent fs_event = 3;
optional ConstantSearchResult constant_search_result = 4;
}
message BuilderMessage {
@@ -84,6 +93,7 @@ message Message {
PARAM_REQUEST = 1;
BUILD_EVENT = 2;
COMPILE_MESSAGE = 3;
CONSTANT_SEARCH_TASK = 4;
}
message BuildEvent {
@@ -128,9 +138,18 @@ message Message {
optional float done = 9;
}
message ConstantSearchTask {
required string owner_class_name = 1;
required string field_name = 2;
required int32 access_flags = 3;
optional bool is_access_changed = 4 [default = false];
optional bool is_field_removed = 5 [default = false];
}
required Type type = 1;
optional BuildEvent build_event = 2;
optional CompileMessage compile_message = 3;
optional ConstantSearchTask constant_search_task = 4;
}
required UUID session_id = 1;
@@ -0,0 +1,80 @@
package org.jetbrains.jps.api;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* @author Eugene Zhuravlev
* Date: 5/3/12
*/
public class BasicFuture<T> implements Future<T> {
protected final Semaphore mySemaphore = new Semaphore(1);
private final AtomicBoolean myDone = new AtomicBoolean(false);
private final AtomicBoolean myCanceledState = new AtomicBoolean(false);
public BasicFuture() {
}
public void setDone() {
if (!myDone.getAndSet(true)) {
mySemaphore.release();
}
}
public boolean cancel(boolean mayInterruptIfRunning) {
if (isDone()) {
return false;
}
if (!myCanceledState.getAndSet(true)) {
try {
performCancel();
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
return true;
}
protected void performCancel() throws Exception {
}
public boolean isCancelled() {
return myCanceledState.get();
}
public boolean isDone() {
return myDone.get();
}
public void waitFor() {
try {
while (!isDone()) {
mySemaphore.tryAcquire(100L, TimeUnit.MILLISECONDS);
}
}
catch (InterruptedException ignored) {
}
}
public boolean waitFor(long timeout, TimeUnit unit) {
try {
if (!isDone()) {
mySemaphore.tryAcquire(timeout, unit);
}
}
catch (InterruptedException ignored) {
}
return isDone();
}
public T get() throws InterruptedException, ExecutionException {
waitFor();
return null;
}
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
waitFor(timeout, unit);
return null;
}
}
File diff suppressed because it is too large Load Diff
@@ -18,99 +18,40 @@ package org.jetbrains.jps.api;
import org.jetbrains.annotations.Nullable;
import java.util.UUID;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* @author Eugene Zhuravlev
* Date: 9/13/11
*/
public class RequestFuture<T> implements Future {
private final Semaphore mySemaphore = new Semaphore(1);
private final AtomicBoolean myDone = new AtomicBoolean(false);
public class RequestFuture<T> extends BasicFuture<T> {
private final T myHandler;
private final UUID myRequestID;
@Nullable private final CancelAction<T> myCancelAction;
private final AtomicBoolean myCanceledState = new AtomicBoolean(false);
public interface CancelAction<T> {
void cancel(RequestFuture<T> future) throws Exception;
}
public RequestFuture(T handler, UUID requestID, @Nullable CancelAction<T> cancelAction) {
super();
myCancelAction = cancelAction;
myHandler = handler;
myRequestID = requestID;
myCancelAction = cancelAction;
mySemaphore.acquireUninterruptibly();
}
public void setDone() {
if (!myDone.getAndSet(true)) {
mySemaphore.release();
}
}
public UUID getRequestID() {
return myRequestID;
}
public boolean cancel(boolean mayInterruptIfRunning) {
if (isDone()) {
return false;
}
if (!myCanceledState.getAndSet(true)) {
try {
if (myCancelAction != null) {
myCancelAction.cancel(this);
}
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
return true;
}
public boolean isCancelled() {
return myCanceledState.get();
}
public boolean isDone() {
return myDone.get();
}
public void waitFor() {
try {
while (!isDone()) {
mySemaphore.tryAcquire(100L, TimeUnit.MILLISECONDS);
}
}
catch (InterruptedException ignored) {
}
}
public boolean waitFor(long timeout, TimeUnit unit) {
try {
if (!isDone()) {
mySemaphore.tryAcquire(timeout, unit);
}
}
catch (InterruptedException ignored) {
}
return isDone();
}
public Object get() throws InterruptedException, ExecutionException {
waitFor();
return null;
}
public Object get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
waitFor(timeout, unit);
return null;
}
public T getMessageHandler() {
return myHandler;
}
@Override
protected void performCancel() throws Exception {
if (myCancelAction != null) {
myCancelAction.cancel(this);
}
}
}
@@ -110,6 +110,14 @@ public class BuildMain {
return;
}
case CONSTANT_SEARCH_RESULT: {
final BuildSession session = mySession;
if (session != null) {
session.processConstantSearchResult(controllerMessage.getConstantSearchResult());
}
return;
}
case CANCEL_BUILD_COMMAND: {
final BuildSession session = mySession;
if (session != null) {
@@ -15,6 +15,7 @@ import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.Channels;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.ether.dependencyView.Callbacks;
import org.jetbrains.jps.Library;
import org.jetbrains.jps.Module;
import org.jetbrains.jps.Project;
@@ -34,6 +35,10 @@ import org.jetbrains.jps.server.ProjectDescriptor;
import java.io.*;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
/**
@@ -65,6 +70,8 @@ final class BuildSession implements Runnable, CanceledStatus {
private EventsProcessor myEventsProcessor = new EventsProcessor();
private volatile long myLastEventOrdinal;
private volatile ProjectDescriptor myProjectDescriptor;
private final Map<Pair<String, String>, ConstantSearchFuture> mySearchTasks = Collections.synchronizedMap(new HashMap<Pair<String, String>, ConstantSearchFuture>());
private final ConstantSearch myConstantSearch = new ConstantSearch();
BuildSession(UUID sessionId,
Channel channel,
@@ -208,7 +215,7 @@ final class BuildSession implements Runnable, CanceledStatus {
final Timestamps timestamps = pd.timestamps.getStorage();
final CompileScope compileScope = createCompilationScope(buildType, pd, timestamps, modules, artifacts, paths);
final IncProjectBuilder builder = new IncProjectBuilder(pd, BuilderRegistry.getInstance(), timestamps, builderParams, cs);
final IncProjectBuilder builder = new IncProjectBuilder(pd, BuilderRegistry.getInstance(), timestamps, builderParams, cs, myConstantSearch);
builder.addMessageHandler(msgHandler);
try {
switch (buildType) {
@@ -262,6 +269,23 @@ final class BuildSession implements Runnable, CanceledStatus {
});
}
public void processConstantSearchResult(CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult result) {
final ConstantSearchFuture future = mySearchTasks.remove(Pair.create(result.getOwnerClassName(), result.getFieldName()));
if (future != null) {
if (result.getIsSuccess()) {
final List<String> paths = result.getPathList();
final List<File> files = new ArrayList<File>(paths.size());
for (String path : paths) {
files.add(new File(path));
}
future.setResult(files);
}
else {
future.setDone();
}
}
}
private void applyFSEvent(ProjectDescriptor pd, @Nullable CmdlineRemoteProto.Message.ControllerMessage.FSEvent event) throws IOException {
if (event == null) {
return;
@@ -600,4 +624,52 @@ final class BuildSession implements Runnable, CanceledStatus {
}
}
}
private class ConstantSearch implements Callbacks.ConstantAffectionResolver {
@Nullable @Override
public Future<Callbacks.ConstantAffection> request(String ownerClassName, String fieldName, int accessFlags, boolean fieldRemoved, boolean accessChanged) {
final CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask.Builder task =
CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask.newBuilder();
task.setOwnerClassName(ownerClassName);
task.setFieldName(fieldName);
task.setAccessFlags(accessFlags);
task.setIsAccessChanged(accessChanged);
task.setIsFieldRemoved(fieldRemoved);
final ConstantSearchFuture future = new ConstantSearchFuture();
final ConstantSearchFuture prev = mySearchTasks.put(new Pair<String, String>(ownerClassName, fieldName), future);
if (prev != null) {
prev.setDone();
}
Channels.write(myChannel,
CmdlineProtoUtil.toMessage(
mySessionId, CmdlineRemoteProto.Message.BuilderMessage.newBuilder().setType(CmdlineRemoteProto.Message.BuilderMessage.Type.CONSTANT_SEARCH_TASK).setConstantSearchTask(task.build()).build()
)
);
return future;
}
}
private static class ConstantSearchFuture extends BasicFuture<Callbacks.ConstantAffection> {
private volatile Callbacks.ConstantAffection myResult = Callbacks.ConstantAffection.EMPTY;
private ConstantSearchFuture() {
}
public void setResult(final Collection<File> affectedFiles) {
myResult = new Callbacks.ConstantAffection(affectedFiles);
setDone();
}
@Override
public Callbacks.ConstantAffection get() throws InterruptedException, ExecutionException {
super.get();
return myResult;
}
@Override
public Callbacks.ConstantAffection get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
super.get(timeout, unit);
return myResult;
}
}
}
@@ -8,6 +8,8 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.io.MappingFailedException;
import com.intellij.util.io.PersistentEnumerator;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.ether.dependencyView.Callbacks;
import org.jetbrains.ether.dependencyView.Mappings;
import org.jetbrains.jps.*;
import org.jetbrains.jps.api.CanceledStatus;
@@ -49,6 +51,7 @@ public class IncProjectBuilder {
private final BuilderRegistry myBuilderRegistry;
private final Map<String, String> myBuilderParams;
private final CanceledStatus myCancelStatus;
@Nullable private final Callbacks.ConstantAffectionResolver myConstantSearch;
private ProjectChunks myProductionChunks;
private ProjectChunks myTestChunks;
private final List<MessageHandler> myMessageHandlers = new ArrayList<MessageHandler>();
@@ -70,11 +73,12 @@ public class IncProjectBuilder {
BuilderRegistry builderRegistry,
final Timestamps timestamps,
Map<String, String> builderParams,
CanceledStatus cs) {
CanceledStatus cs, @Nullable Callbacks.ConstantAffectionResolver constantSearch) {
myProjectDescriptor = pd;
myBuilderRegistry = builderRegistry;
myBuilderParams = builderParams;
myCancelStatus = cs;
myConstantSearch = constantSearch;
myProductionChunks = new ProjectChunks(pd.project, ClasspathKind.PRODUCTION_COMPILE);
myTestChunks = new ProjectChunks(pd.project, ClasspathKind.TEST_COMPILE);
myTotalModulesWork = (float)pd.rootsIndex.getTotalModuleCount() * 2; /* multiply by 2 to reflect production and test sources */
@@ -246,10 +250,12 @@ public class IncProjectBuilder {
}
private CompileContext createContext(CompileScope scope, boolean isMake, final boolean isProjectRebuild) throws ProjectBuildException {
return new CompileContext(
final CompileContext context = new CompileContext(
scope, myProjectDescriptor, isMake, isProjectRebuild, myProductionChunks, myTestChunks, myMessageDispatcher,
myBuilderParams, myTimestamps, myCancelStatus
);
ModuleLevelBuilder.CONSTANT_SEARCH_SERVICE.set(context, myConstantSearch);
return context;
}
private void cleanOutputRoots(CompileContext context) throws ProjectBuildException {
@@ -3,6 +3,7 @@ package org.jetbrains.jps.incremental;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import org.jetbrains.ether.dependencyView.Callbacks;
import org.jetbrains.ether.dependencyView.Mappings;
import org.jetbrains.jps.Module;
import org.jetbrains.jps.ModuleChunk;
@@ -25,6 +26,7 @@ public abstract class ModuleLevelBuilder extends Builder {
private static final Key<Set<File>> ALL_AFFECTED_FILES_KEY = Key.create("_all_affected_files_");
private static final Key<Set<File>> ALL_COMPILED_FILES_KEY = Key.create("_all_compiled_files_");
static final Key<Callbacks.ConstantAffectionResolver> CONSTANT_SEARCH_SERVICE = Key.create("_constant_search_service_");
private final BuilderCategory myCategory;
@@ -83,7 +85,7 @@ public abstract class ModuleLevelBuilder extends Builder {
final ModulesBasedFileFilter moduleBasedFilter = new ModulesBasedFileFilter(context, chunk);
final boolean incremental = globalMappings.differentiate(
delta, removedPaths, filesToCompile, allCompiledFiles, allAffectedFiles, moduleBasedFilter, null
delta, removedPaths, filesToCompile, allCompiledFiles, allAffectedFiles, moduleBasedFilter, CONSTANT_SEARCH_SERVICE.get(context)
);
if (LOG.isDebugEnabled()) {
@@ -181,7 +181,7 @@ class ServerState {
final Timestamps timestamps = pd.timestamps.getStorage();
final CompileScope compileScope = createCompilationScope(buildType, pd, timestamps, modules, artifacts, paths);
final IncProjectBuilder builder = new IncProjectBuilder(pd, BuilderRegistry.getInstance(), timestamps, builderParams, cs);
final IncProjectBuilder builder = new IncProjectBuilder(pd, BuilderRegistry.getInstance(), timestamps, builderParams, cs, null);
builder.addMessageHandler(msgHandler);
try {
switch (buildType) {
@@ -208,8 +208,8 @@ public abstract class IncrementalTestCase extends TestCase {
new BuildDataManager(dataStorageRoot, true), new BuildLoggingManager(new ArtifactBuilderLoggerImpl(), javaBuilderLogger));
try {
new IncProjectBuilder(
projectDescriptor, BuilderRegistry.getInstance(), projectDescriptor.timestamps.getStorage(), Collections.<String, String>emptyMap(), CanceledStatus.NULL
).build(
projectDescriptor, BuilderRegistry.getInstance(), projectDescriptor.timestamps.getStorage(), Collections.<String, String>emptyMap(), CanceledStatus.NULL,
null).build(
new AllProjectScope(project, Collections.<Artifact>emptySet(), true), false, true, false
);
@@ -220,8 +220,8 @@ public abstract class IncrementalTestCase extends TestCase {
}
new IncProjectBuilder(
projectDescriptor, BuilderRegistry.getInstance(), projectDescriptor.timestamps.getStorage(), Collections.<String, String>emptyMap(), CanceledStatus.NULL
).build(
projectDescriptor, BuilderRegistry.getInstance(), projectDescriptor.timestamps.getStorage(), Collections.<String, String>emptyMap(), CanceledStatus.NULL,
null).build(
new AllProjectScope(project, Collections.<Artifact>emptySet(), false), true, false, false
);
@@ -181,7 +181,8 @@ public abstract class ArtifactBuilderTestCase extends UsefulTestCase {
}
myArtifactBuilderLogger.clear();
final Timestamps timestamps = myDescriptor.timestamps.getStorage();
IncProjectBuilder builder = new IncProjectBuilder(myDescriptor, BuilderRegistry.getInstance(), timestamps, Collections.<String, String>emptyMap(), CanceledStatus.NULL);
IncProjectBuilder builder = new IncProjectBuilder(myDescriptor, BuilderRegistry.getInstance(), timestamps, Collections.<String, String>emptyMap(), CanceledStatus.NULL,
null);
final List<BuildMessage> errorMessages = new ArrayList<BuildMessage>();
final List<BuildMessage> infoMessages = new ArrayList<BuildMessage>();
builder.addMessageHandler(new MessageHandler() {
@@ -21,6 +21,7 @@ public class Callbacks {
}
public static class ConstantAffection {
public static final ConstantAffection EMPTY = new ConstantAffection();
private final boolean myKnown;
private final Collection<File> myAffectedFiles;
@@ -44,6 +45,10 @@ public class Callbacks {
}
public interface ConstantAffectionResolver {
Future<ConstantAffection> request(final String owner, final String name);
Future<ConstantAffection> request(final String ownerClassName,
final String fieldName,
int accessFlags,
boolean fieldRemoved,
boolean accessChanged);
}
}
@@ -772,10 +772,7 @@ public class Mappings {
}
}
private boolean incrementalDecision(final int owner,
final Proto member,
final Collection<File> affectedFiles,
final DependentFilesFilter filter) {
private boolean incrementalDecision(final int owner, final Proto member, final Collection<File> affectedFiles, final DependentFilesFilter filter) {
final boolean isField = member instanceof FieldRepr;
final Util self = new Util(this);
@@ -844,28 +841,25 @@ public class Mappings {
final Collection<File> compiledFiles,
final Collection<File> affectedFiles,
final DependentFilesFilter filter,
final Callbacks.ConstantAffectionResolver lastResort) {
@Nullable final Callbacks.ConstantAffectionResolver constantSearch) {
synchronized (myLock) {
class DelayedWorks {
class Triple {
final int owner;
final FieldRepr field;
@Nullable
final Future<Callbacks.ConstantAffection> affection;
private Triple(final int owner, final FieldRepr field, final Future<Callbacks.ConstantAffection> affection) {
private Triple(final int owner, final FieldRepr field, @Nullable final Future<Callbacks.ConstantAffection> affection) {
this.owner = owner;
this.field = field;
this.affection = affection;
}
Callbacks.ConstantAffection getAffection() {
if (affection == null) {
return null;
}
try {
return affection.get();
return affection != null? affection.get() : Callbacks.ConstantAffection.EMPTY;
}
catch (Exception e) {
throw new RuntimeException(e);
@@ -875,35 +869,46 @@ public class Mappings {
final Collection<Triple> myQueue = new LinkedList<Triple>();
void addConstantWork(final int owner, final FieldRepr field) {
myQueue.add(new Triple(owner, field, lastResort.request(myContext.getValue(owner), myContext.getValue(field.name))));
void addConstantWork(final int ownerClass, final FieldRepr changedField, final boolean isRemoved, boolean accessChanged) {
final Future<Callbacks.ConstantAffection> future;
if (constantSearch == null) {
future = null;
}
else {
final String className = myContext.getValue(ownerClass);
final String fieldName = myContext.getValue(changedField.name);
future = constantSearch.request(className.replace('/', '.'), fieldName, changedField.access, isRemoved, accessChanged);
}
myQueue.add(new Triple(ownerClass, changedField, future));
}
boolean doWork(final Collection<File> affectedFiles) {
debug("Starting delayed works.");
if (!myQueue.isEmpty()) {
debug("Starting delayed works.");
for (final Triple t : myQueue) {
final Callbacks.ConstantAffection affection = t.getAffection();
for (final Triple t : myQueue) {
final Callbacks.ConstantAffection affection = t.getAffection();
debug("Class: ", t.owner);
debug("Field: ", t.field.name);
debug("Class: ", t.owner);
debug("Field: ", t.field.name);
if (!affection.isKnown()) {
debug("No external dependency information available.");
debug("Trying to soften non-incremental decision.");
if (!incrementalDecision(t.owner, t.field, affectedFiles, filter)) {
debug("No luck.");
debug("End of delayed work, returning false.");
return false;
if (!affection.isKnown()) {
debug("No external dependency information available.");
debug("Trying to soften non-incremental decision.");
if (!incrementalDecision(t.owner, t.field, affectedFiles, filter)) {
debug("No luck.");
debug("End of delayed work, returning false.");
return false;
}
}
else {
debug("External dependency information retrieved.");
affectedFiles.addAll(affection.getAffectedFiles());
}
}
else {
debug("External dependency information retrieved.");
affectedFiles.addAll(affection.getAffectedFiles());
}
}
debug("End of delayed work, returning true.");
debug("End of delayed work, returning true.");
}
return true;
}
}
@@ -1472,8 +1477,8 @@ public class Mappings {
if ((f.access & Opcodes.ACC_PRIVATE) == 0 && (f.access & mask) == mask && f.hasValue()) {
debug("Field had value and was (non-private) final static => a switch to non-incremental mode requested");
if (lastResort != null) {
works.addConstantWork(it.name, f);
if (constantSearch != null) {
works.addConstantWork(it.name, f, true, false);
}
else {
if (!incrementalDecision(it.name, f, affectedFiles, filter)) {
@@ -1503,8 +1508,8 @@ public class Mappings {
if (harmful || valueChanged || (accessChanged && !d.weakedAccess())) {
debug("Inline field changed it's access or value => a switch to non-incremental mode requested");
if (lastResort != null) {
works.addConstantWork(it.name, field);
if (constantSearch != null) {
works.addConstantWork(it.name, field, false, accessChanged);
}
else {
if (!incrementalDecision(it.name, field, affectedFiles, filter)) {