diff --git a/jps/jps-builders/proto/javac_remote_proto.proto b/jps/jps-builders/proto/javac_remote_proto.proto index 1f280d6c9e92..c9991c036046 100644 --- a/jps/jps-builders/proto/javac_remote_proto.proto +++ b/jps/jps-builders/proto/javac_remote_proto.proto @@ -47,8 +47,9 @@ message Message { enum Type { BUILD_MESSAGE = 1; OUTPUT_OBJECT = 2; - BUILD_COMPLETED = 3; - REQUEST_ACK = 4; + CLASS_DATA = 3; + BUILD_COMPLETED = 4; + REQUEST_ACK = 5; } message CompileMessage { @@ -87,10 +88,18 @@ message Message { optional bytes content = 7; } + message ClassData { + required string class_name = 1; + repeated string import_statement = 2; + repeated string static_import = 3; + repeated string identifier = 4; + } + required Type response_type = 1; optional CompileMessage compile_message = 2; optional OutputObject output_object = 3; - optional bool completion_status = 4; + optional ClassData class_data = 4; + optional bool completion_status = 5; } required UUID session_id = 1; diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java index bfde575cf4d9..abcb48adad05 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java @@ -70,6 +70,8 @@ public class JavaBuilder extends ModuleLevelBuilder { private static final Key DELTA_MAPPINGS_CALLBACK_KEY = Key.create("_dependency_data_"); private final ExecutorService myTaskRunner; + private int myTasksInProgress = 0; + private final Object myCounterLock = new Object(); private final List myClassProcessors = new ArrayList(); public JavaBuilder(ExecutorService tasksExecutor) { @@ -375,10 +377,45 @@ public class JavaBuilder extends ModuleLevelBuilder { return rc; } finally { - classesConsumer.ensurePendingTasksCompleted(); + ensurePendingTasksCompleted(); } } + private void ensurePendingTasksCompleted() { + synchronized (myCounterLock) { + while (myTasksInProgress > 0) { + try { + myCounterLock.wait(); + } + catch (InterruptedException ignored) { + } + } + } + } + + private void submitAsyncTask(final Runnable taskRunnable) { + synchronized (myCounterLock) { + myTasksInProgress++; + } + myTaskRunner.submit(new Runnable() { + public void run() { + try { + taskRunnable.run(); + } + finally { + synchronized (myCounterLock) { + myTasksInProgress = Math.max(0, myTasksInProgress - 1); + if (myTasksInProgress == 0) { + myCounterLock.notifyAll(); + } + } + } + } + }); + } + + + private static JavacServerClient ensureJavacServerLaunched(CompileContext context) throws Exception { final ExternalJavacDescriptor descriptor = ExternalJavacDescriptor.KEY.get(context); if (descriptor != null) { @@ -736,7 +773,7 @@ public class JavaBuilder extends ModuleLevelBuilder { return version >= Opcodes.V1_6 && version != Opcodes.V1_1 ? ClassWriter.COMPUTE_FRAMES : ClassWriter.COMPUTE_MAXS; } - private static class DiagnosticSink implements DiagnosticOutputConsumer { + private class DiagnosticSink implements DiagnosticOutputConsumer { private final CompileContext myContext; private volatile int myErrorCount = 0; private volatile int myWarningCount = 0; @@ -745,6 +782,20 @@ public class JavaBuilder extends ModuleLevelBuilder { myContext = context; } + public void registerImports(final String className, final Collection imports, final Collection staticImports) { + submitAsyncTask(new Runnable() { + public void run() { + final Callbacks.Backend callback = DELTA_MAPPINGS_CALLBACK_KEY.get(myContext); + if (callback != null) { + final BuildDataManager dataManager = myContext.getDataManager(); + synchronized (dataManager.getMappings()) { + callback.registerImports(className, imports, staticImports); + } + } + } + }); + } + public void outputLineAvailable(String line) { if (!StringUtil.isEmpty(line)) { //if (line.startsWith("[") && line.endsWith("]")) { @@ -1068,8 +1119,6 @@ public class JavaBuilder extends ModuleLevelBuilder { private class ClassProcessingConsumer implements OutputFileConsumer { private final CompileContext myCompileContext; private final OutputFileConsumer myDelegateOutputFileSink; - private int myTasksInProgress = 0; - private final Object myCounterLock = new Object(); public ClassProcessingConsumer(CompileContext compileContext, OutputFileConsumer sink) { myCompileContext = compileContext; @@ -1081,8 +1130,7 @@ public class JavaBuilder extends ModuleLevelBuilder { } public void save(@NotNull final OutputFileObject fileObject) { - incTaskCount(); - myTaskRunner.submit(new Runnable() { + submitAsyncTask(new Runnable() { public void run() { try { for (ClassPostProcessor processor : myClassProcessors) { @@ -1090,43 +1138,10 @@ public class JavaBuilder extends ModuleLevelBuilder { } } finally { - try { - myDelegateOutputFileSink.save(fileObject); - } - finally { - decTaskCount(); - } + myDelegateOutputFileSink.save(fileObject); } } }); } - - private void decTaskCount() { - synchronized (myCounterLock) { - myTasksInProgress = Math.max(0, myTasksInProgress - 1); - if (myTasksInProgress == 0) { - myCounterLock.notifyAll(); - } - } - } - - private void incTaskCount() { - synchronized (myCounterLock) { - myTasksInProgress++; - } - } - - public void ensurePendingTasksCompleted() { - synchronized (myCounterLock) { - while (myTasksInProgress > 0) { - try { - myCounterLock.wait(); - } - catch (InterruptedException ignored) { - } - } - } - } - } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/DiagnosticOutputConsumer.java b/jps/jps-builders/src/org/jetbrains/jps/javac/DiagnosticOutputConsumer.java index 0230d254f7c1..f052f1e30653 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/DiagnosticOutputConsumer.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/DiagnosticOutputConsumer.java @@ -1,7 +1,7 @@ package org.jetbrains.jps.javac; -import javax.tools.DiagnosticListener; -import javax.tools.JavaFileObject; +import javax.tools.*; +import java.util.Collection; /** * @author Eugene Zhuravlev @@ -9,4 +9,5 @@ import javax.tools.JavaFileObject; */ public interface DiagnosticOutputConsumer extends DiagnosticListener { void outputLineAvailable(String line); + void registerImports(String className, Collection imports, Collection staticImports); } diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacASTAnalyser.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacASTAnalyser.java index 33d78d74661f..a76d5ccb104e 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacASTAnalyser.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacASTAnalyser.java @@ -1,17 +1,16 @@ package org.jetbrains.jps.javac; -import com.sun.source.tree.*; +import com.sun.source.tree.ClassTree; +import com.sun.source.tree.ImportTree; +import com.sun.source.tree.Tree; import com.sun.source.util.TreeScanner; import com.sun.source.util.Trees; -import javax.annotation.processing.AbstractProcessor; -import javax.annotation.processing.ProcessingEnvironment; -import javax.annotation.processing.RoundEnvironment; -import javax.annotation.processing.SupportedAnnotationTypes; +import javax.annotation.processing.*; +import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; -import javax.lang.model.element.Modifier; -import javax.lang.model.element.Name; import javax.lang.model.element.TypeElement; +import java.util.HashSet; import java.util.Set; /** @@ -19,13 +18,15 @@ import java.util.Set; * Date: 2/1/12 * */ -//@SupportedSourceVersion(SourceVersion.RELEASE_7) +@SupportedSourceVersion(SourceVersion.RELEASE_7) @SupportedAnnotationTypes("*") public class JavacASTAnalyser extends AbstractProcessor{ private Trees myTrees; + private final DiagnosticOutputConsumer myOutputConsumer; private final boolean mySuppressOtherProcessors; - public JavacASTAnalyser(boolean suppressOtherProcessors) { + public JavacASTAnalyser(DiagnosticOutputConsumer outputConsumer, boolean suppressOtherProcessors) { + myOutputConsumer = outputConsumer; mySuppressOtherProcessors = suppressOtherProcessors; } @@ -37,65 +38,158 @@ public class JavacASTAnalyser extends AbstractProcessor{ @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { - MyAnalyzer scaner = new MyAnalyzer(); - for (Element element : roundEnv.getRootElements()) { - final Tree tree = myTrees.getTree(element); - scaner.scan(tree, myTrees); - } + final Set elements = roundEnv.getRootElements(); + for (Element element : elements) { + if (!(element instanceof TypeElement)) { + continue; + } + final TypeElement typeElement = (TypeElement)element; + final ImportsCollector importsCollector = new ImportsCollector(); + importsCollector.scan(myTrees.getPath(typeElement).getParentPath().getLeaf(), myTrees); + + final Set imports = importsCollector.getImports(); + final Set staticImports = importsCollector.getStaticImports(); + + if (!imports.isEmpty() || !staticImports.isEmpty()) { + final String className = typeElement.getQualifiedName().toString(); + myOutputConsumer.registerImports(className, imports, staticImports); + } + break; + } return mySuppressOtherProcessors; } + private static class ImportsCollector extends TreeScanner { + private Set myImports = new HashSet(); + private Set myStaticImports = new HashSet(); + + public Set getImports() { + return myImports; + } + + public Set getStaticImports() { + return myStaticImports; + } - private static class MyAnalyzer extends TreeScanner { - @Override public Object visitImport(ImportTree node, Trees trees) { - return null/*super.visitImport(node, trees)*/; + final Tree identifier = node.getQualifiedIdentifier(); + final Set container = node.isStatic()? myStaticImports : myImports; + container.add(identifier.toString()); + return null; } - @Override public Object visitClass(ClassTree node, Trees trees) { - return scan(node.getMembers(), trees); - } - - @Override - public Object visitVariable(VariableTree node, Trees trees) { - final ModifiersTree modifiers = node.getModifiers(); - final Set flags = modifiers.getFlags(); - if (flags.contains(Modifier.STATIC) && flags.contains(Modifier.FINAL)) { - final Name variableName = node.getName(); - // todo register constant - final ConstantRefsFinder finder = new ConstantRefsFinder(); - finder.scan(node.getInitializer(), trees); - // todo: process found refs - } return null; } - @Override - public Object visitMethod(MethodTree node, Trees trees) { - final ConstantRefsFinder finder = new ConstantRefsFinder(); - finder.scan(node.getBody(), trees); - // todo: process found refs - return null; - } - } + //public void registerOverriddenMethod(TypeElement classElement, ExecutableElement method) { + // final Elements utils = myProcessingEnvironment.getElementUtils(); + // final String qName = utils.getBinaryName(classElement).toString(); + // List descriptors = myOverriddenMethods.get(qName); + // if (descriptors == null) { + // descriptors = new ArrayList(); + // myOverriddenMethods.put(qName, descriptors); + // } + // final StringBuilder buf = new StringBuilder(); + // buf.append("("); + // for (VariableElement param : method.getParameters()) { + // buf.append(getSignature(param.asType())); + // } + // buf.append(")").append(getSignature(method.getReturnType())); + // descriptors.add(new MethodDescriptor(method.getSimpleName().toString(), buf.toString())); + //} - private static class ConstantRefsFinder extends TreeScanner { - @Override - public Object visitMethodInvocation(MethodInvocationTree node, Trees trees) { - return scan(node.getArguments(), trees); - } - - @Override - public Object visitMemberSelect(MemberSelectTree node, Trees trees) { - return super.visitMemberSelect(node, trees); - } - - @Override - public Object visitIdentifier(IdentifierTree node, Trees trees) { - return super.visitIdentifier(node, trees); - } + //private static String getSignature(TypeMirror type) { + // switch (type.getKind()) { + // case BOOLEAN: return "Z"; + // case BYTE: return "B"; + // case CHAR: return "C"; + // case SHORT: return "S"; + // case INT: return "I"; + // case LONG: return "J"; + // case FLOAT: return "F"; + // case DOUBLE: return "D"; + // case VOID: return "V"; + // case ARRAY: + // final String signature = getSignature(((ArrayType)type).getComponentType()); + // return signature != null? "[" + signature : null; + // case DECLARED: + // final TypeElement typeElement = (TypeElement)((DeclaredType)type).asElement(); + // final String qName = typeElement.getQualifiedName().toString().replace(".", "/"); + // return "L" + qName + ";"; + // default: + // return null; + // } + //} } + //private static class IdentifiersCollector extends TreeScanner { + // private Set myIdentifiers = new HashSet(); + // private Set myImports = new HashSet(); + // private Set myStaticImports = new HashSet(); + // + // public Set getIdentifiers() { + // final HashSet result = new HashSet(); + // for (Name name : myIdentifiers) { + // result.add(name.toString()); + // } + // return result; + // } + // + // @Override + // public Object visitImport(ImportTree node, Trees trees) { + // final Tree identifier = node.getQualifiedIdentifier(); + // final Set container = node.isStatic()? myStaticImports : myImports; + // container.add(identifier.toString()); + // return null; + // } + // + // @Override + // public Object visitAnnotation(AnnotationTree node, Trees trees) { + // return scan(node.getArguments(), trees); + // } + // + // @Override + // public Object visitIdentifier(IdentifierTree node, Trees trees) { + // myIdentifiers.add(node.getName()); + // return super.visitIdentifier(node, trees); + // } + // + // @Override + // public Object visitMemberSelect(MemberSelectTree node, Trees trees) { + // myIdentifiers.add(node.getIdentifier()); + // return scan(node.getExpression(), trees); + // } + // + // @Override + // public Object visitClass(ClassTree node, Trees trees) { + // return scan(node.getMembers(), trees); + // } + // + // @Override + // public Object visitVariable(VariableTree node, Trees trees) { + // return scan(node.getInitializer(), trees); + // } + // + // @Override + // public Object visitMethod(MethodTree node, Trees trees) { + // return scan(node.getBody(), trees); + // } + // + // @Override + // public Object visitMethodInvocation(MethodInvocationTree node, Trees trees) { + // return scan(node.getArguments(), trees); + // } + // + // @Override + // public Object visitTypeCast(TypeCastTree node, Trees trees) { + // return scan(node.getExpression(), trees); + // } + // + // @Override + // public Object visitInstanceOf(InstanceOfTree node, Trees trees) { + // return scan(node.getExpression(), trees); + // } + //} } diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java index f1db6c780dba..8aad8cffe136 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java @@ -68,8 +68,8 @@ public class JavacMain { final JavaCompiler.CompilationTask task = compiler.getTask( out, fileManager, outConsumer, filterOptionList(options), null, fileManager.toJavaFileObjects(sources) ); - //final JavacASTAnalyser analyzer = new JavacASTAnalyser(shouldSuppressAnnotationProcessing(options)); - //task.setProcessors(Collections.singleton(analyzer)); + final JavacASTAnalyser analyzer = new JavacASTAnalyser(outConsumer, shouldSuppressAnnotationProcessing(options)); + task.setProcessors(Collections.singleton(analyzer)); return task.call(); } finally { diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacProtoUtil.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacProtoUtil.java index dfda083e3fec..8f511c1650e8 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacProtoUtil.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacProtoUtil.java @@ -4,8 +4,7 @@ import com.google.protobuf.ByteString; import com.intellij.openapi.util.io.FileUtil; import org.jetbrains.annotations.Nullable; -import javax.tools.Diagnostic; -import javax.tools.JavaFileObject; +import javax.tools.*; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.PrintStream; @@ -86,6 +85,20 @@ public class JavacProtoUtil { return builder.build(); } + public static JavacRemoteProto.Message.Response createClassDataResponse(String className, Collection imports, Collection staticImports) { + final JavacRemoteProto.Message.Response.ClassData.Builder msgBuilder = JavacRemoteProto.Message.Response.ClassData.newBuilder(); + msgBuilder.setClassName(className); + if (!imports.isEmpty()) { + msgBuilder.addAllImportStatement(imports); + } + if (!staticImports.isEmpty()) { + msgBuilder.addAllStaticImport(imports); + } + final JavacRemoteProto.Message.Response.Builder builder = JavacRemoteProto.Message.Response.newBuilder(); + builder.setResponseType(JavacRemoteProto.Message.Response.Type.CLASS_DATA).setClassData(msgBuilder.build()); + return builder.build(); + } + public static JavacRemoteProto.Message.Response createStdOutputResponse(String text) { final JavacRemoteProto.Message.Response.CompileMessage.Builder msgBuilder = JavacRemoteProto.Message.Response.CompileMessage.newBuilder(); msgBuilder.setKind(JavacRemoteProto.Message.Response.CompileMessage.Kind.STD_OUT); diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacRemoteProto.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacRemoteProto.java index 624e09be1800..9bb4156cf536 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacRemoteProto.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacRemoteProto.java @@ -1831,8 +1831,9 @@ public final class JavacRemoteProto { implements com.google.protobuf.Internal.EnumLite { BUILD_MESSAGE(0, 1), OUTPUT_OBJECT(1, 2), - BUILD_COMPLETED(2, 3), - REQUEST_ACK(3, 4), + CLASS_DATA(2, 3), + BUILD_COMPLETED(3, 4), + REQUEST_ACK(4, 5), ; @@ -1842,8 +1843,9 @@ public final class JavacRemoteProto { switch (value) { case 1: return BUILD_MESSAGE; case 2: return OUTPUT_OBJECT; - case 3: return BUILD_COMPLETED; - case 4: return REQUEST_ACK; + case 3: return CLASS_DATA; + case 4: return BUILD_COMPLETED; + case 5: return REQUEST_ACK; default: return null; } } @@ -3014,6 +3016,496 @@ public final class JavacRemoteProto { // @@protoc_insertion_point(class_scope:org.jetbrains.javac.Message.Response.OutputObject) } + public static final class ClassData extends + com.google.protobuf.GeneratedMessageLite { + // Use ClassData.newBuilder() to construct. + private ClassData() { + initFields(); + } + private ClassData(boolean noInit) {} + + private static final ClassData defaultInstance; + public static ClassData getDefaultInstance() { + return defaultInstance; + } + + public ClassData getDefaultInstanceForType() { + return defaultInstance; + } + + // required string class_name = 1; + public static final int CLASS_NAME_FIELD_NUMBER = 1; + private boolean hasClassName; + private java.lang.String className_ = ""; + public boolean hasClassName() { return hasClassName; } + public java.lang.String getClassName() { return className_; } + + // repeated string import_statement = 2; + public static final int IMPORT_STATEMENT_FIELD_NUMBER = 2; + private java.util.List importStatement_ = + java.util.Collections.emptyList(); + public java.util.List getImportStatementList() { + return importStatement_; + } + public int getImportStatementCount() { return importStatement_.size(); } + public java.lang.String getImportStatement(int index) { + return importStatement_.get(index); + } + + // repeated string static_import = 3; + public static final int STATIC_IMPORT_FIELD_NUMBER = 3; + private java.util.List staticImport_ = + java.util.Collections.emptyList(); + public java.util.List getStaticImportList() { + return staticImport_; + } + public int getStaticImportCount() { return staticImport_.size(); } + public java.lang.String getStaticImport(int index) { + return staticImport_.get(index); + } + + // repeated string identifier = 4; + public static final int IDENTIFIER_FIELD_NUMBER = 4; + private java.util.List identifier_ = + java.util.Collections.emptyList(); + public java.util.List getIdentifierList() { + return identifier_; + } + public int getIdentifierCount() { return identifier_.size(); } + public java.lang.String getIdentifier(int index) { + return identifier_.get(index); + } + + private void initFields() { + } + public final boolean isInitialized() { + if (!hasClassName) return false; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasClassName()) { + output.writeString(1, getClassName()); + } + for (java.lang.String element : getImportStatementList()) { + output.writeString(2, element); + } + for (java.lang.String element : getStaticImportList()) { + output.writeString(3, element); + } + for (java.lang.String element : getIdentifierList()) { + output.writeString(4, element); + } + } + + private int memoizedSerializedSize = -1; + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasClassName()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(1, getClassName()); + } + { + int dataSize = 0; + for (java.lang.String element : getImportStatementList()) { + dataSize += com.google.protobuf.CodedOutputStream + .computeStringSizeNoTag(element); + } + size += dataSize; + size += 1 * getImportStatementList().size(); + } + { + int dataSize = 0; + for (java.lang.String element : getStaticImportList()) { + dataSize += com.google.protobuf.CodedOutputStream + .computeStringSizeNoTag(element); + } + size += dataSize; + size += 1 * getStaticImportList().size(); + } + { + int dataSize = 0; + for (java.lang.String element : getIdentifierList()) { + dataSize += com.google.protobuf.CodedOutputStream + .computeStringSizeNoTag(element); + } + size += dataSize; + size += 1 * getIdentifierList().size(); + } + memoizedSerializedSize = size; + return size; + } + + public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData prototype) { + return newBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessageLite.Builder< + org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData, Builder> { + private org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData result; + + // Construct using org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData(); + return builder; + } + + protected org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData internalGetResult() { + return result; + } + + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData(); + return this; + } + + public Builder clone() { + return create().mergeFrom(result); + } + + public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData getDefaultInstanceForType() { + return org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData.getDefaultInstance(); + } + + public boolean isInitialized() { + return result.isInitialized(); + } + public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.importStatement_ != java.util.Collections.EMPTY_LIST) { + result.importStatement_ = + java.util.Collections.unmodifiableList(result.importStatement_); + } + if (result.staticImport_ != java.util.Collections.EMPTY_LIST) { + result.staticImport_ = + java.util.Collections.unmodifiableList(result.staticImport_); + } + if (result.identifier_ != java.util.Collections.EMPTY_LIST) { + result.identifier_ = + java.util.Collections.unmodifiableList(result.identifier_); + } + org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData returnMe = result; + result = null; + return returnMe; + } + + public Builder mergeFrom(org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData other) { + if (other == org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData.getDefaultInstance()) return this; + if (other.hasClassName()) { + setClassName(other.getClassName()); + } + if (!other.importStatement_.isEmpty()) { + if (result.importStatement_.isEmpty()) { + result.importStatement_ = new java.util.ArrayList(); + } + result.importStatement_.addAll(other.importStatement_); + } + if (!other.staticImport_.isEmpty()) { + if (result.staticImport_.isEmpty()) { + result.staticImport_ = new java.util.ArrayList(); + } + result.staticImport_.addAll(other.staticImport_); + } + if (!other.identifier_.isEmpty()) { + if (result.identifier_.isEmpty()) { + result.identifier_ = new java.util.ArrayList(); + } + result.identifier_.addAll(other.identifier_); + } + return this; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + return this; + default: { + if (!parseUnknownField(input, extensionRegistry, tag)) { + return this; + } + break; + } + case 10: { + setClassName(input.readString()); + break; + } + case 18: { + addImportStatement(input.readString()); + break; + } + case 26: { + addStaticImport(input.readString()); + break; + } + case 34: { + addIdentifier(input.readString()); + break; + } + } + } + } + + + // required string class_name = 1; + public boolean hasClassName() { + return result.hasClassName(); + } + public java.lang.String getClassName() { + return result.getClassName(); + } + public Builder setClassName(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasClassName = true; + result.className_ = value; + return this; + } + public Builder clearClassName() { + result.hasClassName = false; + result.className_ = getDefaultInstance().getClassName(); + return this; + } + + // repeated string import_statement = 2; + public java.util.List getImportStatementList() { + return java.util.Collections.unmodifiableList(result.importStatement_); + } + public int getImportStatementCount() { + return result.getImportStatementCount(); + } + public java.lang.String getImportStatement(int index) { + return result.getImportStatement(index); + } + public Builder setImportStatement(int index, java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.importStatement_.set(index, value); + return this; + } + public Builder addImportStatement(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.importStatement_.isEmpty()) { + result.importStatement_ = new java.util.ArrayList(); + } + result.importStatement_.add(value); + return this; + } + public Builder addAllImportStatement( + java.lang.Iterable values) { + if (result.importStatement_.isEmpty()) { + result.importStatement_ = new java.util.ArrayList(); + } + super.addAll(values, result.importStatement_); + return this; + } + public Builder clearImportStatement() { + result.importStatement_ = java.util.Collections.emptyList(); + return this; + } + + // repeated string static_import = 3; + public java.util.List getStaticImportList() { + return java.util.Collections.unmodifiableList(result.staticImport_); + } + public int getStaticImportCount() { + return result.getStaticImportCount(); + } + public java.lang.String getStaticImport(int index) { + return result.getStaticImport(index); + } + public Builder setStaticImport(int index, java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.staticImport_.set(index, value); + return this; + } + public Builder addStaticImport(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.staticImport_.isEmpty()) { + result.staticImport_ = new java.util.ArrayList(); + } + result.staticImport_.add(value); + return this; + } + public Builder addAllStaticImport( + java.lang.Iterable values) { + if (result.staticImport_.isEmpty()) { + result.staticImport_ = new java.util.ArrayList(); + } + super.addAll(values, result.staticImport_); + return this; + } + public Builder clearStaticImport() { + result.staticImport_ = java.util.Collections.emptyList(); + return this; + } + + // repeated string identifier = 4; + public java.util.List getIdentifierList() { + return java.util.Collections.unmodifiableList(result.identifier_); + } + public int getIdentifierCount() { + return result.getIdentifierCount(); + } + public java.lang.String getIdentifier(int index) { + return result.getIdentifier(index); + } + public Builder setIdentifier(int index, java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.identifier_.set(index, value); + return this; + } + public Builder addIdentifier(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.identifier_.isEmpty()) { + result.identifier_ = new java.util.ArrayList(); + } + result.identifier_.add(value); + return this; + } + public Builder addAllIdentifier( + java.lang.Iterable values) { + if (result.identifier_.isEmpty()) { + result.identifier_ = new java.util.ArrayList(); + } + super.addAll(values, result.identifier_); + return this; + } + public Builder clearIdentifier() { + result.identifier_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:org.jetbrains.javac.Message.Response.ClassData) + } + + static { + defaultInstance = new ClassData(true); + org.jetbrains.jps.javac.JavacRemoteProto.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:org.jetbrains.javac.Message.Response.ClassData) + } + // required .org.jetbrains.javac.Message.Response.Type response_type = 1; public static final int RESPONSE_TYPE_FIELD_NUMBER = 1; private boolean hasResponseType; @@ -3035,8 +3527,15 @@ public final class JavacRemoteProto { public boolean hasOutputObject() { return hasOutputObject; } public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject getOutputObject() { return outputObject_; } - // optional bool completion_status = 4; - public static final int COMPLETION_STATUS_FIELD_NUMBER = 4; + // optional .org.jetbrains.javac.Message.Response.ClassData class_data = 4; + public static final int CLASS_DATA_FIELD_NUMBER = 4; + private boolean hasClassData; + private org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData classData_; + public boolean hasClassData() { return hasClassData; } + public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData getClassData() { return classData_; } + + // optional bool completion_status = 5; + public static final int COMPLETION_STATUS_FIELD_NUMBER = 5; private boolean hasCompletionStatus; private boolean completionStatus_ = false; public boolean hasCompletionStatus() { return hasCompletionStatus; } @@ -3046,6 +3545,7 @@ public final class JavacRemoteProto { responseType_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.Type.BUILD_MESSAGE; compileMessage_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage.getDefaultInstance(); outputObject_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject.getDefaultInstance(); + classData_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData.getDefaultInstance(); } public final boolean isInitialized() { if (!hasResponseType) return false; @@ -3055,6 +3555,9 @@ public final class JavacRemoteProto { if (hasOutputObject()) { if (!getOutputObject().isInitialized()) return false; } + if (hasClassData()) { + if (!getClassData().isInitialized()) return false; + } return true; } @@ -3070,8 +3573,11 @@ public final class JavacRemoteProto { if (hasOutputObject()) { output.writeMessage(3, getOutputObject()); } + if (hasClassData()) { + output.writeMessage(4, getClassData()); + } if (hasCompletionStatus()) { - output.writeBool(4, getCompletionStatus()); + output.writeBool(5, getCompletionStatus()); } } @@ -3093,9 +3599,13 @@ public final class JavacRemoteProto { size += com.google.protobuf.CodedOutputStream .computeMessageSize(3, getOutputObject()); } + if (hasClassData()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(4, getClassData()); + } if (hasCompletionStatus()) { size += com.google.protobuf.CodedOutputStream - .computeBoolSize(4, getCompletionStatus()); + .computeBoolSize(5, getCompletionStatus()); } memoizedSerializedSize = size; return size; @@ -3250,6 +3760,9 @@ public final class JavacRemoteProto { if (other.hasOutputObject()) { mergeOutputObject(other.getOutputObject()); } + if (other.hasClassData()) { + mergeClassData(other.getClassData()); + } if (other.hasCompletionStatus()) { setCompletionStatus(other.getCompletionStatus()); } @@ -3297,7 +3810,16 @@ public final class JavacRemoteProto { setOutputObject(subBuilder.buildPartial()); break; } - case 32: { + case 34: { + org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData.Builder subBuilder = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData.newBuilder(); + if (hasClassData()) { + subBuilder.mergeFrom(getClassData()); + } + input.readMessage(subBuilder, extensionRegistry); + setClassData(subBuilder.buildPartial()); + break; + } + case 40: { setCompletionStatus(input.readBool()); break; } @@ -3401,7 +3923,44 @@ public final class JavacRemoteProto { return this; } - // optional bool completion_status = 4; + // optional .org.jetbrains.javac.Message.Response.ClassData class_data = 4; + public boolean hasClassData() { + return result.hasClassData(); + } + public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData getClassData() { + return result.getClassData(); + } + public Builder setClassData(org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasClassData = true; + result.classData_ = value; + return this; + } + public Builder setClassData(org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData.Builder builderForValue) { + result.hasClassData = true; + result.classData_ = builderForValue.build(); + return this; + } + public Builder mergeClassData(org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData value) { + if (result.hasClassData() && + result.classData_ != org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData.getDefaultInstance()) { + result.classData_ = + org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData.newBuilder(result.classData_).mergeFrom(value).buildPartial(); + } else { + result.classData_ = value; + } + result.hasClassData = true; + return this; + } + public Builder clearClassData() { + result.hasClassData = false; + result.classData_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData.getDefaultInstance(); + return this; + } + + // optional bool completion_status = 5; public boolean hasCompletionStatus() { return result.hasCompletionStatus(); } diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServer.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServer.java index 537cdf6a64e8..fd7ae5789180 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServer.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServer.java @@ -122,6 +122,12 @@ public class JavacServer { final JavacRemoteProto.Message.Response response = JavacProtoUtil.createBuildMessageResponse(diagnostic); Channels.write(ctx.getChannel(), JavacProtoUtil.toMessage(sessionId, response)); } + + @Override + public void registerImports(String className, Collection imports, Collection staticImports) { + final JavacRemoteProto.Message.Response response = JavacProtoUtil.createClassDataResponse(className, imports, staticImports); + Channels.write(ctx.getChannel(), JavacProtoUtil.toMessage(sessionId, response)); + } }; final OutputFileConsumer outputSink = new OutputFileConsumer() { diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerResponseHandler.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerResponseHandler.java index f7232bec5968..00e3a08cc175 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerResponseHandler.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerResponseHandler.java @@ -4,10 +4,10 @@ import com.google.protobuf.ByteString; import com.google.protobuf.MessageLite; import org.jetbrains.jps.client.ProtobufResponseHandler; -import javax.tools.Diagnostic; -import javax.tools.JavaFileObject; +import javax.tools.*; import java.io.File; import java.net.URI; +import java.util.Collection; import java.util.Locale; /** @@ -82,6 +82,15 @@ public class JavacServerResponseHandler implements ProtobufResponseHandler{ return false; } + if (responseType == JavacRemoteProto.Message.Response.Type.CLASS_DATA) { + final JavacRemoteProto.Message.Response.ClassData data = response.getClassData(); + final String className = data.getClassName(); + final Collection imports = data.getImportStatementList(); + final Collection staticImports = data.getStaticImportList(); + myDiagnosticSink.registerImports(className, imports, staticImports); + return false; + } + if (responseType == JavacRemoteProto.Message.Response.Type.BUILD_COMPLETED) { myTerminatedSuccessfully = response.getCompletionStatus(); return true; diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/Callbacks.java b/jps/model/src/org/jetbrains/ether/dependencyView/Callbacks.java index 51d644f2ec40..c4d7b133f4ed 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/Callbacks.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/Callbacks.java @@ -1,6 +1,7 @@ package org.jetbrains.ether.dependencyView; import org.objectweb.asm.ClassReader; + import java.util.Collection; /** @@ -26,8 +27,7 @@ public class Callbacks { public interface Backend { Collection getClassFiles(); void associate(String classFileName, SourceFileNameLookup sourceLookup, ClassReader cr); - void markOverride(String className, String methodName, String methodSignature); void registerConstantUsage(String className, String fieldName, String fieldOwner); - void registerImports(Collection imports, String rootClass); + void registerImports(String className, Collection imports, Collection staticImports); } } diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java index cc586037d2b9..530832021ad7 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java @@ -1732,23 +1732,24 @@ public class Mappings { } } - @Override - public void markOverride(final String className, final String methodName, final String methodSignature) { - //To change body of implemented methods use File | Settings | File Templates. - } - @Override public void registerConstantUsage(final String className, final String fieldName, final String fieldOwner) { //To change body of implemented methods use File | Settings | File Templates. } @Override - public void registerImports(final Collection imports, final String rootClass) { - final DependencyContext.S rootClassName = myContext.get(rootClass); + public void registerImports(final String className, final Collection imports, Collection staticImports) { + // todo: proces static imports as well + final DependencyContext.S rootClassName = myContext.get(className.replace(".", "/")); + + // todo: postpone processing until data collected is complete and myClassToSourceFile contains the mapping final DependencyContext.S fileName = myClassToSourceFile.get(rootClassName); for (final String i : imports) { - final DependencyContext.S iname = myContext.get(i); + if (i.endsWith("*")) { + continue; // filter out wildcard imports + } + final DependencyContext.S iname = myContext.get(i.replace(".", "/")); myClassToClassDependency.put(rootClassName, iname);