mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
support of "constant search" callbacks on the build-process side
This commit is contained in:
@@ -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) {
|
||||
|
||||
+3
-1
@@ -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
|
||||
);
|
||||
|
||||
|
||||
+2
-1
@@ -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)) {
|
||||
|
||||
Reference in New Issue
Block a user