deleting old make implementation

This commit is contained in:
Eugene Zhuravlev
2014-05-28 15:14:09 +04:00
parent f723b072a8
commit 29b98dbe5d
183 changed files with 436 additions and 23655 deletions
@@ -1,4 +1,3 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
@@ -23,17 +22,11 @@ package com.intellij.compiler;
import com.intellij.CommonBundle;
import com.intellij.ProjectTopics;
import com.intellij.compiler.impl.TranslatingCompilerFilesMonitor;
import com.intellij.compiler.impl.javaCompiler.BackendCompiler;
import com.intellij.compiler.impl.javaCompiler.api.CompilerAPICompiler;
import com.intellij.compiler.impl.javaCompiler.eclipse.EclipseCompiler;
import com.intellij.compiler.impl.javaCompiler.eclipse.EclipseEmbeddedCompiler;
import com.intellij.compiler.impl.javaCompiler.javac.JavacCompiler;
import com.intellij.compiler.options.ExternalBuildOptionListener;
import com.intellij.compiler.server.BuildManager;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.compiler.CompilerBundle;
import com.intellij.openapi.compiler.CompilerManager;
import com.intellij.openapi.compiler.options.ExcludedEntriesConfiguration;
@@ -80,7 +73,6 @@ import java.util.*;
public class CompilerConfigurationImpl extends CompilerConfiguration implements PersistentStateComponent<Element>, ProjectComponent {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.CompilerConfiguration");
@NonNls public static final String TESTS_EXTERNAL_COMPILER_HOME_PROPERTY_NAME = "tests.external.compiler.home";
public static final int DEPENDENCY_FORMAT_VERSION = 55;
@SuppressWarnings({"WeakerAccess"}) public String DEFAULT_COMPILER;
@NotNull private BackendCompiler myDefaultJavaCompiler;
@@ -128,33 +120,6 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
myProcessorsProfilesMap = null; // clear cache
}
});
connection.subscribe(ExternalBuildOptionListener.TOPIC, new ExternalBuildOptionListener() {
@Override
public void externalBuildOptionChanged(boolean externalBuildEnabled) {
// this will schedule for compilation all files that might become compilable after resource patterns' changing
final TranslatingCompilerFilesMonitor monitor = TranslatingCompilerFilesMonitor.getInstance();
if (externalBuildEnabled) {
monitor.suspendProject(myProject);
}
else {
monitor.watchProject(myProject);
monitor.scanSourcesForCompilableFiles(myProject);
if (!myProject.isDefault()) {
final File buildSystem = BuildManager.getInstance().getBuildSystemDirectory();
final File[] subdirs = buildSystem.listFiles();
if (subdirs != null) {
final String prefix = myProject.getName().toLowerCase(Locale.US) + "_";
for (File subdir : subdirs) {
if (subdir.getName().startsWith(prefix)) {
FileUtil.asyncDelete(subdir);
}
}
}
}
}
}
});
}
public Element getState() {
@@ -290,35 +255,14 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
myRegisteredCompilers.add(JAVAC_EXTERNAL_BACKEND);
if (!ApplicationManager.getApplication().isUnitTestMode()) {
//final BackendCompiler JIKES_BACKEND = new JikesCompiler(myProject);
//myRegisteredCompilers.add(JIKES_BACKEND);
if (EclipseCompiler.isInitialized()) {
final EclipseCompiler eclipse = new EclipseCompiler(myProject);
myRegisteredCompilers.add(eclipse);
}
if (ApplicationManagerEx.getApplicationEx().isInternal()) {
try {
final EclipseEmbeddedCompiler eclipseEmbedded = new EclipseEmbeddedCompiler(myProject);
myRegisteredCompilers.add(eclipseEmbedded);
}
catch (NoClassDefFoundError e) {
// eclipse jar must be not in the classpath
}
try {
CompilerAPICompiler inProcessJavaCompiler = new CompilerAPICompiler(myProject);
myRegisteredCompilers.add(inProcessJavaCompiler);
}
catch (NoClassDefFoundError e) {
// wrong JDK
}
}
}
final BackendCompiler[] compilers = Extensions.getExtensions(BackendCompiler.EP_NAME, myProject);
final Set<FileType> types = new HashSet<FileType>();
for (BackendCompiler compiler : compilers) {
for (BackendCompiler compiler : Extensions.getExtensions(BackendCompiler.EP_NAME, myProject)) {
myRegisteredCompilers.add(compiler);
types.addAll(compiler.getCompilableFileTypes());
}
@@ -327,7 +271,7 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
for (FileType type : types) {
compilerManager.addCompilableFileType(type);
}
myDefaultJavaCompiler = JAVAC_EXTERNAL_BACKEND;
for (BackendCompiler compiler : myRegisteredCompilers) {
if (compiler.getId().equals(DEFAULT_COMPILER)) {
@@ -338,11 +282,6 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
DEFAULT_COMPILER = myDefaultJavaCompiler.getId();
}
public Collection<BackendCompiler> getRegisteredJavaCompilers() {
createCompilers();
return myRegisteredCompilers;
}
public String[] getResourceFilePatterns() {
return getWildcardPatterns();
}
@@ -16,10 +16,6 @@
package com.intellij.compiler;
import com.intellij.compiler.impl.*;
import com.intellij.compiler.impl.javaCompiler.AnnotationProcessingCompiler;
import com.intellij.compiler.impl.javaCompiler.JavaCompiler;
import com.intellij.compiler.impl.resourceCompiler.ResourceCompiler;
import com.intellij.compiler.impl.rmiCompiler.RmicCompiler;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.*;
@@ -35,11 +31,6 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Chunk;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.graph.CachingSemiGraph;
import com.intellij.util.graph.Graph;
import com.intellij.util.graph.GraphGenerator;
import com.intellij.util.messages.MessageBus;
import com.intellij.util.messages.MessageBusConnection;
import org.jetbrains.annotations.NotNull;
@@ -54,28 +45,20 @@ public class CompilerManagerImpl extends CompilerManager {
private final Project myProject;
private final List<Compiler> myCompilers = new ArrayList<Compiler>();
private final List<TranslatingCompiler> myTranslators = new ArrayList<TranslatingCompiler>();
private final List<CompileTask> myBeforeTasks = new ArrayList<CompileTask>();
private final List<CompileTask> myAfterTasks = new ArrayList<CompileTask>();
private final Set<FileType> myCompilableTypes = new HashSet<FileType>();
private final CompilationStatusListener myEventPublisher;
private final Semaphore myCompilationSemaphore = new Semaphore(1, true);
private final Map<Compiler, Set<FileType>> myCompilerToInputTypes = new HashMap<Compiler, Set<FileType>>();
private final Map<Compiler, Set<FileType>> myCompilerToOutputTypes = new HashMap<Compiler, Set<FileType>>();
private final Set<ModuleType> myValidationDisabledModuleTypes = new HashSet<ModuleType>();
private final Set<LocalFileSystem.WatchRequest> myWatchRoots;
public CompilerManagerImpl(final Project project, CompilerConfigurationImpl compilerConfiguration, MessageBus messageBus) {
public CompilerManagerImpl(final Project project, MessageBus messageBus) {
myProject = project;
myEventPublisher = messageBus.syncPublisher(CompilerTopics.COMPILATION_STATUS);
// predefined compilers
addTranslatingCompiler(new AnnotationProcessingCompiler(project), new HashSet<FileType>(Arrays.asList(StdFileTypes.JAVA)), new HashSet<FileType>(Arrays.asList(StdFileTypes.JAVA, StdFileTypes.CLASS)));
addTranslatingCompiler(new JavaCompiler(project), new HashSet<FileType>(Arrays.asList(StdFileTypes.JAVA)), new HashSet<FileType>(Arrays.asList(StdFileTypes.CLASS)));
addCompiler(new ResourceCompiler(project, compilerConfiguration));
addCompiler(new RmicCompiler());
for(Compiler compiler: Extensions.getExtensions(Compiler.EP_NAME, myProject)) {
addCompiler(compiler);
}
@@ -87,7 +70,7 @@ public class CompilerManagerImpl extends CompilerManager {
}
addCompilableFileType(StdFileTypes.JAVA);
final File projectGeneratedSrcRoot = CompilerPaths.getGeneratedDataDirectory(project);
projectGeneratedSrcRoot.mkdirs();
final LocalFileSystem lfs = LocalFileSystem.getInstance();
@@ -100,28 +83,6 @@ public class CompilerManagerImpl extends CompilerManager {
}
}
});
//
//addCompiler(new DummyTransformingCompiler()); // this one is for testing purposes only
//addCompiler(new DummySourceGeneratingCompiler(myProject)); // this one is for testing purposes only
/*
// for testing only
ApplicationManager.getApplication().invokeLater(new Runnable() {
public void run() {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
FileTypeManager.getInstance().registerFileType(DummyTranslatingCompiler.INPUT_FILE_TYPE, DummyTranslatingCompiler.FILETYPE_EXTENSION);
addTranslatingCompiler(
new DummyTranslatingCompiler(),
new HashSet<FileType>(Arrays.asList(DummyTranslatingCompiler.INPUT_FILE_TYPE)),
new HashSet<FileType>(Arrays.asList( StdFileTypes.JAVA))
);
}
});
}
});
*/
}
public Semaphore getCompilationSemaphore() {
@@ -132,68 +93,32 @@ public class CompilerManagerImpl extends CompilerManager {
return myCompilationSemaphore.availablePermits() == 0;
}
public void addTranslatingCompiler(@NotNull final TranslatingCompiler compiler, final Set<FileType> inputTypes, final Set<FileType> outputTypes) {
myTranslators.add(compiler);
myCompilerToInputTypes.put(compiler, inputTypes);
myCompilerToOutputTypes.put(compiler, outputTypes);
final List<Chunk<Compiler>> chunks = ModuleCompilerUtil.getSortedChunks(createCompilerGraph((List<Compiler>)(List)myTranslators));
myTranslators.clear();
for (Chunk<Compiler> chunk : chunks) {
for (Compiler chunkCompiler : chunk.getNodes()) {
myTranslators.add((TranslatingCompiler)chunkCompiler);
}
}
}
@NotNull
public Set<FileType> getRegisteredInputTypes(@NotNull final TranslatingCompiler compiler) {
final Set<FileType> inputs = myCompilerToInputTypes.get(compiler);
return inputs != null? Collections.unmodifiableSet(inputs) : Collections.<FileType>emptySet();
}
@NotNull
public Set<FileType> getRegisteredOutputTypes(@NotNull final TranslatingCompiler compiler) {
final Set<FileType> outs = myCompilerToOutputTypes.get(compiler);
return outs != null? Collections.unmodifiableSet(outs) : Collections.<FileType>emptySet();
}
public final void addCompiler(@NotNull Compiler compiler) {
if (compiler instanceof TranslatingCompiler) {
myTranslators.add((TranslatingCompiler)compiler);
myCompilers.add(compiler);
// supporting file instrumenting compilers and validators for external build
// Since these compilers are IDE-specific and use PSI, it is ok to run them before and after the build in the IDE
if (compiler instanceof SourceInstrumentingCompiler) {
addBeforeTask(new FileProcessingCompilerAdapterTask((FileProcessingCompiler)compiler));
}
else {
myCompilers.add(compiler);
// supporting file instrumenting compilers and validators for external build
// Since these compilers are IDE-specific and use PSI, it is ok to run them before and after the build in the IDE
if (compiler instanceof SourceInstrumentingCompiler) {
addBeforeTask(new FileProcessingCompilerAdapterTask((FileProcessingCompiler)compiler));
}
else if (compiler instanceof Validator) {
addAfterTask(new FileProcessingCompilerAdapterTask((FileProcessingCompiler)compiler));
}
else if (compiler instanceof Validator) {
addAfterTask(new FileProcessingCompilerAdapterTask((FileProcessingCompiler)compiler));
}
}
@Deprecated
public void addTranslatingCompiler(@NotNull TranslatingCompiler compiler, Set<FileType> inputTypes, Set<FileType> outputTypes) {
// empty
}
public final void removeCompiler(@NotNull Compiler compiler) {
if (compiler instanceof TranslatingCompiler) {
myTranslators.remove(compiler);
}
else {
if (myCompilers.remove(compiler)) {
for (List<CompileTask> tasks : Arrays.asList(myBeforeTasks, myAfterTasks)) {
for (Iterator<CompileTask> iterator = tasks.iterator(); iterator.hasNext(); ) {
CompileTask task = iterator.next();
if (task instanceof FileProcessingCompilerAdapterTask && ((FileProcessingCompilerAdapterTask)task).getCompiler() == compiler) {
iterator.remove();
}
}
for (List<CompileTask> tasks : Arrays.asList(myBeforeTasks, myAfterTasks)) {
for (Iterator<CompileTask> iterator = tasks.iterator(); iterator.hasNext(); ) {
CompileTask task = iterator.next();
if (task instanceof FileProcessingCompilerAdapterTask && ((FileProcessingCompilerAdapterTask)task).getCompiler() == compiler) {
iterator.remove();
}
}
}
myCompilerToInputTypes.remove(compiler);
myCompilerToOutputTypes.remove(compiler);
}
@NotNull
@@ -209,11 +134,6 @@ public class CompilerManagerImpl extends CompilerManager {
compilers.add((T)item);
}
}
for (final Compiler item : myTranslators) {
if (compilerClass.isAssignableFrom(item.getClass()) && filter.acceptCompiler(item)) {
compilers.add((T)item);
}
}
final T[] array = (T[])Array.newInstance(compilerClass, compilers.size());
return compilers.toArray(array);
}
@@ -263,11 +183,11 @@ public class CompilerManagerImpl extends CompilerManager {
}
public void compile(@NotNull Module module, CompileStatusNotification callback) {
new CompileDriver(myProject).compile(createModuleCompileScope(module, false), new ListenerNotificator(callback), true);
new CompileDriver(myProject).compile(createModuleCompileScope(module, false), new ListenerNotificator(callback));
}
public void compile(@NotNull CompileScope scope, CompileStatusNotification callback) {
new CompileDriver(myProject).compile(scope, new ListenerNotificator(callback), false);
new CompileDriver(myProject).compile(scope, new ListenerNotificator(callback));
}
public void make(CompileStatusNotification callback) {
@@ -372,20 +292,6 @@ public class CompilerManagerImpl extends CompilerManager {
return CompilerConfiguration.getInstance(myProject).isExcludedFromCompilation(file);
}
private static final OutputToSourceMapping OUTPUT_TO_SOURCE_MAPPING = new OutputToSourceMapping() {
public String getSourcePath(final String outputPath) {
final LocalFileSystem lfs = LocalFileSystem.getInstance();
final VirtualFile outputFile = lfs.findFileByPath(outputPath);
final VirtualFile sourceFile = outputFile != null ? TranslatingCompilerFilesMonitor.getSourceFileByOutput(outputFile) : null;
return sourceFile != null? sourceFile.getPath() : null;
}
};
@NotNull
public OutputToSourceMapping getJavaCompilerOutputMapping() {
return OUTPUT_TO_SOURCE_MAPPING;
}
@NotNull
public CompileScope createFilesCompileScope(@NotNull final VirtualFile[] files) {
CompileScope[] scopes = new CompileScope[files.length];
@@ -438,32 +344,6 @@ public class CompilerManagerImpl extends CompilerManager {
return !myValidationDisabledModuleTypes.contains(ModuleType.get(module));
}
private Graph<Compiler> createCompilerGraph(final List<Compiler> compilers) {
return GraphGenerator.create(CachingSemiGraph.create(new GraphGenerator.SemiGraph<Compiler>() {
public Collection<Compiler> getNodes() {
return compilers;
}
public Iterator<Compiler> getIn(Compiler compiler) {
final Set<FileType> compilerInput = myCompilerToInputTypes.get(compiler);
if (compilerInput == null || compilerInput.isEmpty()) {
return Collections.<Compiler>emptySet().iterator();
}
final Set<Compiler> inCompilers = new HashSet<Compiler>();
for (Map.Entry<Compiler, Set<FileType>> entry : myCompilerToOutputTypes.entrySet()) {
final Set<FileType> outputs = entry.getValue();
Compiler comp = entry.getKey();
if (outputs != null && ContainerUtil.intersects(compilerInput, outputs)) {
inCompilers.add(comp);
}
}
return inCompilers.iterator();
}
}));
}
private class ListenerNotificator implements CompileStatusNotification {
private final @Nullable CompileStatusNotification myDelegate;
@@ -23,7 +23,6 @@ import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
@@ -38,12 +37,8 @@ public class CompilerSettingsUsageCollector extends UsagesCollector{
@Override
public Set<UsageDescriptor> getUsages(@Nullable Project project) throws CollectUsagesException {
final CompilerWorkspaceConfiguration wsConfig = CompilerWorkspaceConfiguration.getInstance(project);
if (!wsConfig.useOutOfProcessBuild()) {
return Collections.emptySet();
}
final Set<UsageDescriptor> result = new HashSet<UsageDescriptor>();
result.add(new UsageDescriptor("external_build", 1));
if (wsConfig.MAKE_PROJECT_ON_SAVE) {
result.add(new UsageDescriptor("auto_make", 1));
}
@@ -1,31 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler;
import com.intellij.compiler.make.CacheCorruptedException;
import com.intellij.compiler.make.CachingSearcher;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.extensions.ExtensionPointName;
/**
* @author Eugene Zhuravlev
* Date: Aug 19, 2008
*/
public interface DependencyProcessor {
ExtensionPointName<DependencyProcessor> EXTENSION_POINT_NAME = ExtensionPointName.create("com.intellij.compiler.makeDependencyProcessor");
void processDependencies(CompileContext context, int classQualifiedName, CachingSearcher searcher) throws CacheCorruptedException;
}
@@ -15,7 +15,6 @@
*/
package com.intellij.compiler;
import com.intellij.compiler.impl.javaCompiler.FileObject;
import com.intellij.openapi.compiler.CompilerMessageCategory;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NonNls;
@@ -27,12 +26,12 @@ public abstract class OutputParser {
protected final List<ParserAction> myParserActions = new ArrayList<ParserAction>(10);
public interface Callback {
@NonNls String getNextLine();
@NonNls String getCurrentLine();
String getNextLine();
String getCurrentLine();
void pushBack(String line);
void setProgressText(String text);
void fileProcessed(@NonNls String path);
void fileGenerated(@NonNls FileObject path);
void fileProcessed(String path);
void fileGenerated(String path);
void message(CompilerMessageCategory category, String message, @NonNls String url, int lineNum, int columnNum);
}
@@ -65,8 +64,4 @@ public abstract class OutputParser {
protected static void addMessage(Callback callback, CompilerMessageCategory type, String text, String url, int line, int column){
callback.message(type, text, url, line, column);
}
public boolean isTrimLines() {
return true;
}
}
@@ -1,121 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* @author: Eugene Zhuravlev
* Date: Mar 3, 2003
* Time: 12:34:44 PM
*/
package com.intellij.compiler;
import com.intellij.compiler.make.CacheCorruptedException;
import com.intellij.openapi.compiler.CompilerBundle;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.containers.SLRUCache;
import com.intellij.util.io.PersistentEnumerator;
import com.intellij.util.io.PersistentStringEnumerator;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.IOException;
public class SymbolTable {
private final PersistentStringEnumerator myTrie;
// both caches should have equal size
private static final int STRING_CACHE_SIZE = 1024;
private final SLRUCache<Integer, String> myIndexStringCache = new SLRUCache<Integer, String>(STRING_CACHE_SIZE * 2, STRING_CACHE_SIZE) {
@NotNull
public String createValue(Integer key) {
try {
return myTrie.valueOf(key.intValue());
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
};
private final SLRUCache<String, Integer> myStringIndexCache = new SLRUCache<String, Integer>(STRING_CACHE_SIZE * 2, STRING_CACHE_SIZE) {
@NotNull
public Integer createValue(String key) {
try {
return myTrie.enumerate(key);
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
};
public SymbolTable(File file) throws CacheCorruptedException {
try {
if (!file.exists()) {
FileUtil.createIfDoesntExist(file);
}
myTrie = new PersistentStringEnumerator(file);
}
catch (PersistentEnumerator.CorruptedException e) {
throw new CacheCorruptedException(CompilerBundle.message("error.compiler.caches.corrupted"), e);
}
catch (IOException e) {
throw new CacheCorruptedException(e);
}
}
public synchronized int getId(@NotNull String symbol) throws CacheCorruptedException {
if (symbol.length() == 0) {
return -1;
}
try {
return myStringIndexCache.get(symbol);
}
catch (RuntimeException e) {
if (e.getCause() instanceof IOException) {
throw new CacheCorruptedException(e.getCause());
}
throw e;
}
}
public synchronized String getSymbol(int id) throws CacheCorruptedException {
if (id == -1) {
return "";
}
try {
return myIndexStringCache.get(id);
}
catch (RuntimeException e) {
if (e.getCause() instanceof IOException) {
throw new CacheCorruptedException(e.getCause());
}
throw e;
}
}
public synchronized void dispose() throws CacheCorruptedException {
try {
myIndexStringCache.clear();
myStringIndexCache.clear();
myTrie.close(); // will call "flush()" if needed
}
catch (IOException e) {
throw new CacheCorruptedException(e);
}
}
}
@@ -15,7 +15,6 @@
*/
package com.intellij.compiler.actions;
import com.intellij.compiler.CompilerWorkspaceConfiguration;
import com.intellij.notification.NotificationGroup;
import com.intellij.notification.NotificationType;
import com.intellij.openapi.actionSystem.AnActionEvent;
@@ -126,13 +125,8 @@ public class BuildArtifactAction extends DumbAwareAction {
final CompileScope scope = ArtifactCompileScope.createArtifactsScope(project, artifacts, rebuild);
ArtifactsWorkspaceSettings.getInstance(project).setArtifactsToBuild(artifacts);
if (!rebuild || CompilerWorkspaceConfiguration.getInstance(project).useOutOfProcessBuild()) {
//in external build we can set 'rebuild' flag per target type
CompilerManager.getInstance(project).make(scope, null);
}
else {
CompilerManager.getInstance(project).compile(scope, null);
}
//in external build we can set 'rebuild' flag per target type
CompilerManager.getInstance(project).make(scope, null);
}
private static Set<Artifact> getArtifacts(final List<ArtifactPopupItem> items, final Project project) {
@@ -1,208 +0,0 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.actions;
import com.intellij.compiler.CompilerConfiguration;
import com.intellij.compiler.CompilerWorkspaceConfiguration;
import com.intellij.compiler.impl.FileSetCompileScope;
import com.intellij.compiler.impl.ModuleCompileScope;
import com.intellij.compiler.impl.javaCompiler.AnnotationProcessingCompiler;
import com.intellij.compiler.impl.resourceCompiler.ResourceCompiler;
import com.intellij.idea.ActionsBundle;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.compiler.CompilerBundle;
import com.intellij.openapi.compiler.CompilerFilter;
import com.intellij.openapi.compiler.CompilerManager;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.java.compiler.AnnotationProcessingConfiguration;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class ProcessAnnotationsAction extends CompileActionBase {
protected void doAction(DataContext dataContext, Project project) {
final Module module = LangDataKeys.MODULE_CONTEXT.getData(dataContext);
final CompilerFilter filter = new CompilerFilter() {
public boolean acceptCompiler(com.intellij.openapi.compiler.Compiler compiler) {
// EclipseLink CanonicalModelProcessor reads input from output hence adding ResourcesCompiler
return compiler instanceof AnnotationProcessingCompiler || compiler instanceof ResourceCompiler;
}
};
if (module != null) {
CompilerManager.getInstance(project).make(new ModuleCompileScope(module, false), filter, null);
}
else {
final FileSetCompileScope scope = getCompilableFiles(project, CommonDataKeys.VIRTUAL_FILE_ARRAY.getData(dataContext));
if (scope != null) {
CompilerManager.getInstance(project).make(scope, filter, null);
}
}
}
public void update(AnActionEvent event) {
super.update(event);
Presentation presentation = event.getPresentation();
if (!presentation.isEnabled()) {
return;
}
DataContext dataContext = event.getDataContext();
presentation.setVisible(false);
Project project = CommonDataKeys.PROJECT.getData(dataContext);
if (project == null) {
presentation.setEnabled(false);
return;
}
if (CompilerWorkspaceConfiguration.getInstance(project).useOutOfProcessBuild()) {
presentation.setEnabled(false);
return;
}
final CompilerConfiguration compilerConfiguration = CompilerConfiguration.getInstance(project);
final Module module = LangDataKeys.MODULE.getData(dataContext);
final Module moduleContext = LangDataKeys.MODULE_CONTEXT.getData(dataContext);
if (module == null) {
presentation.setEnabled(false);
return;
}
final AnnotationProcessingConfiguration profile = compilerConfiguration.getAnnotationProcessingConfiguration(module);
if (!profile.isEnabled() || (!profile.isObtainProcessorsFromClasspath() && profile.getProcessors().isEmpty())) {
presentation.setEnabled(false);
return;
}
presentation.setVisible(true);
presentation.setText(createPresentationText(""), true);
final FileSetCompileScope scope = getCompilableFiles(project, CommonDataKeys.VIRTUAL_FILE_ARRAY.getData(dataContext));
if (moduleContext == null && scope == null) {
presentation.setEnabled(false);
return;
}
String elementDescription = null;
if (moduleContext != null) {
elementDescription = CompilerBundle.message("action.compile.description.module", moduleContext.getName());
}
else {
PsiPackage aPackage = null;
final Collection<VirtualFile> files = scope.getRootFiles();
if (files.size() == 1) {
final PsiDirectory directory = PsiManager.getInstance(project).findDirectory(files.iterator().next());
if (directory != null) {
aPackage = JavaDirectoryService.getInstance().getPackage(directory);
}
}
else {
PsiElement element = CommonDataKeys.PSI_ELEMENT.getData(dataContext);
if (element instanceof PsiPackage) {
aPackage = (PsiPackage)element;
}
}
if (aPackage != null) {
String name = aPackage.getQualifiedName();
if (name.length() == 0) {
//noinspection HardCodedStringLiteral
name = "<default>";
}
elementDescription = "'" + name + "'";
}
else if (files.size() == 1) {
final VirtualFile file = files.iterator().next();
FileType fileType = file.getFileType();
if (CompilerManager.getInstance(project).isCompilableFileType(fileType)) {
elementDescription = "'" + file.getName() + "'";
}
else {
if (!ActionPlaces.MAIN_MENU.equals(event.getPlace())) {
// the action should be invisible in popups for non-java files
presentation.setEnabled(false);
presentation.setVisible(false);
return;
}
}
}
else {
elementDescription = CompilerBundle.message("action.compile.description.selected.files");
}
}
if (elementDescription == null) {
presentation.setEnabled(false);
return;
}
presentation.setText(createPresentationText(elementDescription), true);
presentation.setEnabled(true);
}
private static String createPresentationText(final String elementDescription) {
int length = elementDescription.length();
String target = length > 23 ? (StringUtil.startsWithChar(elementDescription, '\'') ? "'..." : "...") + elementDescription.substring(length - 20, length) : elementDescription;
return MessageFormat.format(ActionsBundle.actionText(StringUtil.isEmpty(target)? "RunAPT" : "RunAPT.1"), target);
}
@Nullable
private static FileSetCompileScope getCompilableFiles(Project project, VirtualFile[] files) {
if (files == null || files.length == 0) {
return null;
}
final PsiManager psiManager = PsiManager.getInstance(project);
final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
final CompilerManager compilerManager = CompilerManager.getInstance(project);
final List<VirtualFile> filesToCompile = new ArrayList<VirtualFile>();
final List<Module> affectedModules = new ArrayList<Module>();
for (final VirtualFile file : files) {
if (!fileIndex.isInSourceContent(file)) {
continue;
}
if (!file.isInLocalFileSystem()) {
continue;
}
if (file.isDirectory()) {
final PsiDirectory directory = psiManager.findDirectory(file);
if (directory == null || JavaDirectoryService.getInstance().getPackage(directory) == null) {
continue;
}
}
else {
FileType fileType = file.getFileType();
if (!(compilerManager.isCompilableFileType(fileType))) {
continue;
}
}
filesToCompile.add(file);
ContainerUtil.addIfNotNull(fileIndex.getModuleForFile(file), affectedModules);
}
if (filesToCompile.isEmpty()) return null;
return new FileSetCompileScope(filesToCompile, affectedModules.toArray(new Module[affectedModules.size()]));
}
}
@@ -1,85 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.classParsing;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Arrays;
/**
* @author Eugene Zhuravlev
* Date: Apr 2, 2004
*/
public class AnnotationConstantValue extends ConstantValue {
public static final AnnotationConstantValue[] EMPTY_ARRAY = new AnnotationConstantValue[0];
public static final AnnotationConstantValue[][] EMPTY_ARRAY_ARRAY = new AnnotationConstantValue[0][];
public final int myQName;
public final AnnotationNameValuePair[] myMemberValues;
public AnnotationConstantValue(int qName, AnnotationNameValuePair[] memberValues) {
myQName = qName;
myMemberValues = memberValues;
}
public int getAnnotationQName() {
return myQName;
}
/**
* @return an array of Integer -> ConstantValue pairs
*/
public AnnotationNameValuePair[] getMemberValues() {
return myMemberValues;
}
public AnnotationConstantValue(DataInput in) throws IOException {
myQName = in.readInt();
final int size = in.readInt();
myMemberValues = new AnnotationNameValuePair[size];
for (int idx = 0; idx < myMemberValues.length; idx++) {
final int name = in.readInt();
final ConstantValue constantValue = MemberInfoExternalizer.loadConstantValue(in);
myMemberValues[idx] = new AnnotationNameValuePair(name, constantValue);
}
}
public void save(DataOutput out) throws IOException {
out.writeInt(myQName);
out.writeInt(myMemberValues.length);
for (int idx = 0; idx < myMemberValues.length; idx++) {
final AnnotationNameValuePair nameValuePair = myMemberValues[idx];
out.writeInt(nameValuePair.getName());
MemberInfoExternalizer.saveConstantValue(out, nameValuePair.getValue());
}
}
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof AnnotationConstantValue)) return false;
final AnnotationConstantValue annotationConstantValue = (AnnotationConstantValue)o;
if (myQName != annotationConstantValue.myQName) return false;
if (!Arrays.equals(myMemberValues, annotationConstantValue.myMemberValues)) return false;
return true;
}
public int hashCode() {
return myQName;
}
}
@@ -1,38 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.classParsing;
/**
* @author Eugene Zhuravlev
* Date: Apr 8, 2004
*/
public class AnnotationNameValuePair {
private final int myName;
private final ConstantValue myValue;
public AnnotationNameValuePair(int name, ConstantValue value) {
myName = name;
myValue = value;
}
public int getName() {
return myName;
}
public ConstantValue getValue() {
return myValue;
}
}
@@ -1,72 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.classParsing;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
/**
* @author Eugene Zhuravlev
* Date: Apr 2, 2004
*/
public class AnnotationPrimitiveConstantValue extends ConstantValue{
private final char myValueTag;
private final ConstantValue myValue;
public AnnotationPrimitiveConstantValue(char valueTag, ConstantValue value) {
myValueTag = valueTag;
myValue = value;
}
public AnnotationPrimitiveConstantValue(DataInput in) throws IOException {
myValueTag = in.readChar();
myValue = MemberInfoExternalizer.loadConstantValue(in);
}
public char getValueTag() {
return myValueTag;
}
public ConstantValue getValue() {
return myValue;
}
public void save(DataOutput out) throws IOException {
out.writeChar(myValueTag);
MemberInfoExternalizer.saveConstantValue(out, myValue);
}
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof AnnotationPrimitiveConstantValue)) return false;
final AnnotationPrimitiveConstantValue memberValue = (AnnotationPrimitiveConstantValue)o;
if (myValueTag != memberValue.myValueTag) return false;
if (!myValue.equals(memberValue.myValue)) return false;
return true;
}
public int hashCode() {
int result;
result = (int)myValueTag;
result = 29 * result + myValue.hashCode();
return result;
}
}
@@ -1,770 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* created at Jan 2, 2002
* @author Jeka
*/
package com.intellij.compiler.classParsing;
import com.intellij.compiler.SymbolTable;
import com.intellij.compiler.make.CacheCorruptedException;
import com.intellij.openapi.compiler.CompilerBundle;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.psi.CommonClassNames;
import com.intellij.util.ArrayUtil;
import com.intellij.util.cls.BytePointer;
import com.intellij.util.cls.ClsFormatException;
import com.intellij.util.cls.ClsUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class ClassFileReader {
private final File myFile;
private byte[] myData;
private int[] myConstantPoolOffsets = null; // the last offset points to the constant pool end
private String myQualifiedName;
private String myGenericSignature;
private List<ReferenceInfo> myReferences;
private List<FieldInfo> myFields;
private List<MethodInfo> myMethods;
private String mySourceFileName;
private String mySuperClassName;
private String[] mySuperInterfaces;
private final SymbolTable mySymbolTable;
private AnnotationConstantValue[] myRuntimeVisibleAnnotations;
private AnnotationConstantValue[] myRuntimeInvisibleAnnotations;
private static final String CONSTRUCTOR_NAME = "<init>";
private boolean myParsingDone;
public ClassFileReader(@NotNull File file, SymbolTable symbolTable, @Nullable final byte[] fileContent) {
mySymbolTable = symbolTable;
myFile = file;
myData = fileContent;
}
public String getPath() {
return myFile.getAbsolutePath();
}
public Collection<ReferenceInfo> getReferences() throws ClsFormatException {
parseConstantPool();
return myReferences;
}
public MethodInfo[] getMethods() throws ClsFormatException{
parseMembers();
return myMethods.toArray(new MethodInfo[myMethods.size()]);
}
public FieldInfo[] getFields() throws ClsFormatException{
parseMembers();
return myFields.toArray(new FieldInfo[myFields.size()]);
}
private void parseMembers() throws ClsFormatException {
if (myParsingDone) {
return;
}
initConstantPool();
myMethods = new ArrayList<MethodInfo>();
myFields = new ArrayList<FieldInfo>();
BytePointer ptr = new BytePointer(getData(), getConstantPoolEnd());
ptr.offset += 2; // access flags
ptr.offset += 2; // this class
ptr.offset += 2; // super class
int count = ClsUtil.readU2(ptr); // interface count
ptr.offset += 2 * count; // skip interface infos
count = ClsUtil.readU2(ptr); // field count
while (count-- > 0) {
FieldInfo field = (FieldInfo)readMemberStructure(ptr, true);
String name = getSymbol(field.getName());
if (name.indexOf('$') < 0 && name.indexOf('<') < 0){ // skip synthetic fields
myFields.add(field);
}
}
count = ClsUtil.readU2(ptr); // method count
while (count-- > 0) {
MethodInfo method = (MethodInfo)readMemberStructure(ptr, false);
String name = getSymbol(method.getName());
if (name.indexOf('$') < 0 && name.indexOf('<') < 0) { // skip synthetic methods
myMethods.add(method);
}
else
if (CONSTRUCTOR_NAME.equals(name)) { // store constructors
myMethods.add(method);
}
}
final ClsAttributeTable attributeTable = readAttributes(ptr);
mySourceFileName = attributeTable.sourceFile;
myGenericSignature = attributeTable.genericSignature;
myRuntimeVisibleAnnotations = attributeTable.runtimeVisibleAnnotations;
myRuntimeInvisibleAnnotations = attributeTable.runtimeInvisibleAnnotations;
myParsingDone = true;
}
private String getSymbol(final int id) throws ClsFormatException {
try {
return mySymbolTable.getSymbol(id);
}
catch (CacheCorruptedException e) {
throw new ClsFormatException(e.getLocalizedMessage());
}
}
private MemberInfo readMemberStructure(BytePointer ptr, boolean isField) throws ClsFormatException {
int flags = ClsUtil.readU2(ptr);
int nameIndex = ClsUtil.readU2(ptr);
int descriptorIndex = ClsUtil.readU2(ptr);
BytePointer p = new BytePointer(getData(), getOffsetInConstantPool(nameIndex));
String name = ClsUtil.readUtf8Info(p);
p.offset = getOffsetInConstantPool(descriptorIndex);
String descriptor = ClsUtil.readUtf8Info(p);
if (isField) {
final ClsAttributeTable attributeTable = readAttributes(ptr);
return new FieldInfo(
getSymbolId(name),
getSymbolId(descriptor),
attributeTable.genericSignature != null? getSymbolId(attributeTable.genericSignature) : -1,
flags,
attributeTable.constantValue,
attributeTable.runtimeVisibleAnnotations,
attributeTable.runtimeInvisibleAnnotations
);
}
else {
final ClsAttributeTable attributeTable = readAttributes(ptr);
int[] intExceptions = null;
if (attributeTable.exceptions != null) {
intExceptions = ArrayUtil.newIntArray(attributeTable.exceptions.length);
for (int idx = 0; idx < intExceptions.length; idx++) {
intExceptions[idx] = getSymbolId(attributeTable.exceptions[idx]);
}
}
return new MethodInfo(
getSymbolId(name),
getSymbolId(descriptor),
attributeTable.genericSignature != null? getSymbolId(attributeTable.genericSignature) : -1,
flags,
intExceptions,
CONSTRUCTOR_NAME.equals(name),
attributeTable.runtimeVisibleAnnotations,
attributeTable.runtimeInvisibleAnnotations,
attributeTable.runtimeVisibleParameterAnnotations,
attributeTable.runtimeInvisibleParameterAnnotations,
attributeTable.annotationDefault
);
}
}
private int getSymbolId(final String symbol) throws ClsFormatException{
try {
return mySymbolTable.getId(symbol);
}
catch (CacheCorruptedException e) {
throw new ClsFormatException(e.getLocalizedMessage());
}
}
public String getQualifiedName() throws ClsFormatException {
if (myQualifiedName == null) {
BytePointer ptr = new BytePointer(getData(), getConstantPoolEnd() + 2);
ptr.offset = getOffsetInConstantPool(ClsUtil.readU2(ptr));
int tag = ClsUtil.readU1(ptr);
if (tag != ClsUtil.CONSTANT_Class){
throw new ClsFormatException();
}
ptr.offset = getOffsetInConstantPool(ClsUtil.readU2(ptr));
myQualifiedName = ClsUtil.readUtf8Info(ptr, '/', '.'); // keep '$' in the names
}
return myQualifiedName;
}
/**
* @return fully qualified name of the class' superclass. In case there is no super return ""
*/
public String getSuperClass() throws ClsFormatException {
if (mySuperClassName == null) {
BytePointer ptr = new BytePointer(getData(), getConstantPoolEnd() + 4);
int index = ClsUtil.readU2(ptr);
if (index == 0) {
if (CommonClassNames.JAVA_LANG_OBJECT.equals(getQualifiedName())) {
mySuperClassName = "";
}
else {
throw new ClsFormatException();
}
}
else {
ptr.offset = getOffsetInConstantPool(index);
mySuperClassName = readClassInfo(ptr); // keep '$' in the name for anonymous classes
if (isInterface()) {
if (!CommonClassNames.JAVA_LANG_OBJECT.equals(mySuperClassName)) {
throw new ClsFormatException();
}
}
/*
else {
if (!MakeUtil.isAnonymous(mySuperClassName)) {
mySuperClassName = mySuperClassName.replace('$', '.');
}
}
*/
}
}
return mySuperClassName;
}
public String[] getSuperInterfaces() throws ClsFormatException {
if (mySuperInterfaces == null) {
BytePointer ptr = new BytePointer(getData(), getConstantPoolEnd() + 6);
int count = ClsUtil.readU2(ptr);
mySuperInterfaces = ArrayUtil.newStringArray(count);
BytePointer auxPtr = new BytePointer(ptr.bytes, 0);
for (int idx = 0; idx < mySuperInterfaces.length; idx++) {
auxPtr.offset = getOffsetInConstantPool(ClsUtil.readU2(ptr));
mySuperInterfaces[idx] = readClassInfo(auxPtr);
}
}
return mySuperInterfaces;
}
public String getSourceFileName() throws ClsFormatException {
parseMembers();
final String fName = mySourceFileName;
return fName != null? fName : "";
}
public String getGenericSignature() throws ClsFormatException {
parseMembers();
final String genericSignature = myGenericSignature;
return genericSignature != null && !genericSignature.isEmpty() ? genericSignature : null;
}
public AnnotationConstantValue[] getRuntimeVisibleAnnotations() throws ClsFormatException {
parseMembers();
final AnnotationConstantValue[] annotations = myRuntimeVisibleAnnotations;
return annotations != null? annotations : AnnotationConstantValue.EMPTY_ARRAY;
}
public AnnotationConstantValue[] getRuntimeInvisibleAnnotations() throws ClsFormatException {
parseMembers();
final AnnotationConstantValue[] annotations = myRuntimeInvisibleAnnotations;
return annotations != null? annotations : AnnotationConstantValue.EMPTY_ARRAY;
}
private boolean isInterface(){
return (getAccessFlags() & ClsUtil.ACC_INTERFACE) != 0;
}
// helper methods
private void parseConstantPool() throws ClsFormatException {
if (myReferences != null) {
return;
}
myReferences = new ArrayList<ReferenceInfo>();
initConstantPool();
final BytePointer ptr = new BytePointer(getData(), 0);
ConstantPoolIterator iterator = new ConstantPoolIterator(ptr);
while (iterator.hasMoreEntries()) {
final int tag = ClsUtil.readU1(ptr);
if (tag == ClsUtil.CONSTANT_Fieldref || tag == ClsUtil.CONSTANT_Methodref || tag == ClsUtil.CONSTANT_InterfaceMethodref) {
//ptr.offset -= 1; // position to the beginning of the structure
MemberReferenceInfo refInfo = readRefStructure(tag, ptr);
if (refInfo != null) {
myReferences.add(refInfo);
}
/*
String name = mySymbolTable.getSymbol(refInfo.getMemberInfo().getName());
if (name.indexOf('$') < 0 && name.indexOf('<') < 0) { // skip refs to synthetic members
myReferences.add(refInfo);
}
else if ("<init>".equals(name)) { // add instance initializers (constructors)
myReferences.add(refInfo);
}
else {
System.out.println("ReferenceInfo thrown out: " + mySymbolTable.getSymbol(refInfo.getClassName()) + "." + mySymbolTable.getSymbol(refInfo.getMemberInfo().getName()));
ourWasteReferenceObjectsCounter += 1;
}
*/
}
else if (tag == ClsUtil.CONSTANT_Class) {
ptr.offset -= 1; // position to the beginning of the structure
String className = readClassInfo(ptr);
myReferences.add(new ReferenceInfo(getSymbolId(className)));
}
iterator.next();
}
//System.out.println("ourWasteReferenceObjectsCounter = " + ourWasteReferenceObjectsCounter);
}
private MemberReferenceInfo readRefStructure(int tag, BytePointer ptr) throws ClsFormatException {
/*
if (tag != ClsUtil.CONSTANT_Fieldref && tag != ClsUtil.CONSTANT_Methodref && tag != ClsUtil.CONSTANT_InterfaceMethodref) {
throw new ClsFormatException();
}
*/
int classInfoIndex = ClsUtil.readU2(ptr);
int nameTypeInfoIndex = ClsUtil.readU2(ptr);
ptr.offset = getOffsetInConstantPool(classInfoIndex);
if (ClsUtil.CONSTANT_Class != ClsUtil.readU1(ptr)) {
throw new ClsFormatException();
}
ptr.offset = getOffsetInConstantPool(ClsUtil.readU2(ptr));
String className = ClsUtil.readUtf8Info(ptr, '/', '.'); // keep '$' in names
ptr.offset = getOffsetInConstantPool(nameTypeInfoIndex);
if (ClsUtil.CONSTANT_NameAndType != ClsUtil.readU1(ptr)) {
throw new ClsFormatException();
}
int memberNameIndex = ClsUtil.readU2(ptr);
int descriptorIndex = ClsUtil.readU2(ptr);
ptr.offset = getOffsetInConstantPool(memberNameIndex);
String memberName = ClsUtil.readUtf8Info(ptr);
if ((memberName.indexOf('$') >= 0 || memberName.indexOf('<') >= 0) && !CONSTRUCTOR_NAME.equals(memberName)) { // skip refs to synthetic members
return null;
}
ptr.offset = getOffsetInConstantPool(descriptorIndex);
String descriptor = ClsUtil.readUtf8Info(ptr);
MemberInfo info = ClsUtil.CONSTANT_Fieldref == tag? new FieldInfo(getSymbolId(memberName), getSymbolId(descriptor)) : new MethodInfo(getSymbolId(memberName), getSymbolId(descriptor), CONSTRUCTOR_NAME.equals(memberName));
return new MemberReferenceInfo(getSymbolId(className), info);
}
public int getAccessFlags(){
try{
int offset = getConstantPoolEnd();
byte[] data = getData();
if (offset + 2 > data.length){
throw new ClsFormatException();
}
int b1 = data[offset++] & 0xFF;
int b2 = data[offset++] & 0xFF;
return (b1 << 8) + b2;
}
catch(ClsFormatException e){
return 0;
}
}
private byte[] getData(){
if (myData == null) {
try{
myData = FileUtil.loadFileBytes(myFile);
}
catch(IOException e){
myData = ArrayUtil.EMPTY_BYTE_ARRAY;
}
}
return myData;
}
private int getOffsetInConstantPool(int index) throws ClsFormatException {
initConstantPool();
if (index < 1 || index >= myConstantPoolOffsets.length){
throw new ClsFormatException();
}
return myConstantPoolOffsets[index - 1];
}
private int getConstantPoolEnd() throws ClsFormatException {
initConstantPool();
return myConstantPoolOffsets[myConstantPoolOffsets.length - 1];
}
private void initConstantPool() throws ClsFormatException {
if (myConstantPoolOffsets == null){
BytePointer ptr = new BytePointer(getData(), 0);
ConstantPoolIterator iterator = new ConstantPoolIterator(ptr);
myConstantPoolOffsets = new int[iterator.getEntryCount()];
myConstantPoolOffsets[0] = iterator.getCurrentOffset();
int index = 1;
while (iterator.hasMoreEntries()) {
int tag = ClsUtil.readU1(ptr);
if (tag == ClsUtil.CONSTANT_Long || tag == ClsUtil.CONSTANT_Double) {
myConstantPoolOffsets[index++] = ptr.offset + 8; // takes 2 entries!
}
iterator.next();
myConstantPoolOffsets[index++] = iterator.getCurrentOffset();
}
}
}
private String readClassInfo(BytePointer ptr) throws ClsFormatException{
final int tag = ClsUtil.readU1(ptr);
if (tag != ClsUtil.CONSTANT_Class){
throw new ClsFormatException(CompilerBundle.message("class.parsing.error.wrong.record.tag.expected.another", tag, ClsUtil.CONSTANT_Class));
}
int index = ClsUtil.readU2(ptr);
return ClsUtil.readUtf8Info(new BytePointer(ptr.bytes, getOffsetInConstantPool(index)), '/', '.');
}
@SuppressWarnings({"HardCodedStringLiteral"})
private ClsAttributeTable readAttributes(BytePointer ptr) throws ClsFormatException {
int count = ClsUtil.readU2(ptr); // attributeCount
final ClsAttributeTable attributes = new ClsAttributeTable();
while (count-- > 0) {
final String attrName = readAttributeName(ptr);
if ("Exceptions".equals(attrName)) {
attributes.exceptions = readExceptions(ptr);
}
else if ("Signature".equals(attrName)) {
attributes.genericSignature = readSignatureAttribute(ptr);
}
else if ("SourceFile".equals(attrName)) {
attributes.sourceFile = readSourceFileAttribute(ptr);
}
else if ("ConstantValue".equals(attrName)){
attributes.constantValue = readFieldConstantValue(ptr);
}
else if ("RuntimeVisibleAnnotations".equals(attrName)) {
attributes.runtimeVisibleAnnotations = readAnnotations(ptr);
}
else if ("RuntimeInvisibleAnnotations".equals(attrName)) {
attributes.runtimeInvisibleAnnotations = readAnnotations(ptr);
}
else if ("RuntimeVisibleParameterAnnotations".equals(attrName)) {
attributes.runtimeVisibleParameterAnnotations = readParameterAnnotations(ptr);
}
else if ("RuntimeInvisibleParameterAnnotations".equals(attrName)) {
attributes.runtimeInvisibleParameterAnnotations = readParameterAnnotations(ptr);
}
else if ("AnnotationDefault".equals(attrName)) {
attributes.annotationDefault = readAnnotationMemberValue(new BytePointer(ptr.bytes, ptr.offset + 6));
}
gotoNextAttribute(ptr);
}
return attributes;
}
private String readAttributeName(BytePointer p) throws ClsFormatException {
final BytePointer ptr = new BytePointer(p.bytes, p.offset);
final int nameIndex = ClsUtil.readU2(ptr);
ptr.offset = getOffsetInConstantPool(nameIndex);
return ClsUtil.readUtf8Info(ptr);
}
private static void gotoNextAttribute(BytePointer ptr) throws ClsFormatException {
ptr.offset += 2; // skip name index
final int length = ClsUtil.readU4(ptr); // important! Do not inline since ptr.offset is also changed inside ClsUtil.readU4() method
ptr.offset += length;
}
/**
Signature_attribute {
u2 attribute_name_index; (must be equal to "Signature")
u4 attribute_length; (must be equal to 2)
u2 signature_index;
}
*/
private String readSignatureAttribute(BytePointer p) throws ClsFormatException {
final BytePointer ptr = new BytePointer(p.bytes, p.offset + 2); // position to the length
if (ClsUtil.readU4(ptr) != 2) {
return null;
}
ptr.offset = getOffsetInConstantPool(ClsUtil.readU2(ptr));
return ClsUtil.readUtf8Info(ptr);
}
private String[] readExceptions(BytePointer p) throws ClsFormatException{
final BytePointer ptr = new BytePointer(p.bytes, p.offset + 6); // position to the count of exceptions
int count = ClsUtil.readU2(ptr);
final ArrayList<String> array = new ArrayList<String>(count);
while (count-- > 0) {
int idx = ClsUtil.readU2(ptr);
if (idx != 0) {
final String exceptionClass = readClassInfo(new BytePointer(ptr.bytes, getOffsetInConstantPool(idx)));
array.add(exceptionClass);
}
}
return ArrayUtil.toStringArray(array);
}
private String readSourceFileAttribute(BytePointer p) throws ClsFormatException {
BytePointer ptr = new BytePointer(p.bytes, p.offset + 2); // position to the length
if (ClsUtil.readU4(ptr) != 2) {
return null;
}
ptr.offset = getOffsetInConstantPool(ClsUtil.readU2(ptr));
String path = ClsUtil.readUtf8Info(ptr);
// jdk version 1.3.0 puts full path to the source, but later versions store only short name
final int slashIndex = path.lastIndexOf('/');
if (slashIndex >= 0) {
path = path.substring(slashIndex + 1, path.length());
}
return path;
}
private ConstantValue readFieldConstantValue(BytePointer p) throws ClsFormatException{
final BytePointer ptr = new BytePointer(p.bytes, p.offset + 2);
if (ClsUtil.readU4(ptr) != 2) {
throw new ClsFormatException(); // attribute length must be 2
}
int valueIndex = ClsUtil.readU2(ptr);
ptr.offset = getOffsetInConstantPool(valueIndex);
return readConstant(ptr);
}
private ConstantValue readConstant(final BytePointer ptr) throws ClsFormatException {
final int tag = ClsUtil.readU1(ptr);
switch (tag) {
case ClsUtil.CONSTANT_Integer :
int value = ClsUtil.readU4(ptr);
return new IntegerConstantValue(value);
case ClsUtil.CONSTANT_Float:
float floatValue = ClsUtil.readFloat(ptr);
return new FloatConstantValue(floatValue);
case ClsUtil.CONSTANT_Long :
int high = ClsUtil.readU4(ptr);
int low = ClsUtil.readU4(ptr);
long v = ((long)high << 32) | (low & 0xFFFFFFFFL);
return new LongConstantValue(v);
case ClsUtil.CONSTANT_Double :
double doubleValue = ClsUtil.readDouble(ptr);
return new DoubleConstantValue(doubleValue);
case ClsUtil.CONSTANT_String :
int stringIndex = ClsUtil.readU2(ptr);
ptr.offset = getOffsetInConstantPool(stringIndex);
return new StringConstantValue(ClsUtil.readUtf8Info(ptr));
default : throw new ClsFormatException();
}
}
private AnnotationConstantValue[] readAnnotations(BytePointer p) throws ClsFormatException {
final BytePointer ptr = new BytePointer(p.bytes, p.offset + 6);
return readAnnotationsArray(ptr);
}
private AnnotationConstantValue[][] readParameterAnnotations(BytePointer p) throws ClsFormatException {
final BytePointer ptr = new BytePointer(p.bytes, p.offset + 6); // position to the number of parameters
final int numberOfParams = ClsUtil.readU1(ptr);
if (numberOfParams == 0) {
return null;
}
final AnnotationConstantValue[][] annotations = new AnnotationConstantValue[numberOfParams][];
for (int parameterIndex = 0; parameterIndex < numberOfParams; parameterIndex++) {
annotations[parameterIndex] = readAnnotationsArray(ptr);
}
return annotations;
}
private AnnotationConstantValue[] readAnnotationsArray(BytePointer ptr) throws ClsFormatException {
final int numberOfAnnotations = ClsUtil.readU2(ptr);
if (numberOfAnnotations == 0) {
return AnnotationConstantValue.EMPTY_ARRAY;
}
AnnotationConstantValue[] annotations = new AnnotationConstantValue[numberOfAnnotations];
for (int attributeIndex = 0; attributeIndex < numberOfAnnotations; attributeIndex++) {
annotations[attributeIndex] = readAnnotation(ptr);
}
return annotations;
}
private AnnotationConstantValue readAnnotation(BytePointer ptr) throws ClsFormatException {
final int classInfoIndex = ClsUtil.readU2(ptr);
final String qName = readAnnotationClassName(new BytePointer(ptr.bytes, getOffsetInConstantPool(classInfoIndex)));
final List<AnnotationNameValuePair> memberValues = new ArrayList<AnnotationNameValuePair>();
final int numberOfPairs = ClsUtil.readU2(ptr);
for (int idx = 0; idx < numberOfPairs; idx++) {
final int memberNameIndex = ClsUtil.readU2(ptr);
final String memberName = ClsUtil.readUtf8Info(ptr.bytes, getOffsetInConstantPool(memberNameIndex));
final ConstantValue memberValue = readAnnotationMemberValue(ptr);
memberValues.add(new AnnotationNameValuePair(getSymbolId(memberName), memberValue));
}
return new AnnotationConstantValue(getSymbolId(qName), memberValues.toArray(new AnnotationNameValuePair[memberValues.size()]));
}
private String readAnnotationClassName(BytePointer ptr) throws ClsFormatException {
// TODO: need this method because because of incomplete class format spec at the moment of writing
// it is not clear what structure is expected: CONSTANT_Utf8 or CONSTANT_Class
final int tag = ClsUtil.readU1(ptr);
if (tag == ClsUtil.CONSTANT_Utf8) {
return ClsUtil.getTypeText(ptr.bytes, ptr.offset + 2); //skip length
}
if (tag == ClsUtil.CONSTANT_Class){
ptr.offset -= 1; // rollback
return readClassInfo(ptr);
}
//noinspection HardCodedStringLiteral
throw new ClsFormatException(CompilerBundle.message("class.parsing.error.wrong.record.tag.expected.another", tag, "CONSTANT_Utf8(" + ClsUtil.CONSTANT_Utf8 + ") / CONSTANT_Class(" + ClsUtil.CONSTANT_Class + ")"));
}
private ConstantValue readAnnotationMemberValue(BytePointer ptr) throws ClsFormatException {
final char tag = (char)ClsUtil.readU1(ptr);
switch (tag) {
case 'B':
case 'C':
case 'D':
case 'F':
case 'I':
case 'J':
case 'S':
case 'Z': {
final int valueIndex = ClsUtil.readU2(ptr);
return new AnnotationPrimitiveConstantValue(tag, readConstant(new BytePointer(ptr.bytes, getOffsetInConstantPool(valueIndex))));
}
case 's': {
final int valueIndex = ClsUtil.readU2(ptr);
return new StringConstantValue(ClsUtil.readUtf8Info(ptr.bytes, getOffsetInConstantPool(valueIndex)));
}
case 'e': {
final int typeNameIndex = ClsUtil.readU2(ptr);
final int constantNameIndex = ClsUtil.readU2(ptr);
final String typeName = ClsUtil.readUtf8Info(ptr.bytes, getOffsetInConstantPool(typeNameIndex));
final String constantName = ClsUtil.readUtf8Info(ptr.bytes, getOffsetInConstantPool(constantNameIndex));
return new EnumConstantValue(getSymbolId(typeName), getSymbolId(constantName));
}
case 'c' : {
final int classInfoIndex = ClsUtil.readU2(ptr);
BytePointer p = new BytePointer(ptr.bytes, getOffsetInConstantPool(classInfoIndex));
final int recordTag = ClsUtil.readU1(p);
if (recordTag != ClsUtil.CONSTANT_Utf8) {
throw new ClsFormatException(CompilerBundle.message("class.parsing.error.wrong.record.tag.expected.another", recordTag, ClsUtil.CONSTANT_Utf8));
}
p.offset += 2; //Skip length
final String className = ClsUtil.getTypeText(p.bytes, p.offset);
return new ClassInfoConstantValue(getSymbolId(className));
}
case '@' : {
return readAnnotation(ptr);
}
case '[' : {
final int numberOfValues = ClsUtil.readU2(ptr);
final ConstantValue[] values = new ConstantValue[numberOfValues];
for (int idx = 0; idx < numberOfValues; idx++) {
values[idx] = readAnnotationMemberValue(ptr);
}
return new ConstantValueArray(values);
}
default : throw new ClsFormatException(CompilerBundle.message("class.parsing.error.wrong.tag.annotation.member.value", tag));
}
}
private static class ClsAttributeTable {
public String[] exceptions;
public String genericSignature;
public String sourceFile;
public ConstantValue constantValue;
public AnnotationConstantValue[] runtimeVisibleAnnotations;
public AnnotationConstantValue[] runtimeInvisibleAnnotations;
public AnnotationConstantValue[][] runtimeVisibleParameterAnnotations;
public AnnotationConstantValue[][] runtimeInvisibleParameterAnnotations;
public ConstantValue annotationDefault;
}
private static class ConstantPoolIterator {
private final BytePointer myPtr;
private final int myEntryCount;
private int myCurrentEntryIndex;
private int myCurrentOffset;
public ConstantPoolIterator(BytePointer ptr) throws ClsFormatException {
myPtr = ptr;
myPtr.offset = 0;
int magic = ClsUtil.readU4(myPtr);
if (magic != ClsUtil.MAGIC){
throw new ClsFormatException();
}
myPtr.offset += 2; // minor version
myPtr.offset += 2; // major version
myEntryCount = ClsUtil.readU2(myPtr);
if (myEntryCount < 1){
throw new ClsFormatException();
}
myCurrentEntryIndex = 1; // Entry at index 0 is included in the count but is not present in the constant pool
myCurrentOffset = myPtr.offset;
}
public int getEntryCount() {
return myEntryCount;
}
public int getCurrentOffset() {
return myCurrentOffset;
}
/**
* tests if there are unread entries
*/
public boolean hasMoreEntries() {
return myCurrentEntryIndex < myEntryCount;
}
/**
* Positions the pointer to the next entry
*/
public void next() throws ClsFormatException {
myPtr.offset = myCurrentOffset;
int tag = ClsUtil.readU1(myPtr);
switch(tag){
default:
throw new ClsFormatException();
case ClsUtil.CONSTANT_Class:
case ClsUtil.CONSTANT_String:
myPtr.offset += 2;
break;
case ClsUtil.CONSTANT_Fieldref:
case ClsUtil.CONSTANT_Methodref:
case ClsUtil.CONSTANT_InterfaceMethodref:
case ClsUtil.CONSTANT_Integer:
case ClsUtil.CONSTANT_Float:
case ClsUtil.CONSTANT_NameAndType:
myPtr.offset += 4;
break;
case ClsUtil.CONSTANT_Long:
case ClsUtil.CONSTANT_Double:
myPtr.offset += 8;
myCurrentEntryIndex++; // takes 2 entries
break;
case ClsUtil.CONSTANT_Utf8:
int length = ClsUtil.readU2(myPtr);
myPtr.offset += length;
break;
case ClsUtil.CONSTANT_MethodHandle:
myPtr.offset += 3;
break;
case ClsUtil.CONSTANT_MethodType:
myPtr.offset += 2;
break;
case ClsUtil.CONSTANT_InvokeDynamic:
myPtr.offset += 4;
break;
}
myCurrentEntryIndex++;
myCurrentOffset = myPtr.offset;
}
}
}
@@ -1,229 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.classParsing;
import com.intellij.compiler.SymbolTable;
import com.intellij.compiler.make.CacheCorruptedException;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Comparing;
import com.intellij.util.ArrayUtil;
import com.intellij.util.cls.ClsFormatException;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Collection;
/**
@author Eugene Zhuravlev
*/
public final class ClassInfo implements Cloneable {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.classParsing.ClassInfo");
private static final ReferenceInfo[] EMPTY_REF_ARRAY = new ReferenceInfo[0];
private final int myQualifiedName;
private final int myGenericSignature;
private final int mySuperQualifiedName;
private final int myFlags;
private String myPath;
private final String mySourceFileName;
private final int[] mySuperInterfaces;
private final FieldInfo[] myFields;
private final MethodInfo[] myMethods;
private ReferenceInfo[] myReferences;
private final AnnotationConstantValue[] myRuntimeVisibleAnnotations;
private final AnnotationConstantValue[] myRuntimeInvisibleAnnotations;
private boolean myIsDirty = false;
public ClassInfo(ClassFileReader reader, SymbolTable symbolTable) throws CacheCorruptedException {
try {
final int qName = symbolTable.getId(reader.getQualifiedName());
myQualifiedName = qName;
final String genericSignature = reader.getGenericSignature();
myGenericSignature = genericSignature != null? symbolTable.getId(genericSignature) : -1;
myPath = reader.getPath();
final String superClass = reader.getSuperClass();
final int superQName = "".equals(superClass)? -1 : symbolTable.getId(superClass);
mySuperQualifiedName = superQName;
LOG.assertTrue(superQName != qName);
final String[] superInterfaces = reader.getSuperInterfaces();
mySuperInterfaces = ArrayUtil.newIntArray(superInterfaces.length);
for (int idx = 0; idx < superInterfaces.length; idx++) {
mySuperInterfaces[idx] = symbolTable.getId(superInterfaces[idx]);
}
final String sourceFileName = reader.getSourceFileName();
mySourceFileName = sourceFileName != null? sourceFileName : "";
myFlags = reader.getAccessFlags();
myRuntimeVisibleAnnotations = reader.getRuntimeVisibleAnnotations();
myRuntimeInvisibleAnnotations = reader.getRuntimeInvisibleAnnotations();
final Collection<ReferenceInfo> refs = reader.getReferences();
myReferences = refs.toArray(new ReferenceInfo[refs.size()]);
myFields = reader.getFields();
myMethods = reader.getMethods();
}
catch (ClsFormatException e) {
throw new CacheCorruptedException(e);
}
}
public ClassInfo(DataInput in) throws IOException {
myQualifiedName = in.readInt();
mySuperQualifiedName = in.readInt();
myGenericSignature = in.readInt();
myFlags = in.readInt();
myPath = in.readUTF();
mySourceFileName = in.readUTF();
final int ifaceCount = in.readInt();
mySuperInterfaces = new int[ifaceCount];
for (int idx = 0; idx < ifaceCount; idx++) {
mySuperInterfaces[idx] = in.readInt();
}
final int fieldCount = in.readInt();
myFields = new FieldInfo[fieldCount];
for (int idx = 0; idx < fieldCount; idx++) {
myFields[idx] = new FieldInfo(in);
}
final int methodCount = in.readInt();
myMethods = new MethodInfo[methodCount];
for (int idx = 0; idx < methodCount; idx++) {
myMethods[idx] = new MethodInfo(in);
}
final int refCount = in.readInt();
myReferences = refCount > 0? new ReferenceInfo[refCount] : EMPTY_REF_ARRAY;
for (int idx = 0; idx < refCount; idx++) {
myReferences[idx] = MemberInfoExternalizer.loadReferenceInfo(in);
}
myRuntimeVisibleAnnotations = MemberInfoExternalizer.readAnnotationConstantValueArray1(in);
myRuntimeInvisibleAnnotations = MemberInfoExternalizer.readAnnotationConstantValueArray1(in);
}
public ClassInfo clone() {
try {
return (ClassInfo)super.clone();
}
catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
public void save(DataOutput out) throws IOException {
out.writeInt(myQualifiedName);
out.writeInt(mySuperQualifiedName);
out.writeInt(myGenericSignature);
out.writeInt(myFlags);
out.writeUTF(myPath);
out.writeUTF(mySourceFileName);
out.writeInt(mySuperInterfaces.length);
for (int ifaceQName : mySuperInterfaces) {
out.writeInt(ifaceQName);
}
out.writeInt(myFields.length);
for (FieldInfo field : myFields) {
field.save(out);
}
out.writeInt(myMethods.length);
for (MethodInfo method : myMethods) {
method.save(out);
}
out.writeInt(myReferences.length);
for (ReferenceInfo info : myReferences) {
MemberInfoExternalizer.saveReferenceInfo(out, info);
}
MemberInfoExternalizer.writeConstantValueArray1(out, myRuntimeVisibleAnnotations);
MemberInfoExternalizer.writeConstantValueArray1(out, myRuntimeInvisibleAnnotations);
}
public boolean isDirty() {
return myIsDirty;
}
public int getQualifiedName() throws IOException {
return myQualifiedName;
}
public int getGenericSignature() throws IOException {
return myGenericSignature;
}
public int getSuperQualifiedName() throws IOException {
return mySuperQualifiedName;
}
public int[] getSuperInterfaces() throws IOException {
return mySuperInterfaces;
}
public int getFlags() throws IOException {
return myFlags;
}
public String getPath() throws IOException {
return myPath;
}
public void setPath(String path) {
myIsDirty |= !Comparing.equal(myPath, path);
myPath = path;
}
public String getSourceFileName() throws IOException {
return mySourceFileName;
}
public AnnotationConstantValue[] getRuntimeVisibleAnnotations() throws IOException {
return myRuntimeVisibleAnnotations;
}
public AnnotationConstantValue[] getRuntimeInvisibleAnnotations() throws IOException {
return myRuntimeInvisibleAnnotations;
}
public ReferenceInfo[] getReferences() {
return myReferences;
}
public void clearReferences() {
myReferences = EMPTY_REF_ARRAY;
}
public FieldInfo[] getFields() {
return myFields;
}
public MethodInfo[] getMethods() {
return myMethods;
}
}
@@ -1,56 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.classParsing;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
public class ClassInfoConstantValue extends ConstantValue{
private final int myValue;
public ClassInfoConstantValue(int value) {
myValue = value;
}
public ClassInfoConstantValue(DataInput in) throws IOException{
myValue = in.readInt();
}
public int getValue() {
return myValue;
}
public void save(DataOutput out) throws IOException {
super.save(out);
out.writeInt(myValue);
}
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ClassInfoConstantValue)) return false;
final ClassInfoConstantValue classInfoConstantValue = (ClassInfoConstantValue)o;
if (myValue != classInfoConstantValue.myValue) return false;
return true;
}
public int hashCode() {
return myValue;
}
}
@@ -1,35 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* created at Feb 24, 2002
* @author Jeka
*/
package com.intellij.compiler.classParsing;
import java.io.DataOutput;
import java.io.IOException;
public class ConstantValue {
public static final ConstantValue EMPTY_CONSTANT_VALUE = new ConstantValue();
protected ConstantValue() {
}
public void save(DataOutput out) throws IOException {
}
}
@@ -1,68 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.classParsing;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Arrays;
/**
* @author Eugene Zhuravlev
* Date: Apr 2, 2004
*/
public class ConstantValueArray extends ConstantValue{
private final ConstantValue[] myValue;
public ConstantValueArray(ConstantValue[] value) {
myValue = value;
}
public ConstantValueArray(DataInput in) throws IOException {
final int size = in.readInt();
myValue = new ConstantValue[size];
for (int idx = 0; idx < size; idx++) {
myValue[idx] = MemberInfoExternalizer.loadConstantValue(in);
}
}
public ConstantValue[] getValue() {
return myValue;
}
public void save(DataOutput out) throws IOException {
out.writeInt(myValue.length);
for (int idx = 0; idx < myValue.length; idx++) {
MemberInfoExternalizer.saveConstantValue(out, myValue[idx]);
}
}
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ConstantValueArray)) return false;
final ConstantValueArray constantValueArray = (ConstantValueArray)o;
if (!Arrays.equals(myValue, constantValueArray.myValue)) return false;
return true;
}
public int hashCode() {
return 0;
}
}
@@ -1,50 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* created at Feb 24, 2002
* @author Jeka
*/
package com.intellij.compiler.classParsing;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
public class DoubleConstantValue extends ConstantValue{
private final double myValue;
public DoubleConstantValue(double value) {
myValue = value;
}
public DoubleConstantValue(DataInput in) throws IOException{
myValue = in.readDouble();
}
public double getValue() {
return myValue;
}
public void save(DataOutput out) throws IOException {
super.save(out);
out.writeDouble(myValue);
}
public boolean equals(Object obj) {
return (obj instanceof DoubleConstantValue) && (((DoubleConstantValue)obj).myValue == myValue);
}
}
@@ -1,73 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* created at Feb 24, 2002
* @author Jeka
*/
package com.intellij.compiler.classParsing;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
public class EnumConstantValue extends ConstantValue{
private final int myTypeName;
private final int myConstantName;
public EnumConstantValue(int typeName, int constantName) {
myTypeName = typeName;
myConstantName = constantName;
}
public EnumConstantValue(DataInput in) throws IOException{
myTypeName = in.readInt();
myConstantName = in.readInt();
}
public int getTypeName() {
return myTypeName;
}
public int getConstantName() {
return myConstantName;
}
public void save(DataOutput out) throws IOException {
super.save(out);
out.writeInt(myTypeName);
out.writeInt(myConstantName);
}
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof EnumConstantValue)) return false;
final EnumConstantValue enumConstantValue = (EnumConstantValue)o;
if (myConstantName != enumConstantValue.myConstantName) return false;
if (myTypeName != enumConstantValue.myTypeName) return false;
return true;
}
public int hashCode() {
int result;
result = myTypeName;
result = 29 * result + myConstantName;
return result;
}
}
@@ -1,55 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* created at Jan 10, 2002
* @author Jeka
*/
package com.intellij.compiler.classParsing;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
public class FieldInfo extends MemberInfo {
public static final FieldInfo[] EMPTY_ARRAY = new FieldInfo[0];
private final ConstantValue myConstantValue;
public FieldInfo(int name, int descriptor) {
super(name, descriptor);
myConstantValue = ConstantValue.EMPTY_CONSTANT_VALUE;
}
public FieldInfo(int name, int descriptor, final int genericSignature, int flags, ConstantValue value, final AnnotationConstantValue[] runtimeVisibleAnnotations, final AnnotationConstantValue[] runtimeInvisibleAnnotations) {
super(name, descriptor, genericSignature, flags, runtimeVisibleAnnotations, runtimeInvisibleAnnotations);
myConstantValue = value == null ? ConstantValue.EMPTY_CONSTANT_VALUE : value;
}
public FieldInfo(DataInput in) throws IOException {
super(in);
myConstantValue = MemberInfoExternalizer.loadConstantValue(in);
}
public ConstantValue getConstantValue() {
return myConstantValue;
}
public void save(DataOutput out) throws IOException {
super.save(out);
MemberInfoExternalizer.saveConstantValue(out, myConstantValue);
}
}
@@ -1,50 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* created at Feb 24, 2002
* @author Jeka
*/
package com.intellij.compiler.classParsing;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
public class FloatConstantValue extends ConstantValue{
private final float myValue;
public FloatConstantValue(float value) {
myValue = value;
}
public FloatConstantValue(DataInput in) throws IOException{
myValue = in.readFloat();
}
public float getValue() {
return myValue;
}
public void save(DataOutput out) throws IOException {
super.save(out);
out.writeFloat(myValue);
}
public boolean equals(Object obj) {
return (obj instanceof FloatConstantValue) && (((FloatConstantValue)obj).myValue == myValue);
}
}
@@ -1,98 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.classParsing;
import com.intellij.openapi.compiler.CompilerBundle;
import com.intellij.util.ArrayUtil;
import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
import java.util.ArrayList;
import java.util.List;
/**
* @author Eugene Zhuravlev
* Date: Mar 4, 2004
*/
public class GenericMethodSignature {
private final String myFormalTypeParams;
private final String[] myParamSignatures;
private final String myReturnTypeSignature;
private final String myThrowsSignature;
private GenericMethodSignature(String formalTypeParams, String[] paramSignatures, String returnTypeSignature, String throwsSignature) {
myFormalTypeParams = formalTypeParams;
myParamSignatures = paramSignatures;
myReturnTypeSignature = returnTypeSignature;
myThrowsSignature = throwsSignature;
}
public String getFormalTypeParams() {
return myFormalTypeParams;
}
public String[] getParamSignatures() {
return myParamSignatures;
}
public String getReturnTypeSignature() {
return myReturnTypeSignature;
}
public String getThrowsSignature() {
return myThrowsSignature;
}
public static GenericMethodSignature parse(String methodSignature) throws SignatureParsingException {
final StringCharacterIterator it = new StringCharacterIterator(methodSignature);
final StringBuilder formals = new StringBuilder();
if (it.current() == '<') {
SignatureParser.INSTANCE.parseFormalTypeParameters(it, formals);
}
if (it.current() != '(') {
throw new SignatureParsingException(CompilerBundle.message("error.signature.parsing.expected.other.symbol", "(", formals.toString()));
}
it.next(); // skip '('
final String[] paramSignatures;
if (it.current() != ')') {
final List<String> params = new ArrayList<String>();
while (it.current() != ')') {
final StringBuilder typeSignature = new StringBuilder();
SignatureParser.INSTANCE.parseTypeSignature(it, typeSignature);
params.add(typeSignature.toString());
}
paramSignatures = ArrayUtil.toStringArray(params);
}
else {
paramSignatures = ArrayUtil.EMPTY_STRING_ARRAY;
}
it.next(); // skip ')'
final StringBuilder returnTypeSignature = new StringBuilder();
SignatureParser.INSTANCE.parseReturnType(it, returnTypeSignature);
final StringBuilder throwsSignature = new StringBuilder();
if (it.current() != CharacterIterator.DONE) {
SignatureParser.INSTANCE.parseThrowsSignature(it, throwsSignature);
}
return new GenericMethodSignature(formals.toString(), paramSignatures, returnTypeSignature.toString(), throwsSignature.toString());
}
}
@@ -1,50 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* created at Feb 24, 2002
* @author Jeka
*/
package com.intellij.compiler.classParsing;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
public class IntegerConstantValue extends ConstantValue{
private final int myValue;
public IntegerConstantValue(int value) {
myValue = value;
}
public IntegerConstantValue(DataInput in) throws IOException{
myValue = in.readInt();
}
public int getValue() {
return myValue;
}
public void save(DataOutput out) throws IOException {
super.save(out);
out.writeInt(myValue);
}
public boolean equals(Object obj) {
return (obj instanceof IntegerConstantValue) && (((IntegerConstantValue)obj).myValue == myValue);
}
}
@@ -1,49 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* created at Feb 24, 2002
* @author Jeka
*/
package com.intellij.compiler.classParsing;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
public class LongConstantValue extends ConstantValue{
private final long myValue;
public LongConstantValue(long value) {
myValue = value;
}
public LongConstantValue(DataInput in) throws IOException{
myValue = in.readLong();
}
public long getValue() {
return myValue;
}
public void save(DataOutput out) throws IOException {
super.save(out);
out.writeLong(myValue);
}
public boolean equals(Object obj) {
return (obj instanceof LongConstantValue) && (((LongConstantValue)obj).myValue == myValue);
}
}
@@ -1,152 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* created at Jan 8, 2002
* @author Jeka
*/
package com.intellij.compiler.classParsing;
import com.intellij.util.cls.ClsUtil;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
public abstract class MemberInfo {
public static final MemberInfo[] EMPTY_MEMBER_INFO_ARRAY = new MemberInfo[0];
private static final int FLAG_INFO_UNAVAILABLE = 0x8000;
private final int myName;
private final int myDescriptor;
private final int myGenericSignature;
private final int myFlags;
private final AnnotationConstantValue[] myRuntimeVisibleAnnotations;
private final AnnotationConstantValue[] myRuntimeInvisibleAnnotations;
protected MemberInfo(int name, int descriptor) {
this(name, descriptor, -1, FLAG_INFO_UNAVAILABLE, AnnotationConstantValue.EMPTY_ARRAY, AnnotationConstantValue.EMPTY_ARRAY);
}
protected MemberInfo(int name, int descriptor, int genericSignature, int flags, final AnnotationConstantValue[] runtimeVisibleAnnotations, final AnnotationConstantValue[] runtimeInvisibleAnnotations) {
myDescriptor = descriptor;
myGenericSignature = genericSignature;
myName = name;
myFlags = flags;
myRuntimeVisibleAnnotations = runtimeVisibleAnnotations != null? runtimeVisibleAnnotations : AnnotationConstantValue.EMPTY_ARRAY;
myRuntimeInvisibleAnnotations = runtimeInvisibleAnnotations != null? runtimeInvisibleAnnotations : AnnotationConstantValue.EMPTY_ARRAY;
}
protected MemberInfo(DataInput in) throws IOException {
myName = in.readInt();
myDescriptor = in.readInt();
myGenericSignature = in.readInt();
myFlags = in.readInt();
myRuntimeVisibleAnnotations = loadAnnotations(in);
myRuntimeInvisibleAnnotations = loadAnnotations(in);
}
public void save(DataOutput out) throws IOException {
out.writeInt(myName);
out.writeInt(myDescriptor);
out.writeInt(myGenericSignature);
out.writeInt(myFlags);
saveAnnotations(out, myRuntimeVisibleAnnotations);
saveAnnotations(out, myRuntimeInvisibleAnnotations);
}
public int getName() {
return myName;
}
public int getDescriptor() {
return myDescriptor;
}
public int getGenericSignature() {
return myGenericSignature;
}
public boolean isFlagInfoAvailable() {
return myFlags != FLAG_INFO_UNAVAILABLE;
}
public int getFlags() {
return myFlags;
}
public boolean isPublic() {
return ClsUtil.isPublic(myFlags);
}
public boolean isProtected() {
return ClsUtil.isProtected(myFlags);
}
public boolean isFinal() {
return ClsUtil.isFinal(myFlags);
}
public boolean isPrivate() {
return ClsUtil.isPrivate(myFlags);
}
public boolean isPackageLocal() {
return ClsUtil.isPackageLocal(myFlags);
}
public boolean isStatic() {
return ClsUtil.isStatic(myFlags);
}
public boolean equals(Object obj) {
if (!(obj instanceof MemberInfo)) return false;
MemberInfo info = (MemberInfo)obj;
return (myName == info.myName) && (myDescriptor == info.myDescriptor);
}
public int hashCode() {
return myName + myDescriptor;
}
public AnnotationConstantValue[] getRuntimeVisibleAnnotations() {
return myRuntimeVisibleAnnotations;
}
public AnnotationConstantValue[] getRuntimeInvisibleAnnotations() {
return myRuntimeInvisibleAnnotations;
}
protected final void saveAnnotations(DataOutput out, final AnnotationConstantValue[] annotations) throws IOException {
out.writeInt(annotations.length);
for (AnnotationConstantValue annotation : annotations) {
MemberInfoExternalizer.saveConstantValue(out, annotation);
}
}
protected final AnnotationConstantValue[] loadAnnotations(DataInput in) throws IOException {
final int size = in.readInt();
if (size == 0) {
return AnnotationConstantValue.EMPTY_ARRAY;
}
final AnnotationConstantValue[] annotations = new AnnotationConstantValue[size];
for (int idx = 0; idx < size; idx++) {
annotations[idx] = (AnnotationConstantValue)MemberInfoExternalizer.loadConstantValue(in);
}
return annotations;
}
}
@@ -1,219 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* created at Jan 10, 2002
* @author Jeka
*/
package com.intellij.compiler.classParsing;
import com.intellij.openapi.diagnostic.Logger;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
public class MemberInfoExternalizer {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.classParsing.MemberInfoExternalizer");
public static final byte FIELD_INFO_TAG = 1;
public static final byte METHOD_INFO_TAG = 2;
public static final byte DECLARATION_INFO_TAG = 9;
public static final byte REFERENCE_INFO_TAG = 11;
public static final byte MEMBER_REFERENCE_INFO_TAG = 12;
public static final byte LONG_CONSTANT_TAG = 3;
public static final byte FLOAT_CONSTANT_TAG = 4;
public static final byte DOUBLE_CONSTANT_TAG = 5;
public static final byte INTEGER_CONSTANT_TAG = 6;
public static final byte STRING_CONSTANT_TAG = 7;
public static final byte CONSTANT_TAG = 8;
public static final byte ANNOTATION_CONSTANT_TAG = 13;
public static final byte ANNOTATION_PRIMITIVE_CONSTANT_TAG = 14;
public static final byte CONSTANT_VALUE_ARRAY_TAG = 15;
public static final byte CLASS_CONSTANT_VALUE_TAG = 16;
public static final byte ENUM_CONSTANT_VALUE_TAG = 17;
public static MemberInfo loadMemberInfo(DataInput in) throws IOException {
byte tag = in.readByte();
if (tag == METHOD_INFO_TAG) {
return new MethodInfo(in);
}
else if (tag == FIELD_INFO_TAG) {
return new FieldInfo(in);
}
LOG.error("Unknown member info");
return null;
}
public static ReferenceInfo loadReferenceInfo(DataInput in) throws IOException {
final byte tag = in.readByte();
if (tag == REFERENCE_INFO_TAG) {
return new ReferenceInfo(in);
}
else if (tag == MEMBER_REFERENCE_INFO_TAG) {
return new MemberReferenceInfo(in);
}
LOG.error("Unknown declaration info tag: " + tag);
return null;
}
public static ConstantValue loadConstantValue(DataInput in) throws IOException {
final byte tag = in.readByte();
if (tag == LONG_CONSTANT_TAG) {
return new LongConstantValue(in);
}
else if (tag == FLOAT_CONSTANT_TAG) {
return new FloatConstantValue(in);
}
else if (tag == DOUBLE_CONSTANT_TAG) {
return new DoubleConstantValue(in);
}
else if (tag == INTEGER_CONSTANT_TAG) {
return new IntegerConstantValue(in);
}
else if (tag == STRING_CONSTANT_TAG) {
return new StringConstantValue(in);
}
else if (tag == CONSTANT_TAG) {
return ConstantValue.EMPTY_CONSTANT_VALUE;
}
else if (tag == ANNOTATION_CONSTANT_TAG) {
return new AnnotationConstantValue(in);
}
else if (tag == ANNOTATION_PRIMITIVE_CONSTANT_TAG) {
return new AnnotationPrimitiveConstantValue(in);
}
else if (tag == CONSTANT_VALUE_ARRAY_TAG) {
return new ConstantValueArray(in);
}
else if (tag == CLASS_CONSTANT_VALUE_TAG) {
return new ClassInfoConstantValue(in);
}
else if (tag == ENUM_CONSTANT_VALUE_TAG) {
return new EnumConstantValue(in);
}
LOG.error("Unknown constant value type " + tag);
return null;
}
public static void saveMemberInfo(DataOutput out, MemberInfo info) throws IOException {
if (info instanceof MethodInfo) {
out.writeByte(METHOD_INFO_TAG);
}
else if (info instanceof FieldInfo){
out.writeByte(FIELD_INFO_TAG);
}
else {
LOG.error("Unknown member info");
}
info.save(out);
}
public static void saveReferenceInfo(DataOutput out, ReferenceInfo info) throws IOException {
if (info instanceof MemberReferenceInfo) {
out.writeByte(MEMBER_REFERENCE_INFO_TAG);
}
else{
out.writeByte(REFERENCE_INFO_TAG);
}
info.save(out);
}
public static void saveConstantValue(DataOutput out, ConstantValue value) throws IOException {
if (value instanceof LongConstantValue) {
out.writeByte(LONG_CONSTANT_TAG);
}
else if (value instanceof FloatConstantValue){
out.writeByte(FLOAT_CONSTANT_TAG);
}
else if (value instanceof DoubleConstantValue){
out.writeByte(DOUBLE_CONSTANT_TAG);
}
else if (value instanceof IntegerConstantValue){
out.writeByte(INTEGER_CONSTANT_TAG);
}
else if (value instanceof StringConstantValue){
out.writeByte(STRING_CONSTANT_TAG);
}
else if (value instanceof AnnotationConstantValue) {
out.writeByte(ANNOTATION_CONSTANT_TAG);
}
else if (value instanceof AnnotationPrimitiveConstantValue) {
out.writeByte(ANNOTATION_PRIMITIVE_CONSTANT_TAG);
}
else if (value instanceof ConstantValueArray) {
out.writeByte(CONSTANT_VALUE_ARRAY_TAG);
}
else if (value instanceof ClassInfoConstantValue) {
out.writeByte(CLASS_CONSTANT_VALUE_TAG);
}
else if (value instanceof EnumConstantValue) {
out.writeByte(ENUM_CONSTANT_VALUE_TAG);
}
else {
out.writeByte(CONSTANT_TAG);
}
if (value != null) {
value.save(out);
}
}
public static AnnotationConstantValue[] readAnnotationConstantValueArray1(DataInput in) throws IOException {
final int size = in.readInt();
final AnnotationConstantValue[] array = size > 0? new AnnotationConstantValue[size] : AnnotationConstantValue.EMPTY_ARRAY;
for (int idx = 0; idx < size; idx++) {
array[idx] = (AnnotationConstantValue)loadConstantValue(in);
}
return array;
}
public static AnnotationConstantValue[][] readAnnotationConstantValueArray2(DataInput in) throws IOException {
final int size = in.readInt();
final AnnotationConstantValue[][] array = size > 0? new AnnotationConstantValue[size][] : AnnotationConstantValue.EMPTY_ARRAY_ARRAY;
for (int idx = 0; idx < size; idx++) {
array[idx] = readAnnotationConstantValueArray1(in);
}
return array;
}
public static void writeConstantValueArray1(DataOutput writer, final ConstantValue[] array) throws IOException {
if (array != null && array.length > 0) {
writer.writeInt(array.length);
for (ConstantValue value : array) {
saveConstantValue(writer, value);
}
}
else {
writer.writeInt(0);
}
}
public static void writeConstantValueArray2(DataOutput writer, final ConstantValue[][] array) throws IOException {
if (array != null && array.length > 0) {
writer.writeInt(array.length);
for (ConstantValue[] aArray : array) {
writeConstantValueArray1(writer, aArray);
}
}
else {
writer.writeInt(0);
}
}
}
@@ -1,73 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* created at Jan 8, 2002
* @author Jeka
*/
package com.intellij.compiler.classParsing;
import org.jetbrains.annotations.NonNls;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
public class MemberReferenceInfo extends ReferenceInfo {
private final MemberInfo myMemberInfo;
public MemberReferenceInfo(int declaringClass, MemberInfo memberInfo) {
super(declaringClass);
myMemberInfo = memberInfo;
}
public MemberReferenceInfo(DataInput in) throws IOException {
super(in);
myMemberInfo = MemberInfoExternalizer.loadMemberInfo(in);
}
public MemberInfo getMemberInfo() {
return myMemberInfo;
}
public boolean isFieldReference() {
return myMemberInfo instanceof FieldInfo;
}
public boolean isMethodReference() {
return myMemberInfo instanceof MethodInfo;
}
public void save(DataOutput out) throws IOException {
super.save(out);
MemberInfoExternalizer.saveMemberInfo(out, myMemberInfo);
}
public boolean equals(Object o) {
if (!super.equals(o)) {
return false;
}
return myMemberInfo.equals(((MemberReferenceInfo)o).myMemberInfo);
}
public int hashCode() {
return super.hashCode() + myMemberInfo.hashCode();
}
public @NonNls String toString() { // for debug purposes
return "Member reference: [class name=" + getClassName() + ", member name = " + myMemberInfo.getName() + ", member descriptor=" + myMemberInfo.getDescriptor() + ", member signature=" + myMemberInfo.getGenericSignature() + "]";
}
}
@@ -1,263 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* created at Jan 10, 2002
* @author Jeka
*/
package com.intellij.compiler.classParsing;
import com.intellij.compiler.SymbolTable;
import com.intellij.compiler.make.CacheCorruptedException;
import com.intellij.compiler.make.CacheUtils;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.ArrayUtil;
import com.intellij.util.cls.ClsUtil;
import gnu.trove.TIntHashSet;
import org.jetbrains.annotations.NonNls;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.ArrayList;
public class MethodInfo extends MemberInfo {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.classParsing.MethodInfo");
private static final int[] EXCEPTION_INFO_UNAVAILABLE = ArrayUtil.EMPTY_INT_ARRAY;
public static final MethodInfo[] EMPTY_ARRAY = new MethodInfo[0];
private final int[] myThrownExceptions;
// cached (lazy initialized) data
private String mySignature = null;
private String[] myParameterDescriptors = null;
private String myReturnTypeSignature = null;
private final boolean myIsConstructor;
private final AnnotationConstantValue[][] myRuntimeVisibleParameterAnnotations;
private final AnnotationConstantValue[][] myRuntimeInvisibleParameterAnnotations;
private final ConstantValue myAnnotationDefault;
public MethodInfo(int name, int descriptor, boolean isConstructor) {
super(name, descriptor);
myIsConstructor = isConstructor;
myThrownExceptions = EXCEPTION_INFO_UNAVAILABLE;
myRuntimeVisibleParameterAnnotations = AnnotationConstantValue.EMPTY_ARRAY_ARRAY;
myRuntimeInvisibleParameterAnnotations = AnnotationConstantValue.EMPTY_ARRAY_ARRAY;
myAnnotationDefault = ConstantValue.EMPTY_CONSTANT_VALUE;
}
public MethodInfo(int name,
int descriptor,
final int genericSignature,
int flags,
int[] exceptions,
boolean isConstructor,
final AnnotationConstantValue[] runtimeVisibleAnnotations,
final AnnotationConstantValue[] runtimeInvisibleAnnotations,
final AnnotationConstantValue[][] runtimeVisibleParameterAnnotations,
final AnnotationConstantValue[][] runtimeInvisibleParameterAnnotations, ConstantValue annotationDefault) {
super(name, descriptor, genericSignature, flags, runtimeVisibleAnnotations, runtimeInvisibleAnnotations);
myThrownExceptions = exceptions != null? exceptions : ArrayUtil.EMPTY_INT_ARRAY;
myIsConstructor = isConstructor;
myRuntimeVisibleParameterAnnotations = runtimeVisibleParameterAnnotations == null? AnnotationConstantValue.EMPTY_ARRAY_ARRAY : runtimeVisibleParameterAnnotations;
myRuntimeInvisibleParameterAnnotations = runtimeInvisibleParameterAnnotations == null? AnnotationConstantValue.EMPTY_ARRAY_ARRAY : runtimeInvisibleParameterAnnotations;
myAnnotationDefault = annotationDefault;
}
public MethodInfo(DataInput in) throws IOException {
super(in);
myIsConstructor = in.readBoolean();
int count = in.readInt();
if (count == -1) {
myThrownExceptions = EXCEPTION_INFO_UNAVAILABLE;
}
else {
myThrownExceptions = ArrayUtil.newIntArray(count);
for (int idx = 0; idx < count; idx++) {
myThrownExceptions[idx] = in.readInt();
}
}
myRuntimeVisibleParameterAnnotations = loadParameterAnnotations(in);
myRuntimeInvisibleParameterAnnotations = loadParameterAnnotations(in);
myAnnotationDefault = MemberInfoExternalizer.loadConstantValue(in);
}
public void save(DataOutput out) throws IOException {
super.save(out);
out.writeBoolean(myIsConstructor);
if (isExceptionInfoAvailable()) {
out.writeInt(myThrownExceptions.length);
}
else {
out.writeInt(-1);
}
for (int thrownException : myThrownExceptions) {
out.writeInt(thrownException);
}
saveParameterAnnotations(out, myRuntimeVisibleParameterAnnotations);
saveParameterAnnotations(out, myRuntimeInvisibleParameterAnnotations);
MemberInfoExternalizer.saveConstantValue(out, myAnnotationDefault);
}
private boolean isExceptionInfoAvailable() {
return myThrownExceptions != EXCEPTION_INFO_UNAVAILABLE;
}
public boolean areExceptionsEqual(MethodInfo info) {
if (myThrownExceptions.length != info.myThrownExceptions.length) {
return false;
}
if (myThrownExceptions.length != 0) { // optimization
TIntHashSet exceptionsSet = new TIntHashSet();
for (int thrownException : myThrownExceptions) {
exceptionsSet.add(thrownException);
}
for (int exception : info.myThrownExceptions) {
if (!exceptionsSet.contains(exception)) {
return false;
}
}
}
return true;
}
public int[] getThrownExceptions() {
return myThrownExceptions;
}
public String getDescriptor(SymbolTable symbolTable) throws CacheCorruptedException {
if (mySignature == null) {
final String descriptor = symbolTable.getSymbol(getDescriptor());
final String name = symbolTable.getSymbol(getName());
mySignature = CacheUtils.getMethodSignature(name, descriptor);
}
return mySignature;
}
public String getReturnTypeDescriptor(SymbolTable symbolTable) throws CacheCorruptedException {
if (myReturnTypeSignature == null) {
String descriptor = symbolTable.getSymbol(getDescriptor());
myReturnTypeSignature = descriptor.substring(descriptor.indexOf(')') + 1, descriptor.length());
}
return myReturnTypeSignature;
}
public String[] getParameterDescriptors(SymbolTable symbolTable) throws CacheCorruptedException {
if (myParameterDescriptors == null) {
String descriptor = symbolTable.getSymbol(getDescriptor());
int endIndex = descriptor.indexOf(')');
if (endIndex <= 0) {
LOG.error("Corrupted method descriptor: " + descriptor);
}
myParameterDescriptors = parseParameterDescriptors(descriptor.substring(1, endIndex));
}
return myParameterDescriptors;
}
public boolean isAbstract() {
return ClsUtil.isAbstract(getFlags());
}
public boolean isConstructor() {
return myIsConstructor;
}
private String[] parseParameterDescriptors(String signature) {
ArrayList<String> list = new ArrayList<String>();
String paramSignature = parseFieldType(signature);
while (paramSignature != null && !"".equals(paramSignature)) {
list.add(paramSignature);
signature = signature.substring(paramSignature.length());
paramSignature = parseFieldType(signature);
}
return ArrayUtil.toStringArray(list);
}
private @NonNls String parseFieldType(@NonNls String signature) {
if (signature.length() == 0) {
return null;
}
if (signature.charAt(0) == 'B') {
return "B";
}
if (signature.charAt(0) == 'C') {
return "C";
}
if (signature.charAt(0) == 'D') {
return "D";
}
if (signature.charAt(0) == 'F') {
return "F";
}
if (signature.charAt(0) == 'I') {
return "I";
}
if (signature.charAt(0) == 'J') {
return "J";
}
if (signature.charAt(0) == 'S') {
return "S";
}
if (signature.charAt(0) == 'Z') {
return "Z";
}
if (signature.charAt(0) == 'L') {
return signature.substring(0, signature.indexOf(";") + 1);
}
if (signature.charAt(0) == '[') {
String s = parseFieldType(signature.substring(1));
return (s != null)? ("[" + s) : null;
}
return null;
}
public AnnotationConstantValue[][] getRuntimeVisibleParameterAnnotations() {
return myRuntimeVisibleParameterAnnotations;
}
public AnnotationConstantValue[][] getRuntimeInvisibleParameterAnnotations() {
return myRuntimeInvisibleParameterAnnotations;
}
public String toString() {
return mySignature;
}
private AnnotationConstantValue[][] loadParameterAnnotations(DataInput in) throws IOException {
final int size = in.readInt();
if (size == 0) {
return AnnotationConstantValue.EMPTY_ARRAY_ARRAY;
}
final AnnotationConstantValue[][] paramAnnotations = new AnnotationConstantValue[size][];
for (int idx = 0; idx < size; idx++) {
paramAnnotations[idx] = loadAnnotations(in);
}
return paramAnnotations;
}
private void saveParameterAnnotations(DataOutput out, AnnotationConstantValue[][] parameterAnnotations) throws IOException {
out.writeInt(parameterAnnotations.length);
for (AnnotationConstantValue[] parameterAnnotation : parameterAnnotations) {
saveAnnotations(out, parameterAnnotation);
}
}
public ConstantValue getAnnotationDefault() {
return myAnnotationDefault;
}
}
@@ -1,65 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* @author Eugene Zhuravlev
*/
package com.intellij.compiler.classParsing;
import org.jetbrains.annotations.NonNls;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
public class ReferenceInfo {
private final int myClassName;
public ReferenceInfo(int declaringClassName) {
myClassName = declaringClassName;
}
public ReferenceInfo(DataInput in) throws IOException {
this(in.readInt());
}
public @NonNls String toString() { // for debug purposes
return "Class reference[class name=" + String.valueOf(getClassName()) + "]";
}
public void save(DataOutput out) throws IOException {
out.writeInt(myClassName);
}
public int getClassName() {
return myClassName;
}
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ReferenceInfo that = (ReferenceInfo)o;
if (myClassName != that.myClassName) return false;
return true;
}
public int hashCode() {
return myClassName;
}
}
@@ -1,259 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.classParsing;
import com.intellij.openapi.compiler.CompilerBundle;
import java.text.CharacterIterator;
/**
* @author Eugene Zhuravlev
* Date: Mar 4, 2004
*/
public class SignatureParser {
public static final SignatureParser INSTANCE = new SignatureParser();
public void parseIdentifier(CharacterIterator it, final StringBuilder buf) {
while (Character.isJavaIdentifierPart(it.current())) {
buf.append(it.current());
it.next();
}
}
public void parseFormalTypeParameters(CharacterIterator it, final StringBuilder buf) throws SignatureParsingException {
if (it.current() != '<') {
throw new SignatureParsingException(CompilerBundle.message("error.signature.parsing.expected.other.symbol", "<", buf.toString()));
}
buf.append(it.current()); // skip '<'
it.next();
while (it.current() != '>') {
parseFormalTypeParameter(it, buf);
}
buf.append(it.current());
it.next();
}
public void parseFormalTypeParameter(CharacterIterator it, final StringBuilder buf) throws SignatureParsingException {
parseIdentifier(it, buf);
parseClassBound(it, buf);
while (it.current() == ':') {
parseInterfaceBound(it, buf);
}
}
public void parseClassBound(CharacterIterator it, final StringBuilder buf) throws SignatureParsingException {
if (it.current() != ':') {
throw new SignatureParsingException(CompilerBundle.message("error.signature.parsing.expected.other.symbol", ":", buf.toString()));
}
buf.append(it.current());
it.next();
final char current = it.current();
if (current != CharacterIterator.DONE && current != ':') {
parseFieldTypeSignature(it, buf);
}
}
public void parseInterfaceBound(CharacterIterator it, final StringBuilder buf) throws SignatureParsingException {
if (it.current() != ':') {
throw new SignatureParsingException(CompilerBundle.message("error.signature.parsing.expected.other.symbol", ":", buf.toString()));
}
buf.append(it.current());
it.next();
parseFieldTypeSignature(it, buf);
}
public void parseSuperclassSignature(CharacterIterator it, final StringBuilder buf) throws SignatureParsingException {
parseClassTypeSignature(it, buf);
}
public void parseSuperinterfaceSignature(CharacterIterator it, final StringBuilder buf) throws SignatureParsingException {
parseClassTypeSignature(it, buf);
}
public void parseFieldTypeSignature(CharacterIterator it, final StringBuilder buf) throws SignatureParsingException {
if (it.current() == 'L') {
parseClassTypeSignature(it, buf);
}
else if (it.current() == '[') {
parseArrayTypeSignature(it, buf);
}
else if (it.current() == 'T') {
parseTypeVariableSignature(it, buf);
}
else {
//noinspection HardCodedStringLiteral
throw new SignatureParsingException(CompilerBundle.message("error.signature.parsing.expected.other.symbol", "'L' / '[' / 'T'", buf.toString()));
}
}
public void parseClassTypeSignature(CharacterIterator it, final StringBuilder buf) throws SignatureParsingException {
buf.append(it.current());
it.next(); // consume 'L'
parseSimpleClassTypeSignature(it, buf);
while (it.current() == '/' || it.current() == '.') { // Eclipse compiler generates '.' for inner classes
parseClassTypeSignatureSuffix(it, buf);
}
if (it.current() != ';') {
throw new SignatureParsingException(CompilerBundle.message("error.signature.parsing.expected.other.symbol", ";", buf.toString()));
}
buf.append(it.current());
it.next(); // consume ';'
}
public void parseSimpleClassTypeSignature(CharacterIterator it, final StringBuilder buf) throws SignatureParsingException {
parseIdentifier(it, buf);
if (it.current() == '<') {
parseTypeArguments(it, buf);
}
}
public void parseClassTypeSignatureSuffix(CharacterIterator it, final StringBuilder buf) throws SignatureParsingException {
buf.append(it.current());
it.next();
parseSimpleClassTypeSignature(it, buf);
}
public void parseTypeVariableSignature(CharacterIterator it, final StringBuilder buf) throws SignatureParsingException {
buf.append(it.current());
it.next(); // consume 'T'
parseIdentifier(it, buf);
if (it.current() != ';') {
throw new SignatureParsingException(CompilerBundle.message("error.signature.parsing.expected.other.symbol", ";", buf.toString()));
}
buf.append(it.current());
it.next(); // consume ';'
}
public void parseTypeArguments(CharacterIterator it, final StringBuilder buf) throws SignatureParsingException {
buf.append(it.current());
it.next(); // consume '<'
while (it.current() != '>') {
parseTypeArgument(it, buf);
}
buf.append(it.current());
it.next(); // consume '>'
}
public void parseTypeArgument(CharacterIterator it, final StringBuilder buf) throws SignatureParsingException {
if (it.current() == '*') {
parseWildcardIndicator(it, buf);
}
else {
if (it.current() == '+' || it.current() == '-') {
parseWildcardIndicator(it, buf);
}
parseFieldTypeSignature(it, buf);
}
}
public void parseWildcardIndicator(CharacterIterator it, final StringBuilder buf) {
buf.append(it.current());
it.next();
}
public void parseArrayTypeSignature(CharacterIterator it, final StringBuilder buf) throws SignatureParsingException {
buf.append(it.current());
it.next(); // consume '['
parseTypeSignature(it, buf);
}
public void parseTypeSignature(CharacterIterator it, final StringBuilder buf) throws SignatureParsingException {
char current = it.current();
if (current == 'B' || current == 'C' || current == 'D' || current == 'F' || current == 'I' || current == 'J' || current == 'S' || current == 'Z') {
buf.append(it.current());
it.next(); // base type
}
else if (current == 'L' || current == '[' || current == 'T') {
parseFieldTypeSignature(it, buf);
}
else {
throw new SignatureParsingException(CompilerBundle.message("error.signature.parsing.unknown.type.signature"));
}
}
public void parseReturnType(CharacterIterator it, final StringBuilder buf) throws SignatureParsingException {
if (it.current() == 'V') {
buf.append(it.current());
it.next();
}
else {
parseTypeSignature(it, buf);
}
}
public void parseThrowsSignature(CharacterIterator it, final StringBuilder buf) throws SignatureParsingException {
if (it.current() != '^') {
throw new SignatureParsingException(CompilerBundle.message("error.signature.parsing.expected.other.symbol", "^", buf.toString()));
}
buf.append(it.current());
it.next();
if (it.current() == 'T') {
parseTypeVariableSignature(it, buf);
}
else {
parseClassTypeSignature(it, buf);
}
}
public void parseMethodSignature(CharacterIterator it, final StringBuilder buf) throws SignatureParsingException {
if (it.current() == '<') {
parseFormalTypeParameters(it, buf);
}
if (it.current() != '(') {
throw new SignatureParsingException(CompilerBundle.message("error.signature.parsing.expected.other.symbol", "(", buf.toString()));
}
buf.append(it.current());
it.next(); // skip '('
while (it.current() != ')') {
parseTypeSignature(it, buf);
}
buf.append(it.current());
it.next(); // skip ')'
parseReturnType(it, buf);
if (it.current() != CharacterIterator.DONE) {
parseThrowsSignature(it, buf);
}
}
public void parseClassSignature(CharacterIterator it, final StringBuilder buf) throws SignatureParsingException {
if (it.current() == '<') {
buf.append(it.current());
it.next();
while (it.current() != '>') {
parseFormalTypeParameter(it, buf);
}
buf.append(it.current());
it.next();
}
parseClassTypeSignature(it, buf);
while (it.current() != CharacterIterator.DONE) {
parseClassTypeSignature(it, buf);
}
}
}
@@ -1,26 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.classParsing;
/**
* @author Eugene Zhuravlev
* Date: Mar 4, 2004
*/
public class SignatureParsingException extends Exception{
public SignatureParsingException(String message) {
super(message);
}
}
@@ -1,52 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* created at Feb 24, 2002
* @author Jeka
*/
package com.intellij.compiler.classParsing;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
public class StringConstantValue extends ConstantValue{
private final String myValue;
public StringConstantValue(String value) {
myValue = value;
}
public StringConstantValue(DataInput in) throws IOException{
myValue = in.readUTF();
}
public String getValue() {
return myValue;
}
public void save(DataOutput out) throws IOException {
super.save(out);
out.writeUTF(myValue);
}
public boolean equals(Object obj) {
return
(obj instanceof StringConstantValue) &&
((myValue == null)? ((StringConstantValue)obj).myValue == null : myValue.equals(((StringConstantValue)obj).myValue));
}
}
@@ -1,34 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl;
import com.intellij.openapi.compiler.CompilerFilter;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.compiler.CompileScope;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author nik
*/
public abstract class AdditionalCompileScopeProvider {
public static final ExtensionPointName<AdditionalCompileScopeProvider> EXTENSION_POINT_NAME = ExtensionPointName.create("com.intellij.compiler.additionalCompileScopeProvider");
@Nullable
public abstract CompileScope getAdditionalScope(@NotNull CompileScope baseScope, @NotNull CompilerFilter filter, @NotNull Project project);
}
@@ -1,183 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl;
import com.intellij.compiler.make.DependencyCache;
import com.intellij.openapi.compiler.CompileScope;
import com.intellij.openapi.compiler.CompilerMessage;
import com.intellij.openapi.compiler.CompilerMessageCategory;
import com.intellij.openapi.compiler.ex.CompileContextEx;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.Navigatable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.Set;
/**
* @author Eugene Zhuravlev
* Date: Dec 4, 2007
*/
public class CompileContextExProxy implements CompileContextEx {
private final CompileContextEx myDelegate;
public CompileContextExProxy(CompileContextEx delegate) {
myDelegate = delegate;
}
public Project getProject() {
return myDelegate.getProject();
}
public DependencyCache getDependencyCache() {
return myDelegate.getDependencyCache();
}
public VirtualFile getSourceFileByOutputFile(final VirtualFile outputFile) {
return myDelegate.getSourceFileByOutputFile(outputFile);
}
public void addMessage(final CompilerMessage message) {
myDelegate.addMessage(message);
}
@NotNull
public Set<VirtualFile> getTestOutputDirectories() {
return myDelegate.getTestOutputDirectories();
}
public boolean isInTestSourceContent(@NotNull final VirtualFile fileOrDir) {
return myDelegate.isInTestSourceContent(fileOrDir);
}
public boolean isInSourceContent(@NotNull final VirtualFile fileOrDir) {
return myDelegate.isInSourceContent(fileOrDir);
}
public void addScope(final CompileScope additionalScope) {
myDelegate.addScope(additionalScope);
}
public void addMessage(final CompilerMessageCategory category,
final String message, @Nullable final String url, final int lineNum, final int columnNum) {
myDelegate.addMessage(category, message, url, lineNum, columnNum);
}
public void addMessage(final CompilerMessageCategory category, final String message, @Nullable final String url,
final int lineNum,
final int columnNum,
final Navigatable navigatable) {
myDelegate.addMessage(category, message, url, lineNum, columnNum, navigatable);
}
public CompilerMessage[] getMessages(final CompilerMessageCategory category) {
return myDelegate.getMessages(category);
}
public int getMessageCount(final CompilerMessageCategory category) {
return myDelegate.getMessageCount(category);
}
public ProgressIndicator getProgressIndicator() {
return myDelegate.getProgressIndicator();
}
public CompileScope getCompileScope() {
return myDelegate.getCompileScope();
}
public CompileScope getProjectCompileScope() {
return myDelegate.getProjectCompileScope();
}
public void requestRebuildNextTime(final String message) {
myDelegate.requestRebuildNextTime(message);
}
public boolean isRebuildRequested() {
return myDelegate.isRebuildRequested();
}
@Nullable
public String getRebuildReason() {
return myDelegate.getRebuildReason();
}
public Module getModuleByFile(final VirtualFile file) {
return myDelegate.getModuleByFile(file);
}
public VirtualFile[] getSourceRoots(final Module module) {
return myDelegate.getSourceRoots(module);
}
public VirtualFile[] getAllOutputDirectories() {
return myDelegate.getAllOutputDirectories();
}
public VirtualFile getModuleOutputDirectory(final Module module) {
return myDelegate.getModuleOutputDirectory(module);
}
public VirtualFile getModuleOutputDirectoryForTests(final Module module) {
return myDelegate.getModuleOutputDirectoryForTests(module);
}
public boolean isMake() {
return myDelegate.isMake();
}
public boolean isAnnotationProcessorsEnabled() {
return myDelegate.isAnnotationProcessorsEnabled();
}
public boolean isRebuild() {
return myDelegate.isRebuild();
}
public <T> T getUserData(@NotNull final Key<T> key) {
return myDelegate.getUserData(key);
}
public <T> void putUserData(@NotNull final Key<T> key, final T value) {
myDelegate.putUserData(key, value);
}
public void recalculateOutputDirs() {
myDelegate.recalculateOutputDirs();
}
public void markGenerated(Collection<VirtualFile> files) {
myDelegate.markGenerated(files);
}
public boolean isGenerated(VirtualFile file) {
return myDelegate.isGenerated(file);
}
public long getStartCompilationStamp() {
return myDelegate.getStartCompilationStamp();
}
public void assignModule(@NotNull VirtualFile root, @NotNull Module module, boolean isTestSource, com.intellij.openapi.compiler.Compiler compiler) {
myDelegate.assignModule(root, module, isTestSource, compiler);
}
}
@@ -24,24 +24,21 @@ package com.intellij.compiler.impl;
import com.intellij.compiler.CompilerConfiguration;
import com.intellij.compiler.CompilerMessageImpl;
import com.intellij.compiler.CompilerWorkspaceConfiguration;
import com.intellij.compiler.make.DependencyCache;
import com.intellij.compiler.progress.CompilerTask;
import com.intellij.execution.impl.ExecutionManagerImpl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.*;
import com.intellij.openapi.compiler.Compiler;
import com.intellij.openapi.compiler.CompileScope;
import com.intellij.openapi.compiler.CompilerMessage;
import com.intellij.openapi.compiler.CompilerMessageCategory;
import com.intellij.openapi.compiler.CompilerPaths;
import com.intellij.openapi.compiler.ex.CompileContextEx;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.CompilerModuleExtension;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
@@ -49,14 +46,9 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.pom.Navigatable;
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.HashSet;
import com.intellij.util.containers.OrderedSet;
import com.intellij.util.indexing.FileBasedIndex;
import gnu.trove.TIntHashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.*;
public class CompileContextImpl extends UserDataHolderBase implements CompileContextEx {
@@ -66,7 +58,6 @@ public class CompileContextImpl extends UserDataHolderBase implements CompileCon
private final Map<CompilerMessageCategory, Collection<CompilerMessage>> myMessages = new EnumMap<CompilerMessageCategory, Collection<CompilerMessage>>(CompilerMessageCategory.class);
private final boolean myShouldUpdateProblemsView;
private CompileScope myCompileScope;
private final DependencyCache myDependencyCache;
private final boolean myMake;
private final boolean myIsRebuild;
private final boolean myIsAnnotationProcessorsEnabled;
@@ -74,11 +65,7 @@ public class CompileContextImpl extends UserDataHolderBase implements CompileCon
private String myRebuildReason;
private final Map<VirtualFile, Module> myRootToModuleMap = new HashMap<VirtualFile, Module>();
private final Map<Module, Set<VirtualFile>> myModuleToRootsMap = new HashMap<Module, Set<VirtualFile>>();
private final Map<VirtualFile, Pair<SourceGeneratingCompiler, Module>> myOutputRootToSourceGeneratorMap = new HashMap<VirtualFile, Pair<SourceGeneratingCompiler, Module>>();
private final Set<VirtualFile> myGeneratedTestRoots = new java.util.HashSet<VirtualFile>();
private VirtualFile[] myOutputDirectories;
private Set<VirtualFile> myTestOutputDirectories;
private final TIntHashSet myGeneratedSources = new TIntHashSet();
private final ProjectFileIndex myProjectFileIndex; // cached for performance reasons
private final ProjectCompileScope myProjectCompileScope;
private final long myStartCompilationStamp;
@@ -87,11 +74,10 @@ public class CompileContextImpl extends UserDataHolderBase implements CompileCon
public CompileContextImpl(final Project project,
final CompilerTask compilerSession,
CompileScope compileScope,
DependencyCache dependencyCache, boolean isMake, boolean isRebuild) {
boolean isMake, boolean isRebuild) {
myProject = project;
myTask = compilerSession;
myCompileScope = compileScope;
myDependencyCache = dependencyCache;
myMake = isMake;
myIsRebuild = isRebuild;
myStartCompilationStamp = System.currentTimeMillis();
@@ -108,110 +94,22 @@ public class CompileContextImpl extends UserDataHolderBase implements CompileCon
compilerSession.setSessionId(sessionId);
}
}
recalculateOutputDirs();
final CompilerWorkspaceConfiguration workspaceConfig = CompilerWorkspaceConfiguration.getInstance(myProject);
myShouldUpdateProblemsView = workspaceConfig.useOutOfProcessBuild() && workspaceConfig.MAKE_PROJECT_ON_SAVE;
myShouldUpdateProblemsView = workspaceConfig.MAKE_PROJECT_ON_SAVE;
}
public boolean shouldUpdateProblemsView() {
return myShouldUpdateProblemsView;
}
public void recalculateOutputDirs() {
final Module[] allModules = ModuleManager.getInstance(myProject).getModules();
final Set<VirtualFile> allDirs = new OrderedSet<VirtualFile>();
final Set<VirtualFile> testOutputDirs = new java.util.HashSet<VirtualFile>();
final Set<VirtualFile> productionOutputDirs = new java.util.HashSet<VirtualFile>();
for (Module module : allModules) {
final CompilerModuleExtension manager = CompilerModuleExtension.getInstance(module);
final VirtualFile output = manager.getCompilerOutputPath();
if (output != null && output.isValid()) {
allDirs.add(output);
productionOutputDirs.add(output);
}
final VirtualFile testsOutput = manager.getCompilerOutputPathForTests();
if (testsOutput != null && testsOutput.isValid()) {
allDirs.add(testsOutput);
testOutputDirs.add(testsOutput);
}
}
myOutputDirectories = VfsUtil.toVirtualFileArray(allDirs);
// need this to ensure that the sent contains only _dedicated_ test output dirs
// Directories that are configured for both test and production classes must not be added in the resulting set
testOutputDirs.removeAll(productionOutputDirs);
myTestOutputDirectories = Collections.unmodifiableSet(testOutputDirs);
}
public void markGenerated(Collection<VirtualFile> files) {
for (final VirtualFile file : files) {
myGeneratedSources.add(FileBasedIndex.getFileId(file));
}
}
public long getStartCompilationStamp() {
return myStartCompilationStamp;
}
public boolean isGenerated(VirtualFile file) {
if (myGeneratedSources.contains(FileBasedIndex.getFileId(file))) {
return true;
}
if (VfsUtilCore.isUnder(file, myRootToModuleMap.keySet())) {
return true;
}
final Module module = getModuleByFile(file);
if (module != null) {
final String procGenRoot = CompilerPaths.getAnnotationProcessorsGenerationPath(module);
if (procGenRoot != null && VfsUtil.isAncestor(new File(procGenRoot), new File(file.getPath()), true)) {
return true;
}
}
return false;
}
/*
private JBZipFile lookupZip(String outputDir) {
synchronized (myOpenZipFiles) {
JBZipFile zip = myOpenZipFiles.get(outputDir);
if (zip == null) {
final File zipFile = CompilerPathsEx.getZippedOutputPath(myProject, outputDir);
try {
try {
zip = new JBZipFile(zipFile);
}
catch (FileNotFoundException e) {
try {
zipFile.createNewFile();
zip = new JBZipFile(zipFile);
}
catch (IOException e1) {
zipFile.getParentFile().mkdirs();
zipFile.createNewFile();
zip = new JBZipFile(zipFile);
}
}
myOpenZipFiles.put(outputDir, zip);
}
catch (IOException e) {
LOG.info(e);
addMessage(CompilerMessageCategory.ERROR, "Cannot create zip file " + zipFile.getPath() + ": " + e.getMessage(), null, -1, -1);
}
}
return zip;
}
}
*/
public Project getProject() {
return myProject;
}
public DependencyCache getDependencyCache() {
return myDependencyCache;
}
public CompilerMessage[] getMessages(CompilerMessageCategory category) {
Collection<CompilerMessage> collection = myMessages.get(category);
if (collection == null) {
@@ -221,40 +119,16 @@ public class CompileContextImpl extends UserDataHolderBase implements CompileCon
}
public void addMessage(CompilerMessageCategory category, String message, String url, int lineNum, int columnNum) {
CompilerMessageImpl msg = new CompilerMessageImpl(myProject, category, message, findPresentableFileForMessage(url), lineNum, columnNum, null);
final CompilerMessageImpl msg = new CompilerMessageImpl(myProject, category, message, findFileByUrl(url), lineNum, columnNum, null);
addMessage(msg);
}
public void addMessage(CompilerMessageCategory category, String message, String url, int lineNum, int columnNum,
Navigatable navigatable) {
CompilerMessageImpl msg = new CompilerMessageImpl(myProject, category, message, findPresentableFileForMessage(url), lineNum, columnNum, navigatable);
final CompilerMessageImpl msg = new CompilerMessageImpl(myProject, category, message, findFileByUrl(url), lineNum, columnNum, navigatable);
addMessage(msg);
}
@Nullable
private VirtualFile findPresentableFileForMessage(@Nullable final String url) {
final VirtualFile file = findFileByUrl(url);
if (file == null) {
return null;
}
return ApplicationManager.getApplication().runReadAction(new Computable<VirtualFile>() {
@Override
public VirtualFile compute() {
if (file.isValid()) {
for (final Map.Entry<VirtualFile, Pair<SourceGeneratingCompiler, Module>> entry : myOutputRootToSourceGeneratorMap.entrySet()) {
final VirtualFile root = entry.getKey();
if (VfsUtilCore.isAncestor(root, file, false)) {
final Pair<SourceGeneratingCompiler, Module> pair = entry.getValue();
final VirtualFile presentableFile = pair.getFirst().getPresentableFile(CompileContextImpl.this, pair.getSecond(), root, file);
return presentableFile != null ? presentableFile : file;
}
}
}
return file;
}
});
}
@Nullable
private static VirtualFile findFileByUrl(@Nullable String url) {
if (url == null) {
@@ -312,10 +186,6 @@ public class CompileContextImpl extends UserDataHolderBase implements CompileCon
if (!myRebuildRequested) {
myRebuildRequested = true;
myRebuildReason = message;
final boolean isOutOfProcessBuild = myDependencyCache == null;
if (!isOutOfProcessBuild) {
addMessage(CompilerMessageCategory.ERROR, message, null, -1, -1);
}
}
}
@@ -329,38 +199,9 @@ public class CompileContextImpl extends UserDataHolderBase implements CompileCon
}
public ProgressIndicator getProgressIndicator() {
//if (myProgressIndicatorProxy != null) {
// return myProgressIndicatorProxy;
//}
return myTask.getIndicator();
}
public void assignModule(@NotNull VirtualFile root, @NotNull Module module, final boolean isTestSource, @Nullable Compiler compiler) {
try {
myRootToModuleMap.put(root, module);
Set<VirtualFile> set = myModuleToRootsMap.get(module);
if (set == null) {
set = new HashSet<VirtualFile>();
myModuleToRootsMap.put(module, set);
}
set.add(root);
if (isTestSource) {
myGeneratedTestRoots.add(root);
}
if (compiler instanceof SourceGeneratingCompiler) {
myOutputRootToSourceGeneratorMap.put(root, Pair.create((SourceGeneratingCompiler)compiler, module));
}
}
finally {
myModuleToRootsCache.remove(module);
}
}
@Nullable
public VirtualFile getSourceFileByOutputFile(VirtualFile outputFile) {
return TranslatingCompilerFilesMonitor.getSourceFileByOutput(outputFile);
}
public Module getModuleByFile(VirtualFile file) {
final Module module = myProjectFileIndex.getModuleForFile(file);
if (module != null) {
@@ -419,15 +260,6 @@ public class CompileContextImpl extends UserDataHolderBase implements CompileCon
return true;
}
public VirtualFile[] getAllOutputDirectories() {
return myOutputDirectories;
}
@NotNull
public Set<VirtualFile> getTestOutputDirectories() {
return myTestOutputDirectories;
}
public VirtualFile getModuleOutputDirectory(Module module) {
return CompilerPaths.getModuleOutputDirectory(module, false);
}
File diff suppressed because it is too large Load Diff
@@ -27,8 +27,6 @@ import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
@@ -124,35 +122,6 @@ public class CompilerCacheManager implements ProjectComponent {
return (FileProcessingCompilerStateCache)cache;
}
public synchronized StateCache<ValidityState> getGeneratingCompilerCache(final GeneratingCompiler compiler) throws IOException {
Object cache = myCompilerToCacheMap.get(compiler);
if (cache == null) {
final File cacheDir = getCompilerRootDir(compiler);
final StateCache<ValidityState> stateCache = new StateCache<ValidityState>(new File(cacheDir, "timestamps")) {
public ValidityState read(DataInput stream) throws IOException {
return compiler.createValidityState(stream);
}
public void write(ValidityState validityState, DataOutput out) throws IOException {
validityState.save(out);
}
};
myCompilerToCacheMap.put(compiler, stateCache);
myCacheDisposables.add(new Disposable() {
public void dispose() {
try {
stateCache.close();
}
catch (IOException e) {
LOG.info(e);
}
}
});
cache = stateCache;
}
return (StateCache<ValidityState>)cache;
}
public static String getCompilerIdString(Compiler compiler) {
@NonNls String description = compiler.getDescription();
return description.replaceAll("\\s+", "_").replaceAll("[\\.\\?]", "_").toLowerCase();
@@ -15,7 +15,6 @@
*/
package com.intellij.compiler.impl;
import com.intellij.compiler.CompilerWorkspaceConfiguration;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.*;
import com.intellij.openapi.diagnostic.Logger;
@@ -53,9 +52,6 @@ public class FileProcessingCompilerAdapterTask implements CompileTask {
@Override
public boolean execute(CompileContext context) {
final Project project = context.getProject();
if (!CompilerWorkspaceConfiguration.getInstance(project).useOutOfProcessBuild()) {
return true;
}
try {
final FileProcessingCompiler.ProcessingItem[] items = myCompiler.getProcessingItems(context);
@@ -1,40 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl;
import org.jetbrains.annotations.Nullable;
/**
* @author Eugene Zhuravlev
* Date: Jun 21, 2006
*/
public class SourceUrlClassNamePair {
private final String mySourceUrl;
private final @Nullable String myClassName;
public SourceUrlClassNamePair(String url, @Nullable String className) {
mySourceUrl = url;
myClassName = className;
}
public String getSourceUrl() {
return mySourceUrl;
}
public @Nullable String getClassName() {
return myClassName;
}
}
File diff suppressed because it is too large Load Diff
@@ -1,151 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* @author: Eugene Zhuravlev
* Date: Jan 17, 2003
* Time: 3:22:59 PM
*/
package com.intellij.compiler.impl.javaCompiler;
import com.intellij.compiler.CompilerConfiguration;
import com.intellij.compiler.CompilerConfigurationImpl;
import com.intellij.compiler.CompilerException;
import com.intellij.compiler.impl.CompileContextExProxy;
import com.intellij.compiler.impl.javaCompiler.javac.JavacCompiler;
import com.intellij.compiler.make.CacheCorruptedException;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.*;
import com.intellij.openapi.compiler.ex.CompileContextEx;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Chunk;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class AnnotationProcessingCompiler implements TranslatingCompiler{
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.javaCompiler.JavaCompiler");
private final Project myProject;
private final CompilerConfiguration myConfig;
public AnnotationProcessingCompiler(Project project) {
myProject = project;
myConfig = CompilerConfiguration.getInstance(project);
}
@NotNull
public String getDescription() {
return CompilerBundle.message("annotation.processing.compiler.description");
}
public boolean isCompilableFile(VirtualFile file, CompileContext context) {
if (!context.isAnnotationProcessorsEnabled()) {
return false;
}
return file.getFileType() == StdFileTypes.JAVA && !isExcludedFromAnnotationProcessing(file, context);
}
public void compile(final CompileContext context, final Chunk<Module> moduleChunk, final VirtualFile[] files, OutputSink sink) {
if (!context.isAnnotationProcessorsEnabled()) {
return;
}
final LocalFileSystem lfs = LocalFileSystem.getInstance();
final CompileContextEx _context = new CompileContextExProxy((CompileContextEx)context) {
public VirtualFile getModuleOutputDirectory(Module module) {
final String path = CompilerPaths.getAnnotationProcessorsGenerationPath(module);
return path != null? lfs.findFileByPath(path) : null;
}
public VirtualFile getModuleOutputDirectoryForTests(Module module) {
return getModuleOutputDirectory(module);
}
};
final JavacCompiler javacCompiler = getBackEndCompiler();
final boolean processorMode = javacCompiler.setAnnotationProcessorMode(true);
final BackendCompilerWrapper wrapper = new BackendCompilerWrapper(moduleChunk, myProject, Arrays.asList(files), _context, javacCompiler, sink);
wrapper.setForceCompileTestsSeparately(true);
try {
wrapper.compile();
}
catch (CompilerException e) {
_context.addMessage(CompilerMessageCategory.ERROR, e.getMessage(), null, -1, -1);
}
catch (CacheCorruptedException e) {
LOG.info(e);
_context.requestRebuildNextTime(e.getMessage());
}
finally {
javacCompiler.setAnnotationProcessorMode(processorMode);
final Set<VirtualFile> dirsToRefresh = new HashSet<VirtualFile>();
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
for (Module module : moduleChunk.getNodes()) {
final VirtualFile out = _context.getModuleOutputDirectory(module);
if (out != null) {
dirsToRefresh.add(out);
}
}
}
});
for (VirtualFile root : dirsToRefresh) {
root.refresh(false, true);
}
}
}
private boolean isExcludedFromAnnotationProcessing(VirtualFile file, CompileContext context) {
if (!context.isAnnotationProcessorsEnabled()) {
return true;
}
final Module module = context.getModuleByFile(file);
if (module != null) {
if (!myConfig.getAnnotationProcessingConfiguration(module).isEnabled()) {
return true;
}
final String path = CompilerPaths.getAnnotationProcessorsGenerationPath(module);
final VirtualFile generationDir = path != null? LocalFileSystem.getInstance().findFileByPath(path) : null;
if (generationDir != null && VfsUtil.isAncestor(generationDir, file, false)) {
return true;
}
}
return myConfig.isExcludedFromCompilation(file);
}
public boolean validateConfiguration(CompileScope scope) {
final JavacCompiler compiler = getBackEndCompiler();
final boolean previousValue = compiler.setAnnotationProcessorMode(true);
try {
return compiler.checkCompiler(scope);
}
finally {
compiler.setAnnotationProcessorMode(previousValue);
}
}
private JavacCompiler getBackEndCompiler() {
CompilerConfigurationImpl configuration = (CompilerConfigurationImpl)myConfig;
return configuration.getJavacCompiler();
}
}
@@ -15,36 +15,26 @@
*/
package com.intellij.compiler.impl.javaCompiler;
import com.intellij.compiler.OutputParser;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.compiler.CompileScope;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.options.Configurable;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.util.Set;
public interface BackendCompiler {
ExtensionPointName<BackendCompiler> EP_NAME = ExtensionPointName.create("com.intellij.java.compiler");
@NotNull @NonNls String getId(); // used for externalization
@NotNull String getPresentableName();
@NotNull Configurable createConfigurable();
@NotNull Set<FileType> getCompilableFileTypes();
@Nullable OutputParser createErrorParser(@NotNull String outputDir, Process process);
@Nullable OutputParser createOutputParser(@NotNull String outputDir);
boolean checkCompiler(final CompileScope scope);
@NotNull Process launchProcess(
@NotNull ModuleChunk chunk,
@NotNull String outputDir,
@NotNull CompileContext compileContext) throws IOException;
void compileFinished();
@NotNull
String getId(); // used for externalization
@NotNull
String getPresentableName();
@NotNull
Configurable createConfigurable();
@NotNull
Set<FileType> getCompilableFileTypes();
}
@@ -1,56 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.javaCompiler;
/**
* @author cdr
*/
final class CompiledClass {
public final int qName;
public final String relativePathToSource;
public final String pathToClass;
CompiledClass(final int qName, final String relativePathToSource, final String pathToClass) {
this.qName = qName;
this.relativePathToSource = relativePathToSource;
this.pathToClass = pathToClass;
}
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final CompiledClass that = (CompiledClass)o;
if (qName != that.qName) return false;
if (!pathToClass.equals(that.pathToClass)) return false;
if (!relativePathToSource.equals(that.relativePathToSource)) return false;
return true;
}
public int hashCode() {
int result;
result = qName;
result = 31 * result + relativePathToSource.hashCode();
result = 31 * result + pathToClass.hashCode();
return result;
}
public String toString() {
return "[" + pathToClass + ";" + relativePathToSource + "]";
}
}
@@ -1,263 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.javaCompiler;
import com.intellij.compiler.OutputParser;
import com.intellij.compiler.impl.CompileDriver;
import com.intellij.compiler.make.CacheCorruptedException;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.compiler.CompilerMessageCategory;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.SpinAllocator;
import com.intellij.util.StringBuilderSpinAllocator;
import org.jetbrains.annotations.NonNls;
import java.io.*;
/**
* @author Eugene Zhuravlev
* Date: Mar 30, 2004
*/
public class CompilerParsingThread implements Runnable, OutputParser.Callback {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.javaCompiler.JavaCompilerParsingThread");
@NonNls public static final String TERMINATION_STRING = "__terminate_read__";
private final Reader myCompilerOutStreamReader;
private Process myProcess;
private final OutputParser myOutputParser;
private final boolean myTrimLines;
private boolean mySkipLF = false;
private Throwable myError = null;
private final boolean myIsUnitTestMode;
private FileObject myClassFileToProcess = null;
private String myLastReadLine = null;
private String myPushBackLine = null;
private volatile boolean myProcessExited = false;
private final CompileContext myContext;
public CompilerParsingThread(Process process, OutputParser outputParser, final boolean readErrorStream, boolean trimLines, CompileContext context) {
myProcess = process;
myOutputParser = outputParser;
myTrimLines = trimLines;
InputStream stream = readErrorStream ? process.getErrorStream() : process.getInputStream();
myCompilerOutStreamReader = stream == null ? null : new BufferedReader(new InputStreamReader(stream), 16384);
myIsUnitTestMode = ApplicationManager.getApplication().isUnitTestMode();
myContext = context;
}
volatile boolean processing;
public void run() {
processing = true;
try {
while (true) {
if (!myIsUnitTestMode && myProcess == null) {
break;
}
if (isCanceled()) {
break;
}
if (!myOutputParser.processMessageLine(this)) {
break;
}
}
if (myClassFileToProcess != null) {
processCompiledClass(myClassFileToProcess);
myClassFileToProcess = null;
}
}
catch (Throwable e) {
e.printStackTrace();
myError = e;
LOG.info(e);
}
finally {
killProcess();
processing = false;
}
}
private void killProcess() {
if (myProcess != null) {
myProcess.destroy();
myProcess = null;
}
}
public Throwable getError() {
return myError;
}
public String getCurrentLine() {
return myLastReadLine;
}
public final String getNextLine() {
final String pushBack = myPushBackLine;
if (pushBack != null) {
myPushBackLine = null;
myLastReadLine = pushBack;
return pushBack;
}
final String line = readLine(myCompilerOutStreamReader);
if (LOG.isDebugEnabled()) {
LOG.debug("LIne read: #" + line + "#");
}
if (CompileDriver.ourDebugMode) {
System.out.println("LIne read: #" + line + "#");
}
if (TERMINATION_STRING.equals(line)) {
myLastReadLine = null;
}
else {
myLastReadLine = line == null ? null : myTrimLines ? line.trim() : line;
}
return myLastReadLine;
}
@Override
public void pushBack(String line) {
myLastReadLine = null;
myPushBackLine = line;
}
public final void fileGenerated(FileObject path) {
// javac first logs file generated, then starts to write the file to disk,
// so this thread sometimes can stumble on not yet existing file,
// hence this complex logic
FileObject previousPath = myClassFileToProcess;
myClassFileToProcess = path;
if (previousPath != null) {
try {
processCompiledClass(previousPath);
}
catch (CacheCorruptedException e) {
if (CompileDriver.ourDebugMode) {
e.printStackTrace();
}
myError = e;
LOG.info(e);
killProcess();
}
}
}
protected boolean isCanceled() {
return myContext.getProgressIndicator().isCanceled();
}
public void setProgressText(String text) {
myContext.getProgressIndicator().setText(text);
}
public void fileProcessed(String path) {
}
public void message(CompilerMessageCategory category, String message, String url, int lineNum, int columnNum) {
myContext.addMessage(category, message, url, lineNum, columnNum);
}
protected void processCompiledClass(final FileObject classFileToProcess) throws CacheCorruptedException {
}
private String readLine(final Reader reader) {
StringBuilder buffer;
boolean releaseBuffer = true;
try {
buffer = StringBuilderSpinAllocator.alloc();
}
catch (SpinAllocator.AllocatorExhaustedException e) {
if (CompileDriver.ourDebugMode) {
e.printStackTrace();
}
LOG.info(e);
buffer = new StringBuilder();
releaseBuffer = false;
}
try {
boolean first = true;
while (true) {
int c = readNextByte(reader);
if (c == -1) break;
first = false;
if (c == '\n') {
if (mySkipLF) {
mySkipLF = false;
continue;
}
break;
}
else if (c == '\r') {
mySkipLF = true;
break;
}
else {
mySkipLF = false;
buffer.append((char)c);
}
}
if (first) {
return null;
}
return buffer.toString();
}
finally {
if (releaseBuffer) {
StringBuilderSpinAllocator.dispose(buffer);
}
}
}
private int readNextByte(final Reader reader) {
try {
while(!reader.ready()) {
if (isProcessTerminated()) {
if (reader.ready()) {
break;
}
return -1;
}
try {
Thread.sleep(1L);
}
catch (InterruptedException ignore) {
}
}
return reader.read();
}
catch (IOException e) {
if (CompileDriver.ourDebugMode) {
e.printStackTrace();
}
return -1; // When process terminated Process.getInputStream()'s underlying stream becomes closed on Linux.
}
catch (Throwable t) {
if (CompileDriver.ourDebugMode) {
t.printStackTrace();
}
return -1;
}
}
private boolean isProcessTerminated() {
return myProcessExited;
}
public void setProcessTerminated(final boolean procesExited) {
myProcessExited = procesExited;
}
}
@@ -1,137 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.javaCompiler;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.compiler.CompileScope;
import com.intellij.openapi.compiler.SourceGeneratingCompiler;
import com.intellij.openapi.compiler.ValidityState;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import java.io.DataInput;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* @author Eugene Zhuravlev
* Date: Oct 9, 2004
*/
@SuppressWarnings({"HardCodedStringLiteral"})
public class DummySourceGeneratingCompiler implements SourceGeneratingCompiler{
public static final String MODULE_NAME = "generated";
private final Project myProject;
public DummySourceGeneratingCompiler(Project project) {
myProject = project;
}
@Override
public VirtualFile getPresentableFile(CompileContext context, Module module, VirtualFile outputRoot, VirtualFile generatedFile) {
return null;
}
public GenerationItem[] getGenerationItems(CompileContext context) {
final Module module = findMyModule();
return new GenerationItem[] {
new MyGenerationItem("aaa/p1.properties", module, false),
new MyGenerationItem("bbb/p2.properties", module, false),
new MyGenerationItem("bbb/ccc/p3.properties", module, false),
new MyGenerationItem("aaa/p1.properties", module, true),
new MyGenerationItem("bbb/p2-t.properties", module, true),
new MyGenerationItem("bbb/ccc/p3.properties", module, true)
};
}
private Module findMyModule() {
return ApplicationManager.getApplication().runReadAction(new Computable<Module>() {
public Module compute() {
Module[] modules = ModuleManager.getInstance(myProject).getModules();
for (Module module : modules) {
if (MODULE_NAME.equals(module.getName())) {
return module;
}
}
return null;
}
});
}
public GenerationItem[] generate(CompileContext context, GenerationItem[] items, final VirtualFile outputRootDirectory) {
final String rootPath = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
public String compute() {
return outputRootDirectory.getPath();
}
});
final List<GenerationItem> success = new ArrayList<GenerationItem>();
for (GenerationItem item1 : items) {
GenerationItem item = item1;
File file = new File(rootPath + File.separator + item.getPath());
FileUtil.createIfDoesntExist(file);
success.add(item);
}
return success.toArray(new GenerationItem[success.size()]);
}
@NotNull
public String getDescription() {
return "Dummy Source Generator";
}
public boolean validateConfiguration(CompileScope scope) {
return findMyModule() != null;
}
public ValidityState createValidityState(DataInput in) throws IOException {
return null;
}
private static class MyGenerationItem implements GenerationItem {
private final String myRelPath;
private final Module myModule;
private final boolean myIsTestSource;
public MyGenerationItem(String relPath, Module module, final boolean isTestSource) {
myRelPath = relPath;
myModule = module;
myIsTestSource = isTestSource;
}
public String getPath() {
return myRelPath;
}
public ValidityState getValidityState() {
return null;
}
public Module getModule() {
return myModule;
}
public boolean isTestSource() {
return myIsTestSource;
}
}
}
@@ -1,78 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.javaCompiler;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.compiler.CompileScope;
import com.intellij.openapi.compiler.CompilerMessageCategory;
import com.intellij.openapi.compiler.JavaSourceTransformingCompiler;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import java.io.*;
/**
* @author Eugene Zhuravlev
* Date: Jul 10, 2004
*/
@SuppressWarnings({"HardCodedStringLiteral"})
public class DummyTransformingCompiler implements JavaSourceTransformingCompiler{
public boolean isTransformable(VirtualFile file) {
return "A.java".equals(file.getName());
}
public boolean transform(CompileContext context, final VirtualFile file, VirtualFile originalFile) {
System.out.println("DummyTransformingCompiler.transform");
final String url = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
public String compute() {
return file.getPresentableUrl();
}
});
context.getProgressIndicator().setText("Transforming file: " + url);
try {
OutputStream os = new BufferedOutputStream(new FileOutputStream(new File(url)));
DataOutput out = new DataOutputStream(os);
out.writeBytes("package a; ");
out.writeBytes("public class A { public static void main(String[] args) { System.out.println(\"Hello from modified class\");} }");
os.close();
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
public void run() {
file.refresh(false, false);
}
});
return true;
}
catch (FileNotFoundException e) {
context.addMessage(CompilerMessageCategory.ERROR, e.getMessage(), null, -1, -1);
}
catch (IOException e) {
context.addMessage(CompilerMessageCategory.ERROR, e.getMessage(), null, -1, -1);
}
return false;
}
@NotNull
public String getDescription() {
return "a dummy compiler for testing";
}
public boolean validateConfiguration(CompileScope scope) {
return true;
}
}
@@ -1,93 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.javaCompiler;
import com.intellij.compiler.impl.CompilerUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.*;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Chunk;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.IOException;
import java.util.*;
/**
* @author Eugene Zhuravlev
* Date: Dec 4, 2007
*/
public class DummyTranslatingCompiler implements TranslatingCompiler, IntermediateOutputCompiler{
@NonNls private static final String DESCRIPTION = "DUMMY TRANSLATOR";
@NonNls private static final String FILETYPE_EXTENSION = ".dummy";
public boolean isCompilableFile(final VirtualFile file, final CompileContext context) {
return file.getName().endsWith(FILETYPE_EXTENSION);
}
public void compile(final CompileContext context, Chunk<Module> moduleChunk, final VirtualFile[] files, OutputSink sink) {
final List<File> filesToRefresh = new ArrayList<File>();
final Map<String, Collection<OutputItem>> outputs = new HashMap<String, Collection<OutputItem>>();
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
for (final VirtualFile file : files) {
final Module module = context.getModuleByFile(file);
try {
final VirtualFile outputDir = context.getModuleOutputDirectory(module);
if (outputDir != null) {
final String outputDirPath = outputDir.getPath();
final File compiledFile = doCompile(outputDir, file);
filesToRefresh.add(compiledFile);
Collection<OutputItem> collection = outputs.get(outputDirPath);
if (collection == null) {
collection = new ArrayList<OutputItem>();
outputs.put(outputDirPath, collection);
}
collection.add(new OutputItemImpl(FileUtil.toSystemIndependentName(compiledFile.getPath()), file));
}
}
catch (IOException e) {
context.addMessage(CompilerMessageCategory.ERROR, e.getMessage(), null, 0, 0);
}
}
}
});
CompilerUtil.refreshIOFiles(filesToRefresh);
for (Map.Entry<String, Collection<OutputItem>> entry : outputs.entrySet()) {
sink.add(entry.getKey(), entry.getValue(), VirtualFile.EMPTY_ARRAY);
}
}
private static File doCompile(VirtualFile out, VirtualFile src) throws IOException {
final String originalName = src.getName();
String compiledName = originalName.substring(0, originalName.length() - FILETYPE_EXTENSION.length());
final File destFile = new File(out.getPath(), compiledName + ".java");
FileUtil.copy(new File(src.getPath()), destFile);
return destFile;
}
@NotNull
public String getDescription() {
return DESCRIPTION;
}
public boolean validateConfiguration(final CompileScope scope) {
return true;
}
}
@@ -1,83 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.javaCompiler;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.EnvironmentUtil;
import com.intellij.util.StringBuilderSpinAllocator;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.util.Collections;
import java.util.Set;
public abstract class ExternalCompiler implements BackendCompiler {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.javaCompiler.ExternalCompiler");
private static final Set<FileType> COMPILABLE_TYPES = Collections.<FileType>singleton(StdFileTypes.JAVA);
@NotNull
public abstract String[] createStartupCommand(ModuleChunk chunk, CompileContext context, String outputPath)
throws IOException, IllegalArgumentException;
@NotNull
public Set<FileType> getCompilableFileTypes() {
return COMPILABLE_TYPES;
}
/**
* Checks if the compiler can compile the specified file.
*
* @param file the file to check.
* @param context the context for the current compile operation.
* @return true if can compile the file, false otherwise. If the method returns false, <code>file</code>
* will not be included in the list of files passed to {@link #compile(CompileContext, com.intellij.util.Chunk < com.intellij.openapi.module.Module >,com.intellij.openapi.vfs.VirtualFile[], com.intellij.openapi.compiler.TranslatingCompiler.OutputSink)}.
*/
public boolean isCompilableFile(VirtualFile file, CompileContext context) {
return getCompilableFileTypes().contains(file.getFileType());
}
@NotNull
public Process launchProcess(@NotNull final ModuleChunk chunk, @NotNull final String outputDir, @NotNull final CompileContext compileContext) throws IOException {
final String[] commands = createStartupCommand(chunk, compileContext, outputDir);
if (LOG.isDebugEnabled()) {
@NonNls final StringBuilder buf = StringBuilderSpinAllocator.alloc();
try {
buf.append("\n===================================Environment:===========================\n");
for (String pair : EnvironmentUtil.getEnvironment()) {
buf.append("\t").append(pair).append("\n");
}
buf.append("=============================================================================\n");
buf.append("Running compiler: ");
for (final String command : commands) {
buf.append(" ").append(command);
}
LOG.debug(buf.toString());
}
finally {
StringBuilderSpinAllocator.dispose(buf);
}
}
return Runtime.getRuntime().exec(commands);
}
}
@@ -1,73 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.javaCompiler;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* @author cdr
*/
public class FileObject {
private static final byte[] NOT_LOADED = ArrayUtil.EMPTY_BYTE_ARRAY;
private final File myFile;
private final byte[] myContent;
public FileObject(@NotNull File file, @NotNull byte[] content) {
myFile = file;
myContent = content;
}
public FileObject(File file) {
myFile = file;
myContent = NOT_LOADED;
}
public File getFile() {
return myFile;
}
public byte[] getContent() throws IOException {
if (myContent == NOT_LOADED) {
return FileUtil.loadFileBytes(myFile);
}
return myContent;
}
public void save() throws IOException {
if (myContent == NOT_LOADED) {
return; // already on disk
}
try {
FileUtil.writeToFile(myFile, myContent);
}
catch (FileNotFoundException e) {
FileUtil.createParentDirs(myFile);
FileUtil.writeToFile(myFile, myContent);
}
}
@Override
public String toString() {
return getFile().toString();
}
}
@@ -1,94 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* @author: Eugene Zhuravlev
* Date: Jan 17, 2003
* Time: 3:22:59 PM
*/
package com.intellij.compiler.impl.javaCompiler;
import com.intellij.compiler.CompilerConfiguration;
import com.intellij.compiler.CompilerConfigurationImpl;
import com.intellij.compiler.CompilerException;
import com.intellij.compiler.impl.CompileDriver;
import com.intellij.compiler.make.CacheCorruptedException;
import com.intellij.openapi.compiler.*;
import com.intellij.openapi.compiler.ex.CompileContextEx;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Chunk;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
public class JavaCompiler implements TranslatingCompiler {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.javaCompiler.JavaCompiler");
private final Project myProject;
public JavaCompiler(Project project) {
myProject = project;
}
@NotNull
public String getDescription() {
return CompilerBundle.message("java.compiler.description");
}
public boolean isCompilableFile(VirtualFile file, CompileContext context) {
final BackendCompiler backEndCompiler = getBackEndCompiler();
if (backEndCompiler instanceof ExternalCompiler) {
return ((ExternalCompiler)backEndCompiler).isCompilableFile(file, context);
}
return backEndCompiler.getCompilableFileTypes().contains(file.getFileType());
}
public void compile(CompileContext context, Chunk<Module> moduleChunk, VirtualFile[] files, OutputSink sink) {
final BackendCompiler backEndCompiler = getBackEndCompiler();
final BackendCompilerWrapper wrapper = new BackendCompilerWrapper(moduleChunk, myProject, Arrays.asList(files), (CompileContextEx)context, backEndCompiler, sink);
try {
if (CompileDriver.ourDebugMode) {
System.out.println("Starting java compiler; with backend compiler: " + backEndCompiler.getClass().getName());
}
wrapper.compile();
}
catch (CompilerException e) {
if (CompileDriver.ourDebugMode) {
e.printStackTrace();
}
context.addMessage(CompilerMessageCategory.ERROR, e.getMessage(), null, -1, -1);
LOG.info(e);
}
catch (CacheCorruptedException e) {
if (CompileDriver.ourDebugMode) {
e.printStackTrace();
}
LOG.info(e);
context.requestRebuildNextTime(e.getMessage());
}
}
public boolean validateConfiguration(CompileScope scope) {
return getBackEndCompiler().checkCompiler(scope);
}
private BackendCompiler getBackEndCompiler() {
CompilerConfigurationImpl configuration = (CompilerConfigurationImpl)CompilerConfiguration.getInstance(myProject);
return configuration.getDefaultCompiler();
}
}
@@ -1,60 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.javaCompiler;
import org.jetbrains.annotations.NotNull;
/**
* @author cdr
*/
class OutputDir {
private final String myPath;
private final int myKind;
OutputDir(@NotNull String path, int kind) {
myPath = path;
myKind = kind;
}
@NotNull
public String getPath() {
return myPath;
}
public int getKind() {
return myKind;
}
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof OutputDir)) {
return false;
}
final OutputDir outputDir = (OutputDir)o;
return myKind == outputDir.myKind && myPath.equals(outputDir.myPath);
}
public int hashCode() {
int result = myPath.hashCode();
result = 29 * result + myKind;
return result;
}
}
@@ -1,53 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* @author: Eugene Zhuravlev
* Date: Apr 1, 2003
* Time: 5:58:41 PM
*/
package com.intellij.compiler.impl.javaCompiler;
import com.intellij.openapi.compiler.TranslatingCompiler;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.Nullable;
public class OutputItemImpl implements TranslatingCompiler.OutputItem{
private final String myOutputPath;
private final VirtualFile mySourceFile;
public OutputItemImpl(VirtualFile packageInfoFile) {
this(null, packageInfoFile);
}
/**
* @param outputPath absolute path of the output file ('/' slashes used)
* @param sourceFile corresponding source file
*/
public OutputItemImpl(@Nullable String outputPath, VirtualFile sourceFile) {
myOutputPath = outputPath;
mySourceFile = sourceFile;
}
public String getOutputPath() {
return myOutputPath;
}
public VirtualFile getSourceFile() {
return mySourceFile;
}
}
@@ -1,180 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.javaCompiler.api;
import com.intellij.compiler.OutputParser;
import com.intellij.openapi.compiler.CompilerMessageCategory;
import com.sun.source.util.JavacTask;
import com.sun.source.util.TaskEvent;
import com.sun.source.util.TaskListener;
import com.sun.tools.javac.api.JavacTool;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.tools.*;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.net.URI;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
/**
* @author cdr
*/
@SuppressWarnings({"Since15"})
class CompAPIDriver {
private final BlockingQueue<CompilationEvent> myCompilationResults = new LinkedBlockingQueue<CompilationEvent>();
private static final CompilationEvent GUARD = new CompilationEvent() {
@Override
protected void process(OutputParser.Callback callback) {
}
@Override
public String toString() {
return "FINISH";
}
};
private String myOutputDir;
private volatile boolean compiling;
private static final PrintWriter COMPILER_ERRORS = new PrintWriter(System.err);
@Nullable
private final String mySourcesEncoding;
CompAPIDriver(@Nullable String sourcesEncoding) {
mySourcesEncoding = sourcesEncoding;
}
public void compile(List<String> commandLine, List<File> paths, final String outputDir) {
myOutputDir = outputDir;
compiling = true;
assert myCompilationResults.isEmpty();
JavaCompiler compiler = JavacTool.create(); //use current classloader
StandardJavaFileManager standardFileManager = compiler.getStandardFileManager(null, null, null);
MyFileManager manager = new MyFileManager(this, outputDir, standardFileManager, mySourcesEncoding);
Iterable<? extends JavaFileObject> input = manager.getJavaFileObjectsFromFiles(paths);
DiagnosticListener<JavaFileObject> listener = new DiagnosticListener<JavaFileObject>() {
public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
CompilationEvent event = CompilationEvent.diagnostic(diagnostic);
myCompilationResults.offer(event);
}
};
try {
JavaCompiler.CompilationTask task = compiler.getTask(COMPILER_ERRORS, manager, listener, commandLine, null, input);
((JavacTask)task).setTaskListener(new TaskListener() {
public void started(TaskEvent taskEvent) {
JavaFileObject sourceFile = taskEvent.getSourceFile();
CompilationEvent event;
switch (taskEvent.getKind()) {
case ANALYZE:
event = CompilationEvent.progress("Analyzing ",sourceFile);
break;
case PARSE:
event = CompilationEvent.progress("Parsing ", sourceFile);
break;
default:
event = null;
}
if (event != null) {
myCompilationResults.offer(event);
}
}
public void finished(TaskEvent taskEvent) {
CompilationEvent event;
switch (taskEvent.getKind()) {
case ENTER:
event = CompilationEvent.fileProcessed();
break;
default:
event = null;
}
if (event != null) {
myCompilationResults.offer(event);
}
}
});
task.call();
}
catch (IllegalArgumentException e) {
final String message = "Javac in-process compiler error: " + e.getMessage();
myCompilationResults.offer(new CompilationEvent() {
@Override
protected void process(OutputParser.Callback callback) {
callback.message(CompilerMessageCategory.ERROR, message, null, -1, -1);
}
});
}
finally {
compiling = false;
myCompilationResults.offer(GUARD);
try {
manager.close();
}
catch (IOException ignored) {
}
}
}
private volatile boolean processing;
public void processAll(@NotNull OutputParser.Callback callback) {
try {
processing = true;
while (true) {
CompilationEvent event = myCompilationResults.take();
if (event == GUARD) break;
event.process(callback);
}
}
catch (InterruptedException ignored) {
}
finally {
processing = false;
}
}
public void finish() {
assert !compiling : "still compiling to "+myOutputDir;
assert !processing;
//assert myCompilationResults.isEmpty() : myCompilationResults;
myCompilationResults.clear();
cleanupInternalFields();
}
private static void cleanupInternalFields() {
try {
Field freelist = Class.forName("com.sun.tools.javac.util.SharedNameTable").getDeclaredField("freelist");
freelist.setAccessible(true);
freelist.set(null, com.sun.tools.javac.util.List.nil());
}
catch (Exception ignored) {
}
}
public void offerClassFile(URI uri, byte[] bytes) {
CompilationEvent event = CompilationEvent.generateClass(uri, bytes);
myCompilationResults.offer(event);
}
}
@@ -1,127 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.javaCompiler.api;
import com.intellij.compiler.OutputParser;
import com.intellij.compiler.impl.javaCompiler.FileObject;
import com.intellij.openapi.compiler.CompilerMessageCategory;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtil;
import org.jetbrains.annotations.NonNls;
import javax.tools.*;
import java.io.File;
import java.net.URI;
/**
* @author cdr
*/
abstract class CompilationEvent {
protected abstract void process(OutputParser.Callback callback);
static CompilationEvent progress(final String title, final JavaFileObject fileObject) {
return new CompilationEvent() {
@Override
protected void process(OutputParser.Callback callback) {
showProgressFor(title, fileObject.toUri(), callback);
}
@NonNls
@Override
public String toString() {
return "Progress: "+title+" "+fileObject.toUri();
}
};
}
private static void showProgressFor(String title, URI uri, OutputParser.Callback callback) {
String normalizedPath;
try {
normalizedPath = new File(uri).getPath();
}
catch (IllegalArgumentException e) {
normalizedPath = uri.toString();
}
callback.setProgressText(title + StringUtil.last(normalizedPath, 100, true));
}
static CompilationEvent generateClass(final URI uri, final byte[] bytes) {
return new CompilationEvent() {
@Override
protected void process(OutputParser.Callback callback) {
showProgressFor("Writing ", uri, callback);
File file = new File(uri);
callback.fileGenerated(new FileObject(file,bytes));
}
@NonNls
@Override
public String toString() {
return "Write: "+uri;
}
};
}
static CompilationEvent diagnostic(final Diagnostic<? extends JavaFileObject> diagnostic) {
return new CompilationEvent() {
@Override
protected void process(OutputParser.Callback callback) {
JavaFileObject fileObject = diagnostic.getSource();
String message = diagnostic.getMessage(null);
String url;
if (fileObject == null) {
url = null;
}
else {
URI uri = fileObject.toUri();
if (uri.getScheme().equals("file")) {
url = VfsUtil.pathToUrl(FileUtil.toSystemIndependentName(uri.getPath()));
}
else {
url = fileObject.toString();
}
}
CompilerMessageCategory category = diagnostic.getKind() == Diagnostic.Kind.ERROR
? CompilerMessageCategory.ERROR
: diagnostic.getKind() == Diagnostic.Kind.WARNING ||
diagnostic.getKind() == Diagnostic.Kind.MANDATORY_WARNING
? CompilerMessageCategory.WARNING
: CompilerMessageCategory.INFORMATION;
callback.message(category, message, url, (int)diagnostic.getLineNumber(), (int)diagnostic.getColumnNumber());
}
@NonNls
@Override
public String toString() {
return "Diagnostic: "+diagnostic;
}
};
}
public static CompilationEvent fileProcessed() {
return FILE_PROCESSED;
}
private static final CompilationEvent FILE_PROCESSED = new CompilationEvent() {
@Override
protected void process(OutputParser.Callback callback) {
callback.fileProcessed(null);
}
@NonNls
@Override
public String toString() {
return "Processed";
}
};
}
@@ -1,199 +0,0 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.javaCompiler.api;
import com.intellij.compiler.OutputParser;
import com.intellij.compiler.impl.javaCompiler.BackendCompiler;
import com.intellij.compiler.impl.javaCompiler.ModuleChunk;
import com.intellij.compiler.impl.javaCompiler.javac.JavacCompiler;
import com.intellij.compiler.impl.javaCompiler.javac.JavacConfigurable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.compiler.CompileScope;
import com.intellij.openapi.compiler.CompilerMessageCategory;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.JavaSdkVersion;
import com.intellij.openapi.util.ThrowableComputable;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.java.compiler.JavaCompilers;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
public class CompilerAPICompiler implements BackendCompiler {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.javaCompiler.api.CompilerAPICompiler");
private final Project myProject;
private static final Set<FileType> COMPILABLE_TYPES = Collections.<FileType>singleton(StdFileTypes.JAVA);
public CompilerAPICompiler(Project project) {
myProject = project;
}
public boolean checkCompiler(final CompileScope scope) {
return true;
}
@NotNull
@NonNls
public String getId() { // used for externalization
return JavaCompilers.JAVAC_API_ID;
}
@NotNull
public String getPresentableName() {
return "Javac in-process (Java6+ only)";
}
@NotNull
public Configurable createConfigurable() {
return new JavacConfigurable(CompilerAPIConfiguration.getOptions(myProject, CompilerAPIConfiguration.class));
}
@NotNull
public Set<FileType> getCompilableFileTypes() {
return COMPILABLE_TYPES;
}
@Nullable
public OutputParser createErrorParser(@NotNull final String outputDir, final Process process) {
return new OutputParser() {
public boolean processMessageLine(Callback callback) {
((MyProcess)process).myCompAPIDriver.processAll(callback);
return false;
}
};
}
@Nullable
public OutputParser createOutputParser(@NotNull final String outputDir) {
return null;
}
public void compileFinished() {
}
@NotNull
public Process launchProcess(@NotNull final ModuleChunk chunk, @NotNull final String outputDir, @NotNull final CompileContext compileContext) throws IOException {
@NonNls final List<String> commandLine =
ApplicationManager.getApplication().runReadAction(new ThrowableComputable<List<String>, IOException>() {
@Override
public List<String> compute() throws IOException {
List<String> commandLine = new ArrayList<String>();
final List<String> additionalOptions =
JavacCompiler.addAdditionalSettings(commandLine, CompilerAPIConfiguration .getOptions(myProject, CompilerAPIConfiguration.class), false,
JavaSdkVersion.JDK_1_6, chunk, compileContext.isAnnotationProcessorsEnabled());
JavacCompiler.addCommandLineOptions(chunk, commandLine, outputDir, chunk.getJdk(), false, false, null, false, false, false);
commandLine.addAll(additionalOptions);
return commandLine;
}
});
return new MyProcess(commandLine, chunk, outputDir, compileContext);
}
private static void compile(List<String> commandLine, ModuleChunk chunk, String outputDir, CompAPIDriver myCompAPIDriver) {
List<VirtualFile> filesToCompile = chunk.getFilesToCompile();
List<File> paths = new ArrayList<File>(filesToCompile.size());
for (VirtualFile file : filesToCompile) {
paths.add(new File(file.getPresentableUrl()));
}
myCompAPIDriver.compile(commandLine, paths, outputDir);
}
private static class MyProcess extends Process {
private final List<String> myCommandLine;
private final ModuleChunk myChunk;
private final String myOutputDir;
private final CompileContext myCompileContext;
private final CompAPIDriver myCompAPIDriver;
private MyProcess(List<String> commandLine, ModuleChunk chunk, String outputDir, CompileContext compileContext) {
myCommandLine = commandLine;
myChunk = chunk;
myOutputDir = outputDir;
myCompileContext = compileContext;
myCompAPIDriver = new CompAPIDriver(findEncodingValue(commandLine));
}
private static String findEncodingValue(List<String> commandLine) {
boolean found = false;
for (String param : commandLine) {
if (found) {
return param;
}
if ("-encoding".equalsIgnoreCase(param)) {
found = true;
}
}
return null;
}
public OutputStream getOutputStream() {
throw new UnsupportedOperationException();
}
public InputStream getInputStream() {
return null;
}
public InputStream getErrorStream() {
return null;
}
public void destroy() {
myCompAPIDriver.finish();
}
private int myExitCode;
public int waitFor() {
try {
myCommandLine.remove("-verbose");
compile(myCommandLine, myChunk, myOutputDir, myCompAPIDriver);
myExitCode = 0;
return myExitCode;
}
catch (Exception e) {
myCompileContext.addMessage(CompilerMessageCategory.ERROR, e.getMessage(), null, -1, -1);
LOG.info(e);
myExitCode = -1;
return -1;
}
}
public int exitValue() {
return myExitCode;
}
@Override
public String toString() {
return myChunk.toString();
}
}
}
@@ -1,36 +0,0 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.javaCompiler.api;
import com.intellij.compiler.impl.javaCompiler.javac.JavacConfiguration;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.components.StoragePathMacros;
import com.intellij.openapi.components.StorageScheme;
import com.intellij.openapi.project.Project;
@State(
name = "CompilerAPISettings",
storages = {
@Storage(file = StoragePathMacros.PROJECT_FILE),
@Storage(file = StoragePathMacros.PROJECT_CONFIG_DIR + "/compiler.xml", scheme = StorageScheme.DIRECTORY_BASED)
}
)
public class CompilerAPIConfiguration extends JavacConfiguration {
public CompilerAPIConfiguration(Project project) {
super(project);
}
}
@@ -1,99 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.javaCompiler.api;
import com.intellij.compiler.CompilerConfiguration;
import com.intellij.compiler.CompilerConfigurationImpl;
import com.intellij.compiler.impl.javaCompiler.BackendCompiler;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.compiler.CompileStatusNotification;
import com.intellij.openapi.compiler.CompilerManager;
import com.intellij.openapi.project.Project;
import com.intellij.util.containers.ContainerUtil;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* @author cdr
*/
public class CompilerPerfTestAction extends AnAction {
@Override
public void update(AnActionEvent e) {
Project project = e.getData(CommonDataKeys.PROJECT);
e.getPresentation().setEnabled(project != null);
}
public void actionPerformed(AnActionEvent e) {
final Project project = e.getData(CommonDataKeys.PROJECT);
final CompilerManager compilerManager = CompilerManager.getInstance(project);
final CompilerConfigurationImpl configuration = (CompilerConfigurationImpl)CompilerConfiguration.getInstance(project);
List<BackendCompiler> compilers = (List<BackendCompiler>)configuration.getRegisteredJavaCompilers();
final List<BackendCompiler> allCompilers = ContainerUtil.concat(compilers, compilers, compilers, compilers, compilers, compilers, compilers);
final int[] i = new int[1];
CompileStatusNotification callback = new CompileStatusNotification() {
volatile long start;
BackendCompiler compiler;
public void finished(boolean aborted, int errors, int warnings, CompileContext compileContext) {
if (compiler == null) {
next();
return;
}
final long finish = System.currentTimeMillis();
System.out.println("Compiled with '" +
compiler.getPresentableName() + "' " +
" in " +
TimeUnit.MILLISECONDS.toMinutes(finish - start) + "m" +
TimeUnit.MILLISECONDS.toSeconds((finish - start)%60000) + "s" +
" with " +
errors +
" errors, " +
warnings +
" warnings, aborted=" +
aborted+"; free memory="+Runtime.getRuntime().freeMemory()+" bytes");
//ProfilingUtil.forceCaptureMemorySnapshot();
next();
}
void next() {
if (i[0] >= allCompilers.size()) return;
compiler = allCompilers.get(i[0]++);
if (compiler.getId().equals("Jikes")|| compiler.getId().contains("Eclipse")) {
next();
return;
}
boolean success = compiler.checkCompiler(compilerManager.createProjectCompileScope(project));
if (!success) {
next();
return;
}
configuration.setDefaultCompiler(compiler);
start = System.currentTimeMillis();
compilerManager.rebuild(this);
}
};
callback.finished(false,0,0,null);
}
}
@@ -1,70 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.javaCompiler.api;
import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
import com.intellij.openapi.vfs.VirtualFile;
import javax.tools.*;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
/**
* @author cdr
*/
@SuppressWarnings({"Since15"})
public abstract class FileVirtualObject extends SimpleJavaFileObject {
public FileVirtualObject(URI uri, Kind kind) {
super(uri, kind);
}
protected abstract VirtualFile getVirtualFile();
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
VirtualFile virtualFile = getVirtualFile();
if (virtualFile == null) return null;
return LoadTextUtil.loadText(virtualFile);
}
@Override
public InputStream openInputStream() throws IOException {
// in-process compiler does not work well with zipped stream
byte[] bytes = getVirtualFile().contentsToByteArray();
return new ByteArrayInputStream(bytes);
}
@Override
public OutputStream openOutputStream() throws IOException {
return getVirtualFile().getOutputStream(this);
}
@Override
public String toString() {
return toUri().toString();
}
@Override
public int hashCode() {
return toUri().hashCode();
}
@Override
public boolean equals(Object obj) {
return obj instanceof JavaFileObject && toUri().equals(((JavaFileObject)obj).toUri());
}
}
@@ -1,94 +0,0 @@
/*
* Copyright 2000-2010 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.javaCompiler.api;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
/**
* User: cdr
*/
@SuppressWarnings({"Since15"})
class JavaIoFile extends SimpleJavaFileObject {
private final File myFile;
@Nullable
private final String myEncoding;
JavaIoFile(@NotNull File file, @NotNull Kind kind, @Nullable String encoding) {
super(convertToURI(file.getPath()), kind);
myFile = file;
myEncoding = encoding;
}
// File.toURI() asks for File.isDirectory which is too expensive
@NotNull
private static URI convertToURI(@NotNull String path) {
if (File.separatorChar != '/') {
path = path.replace(File.separatorChar, '/');
}
if (!StringUtil.startsWithChar(path, '/')) {
path = "/" + path;
}
if (path.startsWith("//")) {
path = "//" + path;
}
try {
return new URI("file", null, path, null);
}
catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
return FileUtil.loadFile(myFile, myEncoding);
}
@Override
public InputStream openInputStream() throws IOException {
return new BufferedInputStream(new FileInputStream(myFile));
}
@Override
public OutputStream openOutputStream() throws IOException {
return new BufferedOutputStream(new FileOutputStream(myFile));
}
@Override
public String toString() {
return toUri().toString();
}
@Override
public int hashCode() {
return toUri().hashCode();
}
@Override
public boolean equals(Object obj) {
return obj instanceof JavaFileObject && toUri().equals(((JavaFileObject)obj).toUri());
}
}
@@ -1,38 +0,0 @@
/*
* Copyright 2000-2010 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.javaCompiler.api;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import java.io.File;
/**
* User: cdr
*/
@SuppressWarnings({"Since15"})
class JavaVirtualByIoFile extends FileVirtualObject {
private final File myFile;
protected JavaVirtualByIoFile(File file, Kind kind) {
super(file.toURI(), kind);
myFile = file;
}
protected VirtualFile getVirtualFile() {
return LocalFileSystem.getInstance().findFileByIoFile(myFile);
}
}
@@ -1,35 +0,0 @@
/*
* Copyright 2000-2010 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.javaCompiler.api;
import com.intellij.openapi.vfs.VirtualFile;
/**
* User: cdr
*/
@SuppressWarnings({"Since15"})
class JavaVirtualFile extends FileVirtualObject {
private final VirtualFile myFile;
JavaVirtualFile(VirtualFile file, Kind kind) {
super(MyFileManager.createUri(file.getUrl()), kind);
myFile = file;
}
protected VirtualFile getVirtualFile() {
return myFile;
}
}
@@ -1,260 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.javaCompiler.api;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.SmartList;
import com.sun.tools.javac.util.ListBuffer;
import gnu.trove.THashSet;
import gnu.trove.TObjectHashingStrategy;
import javax.tools.FileObject;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.util.*;
/**
* @author cdr
*/
class MyFileManager implements StandardJavaFileManager {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.javaCompiler.api.MyFileManager");
private final String myOutputDir;
private final StandardJavaFileManager myStandardFileManager;
private final String myEncoding;
private final CompAPIDriver myCompAPIDriver;
MyFileManager(CompAPIDriver compAPIDriver, String outputDir, StandardJavaFileManager standardFileManager, String encoding) {
myCompAPIDriver = compAPIDriver;
myOutputDir = outputDir;
myStandardFileManager = standardFileManager;
myEncoding = encoding;
}
@Override
public Iterable<? extends JavaFileObject> getJavaFileObjectsFromFiles(Iterable<? extends File> files) {
int size = ((Collection)files).size();
List<JavaFileObject> result = new ArrayList<JavaFileObject>(size);
for (File file : files) {
JavaFileObject fileObject = new JavaIoFile(file, JavaFileObject.Kind.SOURCE, myEncoding);
result.add(fileObject);
}
return result;
}
@Override
public JavaFileObject getJavaFileForOutput(Location location, String name, JavaFileObject.Kind kind, FileObject fileObject) {
URI uri = toURI(myOutputDir, name, kind);
return new Output(uri, myCompAPIDriver, kind);
}
static URI createUri(String url) {
return URI.create(url.replaceAll(" ","%20"));
}
private static URI toURI(String outputDir, String name, JavaFileObject.Kind kind) {
return createUri("file:///" + outputDir.replace('\\','/') + "/" + name.replace('.', '/') + kind.extension);
}
@Override
public Iterable<JavaFileObject> list(Location location, String packageName, Set<JavaFileObject.Kind> kinds, boolean recurse) throws IOException {
if (recurse) {
throw new IllegalArgumentException();
}
return findInside(location, packageName, kinds, false);
}
private List<JavaFileObject> findInside(Location location, String packageName, Set<JavaFileObject.Kind> kinds, boolean lookForFile)
throws IOException {
Iterable<? extends File> path = getLocation(location);
if (path == null) return Collections.emptyList();
String subdirectory = packageName.replace('.', '/');
List<JavaFileObject> results = null;
for (File directory : path) {
VirtualFile dir = LocalFileSystem.getInstance().findFileByIoFile(directory);
if (dir == null) continue;
if (!dir.isDirectory()) {
dir = JarFileSystem.getInstance().getJarRootForLocalFile(dir);
if (dir == null) continue;
}
VirtualFile virtualFile = StringUtil.isEmptyOrSpaces(subdirectory) ? dir : dir.findFileByRelativePath(subdirectory);
if (virtualFile == null) continue;
VirtualFile[] children;
if (lookForFile) {
if (!virtualFile.isDirectory()) {
children = new VirtualFile[]{virtualFile};
}
else continue;
}
else {
children = virtualFile.getChildren();
}
for (VirtualFile child : children) {
JavaFileObject.Kind kind = getKind("." + child.getExtension());
if (kinds == null || kinds.contains(kind)) {
if (results == null) results = new SmartList<JavaFileObject>();
if (kind == JavaFileObject.Kind.SOURCE && child.getFileSystem() instanceof JarFileSystem) continue; //for some reasdon javac looks for java files inside jar
// use VFS to read content inside .jar
String childPath = child.getPath();
JavaFileObject fileObject = !childPath.contains("!/") ? new JavaIoFile(new File(childPath), kind, myEncoding) : new JavaVirtualFile(child, kind);
results.add(fileObject);
}
}
}
List<JavaFileObject> ret = results == null ? Collections.<JavaFileObject>emptyList() : results;
if (LOG.isDebugEnabled()) {
// for testing consistency
Collection c = (Collection)myStandardFileManager.list(location, packageName, kinds, false);
Collection<JavaFileObject> sup = new HashSet(c);
assert sup.size() == c.size();
assert new HashSet(c).equals(sup);
THashSet<JavaFileObject> s = new THashSet<JavaFileObject>(new TObjectHashingStrategy<JavaFileObject>() {
public int computeHashCode(JavaFileObject object) {
return object.getName().hashCode();
}
public boolean equals(JavaFileObject o1, JavaFileObject o2) {
return o1.getKind() == o2.getKind() && o1.toUri().equals(o2.toUri());
}
});
s.addAll(ret);
s.removeAll(sup);
if (ret.size() != sup.size()) {
assert false : "our implementation differs from javac'";
}
}
return ret;
}
private static JavaFileObject.Kind getKind(String name) {
if (name.endsWith(JavaFileObject.Kind.CLASS.extension))
return JavaFileObject.Kind.CLASS;
else if (name.endsWith(JavaFileObject.Kind.SOURCE.extension))
return JavaFileObject.Kind.SOURCE;
else if (name.endsWith(JavaFileObject.Kind.HTML.extension))
return JavaFileObject.Kind.HTML;
else
return JavaFileObject.Kind.OTHER;
}
@Override
public String inferBinaryName(Location location, JavaFileObject file) {
return FileUtil.getNameWithoutExtension(new File(file.getName()).getName());
}
////////// delegates
@Override
public int isSupportedOption(String option) {
return myStandardFileManager.isSupportedOption(option);
}
@Override
public void close() throws IOException {
myStandardFileManager.close();
}
@Override
public void flush() throws IOException {
myStandardFileManager.flush();
}
@Override
public boolean handleOption(String current, Iterator<String> remaining) {
return myStandardFileManager.handleOption(current, remaining);
}
@Override
public ClassLoader getClassLoader(Location location) {
return myStandardFileManager.getClassLoader(location);
}
@Override
public boolean isSameFile(FileObject a, FileObject b) {
if (a instanceof FileVirtualObject && b instanceof FileVirtualObject || a instanceof Output && b instanceof Output) {
return a.equals(b);
}
return myStandardFileManager.isSameFile(a, b);
}
public Iterable<? extends JavaFileObject> getJavaFileObjects(File... files) {
return getJavaFileObjectsFromFiles(Arrays.asList(files));
}
public Iterable<? extends JavaFileObject> getJavaFileObjects(String... names) {
return getJavaFileObjectsFromStrings(Arrays.asList(names));
}
public Iterable<? extends JavaFileObject> getJavaFileObjectsFromStrings(Iterable<String> names) {
ListBuffer<File> files = new ListBuffer<File>();
for (String name : names) {
files.append(new File(name));
}
return getJavaFileObjectsFromFiles(files.toList());
}
public JavaFileObject getJavaFileForInput(Location location, String className, JavaFileObject.Kind kind) throws IOException {
List<JavaFileObject> result = findInside(location, className, kind == null ? null : Collections.singleton(kind), true);
if (!result.isEmpty()) {
return result.get(0);
}
return null;
}
@Override
public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
return getJavaFileForInput(location, packageName + "/" + relativeName, getKind(relativeName));
}
@Override
public FileObject getFileForOutput(Location location, String packageName, String relativeName, FileObject sibling) throws IOException {
return getJavaFileForOutput(location, packageName + "/" + relativeName, getKind(relativeName), null);
}
@Override
public Iterable<? extends File> getLocation(Location location) {
return myStandardFileManager.getLocation(location);
}
@Override
public void setLocation(Location location, Iterable<? extends File> path) throws IOException {
myStandardFileManager.setLocation(location, path);
}
@Override
public boolean hasLocation(Location location) {
return myStandardFileManager.hasLocation(location);
}
}
@@ -1,80 +0,0 @@
/*
* Copyright 2000-2010 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.javaCompiler.api;
import org.jetbrains.annotations.Nullable;
import javax.tools.*;
import java.io.*;
import java.net.URI;
/**
* User: cdr
*/
@SuppressWarnings({"ALL"})
class Output extends SimpleJavaFileObject {
private final CompAPIDriver myCompAPIDriver;
@Nullable
private volatile byte[] myFileBytes;
Output(URI uri, CompAPIDriver compAPIDriver, final Kind kind) {
super(uri, kind);
myCompAPIDriver = compAPIDriver;
}
@Override
public ByteArrayOutputStream openOutputStream() {
return new ByteArrayOutputStream() {
@Override
public void close() throws IOException {
super.close();
final byte[] bytes = toByteArray();
myFileBytes = bytes;
if (Kind.CLASS.equals(kind)) {
myCompAPIDriver.offerClassFile(toUri(), bytes);
}
}
};
}
@Override
public InputStream openInputStream() throws IOException {
final byte[] bytes = myFileBytes;
if (bytes == null) {
throw new FileNotFoundException(toUri().getPath());
}
return new ByteArrayInputStream(bytes);
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
final byte[] bytes = myFileBytes;
if (bytes == null) {
throw null;
}
return new String(bytes);
}
@Override
public int hashCode() {
return toUri().hashCode();
}
@Override
public boolean equals(Object obj) {
return obj instanceof JavaFileObject && toUri().equals(((JavaFileObject)obj).toUri());
}
}
@@ -15,43 +15,24 @@
*/
package com.intellij.compiler.impl.javaCompiler.eclipse;
import com.intellij.compiler.OutputParser;
import com.intellij.compiler.impl.CompilerUtil;
import com.intellij.compiler.impl.javaCompiler.ExternalCompiler;
import com.intellij.compiler.impl.javaCompiler.ModuleChunk;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.compiler.impl.javaCompiler.BackendCompiler;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.compiler.CompileScope;
import com.intellij.openapi.compiler.CompilerBundle;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.JavaSdkType;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.ThrowableComputable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.java.compiler.EclipseCompilerOptions;
import org.jetbrains.jps.model.java.compiler.JavaCompilers;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
public class EclipseCompiler extends ExternalCompiler {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.javaCompiler.eclipse.EclipseCompiler");
import java.io.File;
import java.io.FilenameFilter;
import java.util.Collections;
import java.util.Set;
public class EclipseCompiler implements BackendCompiler {
private final Project myProject;
private final List<File> myTempFiles = new ArrayList<File>();
private static final String COMPILER_CLASS_NAME = "org.eclipse.jdt.core.compiler.batch.BatchCompiler";
@NonNls private static final String PATH_TO_COMPILER_JAR = findJarPah();
@@ -84,24 +65,6 @@ public class EclipseCompiler extends ExternalCompiler {
return file.exists();
}
public boolean checkCompiler(final CompileScope scope) {
if (!isInitialized()) {
Messages.showMessageDialog(
myProject,
CompilerBundle.message("eclipse.compiler.error.jar.not.found", PATH_TO_COMPILER_JAR),
CompilerBundle.message("compiler.eclipse.name"),
Messages.getErrorIcon()
);
return false;
}
return true;
}
@NonNls
public static String getCompilerClass() {
return "org.eclipse.jdt.internal.compiler.batch.Main";
}
@NotNull
public String getId() { // used for externalization
return JavaCompilers.ECLIPSE_ID;
@@ -117,116 +80,9 @@ public class EclipseCompiler extends ExternalCompiler {
return new EclipseCompilerConfigurable(EclipseCompilerConfiguration.getOptions(myProject, EclipseCompilerConfiguration.class));
}
public OutputParser createErrorParser(@NotNull final String outputDir, Process process) {
return new EclipseCompilerErrorParser();
}
@Nullable
public OutputParser createOutputParser(@NotNull final String outputDir) {
return new EclipseCompilerOutputParser(outputDir);
}
@NotNull
public String[] createStartupCommand(final ModuleChunk chunk, final CompileContext context, final String outputPath)
throws IOException {
final ArrayList<String> commandLine = new ArrayList<String>();
ApplicationManager.getApplication().runReadAction(new ThrowableComputable<Void, IOException>() {
@Override
public Void compute() throws IOException {
createStartupCommand(chunk, commandLine, outputPath, true);
return null;
}
});
return ArrayUtil.toStringArray(commandLine);
}
private void createStartupCommand(final ModuleChunk chunk,
@NonNls final ArrayList<String> commandLine,
final String outputPath,
final boolean useTempFile) throws IOException {
final EclipseCompilerOptions options = EclipseCompilerConfiguration.getOptions(myProject, EclipseCompilerConfiguration.class);
final Sdk projectJdk = JavaAwareProjectJdkTableImpl.getInstanceEx().getInternalJdk();
final String vmExePath = ((JavaSdkType)projectJdk.getSdkType()).getVMExecutablePath(projectJdk);
commandLine.add(vmExePath);
commandLine.add("-Xmx" + options.MAXIMUM_HEAP_SIZE + "m");
CompilerUtil.addLocaleOptions(commandLine, false);
commandLine.add("-classpath");
commandLine.add(PATH_TO_COMPILER_JAR);
commandLine.add(getCompilerClass());
addCommandLineOptions(commandLine, chunk, outputPath, options, useTempFile, true);
}
public void addCommandLineOptions(@NotNull @NonNls final List<String> commandLine,
@NotNull final ModuleChunk chunk,
@NotNull final String outputPath,
@NotNull final EclipseCompilerOptions options,
final boolean useTempFile,
boolean quoteBootClasspath) throws IOException {
final Sdk jdk = chunk.getJdk();
CompilerUtil.addSourceCommandLineSwitch(jdk, chunk.getLanguageLevel(), commandLine);
CompilerUtil.addTargetCommandLineSwitch(chunk, commandLine);
final String bootCp = chunk.getCompilationBootClasspath();
final String classPath = chunk.getCompilationClasspath();
if (!StringUtil.isEmpty(bootCp)) {
commandLine.add("-bootclasspath");
// important: need to quote boot classpath if path to jdk contain spaces
commandLine.add(quoteBootClasspath ? CompilerUtil.quotePath(bootCp) : bootCp);
}
if (!StringUtil.isEmpty(classPath)) {
commandLine.add("-classpath");
commandLine.add(classPath);
}
commandLine.add("-d");
commandLine.add(outputPath.replace('/', File.separatorChar));
commandLine.add("-verbose");
StringTokenizer tokenizer = new StringTokenizer(new EclipseSettingsBuilder(options).getOptionsString(chunk), " ");
while (tokenizer.hasMoreTokens()) {
commandLine.add(tokenizer.nextToken());
}
final List<VirtualFile> files = chunk.getFilesToCompile();
if (useTempFile) {
File sourcesFile = FileUtil.createTempFile("javac", ".tmp");
sourcesFile.deleteOnExit();
myTempFiles.add(sourcesFile);
final PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(sourcesFile)));
try {
for (final VirtualFile file : files) {
// Important: should use "/" slashes!
// but not for JDK 1.5 - see SCR 36673
final String path = file.getPath().replace('/', File.separatorChar);
if (LOG.isDebugEnabled()) {
LOG.debug("Adding path for compilation " + path);
}
writer.println(CompilerUtil.quotePath(path));
}
}
finally {
writer.close();
}
commandLine.add("@" + sourcesFile.getAbsolutePath());
}
else {
for (VirtualFile file : files) {
commandLine.add(file.getPath());
}
}
}
public void compileFinished() {
FileUtil.asyncDelete(myTempFiles);
myTempFiles.clear();
@Override
public Set<FileType> getCompilableFileTypes() {
return Collections.<FileType>singleton(StdFileTypes.JAVA);
}
}
@@ -1,255 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author Alexey
*/
package com.intellij.compiler.impl.javaCompiler.eclipse;
import com.intellij.compiler.OutputParser;
import com.intellij.compiler.impl.javaCompiler.FileObject;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.compiler.CompilerBundle;
import com.intellij.openapi.compiler.CompilerMessageCategory;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.compiler.InvalidInputException;
import org.eclipse.jdt.internal.compiler.*;
import org.eclipse.jdt.internal.compiler.Compiler;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.batch.CompilationUnit;
import org.eclipse.jdt.internal.compiler.batch.FileSystem;
import org.eclipse.jdt.internal.compiler.batch.Main;
import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class EclipseCompilerDriver {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.javaCompiler.eclipse.EclipseCompilerDriver");
private String[] sourceFilePaths;
private Map compilerOptions;
private final BlockingQueue<CompilationResult> myCompilationResults = new LinkedBlockingQueue<CompilationResult>();
private FileSystem classPath;
private void parseCommandLine(String[] args) throws InvalidInputException {
StringWriter err = new StringWriter();
Main driver = new Main(null, new PrintWriter(err), false);
driver.configure(args);
StringBuffer buffer = err.getBuffer();
if (buffer.length() != 0) {
throw new InvalidInputException(buffer.toString());
}
sourceFilePaths = driver.filenames;
compilerOptions = driver.options;
classPath = driver.getLibraryAccess();
}
private CompilationUnit[] getCompilationUnits() {
int fileCount = sourceFilePaths.length;
CompilationUnit[] units = new CompilationUnit[fileCount];
final String defaultEncoding = null;
for (int i = 0; i < fileCount; i++) {
units[i] = new MyCompilationUnit(sourceFilePaths[i], defaultEncoding);
}
return units;
}
private ICompilerRequestor getBatchRequestor(final CompileContext compileContext) {
return new ICompilerRequestor() {
public void acceptResult(CompilationResult compilationResult) {
ProgressIndicator progress = compileContext.getProgressIndicator();
if (progress != null) {
progress.checkCanceled();
}
myCompilationResults.offer(compilationResult);
}
};
}
private static final CompilationResult END_OF_STREAM = new CompilationResult(new char[0], 0, 0, 0);
private INameEnvironment getEnvironment() {
return classPath;
}
private static IProblemFactory getProblemFactory() {
return new DefaultProblemFactory(Locale.getDefault());
}
private static IErrorHandlingPolicy getHandlingPolicy() {
return new IErrorHandlingPolicy() {
public boolean proceedOnErrors() {
return false; // stop if there are some errors
}
public boolean stopOnFirstError() {
return false;
}
};
}
private Map getCompilerOptions() {
return compilerOptions;
}
private void compile(final CompileContext compileContext) {
final INameEnvironment environment = getEnvironment();
Compiler compiler =
new Compiler(
environment,
getHandlingPolicy(),
getCompilerOptions(),
getBatchRequestor(compileContext),
getProblemFactory()){
protected void handleInternalException(Throwable internalException, CompilationUnitDeclaration unit, CompilationResult result) {
if (internalException instanceof ProcessCanceledException) throw (ProcessCanceledException)internalException;
super.handleInternalException(internalException, unit, result);
}
};
compiler.parseThreshold = 2500;
try {
compiler.compile(getCompilationUnits());
}
catch (ProcessCanceledException e) {
//compileContext.addMessage(CompilerMessageCategory.ERROR, "Canceled",null,-1,-1);
}
catch (Exception e) {
ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
if (indicator == null || !indicator.isCanceled()) {
compileContext.addMessage(CompilerMessageCategory.ERROR, "Internal Error: "+e.toString(),null,-1,-1);
}
}
finally {
myCompilationResults.offer(END_OF_STREAM);
environment.cleanup();
}
}
public boolean processMessageLine(final OutputParser.Callback callback, final String outputDir, Project project) {
ProgressManager.checkCanceled();
CompilationResult result;
try {
result = myCompilationResults.take();
}
catch (InterruptedException e) {
LOG.error(e);
return true;
}
if (result == END_OF_STREAM) {
return false;
}
String file = String.valueOf(result.getFileName());
callback.setProgressText(CompilerBundle.message("eclipse.compiler.parsing", file));
callback.fileProcessed(file);
ClassFile[] classFiles = result.getClassFiles();
for (ClassFile classFile : classFiles) {
String filePath = String.valueOf(classFile.fileName());
String relativePath = FileUtil.toSystemDependentName(filePath + ".class");
String path = FileUtil.toSystemDependentName(outputDir) + File.separatorChar + relativePath;
byte[] bytes = classFile.getBytes();
File out = new File(path);
callback.fileGenerated(new FileObject(out,bytes));
}
IProblem[] problems = result.getProblems();
if (problems != null) {
for (IProblem problem : problems) {
CompilerMessageCategory category = problem.isError() ? CompilerMessageCategory.ERROR
: problem.isWarning() ? CompilerMessageCategory.WARNING :
CompilerMessageCategory.INFORMATION;
String filePath = String.valueOf(problem.getOriginatingFileName());
String url = VirtualFileManager.constructUrl(LocalFileSystem.PROTOCOL, FileUtil.toSystemIndependentName(filePath));
int lineNumber = problem.getSourceLineNumber();
int sourceStart = problem.getSourceStart();
int column = getColumn(url, lineNumber, sourceStart, project);
callback.message(category, problem.getMessage(), url, lineNumber, column);
}
}
return true;
}
private static int getColumn(final String url, final int lineNumber, final int sourceStart, final Project project) {
if (sourceStart == 0) return 0;
return ApplicationManager.getApplication().runReadAction(new Computable<Integer>() {
public Integer compute() {
VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(url);
if (file == null) return 0;
Document document = FileDocumentManager.getInstance().getDocument(file);
if (document == null) return 0;
int lineStartOffset = document.getLineStartOffset(lineNumber - 1);
String lineSeparator = FileDocumentManager.getInstance().getLineSeparator(file, project);
int offsetInVirtualFile = sourceStart - (lineNumber - 1) * (lineSeparator.length() - 1);
return offsetInVirtualFile - lineStartOffset + 1;
}
}).intValue();
}
public void parseCommandLineAndCompile(final String[] finalCmds, final CompileContext compileContext) throws Exception {
parseCommandLine(finalCmds);
compile(compileContext);
}
private static class MyCompilationUnit extends CompilationUnit {
private final String myDefaultEncoding;
private MyCompilationUnit(final String sourceFilePath, final String defaultEncoding) {
super(null, sourceFilePath, defaultEncoding);
myDefaultEncoding = defaultEncoding;
}
public char[] getContents() {
final String fileName = String.valueOf(getFileName());
try {
ProgressManager.checkCanceled();
return FileUtil.loadFileText(new File(fileName), myDefaultEncoding);
}
catch (IOException e) {
LOG.error(e);
}
return null;
}
}
}
@@ -1,131 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.javaCompiler.eclipse;
import com.intellij.compiler.OutputParser;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.CompilerMessageCategory;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import org.jetbrains.annotations.NonNls;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class EclipseCompilerErrorParser extends OutputParser {
private final StringBuilder problemText = new StringBuilder();
public boolean processMessageLine(Callback callback) {
@NonNls String line = callback.getNextLine();
if (line == null) {
spitOutProblem(callback);
return false;
}
if (line.trim().length() == 0) {
return true;
}
if (line.equals("----------")) {
spitOutProblem(callback);
problemText.setLength(0);
return true;
}
problemText.append(line);
problemText.append("\n");
return true;
}
private void spitOutProblem(final Callback callback) {
final String problem = problemText.toString();
if (problem.trim().length() == 0) return;
@NonNls final String problemTemplate = "(\\d*)\\. (\\w*) in (.*)" +
"\\s*\\(at line (\\d*)\\)\n" +
"\\s*(.*)\n" +
"(\\s*)\\^+\n" +
"(.*)\\s*";
final Pattern PATTERN = Pattern.compile(problemTemplate, Pattern.DOTALL);
Matcher matcher = PATTERN.matcher(problem);
if (matcher.matches()) {
//String seqN = matcher.group(1);
@NonNls String problemType = matcher.group(2);
String path = matcher.group(3).trim();
String lineNum = matcher.group(4);
String codeSnippet = matcher.group(5);
String indentWhiteSpace = matcher.group(6);
String message = matcher.group(7).trim();
CompilerMessageCategory messageCategory;
if ("WARNING".equals(problemType)) {
messageCategory = CompilerMessageCategory.WARNING;
}
else if ("ERROR".equals(problemType)) {
messageCategory = CompilerMessageCategory.ERROR;
}
else {
messageCategory = CompilerMessageCategory.INFORMATION;
}
final String url = VirtualFileManager.constructUrl(LocalFileSystem.PROTOCOL, FileUtil.toSystemIndependentName(path));
final int line = Integer.parseInt(lineNum);
int col = indentWhiteSpace.length();
final String offendingCode = codeSnippet.substring(col-1);
// try to find similar text inside source file
int colFromFile = ApplicationManager.getApplication().runReadAction(new Computable<Integer>() {
public Integer compute() {
int index = -1;
VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(url);
Document document = file == null ? null : FileDocumentManager.getInstance().getDocument(file);
if (document != null) {
// line is one-based
int docLine = line == 0 ? 0 : line-1;
int startOffset = document.getLineStartOffset(docLine);
int endOffset = document.getLineEndOffset(docLine);
String lineText = document.getText().substring(startOffset, endOffset);
index = lineText.indexOf(offendingCode);
if (index == -1) {
for (index = 0; index < lineText.length(); index++) {
if (!Character.isWhitespace(lineText.charAt(index))) break;
}
if (index == lineText.length()) index = -1;
}
// to one-based
if (index != -1) {
index++;
}
}
return index;
}
}).intValue();
if (colFromFile != -1) {
col = colFromFile;
}
callback.message(messageCategory, message, url, line, col);
}
else {
callback.message(CompilerMessageCategory.WARNING, problem, null, -1, -1);
}
}
public boolean isTrimLines() {
return false;
}
}
@@ -1,90 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.javaCompiler.eclipse;
import com.intellij.compiler.OutputParser;
import com.intellij.compiler.impl.javaCompiler.FileObject;
import com.intellij.openapi.compiler.CompilerBundle;
import com.intellij.openapi.compiler.CompilerMessageCategory;
import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.annotations.NonNls;
import java.io.File;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class EclipseCompilerOutputParser extends OutputParser {
private final String myOutputDir;
public EclipseCompilerOutputParser(final String outputDir) {
myOutputDir = outputDir;
}
@NonNls private static final Pattern PATH_PATTERN = Pattern.compile("\\s*(.*) - #.*");
@NonNls private static final Pattern COMPILED_PATTERN = Pattern.compile("\\[\\d* unit(s)? compiled\\]");
@NonNls private static final Pattern GENERATED_PATTERN = Pattern.compile("\\[\\d* \\.class file(s)? generated\\]");
public boolean processMessageLine(Callback callback) {
@NonNls String line = callback.getNextLine();
if (line == null) {
return false;
}
if (line.trim().length() == 0) {
return true;
}
if (line.startsWith("[parsing ")) {
Matcher matcher = PATH_PATTERN.matcher(line.substring("[parsing ".length()));
matcher.matches();
String path = matcher.group(1);
callback.setProgressText(CompilerBundle.message("eclipse.compiler.parsing", path));
callback.fileProcessed(path);
return true;
}
if (line.startsWith("[reading ")) {
//StringTokenizer tokenizer = new StringTokenizer(line.substring("[reading ".length()), " ]");
//String fqn = tokenizer.nextToken();
callback.setProgressText(CompilerBundle.message("eclipse.compiler.reading"));
return true;
}
if (line.startsWith("[analyzing ")) {
Matcher matcher = PATH_PATTERN.matcher(line.substring("[analyzing ".length()));
matcher.matches();
String path = matcher.group(1);
callback.setProgressText(CompilerBundle.message("eclipse.compiler.analyzing", path));
return true;
}
if (line.startsWith("[completed ")) {
//Matcher matcher = PATH_PATTERN.matcher(line.substring("[completed ".length()));
//matcher.matches();
//String path = matcher.group(1);
//callback.setProgressText(CompilerBundle.message("eclipse.compiler.completed", path));
return true;
}
if (line.startsWith("[writing ")) {
Matcher matcher = PATH_PATTERN.matcher(line.substring("[writing ".length()));
matcher.matches();
String path = matcher.group(1);
String absPath = FileUtil.toSystemDependentName(myOutputDir + '/' + path);
//callback.setProgressText(CompilerBundle.message("eclipse.compiler.writing", absPath));
callback.fileGenerated(new FileObject(new File(absPath)));
return true;
}
if (COMPILED_PATTERN.matcher(line).matches() || GENERATED_PATTERN.matcher(line).matches()) {
return true;
}
callback.message(CompilerMessageCategory.INFORMATION, line, null, -1, -1);
return true;
}
}
@@ -1,155 +0,0 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.javaCompiler.eclipse;
import com.intellij.compiler.OutputParser;
import com.intellij.compiler.impl.javaCompiler.BackendCompiler;
import com.intellij.compiler.impl.javaCompiler.ModuleChunk;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.compiler.CompileScope;
import com.intellij.openapi.compiler.CompilerBundle;
import com.intellij.openapi.compiler.CompilerMessageCategory;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.ThrowableComputable;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.java.compiler.EclipseCompilerOptions;
import org.jetbrains.jps.model.java.compiler.JavaCompilers;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Set;
public class EclipseEmbeddedCompiler implements BackendCompiler {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.javaCompiler.eclipse.EclipseEmbeddedCompiler");
private final Project myProject;
private final EclipseCompiler myEclipseExternalCompiler;
private int myExitCode;
private final EclipseCompilerDriver myEclipseCompilerDriver;
private static final Set<FileType> COMPILABLE_TYPES = Collections.<FileType>singleton(StdFileTypes.JAVA);
public EclipseEmbeddedCompiler(Project project) {
myProject = project;
myEclipseExternalCompiler = new EclipseCompiler(project);
myEclipseCompilerDriver = new EclipseCompilerDriver();
}
public boolean checkCompiler(final CompileScope scope) {
return myEclipseCompilerDriver != null && myEclipseExternalCompiler.checkCompiler(scope);
}
@NotNull
@NonNls
public String getId() { // used for externalization
return JavaCompilers.ECLIPSE_EMBEDDED_ID;
}
@NotNull
public String getPresentableName() {
return CompilerBundle.message("compiler.eclipse.embedded.name");
}
@NotNull
public Configurable createConfigurable() {
return new EclipseCompilerConfigurable(EclipseEmbeddedCompilerConfiguration.getOptions(myProject, EclipseEmbeddedCompilerConfiguration.class));
}
@NotNull
public Set<FileType> getCompilableFileTypes() {
return COMPILABLE_TYPES;
}
@Nullable
public OutputParser createErrorParser(@NotNull final String outputDir, Process process) {
return new OutputParser() {
public boolean processMessageLine(Callback callback) {
return myEclipseCompilerDriver.processMessageLine(callback, outputDir, myProject);
}
};
}
@Nullable
public OutputParser createOutputParser(@NotNull final String outputDir) {
return null;
}
public void compileFinished() {
}
@NotNull
public Process launchProcess(@NotNull final ModuleChunk chunk, @NotNull final String outputDir, @NotNull final CompileContext compileContext) throws IOException {
@NonNls final ArrayList<String> commandLine = new ArrayList<String>();
ApplicationManager.getApplication().runReadAction(new ThrowableComputable<Void, IOException>() {
@Override
public Void compute() throws IOException {
final EclipseCompilerOptions options =
EclipseCompilerConfiguration.getOptions(myProject, EclipseEmbeddedCompilerConfiguration.class);
myEclipseExternalCompiler.addCommandLineOptions(commandLine, chunk, outputDir, options, false, false);
return null;
}
});
return new Process() {
public OutputStream getOutputStream() {
throw new UnsupportedOperationException();
}
public InputStream getInputStream() {
return null;
}
public InputStream getErrorStream() {
return null;
}
public void destroy() {
}
public int waitFor() {
try {
commandLine.remove("-verbose");
String[] finalCmds = ArrayUtil.toStringArray(commandLine);
myEclipseCompilerDriver.parseCommandLineAndCompile(finalCmds, compileContext);
myExitCode = 0;
return myExitCode;
}
catch (Exception e) {
compileContext.addMessage(CompilerMessageCategory.ERROR, e.getMessage(), null, -1, -1);
LOG.info(e);
myExitCode = -1;
return -1;
}
}
public int exitValue() {
return myExitCode;
}
};
}
}
@@ -1,31 +0,0 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.javaCompiler.eclipse;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.components.StoragePathMacros;
import com.intellij.openapi.components.StorageScheme;
@State(
name = "EclipseEmbeddedCompilerSettings",
storages = {
@Storage(file = StoragePathMacros.PROJECT_FILE),
@Storage(file = StoragePathMacros.PROJECT_CONFIG_DIR + "/compiler.xml", scheme = StorageScheme.DIRECTORY_BASED)
}
)
public class EclipseEmbeddedCompilerConfiguration extends EclipseCompilerConfiguration {
}
@@ -16,14 +16,12 @@
package com.intellij.compiler.impl.javaCompiler.javac;
import com.intellij.compiler.OutputParser;
import com.intellij.compiler.impl.javaCompiler.FileObject;
import com.intellij.openapi.compiler.CompilerBundle;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.fileTypes.StdFileTypes;
import java.io.File;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -59,7 +57,7 @@ public class FilePathActionJavac extends JavacParserAction {
callback.setProgressText(CompilerBundle.message("progress.parsing.file", name));
}
else if (StdFileTypes.CLASS.equals(fileType)) {
callback.fileGenerated(new FileObject(new File(filePath)));
callback.fileGenerated(filePath);
}
}
}
@@ -15,122 +15,26 @@
*/
package com.intellij.compiler.impl.javaCompiler.javac;
import com.intellij.compiler.CompilerConfiguration;
import com.intellij.compiler.CompilerConfigurationImpl;
import com.intellij.compiler.CompilerIOUtil;
import com.intellij.compiler.OutputParser;
import com.intellij.compiler.impl.CompilerUtil;
import com.intellij.compiler.impl.javaCompiler.ExternalCompiler;
import com.intellij.compiler.impl.javaCompiler.ModuleChunk;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.compiler.CompileScope;
import com.intellij.compiler.impl.javaCompiler.BackendCompiler;
import com.intellij.openapi.compiler.CompilerBundle;
import com.intellij.openapi.compiler.CompilerPaths;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.*;
import com.intellij.openapi.projectRoots.ex.JavaSdkUtil;
import com.intellij.openapi.projectRoots.impl.MockJdkWrapper;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.rt.compiler.JavacRunner;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.model.java.compiler.AnnotationProcessingConfiguration;
import org.jetbrains.jps.model.java.compiler.JavaCompilers;
import org.jetbrains.jps.model.java.compiler.JpsJavaCompilerOptions;
import java.io.*;
import java.util.*;
import java.util.Collections;
import java.util.Set;
public class JavacCompiler extends ExternalCompiler {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.javaCompiler.javac.JavacCompiler");
public class JavacCompiler implements BackendCompiler {
private final Project myProject;
private final List<File> myTempFiles = new ArrayList<File>();
@NonNls private static final String JAVAC_MAIN_CLASS_OLD = "sun.tools.javac.Main";
@NonNls public static final String JAVAC_MAIN_CLASS = "com.sun.tools.javac.Main";
private boolean myAnnotationProcessorMode = false;
public JavacCompiler(Project project) {
myProject = project;
}
public boolean isAnnotationProcessorMode() {
return myAnnotationProcessorMode;
}
/**
* @param annotationProcessorMode
* @return previous value
*/
public boolean setAnnotationProcessorMode(boolean annotationProcessorMode) {
final boolean oldValue = myAnnotationProcessorMode;
myAnnotationProcessorMode = annotationProcessorMode;
return oldValue;
}
public boolean checkCompiler(final CompileScope scope) {
final Module[] modules = scope.getAffectedModules();
final Set<Sdk> checkedJdks = new HashSet<Sdk>();
for (final Module module : modules) {
final Sdk jdk = ModuleRootManager.getInstance(module).getSdk();
if (jdk == null || checkedJdks.contains(jdk)) {
continue;
}
checkedJdks.add(jdk);
final SdkTypeId sdkType = jdk.getSdkType();
if (!(sdkType instanceof JavaSdkType)) {
continue;
}
final VirtualFile homeDirectory = jdk.getHomeDirectory();
if (homeDirectory == null) {
Messages.showMessageDialog(
myProject, CompilerBundle.jdkHomeNotFoundMessage(jdk), CompilerBundle.message("compiler.javac.name"), Messages.getErrorIcon()
);
return false;
}
final String vmExecutablePath = ((JavaSdkType)sdkType).getVMExecutablePath(jdk);
if (vmExecutablePath == null) {
Messages.showMessageDialog(
myProject, CompilerBundle.message("javac.error.vm.executable.missing", jdk.getName()), CompilerBundle.message("compiler.javac.name"), Messages.getErrorIcon()
);
return false;
}
final String toolsJarPath = ((JavaSdkType)sdkType).getToolsPath(jdk);
if (toolsJarPath == null) {
Messages.showMessageDialog(
myProject, CompilerBundle.message("javac.error.tools.jar.missing", jdk.getName()), CompilerBundle.message("compiler.javac.name"), Messages.getErrorIcon()
);
return false;
}
final String versionString = jdk.getVersionString();
if (versionString == null) {
Messages.showMessageDialog(
myProject, CompilerBundle.message("javac.error.unknown.jdk.version", jdk.getName()), CompilerBundle.message("compiler.javac.name"), Messages.getErrorIcon()
);
return false;
}
if (CompilerUtil.isOfVersion(versionString, "1.0")) {
Messages.showMessageDialog(
myProject, CompilerBundle.message("javac.error.1_0_compilation.not.supported"), CompilerBundle.message("compiler.javac.name"), Messages.getErrorIcon()
);
return false;
}
}
return true;
}
@NotNull
@NonNls
public String getId() { // used for externalization
@@ -147,304 +51,8 @@ public class JavacCompiler extends ExternalCompiler {
return new JavacConfigurable(JavacConfiguration.getOptions(myProject, JavacConfiguration.class));
}
public OutputParser createErrorParser(@NotNull final String outputDir, Process process) {
return new JavacOutputParser(myProject);
}
public OutputParser createOutputParser(@NotNull final String outputDir) {
return null;
}
private static class MyException extends RuntimeException {
private MyException(Throwable cause) {
super(cause);
}
}
@NotNull
public String[] createStartupCommand(final ModuleChunk chunk, final CompileContext context, final String outputPath)
throws IOException, IllegalArgumentException {
try {
return ApplicationManager.getApplication().runReadAction(new Computable<String[]>() {
public String[] compute() {
try {
final List<String> commandLine = new ArrayList<String>();
createStartupCommand(chunk, commandLine, outputPath, JavacConfiguration.getOptions(myProject, JavacConfiguration.class), context.isAnnotationProcessorsEnabled());
return ArrayUtil.toStringArray(commandLine);
}
catch (IOException e) {
throw new MyException(e);
}
}
});
}
catch (MyException e) {
Throwable cause = e.getCause();
if (cause instanceof IOException) {
throw (IOException)cause;
}
throw e;
}
}
private void createStartupCommand(final ModuleChunk chunk, @NonNls final List<String> commandLine, final String outputPath,
JpsJavaCompilerOptions javacOptions, final boolean annotationProcessorsEnabled) throws IOException {
final Sdk jdk = getJdkForStartupCommand(chunk);
final String versionString = jdk.getVersionString();
JavaSdkVersion version = JavaSdk.getInstance().getVersion(jdk);
if (versionString == null || version == null || !(jdk.getSdkType() instanceof JavaSdkType)) {
throw new IllegalArgumentException(CompilerBundle.message("javac.error.unknown.jdk.version", jdk.getName()));
}
final boolean isVersion1_0 = version == JavaSdkVersion.JDK_1_0;
final boolean isVersion1_1 = version == JavaSdkVersion.JDK_1_1;
JavaSdkType sdkType = (JavaSdkType)jdk.getSdkType();
final String toolsJarPath = sdkType.getToolsPath(jdk);
if (toolsJarPath == null) {
throw new IllegalArgumentException(CompilerBundle.message("javac.error.tools.jar.missing", jdk.getName()));
}
final String vmExePath = sdkType.getVMExecutablePath(jdk);
commandLine.add(vmExePath);
if (version.isAtLeast(JavaSdkVersion.JDK_1_2)) {
commandLine.add("-Xmx" + javacOptions.MAXIMUM_HEAP_SIZE + "m");
}
else {
commandLine.add("-mx" + javacOptions.MAXIMUM_HEAP_SIZE + "m");
}
final List<String> additionalOptions =
addAdditionalSettings(commandLine, javacOptions, myAnnotationProcessorMode, version, chunk, annotationProcessorsEnabled);
CompilerUtil.addLocaleOptions(commandLine, false);
commandLine.add("-classpath");
if (isVersion1_0) {
commandLine.add(sdkType.getToolsPath(jdk)); // do not use JavacRunner for jdk 1.0
}
else {
commandLine.add(sdkType.getToolsPath(jdk) + File.pathSeparator + JavaSdkUtil.getIdeaRtJarPath());
commandLine.add(JavacRunner.class.getName());
commandLine.add("\"" + versionString + "\"");
}
if (version.isAtLeast(JavaSdkVersion.JDK_1_3)) {
commandLine.add(JAVAC_MAIN_CLASS);
}
else {
commandLine.add(JAVAC_MAIN_CLASS_OLD);
}
addCommandLineOptions(chunk, commandLine, outputPath, jdk, isVersion1_0, isVersion1_1, myTempFiles, true, true, myAnnotationProcessorMode);
commandLine.addAll(additionalOptions);
final List<VirtualFile> files = chunk.getFilesToCompile();
if (isVersion1_0) {
for (VirtualFile file : files) {
String path = file.getPath();
if (LOG.isDebugEnabled()) {
LOG.debug("Adding path for compilation " + path);
}
commandLine.add(CompilerUtil.quotePath(path));
}
}
else {
File sourcesFile = FileUtil.createTempFile("javac", ".tmp");
sourcesFile.deleteOnExit();
myTempFiles.add(sourcesFile);
final PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(sourcesFile)));
try {
for (final VirtualFile file : files) {
// Important: should use "/" slashes!
// but not for JDK 1.5 - see SCR 36673
final String path = version.isAtLeast(JavaSdkVersion.JDK_1_5) ? file.getPath().replace('/', File.separatorChar) : file.getPath();
if (LOG.isDebugEnabled()) {
LOG.debug("Adding path for compilation " + path);
}
writer.println(isVersion1_1 ? path : CompilerUtil.quotePath(path));
}
}
finally {
writer.close();
}
commandLine.add("@" + sourcesFile.getAbsolutePath());
}
}
public static List<String> addAdditionalSettings(List<String> commandLine, JpsJavaCompilerOptions javacOptions, boolean isAnnotationProcessing,
JavaSdkVersion version, ModuleChunk chunk, boolean annotationProcessorsEnabled) {
final List<String> additionalOptions = new ArrayList<String>();
StringTokenizer tokenizer = new StringTokenizer(new JavacSettingsBuilder(javacOptions).getOptionsString(chunk), " ");
if (!version.isAtLeast(JavaSdkVersion.JDK_1_6)) {
isAnnotationProcessing = false; // makes no sense for these versions
annotationProcessorsEnabled = false;
}
if (isAnnotationProcessing) {
final AnnotationProcessingConfiguration config = CompilerConfiguration.getInstance(chunk.getProject()).getAnnotationProcessingConfiguration(chunk.getModules()[0]);
additionalOptions.add("-Xprefer:source");
additionalOptions.add("-implicit:none");
additionalOptions.add("-proc:only");
if (!config.isObtainProcessorsFromClasspath()) {
final String processorPath = config.getProcessorPath();
additionalOptions.add("-processorpath");
additionalOptions.add(FileUtil.toSystemDependentName(processorPath));
}
final Set<String> processors = config.getProcessors();
if (!processors.isEmpty()) {
additionalOptions.add("-processor");
additionalOptions.add(StringUtil.join(processors, ","));
}
for (Map.Entry<String, String> entry : config.getProcessorOptions().entrySet()) {
additionalOptions.add("-A" + entry.getKey() + "=" +entry.getValue());
}
}
else {
if (annotationProcessorsEnabled) {
// Unless explicitly specified by user, disable annotation processing by default for 'java compilation' mode
// This is needed to suppress unwanted side-effects from auto-discovered processors from compilation classpath
additionalOptions.add("-proc:none");
}
}
while (tokenizer.hasMoreTokens()) {
@NonNls String token = tokenizer.nextToken();
if (version == JavaSdkVersion.JDK_1_0 && "-deprecation".equals(token)) {
continue; // not supported for this version
}
if (!version.isAtLeast(JavaSdkVersion.JDK_1_5) && "-Xlint".equals(token)) {
continue; // not supported in these versions
}
if (isAnnotationProcessing) {
if (token.startsWith("-proc:")) {
continue;
}
if (token.startsWith("-implicit:")) {
continue;
}
}
else { // compiling java
if (annotationProcessorsEnabled) {
// in this mode we have -proc:none already added above, so user's settings should be ignored
if (token.startsWith("-proc:")) {
continue;
}
}
}
if (token.startsWith("-J-")) {
commandLine.add(token.substring("-J".length()));
}
else {
additionalOptions.add(token);
}
}
return additionalOptions;
}
public static void addCommandLineOptions(ModuleChunk chunk, @NonNls List<String> commandLine, String outputPath, Sdk jdk,
boolean version1_0,
boolean version1_1,
List<File> tempFiles, boolean addSourcePath, boolean useTempFile,
boolean isAnnotationProcessingMode) throws IOException {
LanguageLevel languageLevel = chunk.getLanguageLevel();
CompilerUtil.addSourceCommandLineSwitch(jdk, languageLevel, commandLine);
CompilerUtil.addTargetCommandLineSwitch(chunk, commandLine);
commandLine.add("-verbose");
final String cp = chunk.getCompilationClasspath();
final String bootCp = chunk.getCompilationBootClasspath();
final String classPath;
if (version1_0 || version1_1) {
classPath = bootCp + File.pathSeparator + cp;
}
else {
classPath = cp;
commandLine.add("-bootclasspath");
addClassPathValue(jdk, false, commandLine, bootCp, "javac_bootcp", tempFiles, useTempFile);
}
commandLine.add("-classpath");
addClassPathValue(jdk, version1_0, commandLine, classPath, "javac_cp", tempFiles, useTempFile);
if (!version1_1 && !version1_0 && addSourcePath) {
commandLine.add("-sourcepath");
// this way we tell the compiler that the sourcepath is "empty". However, javac thinks that sourcepath is 'new File("")'
// this may cause problems if we have java code in IDEA working directory
if (isAnnotationProcessingMode) {
final int currentSourcesMode = chunk.getSourcesFilter();
commandLine.add(chunk.getSourcePath(currentSourcesMode == ModuleChunk.TEST_SOURCES? ModuleChunk.ALL_SOURCES : currentSourcesMode));
}
else {
commandLine.add("\"\"");
}
}
if (isAnnotationProcessingMode) {
commandLine.add("-s");
commandLine.add(outputPath.replace('/', File.separatorChar));
final String moduleOutputPath = CompilerPaths.getModuleOutputPath(chunk.getModules()[0], false);
if (moduleOutputPath != null) {
commandLine.add("-d");
commandLine.add(moduleOutputPath.replace('/', File.separatorChar));
}
}
else {
commandLine.add("-d");
commandLine.add(outputPath.replace('/', File.separatorChar));
}
}
private static void addClassPathValue(final Sdk jdk, final boolean isVersion1_0, final List<String> commandLine, final String cpString, @NonNls final String tempFileName,
List<File> tempFiles,
boolean useTempFile) throws IOException {
if (!useTempFile) {
commandLine.add(cpString);
return;
}
// must include output path to classpath, otherwise javac will compile all dependent files no matter were they compiled before or not
if (isVersion1_0) {
commandLine.add(((JavaSdkType)jdk.getSdkType()).getToolsPath(jdk) + File.pathSeparator + cpString);
}
else {
File cpFile = FileUtil.createTempFile(tempFileName, ".tmp");
cpFile.deleteOnExit();
tempFiles.add(cpFile);
final DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(cpFile)));
try {
CompilerIOUtil.writeString(cpString, out);
}
finally {
out.close();
}
commandLine.add("@" + cpFile.getAbsolutePath());
}
}
private Sdk getJdkForStartupCommand(final ModuleChunk chunk) {
final Sdk jdk = chunk.getJdk();
if (ApplicationManager.getApplication().isUnitTestMode() && JavacConfiguration.getOptions(myProject, JavacConfiguration.class).isTestsUseExternalCompiler()) {
final String jdkHomePath = CompilerConfigurationImpl.getTestsExternalCompilerHome();
if (jdkHomePath == null) {
throw new IllegalArgumentException("[TEST-MODE] Cannot determine home directory for JDK to use javac from");
}
// when running under Mock JDK use VM executable from the JDK on which the tests run
return new MockJdkWrapper(jdkHomePath, jdk);
}
return jdk;
}
public void compileFinished() {
FileUtil.asyncDelete(myTempFiles);
myTempFiles.clear();
@NotNull
public Set<FileType> getCompilableFileTypes() {
return Collections.<FileType>singleton(StdFileTypes.JAVA);
}
}
@@ -277,7 +277,4 @@ public class JavacOutputParser extends OutputParser {
return Pattern.compile(regexp, Pattern.CASE_INSENSITIVE).matcher("");
}
public boolean isTrimLines() {
return false;
}
}
@@ -1,39 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.javaCompiler.javac;
import com.intellij.compiler.OutputParser;
import com.intellij.openapi.compiler.CompilerBundle;
import org.jetbrains.annotations.Nullable;
import java.util.regex.Matcher;
/**
* @author Eugene Zhuravlev
* Date: Sep 24, 2005
*/
public class StatisticsActionJavac extends JavacParserAction {
private final String myProgressMessageResourceKey;
public StatisticsActionJavac(final Matcher matcher, String progressMessageResourceKey) {
super(matcher);
myProgressMessageResourceKey = progressMessageResourceKey;
}
protected void doExecute(final String line, @Nullable String parsedData, final OutputParser.Callback callback) {
callback.setProgressText(CompilerBundle.message(myProgressMessageResourceKey));
}
}
@@ -1,231 +0,0 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.javaCompiler.jikes;
import com.intellij.compiler.CompilerConfiguration;
import com.intellij.compiler.CompilerConfigurationImpl;
import com.intellij.compiler.OutputParser;
import com.intellij.compiler.impl.CompilerUtil;
import com.intellij.compiler.impl.javaCompiler.BackendCompiler;
import com.intellij.compiler.impl.javaCompiler.ExternalCompiler;
import com.intellij.compiler.impl.javaCompiler.ModuleChunk;
import com.intellij.compiler.options.JavaCompilersTab;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.compiler.CompileScope;
import com.intellij.openapi.compiler.CompilerBundle;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.ThrowableComputable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.StringTokenizer;
public class JikesCompiler extends ExternalCompiler {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.JikesHandler");
private final Project myProject;
private File myTempFile;
public JikesCompiler(Project project) {
myProject = project;
}
public boolean checkCompiler(final CompileScope scope) {
String compilerPath = getCompilerPath();
if (StringUtil.isEmpty(compilerPath)) {
Messages.showMessageDialog(
myProject,
CompilerBundle.message("jikes.error.path.to.compiler.unspecified"), CompilerBundle.message("compiler.jikes.name"),
Messages.getErrorIcon()
);
openConfigurationDialog();
compilerPath = getCompilerPath(); // update path
if (StringUtil.isEmpty(compilerPath)) {
return false;
}
}
File file = new File(compilerPath);
if (!file.exists()) {
Messages.showMessageDialog(
myProject,
CompilerBundle.message("jikes.error.path.to.compiler.missing", compilerPath),
CompilerBundle.message("compiler.jikes.name"),
Messages.getErrorIcon()
);
openConfigurationDialog();
compilerPath = getCompilerPath(); // update path
if (StringUtil.isEmpty(compilerPath)) {
return false;
}
if (!new File(compilerPath).exists()) {
return false;
}
}
return true;
}
private void openConfigurationDialog() {
final CompilerConfigurationImpl configuration = (CompilerConfigurationImpl)CompilerConfiguration.getInstance(myProject);
final Collection<BackendCompiler> compilers = configuration.getRegisteredJavaCompilers();
final BackendCompiler defaultCompiler = configuration.getDefaultCompiler();
final JavaCompilersTab compilersTab = new JavaCompilersTab(myProject, compilers, defaultCompiler);
ShowSettingsUtil.getInstance().editConfigurable(myProject, compilersTab);
}
private String getCompilerPath() {
return JikesConfiguration.getOptions(myProject).JIKES_PATH.replace('/', File.separatorChar);
}
@NotNull
@NonNls
public String getId() // used for externalization
{
return "Jikes";
}
@NotNull
public String getPresentableName() {
return CompilerBundle.message("compiler.jikes.name");
}
@NotNull
public Configurable createConfigurable() {
return new JikesConfigurable(JikesConfiguration.getOptions(myProject));
}
public OutputParser createErrorParser(@NotNull final String outputDir, Process process) {
return new JikesOutputParser(myProject);
}
@Nullable
public OutputParser createOutputParser(@NotNull final String outputDir) {
return null;
}
@NotNull
public String[] createStartupCommand(final ModuleChunk chunk, final CompileContext context, final String outputPath)
throws IOException {
final ArrayList<String> commandLine = new ArrayList<String>();
ApplicationManager.getApplication().runReadAction(new ThrowableComputable<Void, IOException>() {
@Override
public Void compute() throws IOException {
_createStartupCommand(chunk, commandLine, outputPath);
return null;
}
});
return ArrayUtil.toStringArray(commandLine);
}
private void _createStartupCommand(final ModuleChunk chunk, final ArrayList<String> commandLine, @NotNull final String outputPath) throws IOException {
myTempFile = FileUtil.createTempFile("jikes", ".tmp");
myTempFile.deleteOnExit();
final List<VirtualFile> files = chunk.getFilesToCompile();
PrintWriter writer = new PrintWriter(new FileWriter(myTempFile));
try {
for (VirtualFile file : files) {
writer.println(file.getPath());
}
}
finally {
writer.close();
}
String compilerPath = getCompilerPath();
LOG.assertTrue(compilerPath != null, "No path to compiler configured");
commandLine.add(compilerPath);
//noinspection HardCodedStringLiteral
commandLine.add("-verbose");
//noinspection HardCodedStringLiteral
commandLine.add("-classpath");
// must include output path to classpath, otherwise javac will compile all dependent files no matter were they compiled before or not
commandLine.add(chunk.getCompilationBootClasspath() + File.pathSeparator + chunk.getCompilationClasspath());
setupSourceVersion(chunk, commandLine);
//noinspection HardCodedStringLiteral
commandLine.add("-sourcepath");
String sourcePath = chunk.getSourcePath();
if (sourcePath.length() > 0) {
commandLine.add(sourcePath);
}
else {
commandLine.add("\"\"");
}
//noinspection HardCodedStringLiteral
commandLine.add("-d");
commandLine.add(outputPath.replace('/', File.separatorChar));
JikesSettingsBuilder jikesSettings = new JikesSettingsBuilder(JikesConfiguration.getOptions(myProject));
StringTokenizer tokenizer = new StringTokenizer(jikesSettings.getOptionsString(chunk), " ");
while (tokenizer.hasMoreTokens()) {
commandLine.add(tokenizer.nextToken());
}
commandLine.add("@" + myTempFile.getAbsolutePath());
}
@SuppressWarnings({"HardCodedStringLiteral"})
private static void setupSourceVersion(final ModuleChunk chunk, final ArrayList<String> commandLine) {
final Sdk jdk = chunk.getJdk();
final String versionString = jdk.getVersionString();
final LanguageLevel applicableLanguageLevel = CompilerUtil.getApplicableLanguageLevel(versionString, chunk.getLanguageLevel());
if (applicableLanguageLevel.equals(LanguageLevel.JDK_1_5)) {
commandLine.add("-source");
commandLine.add("1.4"); // -source 1.5 not supported yet by jikes, so use the highest possible version
}
else if (applicableLanguageLevel.equals(LanguageLevel.JDK_1_4)) {
commandLine.add("-source");
commandLine.add("1.4");
}
}
public void compileFinished() {
if (myTempFile != null) {
FileUtil.delete(myTempFile);
myTempFile = null;
}
}
}
@@ -1,102 +0,0 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.javaCompiler.jikes;
import com.intellij.compiler.options.ComparingUtils;
import com.intellij.openapi.compiler.CompilerBundle;
import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.RawCommandLineEditor;
import org.jetbrains.jps.model.java.compiler.JikesCompilerOptions;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
/**
* @author Eugene Zhuravlev
* Date: Mar 30, 2004
*/
public class JikesConfigurable implements Configurable {
private JPanel myPanel;
private JCheckBox myCbDebuggingInfo;
private JCheckBox myCbDeprecation;
private JCheckBox myCbGenerateNoWarnings;
private RawCommandLineEditor myAdditionalOptionsField;
private TextFieldWithBrowseButton myPathField;
private final JikesCompilerOptions myJikesSettings;
public JikesConfigurable(JikesCompilerOptions jikesSettings) {
myJikesSettings = jikesSettings;
myPathField.getButton().addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor();
VirtualFile file = FileChooser.chooseFile(descriptor, myPathField, null, null);
if (file != null) {
myPathField.setText(file.getPath().replace('/', File.separatorChar));
}
}
});
myAdditionalOptionsField.setDialogCaption(CompilerBundle.message("java.compiler.option.additional.command.line.parameters"));
}
public String getDisplayName() {
return null;
}
public String getHelpTopic() {
return null;
}
public JComponent createComponent() {
return myPanel;
}
public boolean isModified() {
boolean isModified = false;
isModified |= ComparingUtils.isModified(myPathField, myJikesSettings.JIKES_PATH.replace('/', File.separatorChar));
isModified |= ComparingUtils.isModified(myCbDeprecation, myJikesSettings.DEPRECATION);
isModified |= ComparingUtils.isModified(myCbDebuggingInfo, myJikesSettings.DEBUGGING_INFO);
isModified |= ComparingUtils.isModified(myCbGenerateNoWarnings, myJikesSettings.GENERATE_NO_WARNINGS);
isModified |= ComparingUtils.isModified(myAdditionalOptionsField, myJikesSettings.ADDITIONAL_OPTIONS_STRING);
return isModified;
}
public void apply() throws ConfigurationException {
myJikesSettings.JIKES_PATH = myPathField.getText().trim().replace(File.separatorChar, '/');
myJikesSettings.DEPRECATION = myCbDeprecation.isSelected();
myJikesSettings.DEBUGGING_INFO = myCbDebuggingInfo.isSelected();
myJikesSettings.GENERATE_NO_WARNINGS = myCbGenerateNoWarnings.isSelected();
myJikesSettings.ADDITIONAL_OPTIONS_STRING = myAdditionalOptionsField.getText();
}
public void reset() {
myPathField.setText(myJikesSettings.JIKES_PATH.replace('/', File.separatorChar));
myCbDeprecation.setSelected(myJikesSettings.DEPRECATION);
myCbDebuggingInfo.setSelected(myJikesSettings.DEBUGGING_INFO);
myCbGenerateNoWarnings.setSelected(myJikesSettings.GENERATE_NO_WARNINGS);
myAdditionalOptionsField.setText(myJikesSettings.ADDITIONAL_OPTIONS_STRING);
}
public void disposeUIResources() {
}
}
@@ -1,46 +0,0 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.javaCompiler.jikes;
import com.intellij.openapi.components.*;
import com.intellij.openapi.project.Project;
import com.intellij.util.xmlb.XmlSerializerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.model.java.compiler.JikesCompilerOptions;
@State(
name = "JikesSettings",
storages = {
@Storage(file = StoragePathMacros.PROJECT_FILE),
@Storage(file = StoragePathMacros.PROJECT_CONFIG_DIR + "/compiler.xml", scheme = StorageScheme.DIRECTORY_BASED)
}
)
public class JikesConfiguration implements PersistentStateComponent<JikesCompilerOptions> {
private final JikesCompilerOptions mySettings = new JikesCompilerOptions();
@NotNull
public JikesCompilerOptions getState() {
return mySettings;
}
public void loadState(JikesCompilerOptions state) {
XmlSerializerUtil.copyBean(state, mySettings);
}
public static JikesCompilerOptions getOptions(Project project) {
return ServiceManager.getService(project, JikesConfiguration.class).getState();
}
}
@@ -1,101 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.compiler.impl.javaCompiler.jikes.JikesConfigurable">
<grid id="66887" binding="myPanel" layout-manager="GridLayoutManager" row-count="6" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="103" y="66" width="439" height="254"/>
</constraints>
<properties/>
<clientProperties>
<BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithIndent"/>
</clientProperties>
<border type="etched" title-resource-bundle="messages/CompilerBundle" title-key="jikes.options.group.title"/>
<children>
<component id="3d38f" class="javax.swing.JCheckBox" binding="myCbDebuggingInfo">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<margin top="5" left="2" bottom="2" right="2"/>
<selected value="true"/>
<text resource-bundle="messages/CompilerBundle" key="java.compiler.option.generate.debugging.info"/>
</properties>
</component>
<component id="90803" class="javax.swing.JCheckBox" binding="myCbGenerateNoWarnings">
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<margin top="2" left="2" bottom="2" right="3"/>
<selected value="true"/>
<text resource-bundle="messages/CompilerBundle" key="java.compiler.option.generate.no.warnings"/>
</properties>
</component>
<component id="8538e" class="javax.swing.JCheckBox" binding="myCbDeprecation">
<constraints>
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<margin top="2" left="2" bottom="5" right="2"/>
<selected value="true"/>
<text resource-bundle="messages/CompilerBundle" key="java.compiler.option.report.deprecated"/>
</properties>
</component>
<vspacer id="b6f66">
<constraints>
<grid row="5" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<grid id="31c1" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="415eb" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myPathField">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<component id="327dc" class="javax.swing.JLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="messages/CompilerBundle" key="jikes.option.path.to.executable"/>
</properties>
</component>
</children>
</grid>
<grid id="918d2" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="f8a80" class="javax.swing.JLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="messages/CompilerBundle" key="java.compiler.option.additional.command.line.parameters"/>
</properties>
</component>
<component id="479c2" class="com.intellij.ui.RawCommandLineEditor" binding="myAdditionalOptionsField">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
</children>
</grid>
</children>
</grid>
</form>
@@ -1,133 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.javaCompiler.jikes;
import com.intellij.compiler.OutputParser;
import com.intellij.openapi.compiler.CompilerMessageCategory;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFileManager;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.jps.model.java.compiler.JikesCompilerOptions;
import java.io.File;
import java.util.ArrayList;
import java.util.StringTokenizer;
public class JikesOutputParser extends OutputParser {
private final JikesCompilerOptions myJikesSettings;
@NonNls private static final String JAVA_FILE_MSG_TAIL = ".java:";
@NonNls private static final String CAUTION = "Caution";
@NonNls private static final String WARNING = "Warning";
@NonNls private static final String ERROR = "Error";
@NonNls private static final String SEMANTIC_WARNING = "Semantic Warning";
@NonNls private static final String SEMANTIC_ERROR = "Semantic Error";
@NonNls private static final String ENTER_TO_CONTINUE_REGEXP = ".*Enter\\s+to\\s+continue.*";
public JikesOutputParser(Project project) {
myJikesSettings = JikesConfiguration.getOptions(project);
myParserActions.add(new ParserActionJikes());
}
public boolean processMessageLine(Callback callback) {
if (super.processMessageLine(callback)) {
return true;
}
String line = callback.getCurrentLine();
if (line == null) {
return false;
}
if (line.length() == 0) {
return false;
}
//sae
if (myJikesSettings.IS_EMACS_ERRORS_MODE) {
String filePath = "";
final int tailIndex = line.indexOf(JAVA_FILE_MSG_TAIL);
if (tailIndex > 5) filePath = line.substring(0, tailIndex + 5);
filePath = filePath.replace(File.separatorChar, '/');
final String url = VirtualFileManager.constructUrl(LocalFileSystem.PROTOCOL, filePath);
if (tailIndex > 6) {
line = line.substring(tailIndex + 6);
int lineNum;
//second token = start line
StringTokenizer tokenizer = new StringTokenizer(line, ":");
//first token = filename
String token = tokenizer.nextToken();
try {
lineNum = Integer.parseInt(token);
}
catch (Exception e) {
addMessage(callback, CompilerMessageCategory.INFORMATION, line);
return true;
}
//thrd token = start column
token = tokenizer.nextToken();
int colNum;
try {
colNum = Integer.parseInt(token);
}
catch (Exception e) {
addMessage(callback, CompilerMessageCategory.INFORMATION, line);
return true;
}
//4,5 token = end line/column tmp not used
tokenizer.nextToken();
tokenizer.nextToken();
// 6 error type
CompilerMessageCategory category = CompilerMessageCategory.INFORMATION;
token = tokenizer.nextToken().trim();
if (CAUTION.equalsIgnoreCase(token)) {
category = CompilerMessageCategory.WARNING;
}
else if (WARNING.equalsIgnoreCase(token) || SEMANTIC_WARNING.equalsIgnoreCase(token)) { // Semantic errors/warnings were introduced in jikes 1.18
category = CompilerMessageCategory.WARNING;
}
else if (ERROR.equalsIgnoreCase(token) || SEMANTIC_ERROR.equalsIgnoreCase(token)) {
category = CompilerMessageCategory.ERROR;
}
String message = token;
message = message.concat(" ");
message = message.concat(tokenizer.nextToken(""));
ArrayList<String> messages = new ArrayList<String>();
messages.add(message);
if (colNum > 0 && messages.size() > 0) {
StringBuilder buf = new StringBuilder();
for (String m : messages) {
if (buf.length() > 0) {
buf.append("\n");
}
buf.append(m);
}
addMessage(callback, category, buf.toString(), url, lineNum, colNum);
return true;
}
}
}
//--sae
//Enter to continue
if (!line.matches(ENTER_TO_CONTINUE_REGEXP)) {
addMessage(callback, CompilerMessageCategory.INFORMATION, line);
}
return true;
}
}
@@ -1,50 +0,0 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.javaCompiler.jikes;
import com.intellij.compiler.impl.javaCompiler.javac.JavacSettingsBuilder;
import com.intellij.openapi.module.Module;
import com.intellij.util.Chunk;
import org.jetbrains.jps.model.java.compiler.JikesCompilerOptions;
import java.util.Collection;
public class JikesSettingsBuilder extends JavacSettingsBuilder {
public JikesSettingsBuilder(JikesCompilerOptions options) {
super(options);
}
@Override
public JikesCompilerOptions getOptions() {
return (JikesCompilerOptions)super.getOptions();
}
public Collection<String> getOptions(Chunk<Module> chunk) {
final Collection<String> options = super.getOptions(chunk);
if(getOptions().IS_EMACS_ERRORS_MODE) {
options.add("+E");
}
return options;
}
protected boolean acceptUserOption(String token) {
if (!super.acceptUserOption(token)) {
return false;
}
return !("++".equals(token) || "+M".equals(token) || "+F".equals(token) || "+E".equals(token));
}
}
@@ -1,88 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.javaCompiler.jikes;
import com.intellij.openapi.compiler.CompilerBundle;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.compiler.ParserAction;
import com.intellij.compiler.OutputParser;
import com.intellij.compiler.impl.javaCompiler.FileObject;
import org.jetbrains.annotations.NonNls;
import java.io.File;
/**
* This class provides compatibility with older javac(english locale) and jikes versions and
* implements parsing method from previous IDEA versions for jikes and javac compiler output.
* Used in order not to miss some compiler output messages when jikes is configured as a preferred compiler
* Also used in test mode in which javac is not run via JavacRunner
*
* @author Eugene Zhuravlev
* Date: Sep 24, 2005
*/
public class ParserActionJikes extends ParserAction {
@NonNls private static final String JAVA_EXTENSION = ".java";
public boolean execute(@NonNls String line, final OutputParser.Callback callback) {
if (!StringUtil.startsWithChar(line, '[') || !StringUtil.endsWithChar(line, ']')) {
return false;
}
if (line.startsWith("[parsing started")){ // javac
String filePath = line.substring("[parsing started".length(), line.length() - 1).trim();
processParsingMessage(callback, filePath.replace(File.separatorChar, '/'));
}
else if (line.startsWith("[parsed") && line.contains(JAVA_EXTENSION)) { // javac version 1.2.2
int index = line.indexOf(JAVA_EXTENSION);
String filePath = line.substring("[parsed".length(), index + JAVA_EXTENSION.length()).trim();
processParsingMessage(callback, filePath.replace(File.separatorChar, '/'));
}
else if (line.startsWith("[read") && line.endsWith(".java]")){ // jikes
String filePath = line.substring("[read".length(), line.length() - 1).trim();
processParsingMessage(callback, filePath.replace(File.separatorChar, '/'));
}
else if (line.startsWith("[parsing completed")){
}
else if (line.startsWith("[loading") || line.startsWith("[loaded") || line.startsWith("[read")){
callback.setProgressText(CompilerBundle.message("progress.loading.classes"));
}
else if (line.startsWith("[checking")){
String className = line.substring("[checking".length(), line.length() - 1).trim();
callback.setProgressText(CompilerBundle.message("progress.compiling.class", className));
}
else if (line.startsWith("[wrote") || line.startsWith("[write")){
String filePath = line.substring("[wrote".length(), line.length() - 1).trim();
processParsingMessage(callback, filePath.replace(File.separatorChar, '/'));
}
return true;
}
private static void processParsingMessage(final OutputParser.Callback callback, @NonNls final String filePath) {
int index = filePath.lastIndexOf('/');
final String name = index >= 0 ? filePath.substring(index + 1) : filePath;
final FileType fileType = FileTypeManager.getInstance().getFileTypeByFileName(name);
if (StdFileTypes.JAVA.equals(fileType)) {
callback.fileProcessed(filePath);
callback.setProgressText(CompilerBundle.message("progress.parsing.file", name));
}
else if (StdFileTypes.CLASS.equals(fileType)) {
callback.fileGenerated(new FileObject(new File(filePath)));
}
}
}
@@ -1,80 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author cdr
*/
package com.intellij.compiler.impl.packagingCompiler;
import com.intellij.openapi.compiler.make.BuildInstruction;
import com.intellij.openapi.compiler.make.BuildInstructionVisitor;
import com.intellij.openapi.compiler.make.BuildRecipe;
import com.intellij.openapi.deployment.DeploymentUtil;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
@Deprecated
public class BuildRecipeImpl implements BuildRecipe {
private final List<BuildInstruction> myInstructions = new ArrayList<BuildInstruction>();
public void addInstruction(BuildInstruction instruction) {
if (!contains(instruction)) {
myInstructions.add(instruction);
}
}
public boolean contains(final BuildInstruction instruction) {
return myInstructions.contains(instruction);
}
public boolean visitInstructions(BuildInstructionVisitor visitor, boolean reverseOrder){
try {
return visitInstructionsWithExceptions(visitor, reverseOrder);
}
catch (Exception e) {
if (e instanceof RuntimeException) {
throw (RuntimeException)e;
}
return false;
}
}
public boolean visitInstructionsWithExceptions(BuildInstructionVisitor visitor, boolean reverseOrder) throws Exception {
for (int i = reverseOrder ? myInstructions.size()-1 : 0;
reverseOrder ? i>=0 : i < myInstructions.size();
i += reverseOrder ? -1 : 1) {
BuildInstruction instruction = myInstructions.get(i);
if (!instruction.accept(visitor)) {
return false;
}
}
return true;
}
public void addFileCopyInstruction(@NotNull File file, boolean isDirectory, String outputRelativePath) {
addInstruction(new FileCopyInstructionImpl(file, isDirectory, DeploymentUtil.trimForwardSlashes(outputRelativePath)));
}
public String toString() {
String s = "Build recipe:";
for (BuildInstruction buildInstruction : myInstructions) {
s += "\n" + buildInstruction + "; ";
}
return s;
}
}
@@ -1,236 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* @author: Eugene Zhuravlev
* Date: Jan 17, 2003
* Time: 3:48:26 PM
*/
package com.intellij.compiler.impl.resourceCompiler;
import com.intellij.compiler.CompilerConfiguration;
import com.intellij.compiler.CompilerConfigurationImpl;
import com.intellij.compiler.impl.CompilerUtil;
import com.intellij.compiler.make.MakeUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.*;
import com.intellij.openapi.compiler.ex.CompileContextEx;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.util.Chunk;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.IOException;
import java.util.*;
public class ResourceCompiler implements TranslatingCompiler {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.resourceCompiler.ResourceCompiler");
private final Project myProject;
private final CompilerConfiguration myConfiguration;
private final ResourceCompilerExtension[] myResourceCompilerExtensions = ResourceCompilerExtension.EP_NAME.getExtensions();
public ResourceCompiler(Project project, CompilerConfiguration compilerConfiguration) {
myProject = project;
myConfiguration = compilerConfiguration;
}
@NotNull
public String getDescription() {
return CompilerBundle.message("resource.compiler.description");
}
public boolean validateConfiguration(CompileScope scope) {
((CompilerConfigurationImpl) CompilerConfiguration.getInstance(myProject)).convertPatterns();
return true;
}
public boolean isCompilableFile(VirtualFile file, CompileContext context) {
final Module module = context.getModuleByFile(file);
if (module != null && skipStandardResourceCompiler(module)) {
return false;
}
return myConfiguration.isResourceFile(file);
}
public void compile(final CompileContext context, Chunk<Module> moduleChunk, final VirtualFile[] files, OutputSink sink) {
context.getProgressIndicator().pushState();
context.getProgressIndicator().setText(CompilerBundle.message("progress.copying.resources"));
final Map<String, Collection<OutputItem>> processed = new HashMap<String, Collection<OutputItem>>();
final LinkedList<CopyCommand> copyCommands = new LinkedList<CopyCommand>();
final Module singleChunkModule = moduleChunk.getNodes().size() == 1? moduleChunk.getNodes().iterator().next() : null;
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
for (final VirtualFile file : files) {
if (context.getProgressIndicator().isCanceled()) {
break;
}
final Module module = singleChunkModule != null? singleChunkModule : context.getModuleByFile(file);
if (module == null) {
continue; // looks like file invalidated
}
final VirtualFile fileRoot = MakeUtil.getSourceRoot(context, module, file);
if (fileRoot == null) {
continue;
}
final String sourcePath = file.getPath();
final String relativePath = VfsUtilCore.getRelativePath(file, fileRoot, '/');
final boolean inTests = ((CompileContextEx)context).isInTestSourceContent(file);
final VirtualFile outputDir = inTests? context.getModuleOutputDirectoryForTests(module) : context.getModuleOutputDirectory(module);
if (outputDir == null) {
continue;
}
final String outputPath = outputDir.getPath();
final String packagePrefix = fileIndex.getPackageNameByDirectory(fileRoot);
final String targetPath;
if (packagePrefix != null && packagePrefix.length() > 0) {
targetPath = outputPath + "/" + packagePrefix.replace('.', '/') + "/" + relativePath;
}
else {
targetPath = outputPath + "/" + relativePath;
}
if (sourcePath.equals(targetPath)) {
addToMap(processed, outputPath, new MyOutputItem(targetPath, file));
}
else {
copyCommands.add(new CopyCommand(outputPath, sourcePath, targetPath, file));
}
}
}
});
final List<File> filesToRefresh = new ArrayList<File>();
// do actual copy outside of read action to reduce the time the application is locked on it
while (!copyCommands.isEmpty()) {
final CopyCommand command = copyCommands.removeFirst();
if (context.getProgressIndicator().isCanceled()) {
break;
}
//context.getProgressIndicator().setFraction((idx++) * 1.0 / total);
context.getProgressIndicator().setText2("Copying " + command.getFromPath() + "...");
try {
final MyOutputItem outputItem = command.copy(filesToRefresh);
addToMap(processed, command.getOutputPath(), outputItem);
}
catch (IOException e) {
context.addMessage(
CompilerMessageCategory.ERROR,
CompilerBundle.message("error.copying", command.getFromPath(), command.getToPath(), e.getMessage()),
command.getSourceFileUrl(), -1, -1
);
}
}
if (!filesToRefresh.isEmpty()) {
CompilerUtil.refreshIOFiles(filesToRefresh);
filesToRefresh.clear();
}
for (Iterator<Map.Entry<String, Collection<OutputItem>>> it = processed.entrySet().iterator(); it.hasNext();) {
Map.Entry<String, Collection<OutputItem>> entry = it.next();
sink.add(entry.getKey(), entry.getValue(), VirtualFile.EMPTY_ARRAY);
it.remove(); // to free memory
}
context.getProgressIndicator().popState();
}
private boolean skipStandardResourceCompiler(final Module module) {
for (ResourceCompilerExtension extension : myResourceCompilerExtensions) {
if (extension.skipStandardResourceCompiler(module)) {
return true;
}
}
return false;
}
private static void addToMap(Map<String, Collection<OutputItem>> map, String outputDir, OutputItem item) {
Collection<OutputItem> list = map.get(outputDir);
if (list == null) {
list = new ArrayList<OutputItem>();
map.put(outputDir, list);
}
list.add(item);
}
private static class CopyCommand {
private final String myOutputPath;
private final String myFromPath;
private final String myToPath;
private final VirtualFile mySourceFile;
private CopyCommand(String outputPath, String fromPath, String toPath, VirtualFile sourceFile) {
myOutputPath = outputPath;
myFromPath = fromPath;
myToPath = toPath;
mySourceFile = sourceFile;
}
public MyOutputItem copy(List<File> filesToRefresh) throws IOException {
if (LOG.isDebugEnabled()) {
LOG.debug("Copying " + myFromPath + " to " + myToPath);
}
final File targetFile = new File(myToPath);
FileUtil.copyContent(new File(myFromPath), targetFile);
filesToRefresh.add(targetFile);
return new MyOutputItem(myToPath, mySourceFile);
}
public String getOutputPath() {
return myOutputPath;
}
public String getFromPath() {
return myFromPath;
}
public String getToPath() {
return myToPath;
}
public String getSourceFileUrl() {
// do not use mySourseFile.getUrl() directly as it requires read action
return VirtualFileManager.constructUrl(mySourceFile.getFileSystem().getProtocol(), myFromPath);
}
}
private static class MyOutputItem implements OutputItem {
private final String myTargetPath;
private final VirtualFile myFile;
private MyOutputItem(String targetPath, VirtualFile sourceFile) {
myTargetPath = targetPath;
myFile = sourceFile;
}
public String getOutputPath() {
return myTargetPath;
}
public VirtualFile getSourceFile() {
return myFile;
}
}
}
@@ -1,14 +0,0 @@
package com.intellij.compiler.impl.resourceCompiler;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.module.Module;
import org.jetbrains.annotations.NotNull;
public abstract class ResourceCompilerExtension {
public static final ExtensionPointName<ResourceCompilerExtension> EP_NAME =
ExtensionPointName.create("com.intellij.compiler.resourceCompilerExtension");
public boolean skipStandardResourceCompiler(final @NotNull Module module) {
return false;
}
}
@@ -1,117 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.rmiCompiler;
import com.intellij.compiler.OutputParser;
import com.intellij.compiler.impl.CompilerUtil;
import com.intellij.compiler.impl.javaCompiler.CompilerParsingThread;
import com.intellij.compiler.impl.javaCompiler.javac.JavacOutputParser;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.compiler.CompilerBundle;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.JavaSdkType;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.ex.JavaSdkUtil;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.rt.compiler.JavacResourcesReader;
import com.intellij.util.ArrayUtil;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
/**
* @author Eugene Zhuravlev
* Date: Oct 10, 2005
*/
public class JavacOutputParserPool {
protected final Project myProject;
private final CompileContext myContext;
private final Map<Sdk, OutputParser> myProjectToParserMap = new HashMap<Sdk, OutputParser>();
protected JavacOutputParserPool(Project project, final CompileContext context) {
myProject = project;
myContext = context;
}
public OutputParser getJavacOutputParser(Sdk jdk) throws IOException {
OutputParser outputParser = myProjectToParserMap.get(jdk);
if (outputParser == null) {
outputParser = createJavacOutputParser(jdk);
myProjectToParserMap.put(jdk, outputParser);
}
return outputParser;
}
private OutputParser createJavacOutputParser(final Sdk jdk) throws IOException {
final JavacOutputParser outputParser = new JavacOutputParser(myProject);
// first, need to setup the output parser
final String[] setupCmdLine = ApplicationManager.getApplication().runReadAction(new Computable<String[]>() {
public String[] compute() {
return createParserSetupCommand(jdk);
}
});
final Process setupProcess = Runtime.getRuntime().exec(setupCmdLine);
final CompilerParsingThread setupProcessParsingThread = new CompilerParsingThread(setupProcess, outputParser, true, true,myContext);
final Future<?> parsingThreadFuture = ApplicationManager.getApplication().executeOnPooledThread(setupProcessParsingThread);
try {
setupProcess.waitFor();
}
catch (InterruptedException ignored) {
}
finally {
setupProcessParsingThread.setProcessTerminated(true);
}
try {
parsingThreadFuture.get();
}
catch (InterruptedException e) {
}
catch (ExecutionException e) {
}
return outputParser;
}
private static String[] createParserSetupCommand(final Sdk jdk) {
final VirtualFile homeDirectory = jdk.getHomeDirectory();
if (homeDirectory == null) {
throw new IllegalArgumentException(CompilerBundle.jdkHomeNotFoundMessage(jdk));
}
final List<String> commandLine = new ArrayList<String>();
commandLine.add(((JavaSdkType)jdk.getSdkType()).getVMExecutablePath(jdk));
CompilerUtil.addLocaleOptions(commandLine, false);
//noinspection HardCodedStringLiteral
commandLine.add("-classpath");
commandLine.add(((JavaSdkType)jdk.getSdkType()).getToolsPath(jdk) + File.pathSeparator + JavaSdkUtil.getIdeaRtJarPath());
commandLine.add(JavacResourcesReader.class.getName());
return ArrayUtil.toStringArray(commandLine);
}
}
@@ -1,522 +0,0 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.rmiCompiler;
import com.intellij.compiler.OutputParser;
import com.intellij.compiler.impl.CompilerUtil;
import com.intellij.compiler.impl.javaCompiler.CompilerParsingThread;
import com.intellij.compiler.impl.javaCompiler.FileObject;
import com.intellij.compiler.make.Cache;
import com.intellij.compiler.make.CacheCorruptedException;
import com.intellij.compiler.make.DependencyCache;
import com.intellij.compiler.make.MakeUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.*;
import com.intellij.openapi.compiler.ex.CompileContextEx;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.OrderEnumerator;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Chunk;
import com.intellij.util.PathsList;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
/**
* @author Eugene Zhuravlev
* Date: Mar 29, 2004
*/
public class RmicCompiler implements ClassPostProcessingCompiler{
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.rmiCompiler.RmicCompiler");
//private static final FileFilter CLASSES_AND_DIRECTORIES_FILTER = new FileFilter() {
// public boolean accept(File pathname) {
// return pathname.isDirectory() || pathname.getName().endsWith(".class");
// }
//};
//private static final String REMOTE_INTERFACE_NAME = Remote.class.getName();
@NotNull
public ProcessingItem[] getProcessingItems(final CompileContext context) {
if (!RmicConfiguration.getOptions(context.getProject()).IS_EANABLED) {
return ProcessingItem.EMPTY_ARRAY;
}
final Project project = context.getProject();
final List<ProcessingItem> items = new ArrayList<ProcessingItem>();
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
DependencyCache dependencyCache = ((CompileContextEx)context).getDependencyCache();
try {
final Cache cache = dependencyCache.getCache();
final int[] allClassNames = cache.getAllClassNames();
final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
final LocalFileSystem lfs = LocalFileSystem.getInstance();
for (final int className : allClassNames) {
final boolean isRemoteObject = cache.isRemote(className) && !MakeUtil.isInterface(cache.getFlags(className));
if (!isRemoteObject && !dependencyCache.wasRemote(className)) {
continue;
}
final String outputPath = cache.getPath(className);
if (outputPath == null) {
continue;
}
final VirtualFile outputClassFile = lfs.findFileByPath(outputPath.replace(File.separatorChar, '/'));
if (outputClassFile == null) {
continue;
}
final VirtualFile sourceFile = ((CompileContextEx)context).getSourceFileByOutputFile(outputClassFile);
if (sourceFile == null) {
continue;
}
final Module module = context.getModuleByFile(sourceFile);
if (module == null) {
continue;
}
final VirtualFile outputDir = fileIndex.isInTestSourceContent(sourceFile)
? context.getModuleOutputDirectoryForTests(module)
: context.getModuleOutputDirectory(module);
if (outputDir == null) {
continue;
}
if (!VfsUtil.isAncestor(outputDir, outputClassFile, true)) {
LOG.error(outputClassFile.getPath() + " should be located under the output root " + outputDir.getPath());
}
final ProcessingItem item = createProcessingItem(module, outputClassFile, outputDir,
isRemoteObject, dependencyCache.resolve(className));
items.add(item);
}
}
catch (CacheCorruptedException e) {
context.addMessage(CompilerMessageCategory.ERROR, e.getMessage(), null, -1, -1);
LOG.info(e);
}
}
});
return items.toArray(new ProcessingItem[items.size()]);
}
public static ProcessingItem createProcessingItem(final Module module,
final VirtualFile outputClassFile,
final VirtualFile outputDir,
final boolean remoteObject, String qName) {
final RmicProcessingItem item = new RmicProcessingItem(
module, outputClassFile, new File(outputDir.getPath()), qName
);
item.setIsRemoteObject(remoteObject);
return item;
}
public ProcessingItem[] process(CompileContext context, ProcessingItem[] items) {
final Project project = context.getProject();
if (!RmicConfiguration.getOptions(project).IS_EANABLED) {
return ProcessingItem.EMPTY_ARRAY;
}
final ProgressIndicator progressIndicator = context.getProgressIndicator();
progressIndicator.pushState();
try {
progressIndicator.setText(CompilerBundle.message("progress.generating.rmi.stubs"));
final Map<Pair<Module, File>, List<RmicProcessingItem>> sortedByModuleAndOutputPath = new HashMap<Pair<Module,File>, List<RmicProcessingItem>>();
for (ProcessingItem item1 : items) {
final RmicProcessingItem item = (RmicProcessingItem)item1;
final Pair<Module, File> moduleOutputPair = Pair.create(item.getModule(), item.getOutputDir());
List<RmicProcessingItem> dirItems = sortedByModuleAndOutputPath.get(moduleOutputPair);
if (dirItems == null) {
dirItems = new ArrayList<RmicProcessingItem>();
sortedByModuleAndOutputPath.put(moduleOutputPair, dirItems);
}
dirItems.add(item);
}
final List<ProcessingItem> processed = new ArrayList<ProcessingItem>();
final JavacOutputParserPool parserPool = new JavacOutputParserPool(project, context);
for (final Pair<Module, File> pair : sortedByModuleAndOutputPath.keySet()) {
if (progressIndicator.isCanceled()) {
break;
}
final List<RmicProcessingItem> dirItems = sortedByModuleAndOutputPath.get(pair);
try {
// should delete all previously generated files for the remote class if there are any
for (Iterator itemIterator = dirItems.iterator(); itemIterator.hasNext();) {
final RmicProcessingItem item = (RmicProcessingItem)itemIterator.next();
item.deleteGeneratedFiles();
if (!item.isRemoteObject()) {
itemIterator
.remove(); // the object was remote and currently is not, so remove it from the list and do not generate stubs for it
}
}
if (!dirItems.isEmpty()) {
final RmicProcessingItem[] successfullyProcessed = invokeRmic(context, parserPool, pair.getFirst(), dirItems, pair.getSecond());
ContainerUtil.addAll(processed, successfullyProcessed);
}
progressIndicator.setFraction(((double)processed.size()) / ((double)items.length));
}
catch (IOException e) {
context.addMessage(CompilerMessageCategory.ERROR, e.getMessage(), null, -1, -1);
LOG.info(e);
}
}
// update state so that the latest timestamps are recorded by make
final ProcessingItem[] processedItems = processed.toArray(new ProcessingItem[processed.size()]);
final List<File> filesToRefresh = new ArrayList<File>(processedItems.length * 3);
for (ProcessingItem processedItem : processedItems) {
RmicProcessingItem item = (RmicProcessingItem)processedItem;
item.updateState();
filesToRefresh.add(item.myStub);
filesToRefresh.add(item.mySkel);
filesToRefresh.add(item.myTie);
}
CompilerUtil.refreshIOFiles(filesToRefresh);
return processedItems;
}
finally {
progressIndicator.popState();
}
}
private static RmicProcessingItem[] invokeRmic(final CompileContext context,
final JavacOutputParserPool parserPool, final Module module,
final List<RmicProcessingItem> dirItems,
final File outputDir
) throws IOException{
final Sdk jdk = ModuleRootManager.getInstance(module).getSdk();
final Map<String, RmicProcessingItem> pathToItemMap = new HashMap<String, RmicProcessingItem>();
final String[] cmdLine = ApplicationManager.getApplication().runReadAction(new Computable<String[]>() {
public String[] compute() {
for (final RmicProcessingItem item : dirItems) {
pathToItemMap.put(item.myStub.getPath().replace(File.separatorChar, '/'), item);
pathToItemMap.put(item.mySkel.getPath().replace(File.separatorChar, '/'), item);
pathToItemMap.put(item.myTie.getPath().replace(File.separatorChar, '/'), item);
}
return createStartupCommand(module, outputDir.getPath(), dirItems.toArray(new RmicProcessingItem[dirItems.size()]));
}
});
if (LOG.isDebugEnabled()) {
StringBuilder buf = new StringBuilder();
for (int idx = 0; idx < cmdLine.length; idx++) {
if (idx > 0) {
buf.append(" ");
}
buf.append(cmdLine[idx]);
}
LOG.debug(buf.toString());
}
// obtain parser before running the process because configuring parser may involve starting another process
final OutputParser outputParser = parserPool.getJavacOutputParser(jdk);
final Process process = Runtime.getRuntime().exec(cmdLine);
final Set<RmicProcessingItem> successfullyCompiledItems = new HashSet<RmicProcessingItem>();
final CompilerParsingThread parsingThread = new CompilerParsingThread(process, outputParser, false, true,context) {
protected void processCompiledClass(FileObject classFileToProcess) {
String key = classFileToProcess.getFile().getPath().replace(File.separatorChar, '/');
final RmicProcessingItem item = pathToItemMap.get(key);
if (item != null) {
successfullyCompiledItems.add(item);
}
}
};
final Future<?> parsingThreadFuture = ApplicationManager.getApplication().executeOnPooledThread(parsingThread);
try {
process.waitFor();
}
catch (InterruptedException ignored) {
}
finally {
parsingThread.setProcessTerminated(true);
}
try {
parsingThreadFuture.get();
}
catch (InterruptedException ignored) {
}
catch (ExecutionException ignored) {
}
return successfullyCompiledItems.toArray(new RmicProcessingItem[successfullyCompiledItems.size()]);
}
private static String[] createStartupCommand(final Module module, final String outputPath, final RmicProcessingItem[] items) {
final Sdk jdk = ModuleRootManager.getInstance(module).getSdk();
final VirtualFile homeDirectory = jdk.getHomeDirectory();
if (homeDirectory == null) {
throw new IllegalArgumentException(CompilerBundle.jdkHomeNotFoundMessage(jdk));
}
final String jdkPath = homeDirectory.getPath().replace('/', File.separatorChar);
@NonNls final String compilerPath = jdkPath + File.separator + "bin" + File.separator + "rmic";
@NonNls final List<String> commandLine = new ArrayList<String>();
commandLine.add(compilerPath);
CompilerUtil.addLocaleOptions(commandLine, true);
commandLine.add("-verbose");
final Project project = module.getProject();
ContainerUtil.addAll(commandLine, new RmicSettingsBuilder(RmicConfiguration.getOptions(project)).getOptions(new Chunk<Module>(module)));
commandLine.add("-classpath");
commandLine.add(getCompilationClasspath(module));
commandLine.add("-d");
commandLine.add(outputPath);
for (RmicProcessingItem item : items) {
commandLine.add(item.getClassQName());
}
return ArrayUtil.toStringArray(commandLine);
}
@NotNull
public String getDescription() {
return CompilerBundle.message("rmi.compiler.description");
}
public boolean validateConfiguration(CompileScope scope) {
return true;
}
/*
private void addAllRemoteFilesFromModuleOutput(final CompileContext context, final Module module, final List<ProcessingItem> items, final File outputDir, File fromDir, final JavaClass remoteInterface) {
final File[] children = fromDir.listFiles(CLASSES_AND_DIRECTORIES_FILTER);
for (int idx = 0; idx < children.length; idx++) {
final File child = children[idx];
if (child.isDirectory()) {
addAllRemoteFilesFromModuleOutput(context, module, items, outputDir, child, remoteInterface);
}
else {
final String path = child.getPath();
try {
final ClassParser classParser = new ClassParser(path);
final JavaClass javaClass = classParser.parse();
// important! Need this in order to resolve other classes in the project (e.g. superclasses)
javaClass.setRepository(BcelUtils.getActiveRepository());
if (isRmicCompilable(javaClass, remoteInterface)) {
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
final VirtualFile outputClassFile = LocalFileSystem.getInstance().findFileByIoFile(child);
if (outputClassFile != null) {
items.add(new RmicProcessingItem(module, outputClassFile, outputDir, javaClass.getClassName()));
}
}
});
}
}
catch (IOException e) {
context.addMessage(CompilerMessageCategory.ERROR, "Cannot parse class file " + path + ": " + e.toString(), null, -1, -1);
}
catch (ClassFormatException e) {
context.addMessage(CompilerMessageCategory.ERROR, "Class format exception: " + e.getMessage() + " File: " + path, null, -1, -1);
}
}
}
}
*/
/*
private boolean isRmicCompilable(final JavaClass javaClass, final JavaClass remoteInterface) {
// stubs are needed for classes that _directly_ implement remote interfaces
if (javaClass.isInterface() || isGenerated(javaClass)) {
return false;
}
final JavaClass[] directlyImplementedInterfaces = javaClass.getInterfaces();
if (directlyImplementedInterfaces != null) {
for (int i = 0; i < directlyImplementedInterfaces.length; i++) {
if (directlyImplementedInterfaces[i].instanceOf(remoteInterface)) {
return true;
}
}
}
return false;
}
*/
/*
private boolean isGenerated(JavaClass javaClass) {
final String sourceFileName = javaClass.getSourceFileName();
return sourceFileName == null || !sourceFileName.endsWith(".java");
}
*/
public ValidityState createValidityState(DataInput in) throws IOException {
return new RemoteClassValidityState(in.readLong(), in.readLong(), in.readLong(), in.readLong());
}
private static String getCompilationClasspath(Module module) {
final OrderEnumerator enumerator = ModuleRootManager.getInstance(module).orderEntries().withoutSdk().compileOnly().recursively().exportedOnly();
final PathsList pathsList = enumerator.getPathsList();
return pathsList.getPathsString();
}
private static final class RemoteClassValidityState implements ValidityState {
private final long myRemoteClassTimestamp;
private final long myStubTimestamp;
private final long mySkelTimestamp;
private final long myTieTimestamp;
private RemoteClassValidityState(long remoteClassTimestamp, long stubTimestamp, long skelTimestamp, long tieTimestamp) {
myRemoteClassTimestamp = remoteClassTimestamp;
myStubTimestamp = stubTimestamp;
mySkelTimestamp = skelTimestamp;
myTieTimestamp = tieTimestamp;
}
public boolean equalsTo(ValidityState otherState) {
if (otherState instanceof RemoteClassValidityState) {
final RemoteClassValidityState state = (RemoteClassValidityState)otherState;
return myRemoteClassTimestamp == state.myRemoteClassTimestamp &&
myStubTimestamp == state.myStubTimestamp &&
mySkelTimestamp == state.mySkelTimestamp &&
myTieTimestamp == state.myTieTimestamp;
}
return false;
}
public void save(DataOutput out) throws IOException {
out.writeLong(myRemoteClassTimestamp);
out.writeLong(myStubTimestamp);
out.writeLong(mySkelTimestamp);
out.writeLong(myTieTimestamp);
}
}
private static final class RmicProcessingItem implements ProcessingItem {
private final Module myModule;
private final VirtualFile myOutputClassFile;
private final File myOutputDir;
private final String myQName;
private RemoteClassValidityState myState;
private final File myStub;
private final File mySkel;
private final File myTie;
private boolean myIsRemoteObject = false;
private RmicProcessingItem(Module module, final VirtualFile outputClassFile, File outputDir, String qName) {
myModule = module;
myOutputClassFile = outputClassFile;
myOutputDir = outputDir;
myQName = qName;
final String relativePath;
final String baseName;
final int index = qName.lastIndexOf('.');
if (index >= 0) {
relativePath = qName.substring(0, index + 1).replace('.', '/');
baseName = qName.substring(index + 1);
}
else {
relativePath = "";
baseName = qName;
}
final String path = outputDir.getPath().replace(File.separatorChar, '/') + "/" + relativePath;
//noinspection HardCodedStringLiteral
myStub = new File(path + "/" + baseName + "_Stub.class");
//noinspection HardCodedStringLiteral
mySkel = new File(path + "/" + baseName + "_Skel.class");
//noinspection HardCodedStringLiteral
myTie = new File(path + "/_" + baseName + "_Tie.class");
updateState();
}
public boolean isRemoteObject() {
return myIsRemoteObject;
}
public void setIsRemoteObject(boolean isRemote) {
myIsRemoteObject = isRemote;
}
@NotNull
public VirtualFile getFile() {
return myOutputClassFile;
}
public ValidityState getValidityState() {
return myState;
}
public void updateState() {
myState = new RemoteClassValidityState(
myOutputClassFile.getTimeStamp(),
getTimestamp(myStub),
getTimestamp(mySkel),
getTimestamp(myTie)
);
}
private static long getTimestamp(File file) {
long l = file.lastModified();
return l == 0 ? -1L : l;
}
public void deleteGeneratedFiles() {
if (FileUtil.delete(myStub)) {
CompilerUtil.refreshIOFile(myStub);
}
if (FileUtil.delete(mySkel)) {
CompilerUtil.refreshIOFile(mySkel);
}
if (FileUtil.delete(myTie)) {
CompilerUtil.refreshIOFile(myTie);
}
}
public String getClassQName() {
return myQName;
}
public File getOutputDir() {
return myOutputDir;
}
public Module getModule() {
return myModule;
}
}
}
@@ -1,55 +0,0 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.rmiCompiler;
import com.intellij.compiler.impl.javaCompiler.javac.JavacSettingsBuilder;
import com.intellij.openapi.module.Module;
import com.intellij.util.Chunk;
import org.jetbrains.jps.model.java.compiler.RmicCompilerOptions;
import java.util.Collection;
public class RmicSettingsBuilder extends JavacSettingsBuilder {
public RmicSettingsBuilder(final RmicCompilerOptions options) {
super(options);
getOptions().DEPRECATION = false; // in this configuration deprecation is false by default
}
@Override
public RmicCompilerOptions getOptions() {
return (RmicCompilerOptions)super.getOptions();
}
public Collection<String> getOptions(Chunk<Module> chunk) {
final Collection<String> options = super.getOptions(chunk);
if(getOptions().GENERATE_IIOP_STUBS) {
options.add("-iiop");
}
return options;
}
protected boolean acceptUserOption(String token) {
if (!super.acceptUserOption(token)) {
return false;
}
return !("-iiop".equals(token));
}
protected boolean acceptEncoding() {
return false;
}
}
@@ -1,66 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.make;
import org.jetbrains.annotations.NonNls;
/**
* @author Eugene Zhuravlev
* Date: Apr 7, 2004
*/
public interface AnnotationTargets {
/** Class, interface or enum declaration */
int TYPE = 0x1;
@NonNls String TYPE_STR = "TYPE";
/** Field declaration (includes enum constants) */
int FIELD = 0x2;
@NonNls String FIELD_STR = "FIELD";
/** Method declaration */
int METHOD = 0x4;
@NonNls String METHOD_STR = "METHOD";
/** Parameter declaration */
int PARAMETER = 0x8;
@NonNls String PARAMETER_STR = "PARAMETER";
/** Constructor declaration */
int CONSTRUCTOR = 0x10;
@NonNls String CONSTRUCTOR_STR = "CONSTRUCTOR";
/** Local variable declaration */
int LOCAL_VARIABLE = 0x20;
@NonNls String LOCAL_VARIABLE_STR = "LOCAL_VARIABLE";
/** Annotation type declaration */
int ANNOTATION_TYPE = 0x40;
@NonNls String ANNOTATION_TYPE_STR = "ANNOTATION_TYPE";
/** Package declaration */
int PACKAGE = 0x80;
@NonNls String PACKAGE_STR = "PACKAGE";
int ALL = TYPE | FIELD | METHOD | PARAMETER | CONSTRUCTOR | LOCAL_VARIABLE | ANNOTATION_TYPE | PACKAGE;
}
@@ -1,511 +0,0 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.make;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Ref;
import com.intellij.util.containers.SLRUCache;
import com.intellij.util.io.DataExternalizer;
import com.intellij.util.io.EnumeratorIntegerDescriptor;
import com.intellij.util.io.PersistentHashMap;
import gnu.trove.*;
import org.jetbrains.annotations.NotNull;
import java.io.*;
import java.util.*;
/**
* @author Eugene Zhuravlev
* Date: Dec 1, 2008
*/
public class BackwardDependenciesStorage implements Flushable, Disposable {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.make.CompilerDependencyStorage");
protected final PersistentHashMap<Integer, DependenciesSet> myMap;
protected final SLRUCache<Integer, ReferencerSetHolder> myCache;
private Integer myKeyToRemove;
private static final int FIELD = 1;
private static final int METHOD = 2;
private static final int CLASS = 3;
public BackwardDependenciesStorage(File file, final int cacheSize) throws IOException {
myMap = new PersistentHashMap<Integer, DependenciesSet>(file, EnumeratorIntegerDescriptor.INSTANCE, new MyDataExternalizer());
myCache = new SLRUCache<Integer, ReferencerSetHolder>(cacheSize * 2, cacheSize) {
@NotNull
public ReferencerSetHolder createValue(Integer key) {
return new ReferencerSetHolder(key);
}
protected void onDropFromCache(Integer key, final ReferencerSetHolder holder) {
if (key.equals(myKeyToRemove) || !holder.isDirty()) {
return;
}
try {
if (holder.isDataLoaded() || !myMap.containsMapping(key)) {
myMap.put(key, new DependenciesSet(holder.getData()));
}
else {
myMap.appendData(key, new PersistentHashMap.ValueDataAppender() {
public void append(final DataOutput out) throws IOException {
final Ref<IOException> exception = new Ref<IOException>(null);
// process removed
holder.myRemoveRequested.forEach(new TIntProcedure() {
public boolean execute(int qName) {
try {
out.writeInt(-qName);
return true;
}
catch (IOException e) {
exception.set(e);
}
return false;
}
});
final IOException _ex = exception.get();
if (_ex != null) {
throw _ex;
}
// process added members
for (ReferencerItem item : holder.myAdded) {
item.save(out);
}
}
});
}
}
catch (IOException e) {
LOG.error(e);
}
}
};
}
public synchronized void remove(Integer qName) throws IOException {
myKeyToRemove = qName;
try {
myCache.remove(qName);
}
finally {
myKeyToRemove = null;
}
myMap.remove(qName);
}
public synchronized void removeReferencer(Integer qName, int referencerQName) throws IOException {
if (myMap.containsMapping(qName)) {
final ReferencerSetHolder set = myCache.get(qName);
set.removeReferencer(referencerQName);
}
}
public synchronized void addClassReferencer(Integer qName, int referencerQName) {
myCache.get(qName).addReferencer(new ReferencerItem(referencerQName));
}
public synchronized void addFieldReferencer(Integer qName, int referencerQName, int fieldName) {
myCache.get(qName).addReferencer(new FieldReferencerItem(referencerQName, fieldName));
}
public synchronized void addMethodReferencer(Integer qName, int referencerQName, int methodName, int descriptor) {
myCache.get(qName).addReferencer(new MethodReferencerItem(referencerQName, methodName, descriptor));
}
public synchronized Dependency[] getDependencies(Integer classQName) throws CacheCorruptedException {
try {
if (!myMap.containsMapping(classQName)) {
return Dependency.EMPTY_ARRAY;
}
return convertToDependencies(classQName.intValue(), myCache.get(classQName).getData());
}
catch (Throwable e) {
throw new CacheCorruptedException(e);
}
}
private static Dependency[] convertToDependencies(int classToSkip, Set<ReferencerItem> data) {
final TIntObjectHashMap<Dependency> dependencies = new TIntObjectHashMap<Dependency>();
for (ReferencerItem item : data) {
if (item.qName == classToSkip) {
continue; // skip self-dependencies
}
final Dependency dependency = addDependency(dependencies, item.qName);
if (item instanceof FieldReferencerItem) {
dependency.addField(((FieldReferencerItem)item).name);
}
else if (item instanceof MethodReferencerItem) {
final MethodReferencerItem methodItem = (MethodReferencerItem)item;
dependency.addMethod(methodItem.name, methodItem.descriptor);
}
}
final Dependency[] dependencyArray = new Dependency[dependencies.size()];
dependencies.forEachValue(new TObjectProcedure<Dependency>() {
private int index = 0;
public boolean execute(Dependency object) {
dependencyArray[index++] = object;
return true;
}
});
return dependencyArray;
}
private static Dependency addDependency(TIntObjectHashMap<Dependency> container, int classQName) {
Dependency dependency = container.get(classQName);
if (dependency == null) {
dependency = new Dependency(classQName);
container.put(classQName, dependency);
}
return dependency;
}
public synchronized void flush() throws IOException {
myCache.clear();
myMap.force();
}
private void flush(Integer key) {
myCache.remove(key); // makes changes into PersistentHashMap
myMap.force(); // flushes internal caches (which consume memory) and writes unsaved data to disk
}
public synchronized void dispose() {
try {
flush();
}
catch (IOException e) {
LOG.info(e);
}
try {
myMap.close();
}
catch (IOException e) {
LOG.info(e);
}
}
private static class ReferencerItem {
public final int qName;
private ReferencerItem(int qName) {
this.qName = qName;
}
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ReferencerItem that = (ReferencerItem)o;
if (qName != that.qName) return false;
return true;
}
public int hashCode() {
return qName;
}
public void save(DataOutput out) throws IOException {
out.writeInt(qName);
out.writeByte(CLASS);
}
}
private static final class MethodReferencerItem extends ReferencerItem {
public final int name;
public final int descriptor;
MethodReferencerItem(int qName, int name, int descriptor) {
super(qName);
this.name = name;
this.descriptor = descriptor;
}
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
MethodReferencerItem that = (MethodReferencerItem)o;
if (descriptor != that.descriptor) return false;
if (name != that.name) return false;
return true;
}
public int hashCode() {
int result = super.hashCode();
result = 31 * result + name;
result = 31 * result + descriptor;
return result;
}
public void save(DataOutput out) throws IOException {
out.writeInt(qName);
out.writeByte(METHOD);
out.writeInt(name);
out.writeInt(descriptor);
}
}
private static final class FieldReferencerItem extends ReferencerItem {
public final int name;
FieldReferencerItem(int qName, int name) {
super(qName);
this.name = name;
}
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
FieldReferencerItem that = (FieldReferencerItem)o;
if (name != that.name) return false;
return true;
}
public int hashCode() {
int result = super.hashCode();
result = 31 * result + name;
return result;
}
public void save(DataOutput out) throws IOException {
out.writeInt(qName);
out.writeByte(FIELD);
out.writeInt(name);
}
}
private class ReferencerSetHolder {
private final Integer myKey;
private TIntHashSet myRemoveRequested = new TIntHashSet();
private Set<ReferencerItem> myAdded = new THashSet<ReferencerItem>();
private Set<ReferencerItem> myData = null;
private boolean myIsDirty = false;
public ReferencerSetHolder(Integer key) {
myKey = key;
}
public void addReferencer(ReferencerItem referencer) {
if (myData != null) {
myIsDirty |= myData.add(referencer);
return;
}
myAdded.add(referencer);
}
public void removeReferencer(int qName) {
if (myData != null) {
myIsDirty |= removeAllReferencerItems(myData, qName);
return;
}
myRemoveRequested.add(qName);
removeAllReferencerItems(myAdded, qName);
}
public boolean isDirty() {
return myData != null? myIsDirty : myRemoveRequested.size() > 0 || myAdded.size() > 0;
}
public boolean isDataLoaded() {
return myData != null;
}
public Set<ReferencerItem> getData() throws IOException {
if (myData == null) {
final DependenciesSet ds = myMap.get(myKey);
Set<ReferencerItem> set = null;
if (ds != null) {
set = ds.set;
myIsDirty |= ds.needsCompacting;
}
if (set == null) {
set = new THashSet<ReferencerItem>();
}
myIsDirty |= removeAllReferencerItems(set, myRemoveRequested);
myIsDirty |= set.addAll(myAdded);
myData = set;
myAdded = null;
myRemoveRequested = null;
}
return Collections.unmodifiableSet(myData);
}
}
private static class MyDataExternalizer implements DataExternalizer<DependenciesSet> {
public void save(@NotNull DataOutput out, DependenciesSet ds) throws IOException {
final TIntHashSet classes = new TIntHashSet();
final Map<Dependency.FieldRef, TIntHashSet> fieldsMap = new HashMap<Dependency.FieldRef, TIntHashSet>();
final Map<Dependency.MethodRef, TIntHashSet> methodsMap = new HashMap<Dependency.MethodRef, TIntHashSet>();
for (ReferencerItem item : ds.set) {
if (item instanceof FieldReferencerItem) {
final Dependency.FieldRef ref = new Dependency.FieldRef(((FieldReferencerItem)item).name);
TIntHashSet referencers = fieldsMap.get(ref);
if (referencers == null) {
referencers = new TIntHashSet();
fieldsMap.put(ref, referencers);
}
referencers.add(item.qName);
}
else if (item instanceof MethodReferencerItem) {
final MethodReferencerItem _item = (MethodReferencerItem)item;
final Dependency.MethodRef ref = new Dependency.MethodRef(_item.name, _item.descriptor);
TIntHashSet referencers = methodsMap.get(ref);
if (referencers == null) {
referencers = new TIntHashSet();
methodsMap.put(ref, referencers);
}
referencers.add(item.qName);
}
else {
classes.add(item.qName);
}
}
out.writeInt(classes.size());
for (TIntIterator it = classes.iterator(); it.hasNext();) {
out.writeInt(it.next());
}
out.writeInt(fieldsMap.size());
for (Map.Entry<Dependency.FieldRef, TIntHashSet> entry : fieldsMap.entrySet()) {
out.writeInt(entry.getKey().name);
final TIntHashSet referencers = entry.getValue();
out.writeInt(referencers.size());
for (TIntIterator rit = referencers.iterator(); rit.hasNext();) {
out.writeInt(rit.next());
}
}
out.writeInt(methodsMap.size());
for (Map.Entry<Dependency.MethodRef, TIntHashSet> entry : methodsMap.entrySet()) {
final Dependency.MethodRef ref = entry.getKey();
out.writeInt(ref.name);
out.writeInt(ref.descriptor);
final TIntHashSet referencers = entry.getValue();
out.writeInt(referencers.size());
for (TIntIterator rit = referencers.iterator(); rit.hasNext();) {
out.writeInt(rit.next());
}
}
}
public DependenciesSet read(@NotNull DataInput in) throws IOException {
final Set<ReferencerItem> set = new THashSet<ReferencerItem>();
int classesCount = in.readInt();
while (classesCount-- > 0) {
set.add(new ReferencerItem(in.readInt()));
}
int fieldsCount = in.readInt();
while (fieldsCount-- > 0) {
final int fieldName = in.readInt();
int referencersCount = in.readInt();
while (referencersCount-- > 0) {
set.add(new FieldReferencerItem(in.readInt(), fieldName));
}
}
int methodsCount = in.readInt();
while (methodsCount-- > 0) {
final int methodName = in.readInt();
final int methodDescriptor = in.readInt();
int referensersCount = in.readInt();
while (referensersCount-- > 0) {
set.add(new MethodReferencerItem(in.readInt(), methodName, methodDescriptor));
}
}
boolean needsCompacting = false;
// manage appends if exist qName, kind, {field | method}
final DataInputStream _in = (DataInputStream)in;
while (_in.available() > 0) {
needsCompacting = true;
final int qName = _in.readInt();
if (qName < 0) {
removeAllReferencerItems(set, -qName);
}
else {
final byte kind = _in.readByte();
if (kind == FIELD) {
set.add(new FieldReferencerItem(qName, _in.readInt()));
}
else if (kind == METHOD) {
final int name = _in.readInt();
final int descriptor = _in.readInt();
set.add(new MethodReferencerItem(qName, name, descriptor));
}
else if (kind == CLASS){
set.add(new ReferencerItem(qName));
}
}
}
return new DependenciesSet(set, needsCompacting);
}
}
private static final class DependenciesSet {
public final Set<ReferencerItem> set;
public final boolean needsCompacting;
public DependenciesSet(Set<ReferencerItem> set, boolean needsCompacting) {
this.set = set;
this.needsCompacting = needsCompacting;
}
public DependenciesSet(Set<ReferencerItem> set) {
this(set, false);
}
}
private static boolean removeAllReferencerItems(final Set<ReferencerItem> from, final TIntHashSet qNames) {
boolean removed = false;
for (Iterator<ReferencerItem> it = from.iterator(); it.hasNext();) {
final ReferencerItem item = it.next();
if (qNames.contains(item.qName)) {
it.remove();
removed = true;
}
}
return removed;
}
private static boolean removeAllReferencerItems(final Set<ReferencerItem> from, final int qNames) {
boolean removed = false;
for (Iterator<ReferencerItem> it = from.iterator(); it.hasNext();) {
final ReferencerItem item = it.next();
if (qNames == item.qName) {
it.remove();
removed = true;
}
}
return removed;
}
}
@@ -1,83 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.make;
import com.intellij.compiler.classParsing.SignatureParser;
import com.intellij.compiler.classParsing.SignatureParsingException;
import com.intellij.util.ArrayUtil;
import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
import java.util.ArrayList;
import java.util.List;
/**
* @author Eugene Zhuravlev
* Date: Mar 10, 2004
*/
public class BoundsParser extends SignatureParser{
final List<String> myInterfaceBounds = new ArrayList<String>();
private int myParsingBound;
public void parseClassBound(CharacterIterator it, StringBuilder buf) throws SignatureParsingException {
myParsingBound += 1;
try {
super.parseClassBound(it, buf);
}
finally {
myParsingBound -= 1;
}
}
public void parseInterfaceBound(CharacterIterator it, StringBuilder buf) throws SignatureParsingException {
myParsingBound += 1;
try {
super.parseInterfaceBound(it, buf);
}
finally {
myParsingBound -= 1;
}
}
public void parseClassTypeSignature(CharacterIterator it, StringBuilder buf) throws SignatureParsingException {
if (myParsingBound > 0) {
final int start = buf.length();
super.parseClassTypeSignature(it, buf);
final String qName = convertToQalifiedName(buf.substring(start + 1, buf.length() - 1));
myInterfaceBounds.add(qName);
}
else {
super.parseClassTypeSignature(it, buf);
}
}
private static String convertToQalifiedName(String ifaceSignature) {
ifaceSignature = ifaceSignature.replaceAll("<.*>", "");
return ifaceSignature.replace('/', '.');
}
public String[] getBounds() {
return ArrayUtil.toStringArray(myInterfaceBounds);
}
public static String[] getBounds(String classSignature) throws SignatureParsingException {
final BoundsParser parser = new BoundsParser();
parser.parseClassSignature(new StringCharacterIterator(classSignature), new StringBuilder());
return parser.getBounds();
}
}
@@ -1,521 +0,0 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.make;
import com.intellij.compiler.SymbolTable;
import com.intellij.compiler.classParsing.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.cls.ClsFormatException;
import com.intellij.util.io.DataExternalizer;
import com.intellij.util.io.EnumeratorIntegerDescriptor;
import com.intellij.util.io.PersistentHashMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.File;
import java.io.IOException;
import java.util.*;
/**
* @author Eugene Zhuravlev
* Date: Aug 8, 2003
* Time: 7:03:56 PM
*/
public class Cache {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.make.Cache");
public static final int UNKNOWN = -1;
private final PersistentHashMap<Integer, ClassInfo> myQNameToClassInfoMap;
private final BackwardDependenciesStorage myDependencies;
private final CompilerDependencyStorage<Integer> myQNameToReferencedClassesMap;
private final CompilerDependencyStorage<Integer> myQNameToSubclassesMap;
private final PersistentHashMap<Integer, Boolean> myRemoteQNames;
private final String myStorePath;
public Cache(@NonNls final String storePath, final int cacheSize) throws IOException {
myStorePath = storePath;
new File(storePath).mkdirs();
myQNameToClassInfoMap = new CachedPersistentHashMap<Integer, ClassInfo>(getOrCreateFile("classes"), EnumeratorIntegerDescriptor.INSTANCE, new DataExternalizer<ClassInfo>() {
public void save(@NotNull DataOutput out, ClassInfo value) throws IOException {
value.save(out);
}
public ClassInfo read(@NotNull DataInput in) throws IOException {
return new ClassInfo(in);
}
}, cacheSize * 2) {
protected boolean isValueDirty(ClassInfo classInfo) {
return classInfo.isDirty();
}
};
myDependencies = new BackwardDependenciesStorage(getOrCreateFile("bdeps"), cacheSize);
myQNameToReferencedClassesMap = new CompilerDependencyStorage<Integer>(getOrCreateFile("fdeps"), EnumeratorIntegerDescriptor.INSTANCE, cacheSize);
myQNameToSubclassesMap = new CompilerDependencyStorage<Integer>(getOrCreateFile("subclasses"), EnumeratorIntegerDescriptor.INSTANCE, cacheSize);
myRemoteQNames = new PersistentHashMap<Integer, Boolean>(getOrCreateFile("remote"), EnumeratorIntegerDescriptor.INSTANCE, new DataExternalizer<Boolean>() {
public void save(@NotNull DataOutput out, Boolean value) throws IOException {
out.writeBoolean(value.booleanValue());
}
public Boolean read(@NotNull DataInput in) throws IOException {
return in.readBoolean();
}
}, cacheSize);
}
private File getOrCreateFile(final String fileName) throws IOException {
final File file = new File(myStorePath, fileName);
FileUtil.createIfDoesntExist(file);
return file;
}
public void dispose() throws CacheCorruptedException {
CacheCorruptedException ex = null;
try {
myQNameToClassInfoMap.close();
}
catch (IOException e) {
LOG.info(e);
ex = new CacheCorruptedException(e);
}
try {
myRemoteQNames.close();
}
catch (IOException e) {
LOG.info(e);
if (ex != null) {
ex = new CacheCorruptedException(e);
}
}
myQNameToReferencedClassesMap.dispose();
myDependencies.dispose();
myQNameToSubclassesMap.dispose();
if (ex != null) {
throw ex;
}
}
public int[] getAllClassNames() throws CacheCorruptedException {
try {
final Collection<Integer> allKeys = myQNameToClassInfoMap.getAllKeysWithExistingMapping();
final int[] array = ArrayUtil.newIntArray(allKeys.size());
int idx = 0;
for (Integer id : allKeys) {
array[idx++] = id.intValue();
}
return array;
}
catch (IOException e) {
throw new CacheCorruptedException(e);
}
}
public int importClassInfo(ClassFileReader reader, SymbolTable symbolTable) throws ClsFormatException, CacheCorruptedException {
try {
final ClassInfo classInfo = new ClassInfo(reader, symbolTable);
myQNameToClassInfoMap.put(classInfo.getQualifiedName(), classInfo);
return classInfo.getQualifiedName();
}
catch (IOException e) {
throw new CacheCorruptedException(e);
}
}
public void importClassInfo(Cache fromCache, final int qName) throws CacheCorruptedException {
try {
final ClassInfo classInfo = fromCache.myQNameToClassInfoMap.get(qName);
if (classInfo != null) {
final ClassInfo clone = classInfo.clone();
clone.clearReferences();
myQNameToClassInfoMap.put(qName, clone);
}
}
catch (Throwable e) {
throw new CacheCorruptedException(e);
}
}
public AnnotationConstantValue[] getRuntimeVisibleAnnotations(int classId) throws CacheCorruptedException {
try {
final ClassInfo classInfo = myQNameToClassInfoMap.get(classId);
return classInfo != null? classInfo.getRuntimeVisibleAnnotations() : AnnotationConstantValue.EMPTY_ARRAY;
}
catch (Throwable e) {
throw new CacheCorruptedException(e);
}
}
public AnnotationConstantValue[] getRuntimeInvisibleAnnotations(int classId) throws CacheCorruptedException {
try {
final ClassInfo classInfo = myQNameToClassInfoMap.get(classId);
return classInfo != null? classInfo.getRuntimeInvisibleAnnotations() : AnnotationConstantValue.EMPTY_ARRAY;
}
catch (Throwable e) {
throw new CacheCorruptedException(e);
}
}
public int[] getSubclasses(int classId) throws CacheCorruptedException {
try {
return myQNameToSubclassesMap.getValues(classId);
}
catch (Throwable e) {
throw new CacheCorruptedException(e);
}
}
public void addSubclass(int classId, int subclassQName) throws CacheCorruptedException {
try {
myQNameToSubclassesMap.addValue(classId, subclassQName);
}
catch (Throwable e) {
throw new CacheCorruptedException(e);
}
}
public void removeSubclass(int classId, int subclassQName) throws CacheCorruptedException {
try {
myQNameToSubclassesMap.removeValue(classId, subclassQName);
}
catch (Throwable e) {
throw new CacheCorruptedException(e);
}
}
public int[] getReferencedClasses(int qName) throws CacheCorruptedException {
try {
return myQNameToReferencedClassesMap.getValues(qName);
}
catch (Throwable e) {
throw new CacheCorruptedException(e);
}
}
public void clearReferencedClasses(int qName) throws CacheCorruptedException {
try {
myQNameToReferencedClassesMap.remove(qName);
}
catch (Throwable e) {
throw new CacheCorruptedException(e);
}
}
public Collection<ReferenceInfo> getReferences(int classId) throws CacheCorruptedException {
try {
final ClassInfo classInfo = myQNameToClassInfoMap.get(classId);
return classInfo != null? Arrays.asList(classInfo.getReferences()) : Collections.<ReferenceInfo>emptyList();
}
catch (Throwable e) {
throw new CacheCorruptedException(e);
}
}
public String getSourceFileName(int classId) throws CacheCorruptedException {
try {
final ClassInfo classInfo = myQNameToClassInfoMap.get(classId);
return classInfo != null? classInfo.getSourceFileName() : "";
}
catch (Throwable e) {
throw new CacheCorruptedException(e);
}
}
public boolean isRemote(int classId) throws CacheCorruptedException {
try {
return myRemoteQNames.containsMapping(classId);
}
catch (Throwable e) {
throw new CacheCorruptedException(e);
}
}
public void setRemote(int classId, boolean remote) throws CacheCorruptedException {
try {
if (remote) {
myRemoteQNames.put(classId, Boolean.TRUE);
}
else {
myRemoteQNames.remove(classId);
}
}
catch (Throwable e) {
throw new CacheCorruptedException(e);
}
}
public int getSuperQualifiedName(int classId) throws CacheCorruptedException {
try {
final ClassInfo classInfo = myQNameToClassInfoMap.get(classId);
return classInfo != null? classInfo.getSuperQualifiedName() : UNKNOWN;
}
catch (Throwable e) {
throw new CacheCorruptedException(e);
}
}
public String getPath(int classId) throws CacheCorruptedException {
try {
final ClassInfo classInfo = myQNameToClassInfoMap.get(classId);
return classInfo != null? classInfo.getPath() : "";
}
catch (Throwable e) {
throw new CacheCorruptedException(e);
}
}
public void setPath(int classId, String path) throws CacheCorruptedException {
try {
final ClassInfo classInfo = myQNameToClassInfoMap.get(classId);
if (classInfo != null) {
classInfo.setPath(path);
}
}
catch (Throwable e) {
throw new CacheCorruptedException(e);
}
}
public int getGenericSignature(int classId) throws CacheCorruptedException {
try {
final ClassInfo classInfo = myQNameToClassInfoMap.get(classId);
return classInfo != null? classInfo.getGenericSignature() : UNKNOWN;
}
catch (Throwable e) {
throw new CacheCorruptedException(e);
}
}
public boolean containsClass(int qName) throws CacheCorruptedException {
try {
return myQNameToClassInfoMap.containsMapping(qName);
}
catch (IOException e) {
throw new CacheCorruptedException(e);
}
}
public int[] getSuperInterfaces(int classId) throws CacheCorruptedException {
try {
final ClassInfo classInfo = myQNameToClassInfoMap.get(classId);
return classInfo != null? classInfo.getSuperInterfaces() : ArrayUtil.EMPTY_INT_ARRAY;
}
catch (Throwable e) {
throw new CacheCorruptedException(e);
}
}
public int getFlags(int classId) throws CacheCorruptedException {
try {
final ClassInfo classInfo = myQNameToClassInfoMap.get(classId);
return classInfo != null? classInfo.getFlags() : UNKNOWN;
}
catch (Throwable e) {
throw new CacheCorruptedException(e);
}
}
public FieldInfo[] getFields(int qName) throws CacheCorruptedException{
try {
final ClassInfo classInfo = myQNameToClassInfoMap.get(qName);
return classInfo != null? classInfo.getFields() : FieldInfo.EMPTY_ARRAY;
}
catch (Throwable e) {
throw new CacheCorruptedException(e);
}
}
@Nullable
public FieldInfo findField(final int classDeclarationId, final int name, final int descriptor) throws CacheCorruptedException{
try {
for (FieldInfo fieldInfo : getFields(classDeclarationId)) {
if (fieldInfo.getName() == name && fieldInfo.getDescriptor() == descriptor) {
return fieldInfo;
}
}
return null;
}
catch (Throwable e) {
throw new CacheCorruptedException(e);
}
}
@Nullable
public FieldInfo findFieldByName(final int classDeclarationId, final int name) throws CacheCorruptedException{
try {
for (FieldInfo fieldInfo : getFields(classDeclarationId)) {
if (fieldInfo.getName() == name) {
return fieldInfo;
}
}
return null;
}
catch (Throwable e) {
throw new CacheCorruptedException(e);
}
}
public MethodInfo[] getMethods(int classQName) throws CacheCorruptedException{
try {
final ClassInfo classInfo = myQNameToClassInfoMap.get(classQName);
return classInfo != null? classInfo.getMethods() : MethodInfo.EMPTY_ARRAY;
}
catch (Throwable e) {
throw new CacheCorruptedException(e);
}
}
@Nullable
public MethodInfo findMethod(final int classQName, final int name, final int descriptor) throws CacheCorruptedException{
try {
for (MethodInfo methodInfo : getMethods(classQName)) {
if (methodInfo.getName() == name && methodInfo.getDescriptor() == descriptor) {
return methodInfo;
}
}
return null;
}
catch (Throwable e) {
throw new CacheCorruptedException(e);
}
}
public List<MethodInfo> findMethodsByName(final int classDeclarationId, final int name) throws CacheCorruptedException{
try {
final List<MethodInfo> methods = new ArrayList<MethodInfo>();
for (MethodInfo methodInfo : getMethods(classDeclarationId)) {
if (methodInfo.getName() == name) {
methods.add(methodInfo);
}
}
return methods;
}
catch (Throwable e) {
throw new CacheCorruptedException(e);
}
}
@Nullable
public MethodInfo findMethodsBySignature(final int classDeclarationId, final String signature, SymbolTable symbolTable) throws CacheCorruptedException{
try {
for (MethodInfo methodInfo : getMethods(classDeclarationId)) {
if (signature.equals(CacheUtils.getMethodSignature(symbolTable.getSymbol(methodInfo.getName()), symbolTable.getSymbol(methodInfo.getDescriptor())))) {
return methodInfo;
}
}
return null;
}
catch (Throwable e) {
throw new CacheCorruptedException(e);
}
}
public void addClassReferencer(int qName, int referencerQName) throws CacheCorruptedException {
try {
if (qName == referencerQName) {
return; // do not log self-dependencies
}
if (myQNameToClassInfoMap.containsMapping(qName)) {
myDependencies.addClassReferencer(qName, referencerQName);
myQNameToReferencedClassesMap.addValue(referencerQName, qName);
}
}
catch (Throwable e) {
throw new CacheCorruptedException(e);
}
}
public void removeClassReferencer(int qName, int referencerQName) throws CacheCorruptedException {
try {
myDependencies.removeReferencer(qName, referencerQName);
}
catch (Throwable e) {
throw new CacheCorruptedException(e);
}
}
public void addFieldReferencer(int qName, int fieldName, int referencerQName) throws CacheCorruptedException {
try {
if (qName != referencerQName && myQNameToClassInfoMap.containsMapping(qName)) {
myDependencies.addFieldReferencer(qName, referencerQName, fieldName);
myQNameToReferencedClassesMap.addValue(referencerQName, qName);
}
}
catch (Throwable e) {
throw new CacheCorruptedException(e);
}
}
public void addMethodReferencer(int qName, int methodName, int methodDescriptor, int referencerQName) throws CacheCorruptedException {
try {
if (qName != referencerQName && myQNameToClassInfoMap.containsMapping(qName)) {
myDependencies.addMethodReferencer(qName, referencerQName, methodName, methodDescriptor);
myQNameToReferencedClassesMap.addValue(referencerQName, qName);
}
}
catch (Throwable e) {
throw new CacheCorruptedException(e);
}
}
/** @NotNull */
public Dependency[] getBackDependencies(final int classQName) throws CacheCorruptedException{
return myDependencies.getDependencies(classQName);
}
public void wipe() {
try {
dispose();
}
catch (CacheCorruptedException ignored) {
}
finally {
final File[] files = new File(myStorePath).listFiles();
if (files != null) {
for (File file : files) {
if (!file.isDirectory()) {
FileUtil.delete(file);
}
}
}
}
}
public void removeClass(final int qName) throws CacheCorruptedException {
try {
final ClassInfo classInfo = myQNameToClassInfoMap.get(qName);
if (classInfo == null) {
return;
}
myDependencies.remove(qName);
myQNameToClassInfoMap.remove(qName);
myQNameToReferencedClassesMap.remove(qName);
myQNameToSubclassesMap.remove(qName);
myRemoteQNames.remove(qName);
}
catch (Throwable e) {
throw new CacheCorruptedException(e);
}
}
}
@@ -1,43 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* @author: Eugene Zhuravlev
* Date: Jul 10, 2003
* Time: 4:51:25 PM
*/
package com.intellij.compiler.make;
import com.intellij.openapi.compiler.CompilerBundle;
public class CacheCorruptedException extends Exception{
private static final String DEFAULT_MESSAGE = CompilerBundle.message("error.dependency.info.on.disk.corrupted");
public CacheCorruptedException(String message) {
super((message == null || message.length() == 0)? DEFAULT_MESSAGE : message);
}
public CacheCorruptedException(Throwable cause) {
super(DEFAULT_MESSAGE, cause);
}
public CacheCorruptedException(String message, Throwable cause) {
super((message == null || message.length() == 0)? DEFAULT_MESSAGE : message, cause);
}
public String getMessage() {
return super.getMessage();
}
}
@@ -1,205 +0,0 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.make;
import com.intellij.compiler.CompilerConfiguration;
import com.intellij.compiler.CompilerManagerImpl;
import com.intellij.compiler.SymbolTable;
import com.intellij.compiler.classParsing.MethodInfo;
import com.intellij.compiler.impl.ExitException;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.CompilerBundle;
import com.intellij.openapi.compiler.CompilerMessage;
import com.intellij.openapi.compiler.CompilerMessageCategory;
import com.intellij.openapi.compiler.ex.CompileContextEx;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.ThrowableComputable;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.StringBuilderSpinAllocator;
import gnu.trove.TIntHashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
/**
* @author Eugene Zhuravlev
* Date: Aug 18, 2003
* Time: 6:32:32 PM
*/
public class CacheUtils {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.make.CacheUtils");
public static String[] getParameterSignatures(MethodInfo methodDeclarationId, SymbolTable symbolTable) throws CacheCorruptedException {
String descriptor = symbolTable.getSymbol(methodDeclarationId.getDescriptor());
int endIndex = descriptor.indexOf(')');
if (endIndex <= 0) {
LOG.error("Corrupted method descriptor: " + descriptor);
}
return parseSignature(descriptor.substring(1, endIndex));
}
private static String[] parseSignature(String signature) {
final ArrayList<String> list = new ArrayList<String>();
String paramSignature = parseParameterSignature(signature);
while (paramSignature != null && !"".equals(paramSignature)) {
list.add(paramSignature);
signature = signature.substring(paramSignature.length());
paramSignature = parseParameterSignature(signature);
}
return ArrayUtil.toStringArray(list);
}
@SuppressWarnings({"HardCodedStringLiteral"})
private static @Nullable String parseParameterSignature(String signature) {
if (StringUtil.startsWithChar(signature, 'B')) {
return "B";
}
if (StringUtil.startsWithChar(signature, 'C')) {
return "C";
}
if (StringUtil.startsWithChar(signature, 'D')) {
return "D";
}
if (StringUtil.startsWithChar(signature, 'F')) {
return "F";
}
if (StringUtil.startsWithChar(signature, 'I')) {
return "I";
}
if (StringUtil.startsWithChar(signature, 'J')) {
return "J";
}
if (StringUtil.startsWithChar(signature, 'S')) {
return "S";
}
if (StringUtil.startsWithChar(signature, 'Z')) {
return "Z";
}
if (StringUtil.startsWithChar(signature, 'L')) {
return signature.substring(0, signature.indexOf(";") + 1);
}
if (StringUtil.startsWithChar(signature, '[')) {
String s = parseParameterSignature(signature.substring(1));
return (s != null) ? ("[" + s) : null;
}
return null;
}
public static String getMethodSignature(String name, String descriptor) {
final StringBuilder builder = StringBuilderSpinAllocator.alloc();
try {
builder.append(name);
builder.append(descriptor.substring(0, descriptor.indexOf(')') + 1));
return builder.toString();
}
finally {
StringBuilderSpinAllocator.dispose(builder);
}
}
public static boolean areArraysContentsEqual(int[] exceptions1, int[] exceptions2) {
if (exceptions1.length != exceptions2.length) {
return false;
}
if (exceptions1.length != 0) { // optimization
TIntHashSet exceptionsSet = new TIntHashSet(exceptions1);
for (int exception : exceptions2) {
if (!exceptionsSet.contains(exception)) {
return false;
}
}
}
return true;
}
public static Collection<VirtualFile> findDependentFiles(
final CompileContextEx context,
final Set<VirtualFile> compiledWithErrors,
final @Nullable Function<Pair<int[], Set<VirtualFile>>, Pair<int[], Set<VirtualFile>>> filter)
throws CacheCorruptedException, ExitException {
if (!CompilerConfiguration.MAKE_ENABLED) {
return Collections.emptyList();
}
context.getProgressIndicator().setText(CompilerBundle.message("progress.checking.dependencies"));
final DependencyCache dependencyCache = context.getDependencyCache();
final Pair<int[], Set<VirtualFile>> deps = dependencyCache.findDependentClasses(context, context.getProject(), compiledWithErrors);
final Pair<int[], Set<VirtualFile>> filteredDeps = filter != null ? filter.fun(deps) : deps;
final Set<VirtualFile> dependentFiles = new HashSet<VirtualFile>();
ApplicationManager.getApplication().runReadAction(new ThrowableComputable<Void, CacheCorruptedException>() {
@Override
public Void compute() throws CacheCorruptedException {
CompilerConfiguration compilerConfiguration = CompilerConfiguration.getInstance(context.getProject());
SourceFileFinder sourceFileFinder = new SourceFileFinder(context.getProject(), context);
final Cache cache = dependencyCache.getCache();
for (final int infoQName : filteredDeps.getFirst()) {
final String qualifiedName = dependencyCache.resolve(infoQName);
final String sourceFileName = cache.getSourceFileName(infoQName);
final VirtualFile file = sourceFileFinder.findSourceFile(qualifiedName, sourceFileName, true);
if (file != null) {
dependentFiles.add(file);
if (ApplicationManager.getApplication().isUnitTestMode()) {
LOG.assertTrue(file.isValid());
CompilerManagerImpl.addRecompiledPath(file.getPath());
}
}
else {
LOG.info("No source file for " + dependencyCache.resolve(infoQName) + " found; source file name=" + sourceFileName);
}
}
for (final VirtualFile file : filteredDeps.getSecond()) {
if (!compilerConfiguration.isExcludedFromCompilation(file)) {
dependentFiles.add(file);
if (ApplicationManager.getApplication().isUnitTestMode()) {
LOG.assertTrue(file.isValid());
CompilerManagerImpl.addRecompiledPath(file.getPath());
}
}
}
return null;
}
});
context.getProgressIndicator().setText(
dependentFiles.size() > 0 ? CompilerBundle.message("progress.found.dependent.files", dependentFiles.size()) : ""
);
return dependentFiles;
}
@NotNull
public static Set<VirtualFile> getFilesCompiledWithErrors(final CompileContextEx context) {
CompilerMessage[] messages = context.getMessages(CompilerMessageCategory.ERROR);
Set<VirtualFile> compiledWithErrors = Collections.emptySet();
if (messages.length > 0) {
compiledWithErrors = new HashSet<VirtualFile>(messages.length);
for (CompilerMessage message : messages) {
final VirtualFile file = message.getVirtualFile();
if (file != null) {
compiledWithErrors.add(file);
}
}
}
return compiledWithErrors;
}
}
@@ -1,116 +0,0 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.make;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.containers.SLRUMap;
import com.intellij.util.io.DataExternalizer;
import com.intellij.util.io.KeyDescriptor;
import com.intellij.util.io.PersistentHashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
/**
* @author Eugene Zhuravlev
* Date: Dec 1, 2008
*/
public class CachedPersistentHashMap<Key, Value> extends PersistentHashMap<Key, Value> {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.make.CachedPersistentHashMap");
protected final SLRUMap<Key, Value> myCache;
public CachedPersistentHashMap(File file, KeyDescriptor<Key> keyDescriptor, DataExternalizer<Value> valDescriptor, final int cacheSize) throws IOException {
super(file, keyDescriptor, valDescriptor);
myCache = new SLRUMap<Key,Value>(cacheSize * 2, cacheSize) {
protected void onDropFromCache(Key key, Value value) {
if (isValueDirty(value)) {
try {
CachedPersistentHashMap.super.put(key, value);
}
catch (IOException e) {
LOG.info(e);
}
}
}
};
}
protected boolean isValueDirty(Value value) {
return false;
}
@Override
protected void doPut(Key key, Value value) throws IOException {
myCache.remove(key);
super.doPut(key, value);
}
@Override
protected void doAppendData(Key key, @NotNull ValueDataAppender appender) throws IOException {
myCache.remove(key);
super.doAppendData(key, appender);
}
@Nullable
protected Value doGet(Key key) throws IOException {
Value value = myCache.get(key);
if (value == null) {
value = super.doGet(key);
if (value != null) {
myCache.put(key, value);
}
}
return value;
}
@Override
protected boolean doContainsMapping(Key key) throws IOException {
final Value value = myCache.get(key);
return value != null || super.doContainsMapping(key);
}
@Override
protected void doRemove(Key key) throws IOException {
myCache.remove(key);
super.doRemove(key);
}
@Override
protected void doForce() {
try {
clearCache();
}
finally {
super.doForce();
}
}
@Override
protected void doClose() throws IOException {
try {
clearCache();
}
finally {
super.doClose();
}
}
private void clearCache() {
myCache.clear();
}
}
@@ -1,57 +0,0 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.make;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.util.Query;
import com.intellij.util.containers.SoftHashMap;
import java.util.Collection;
import java.util.Map;
/**
* @author Eugene Zhuravlev
* Date: Oct 15
* @author 2003
*/
public class CachingSearcher {
private final Project myProject;
private final Map<Pair<PsiElement, Boolean>, Collection<PsiReference>> myElementToReferencersMap = new SoftHashMap<Pair<PsiElement, Boolean>, Collection<PsiReference>>();
public CachingSearcher(Project project) {
myProject = project;
}
public Collection<PsiReference> findReferences(PsiElement element, final boolean ignoreAccessScope) {
final Pair<PsiElement, Boolean> key = Pair.create(element, ignoreAccessScope ? Boolean.TRUE : Boolean.FALSE);
Collection<PsiReference> psiReferences = myElementToReferencersMap.get(key);
if (psiReferences == null) {
GlobalSearchScope searchScope = GlobalSearchScope.projectScope(myProject);
searchScope = GlobalSearchScope.getScopeRestrictedByFileTypes(searchScope, StdFileTypes.JAVA);
final Query<PsiReference> query = ReferencesSearch.search(element, searchScope, ignoreAccessScope);
psiReferences = query.findAll();
myElementToReferencersMap.put(key, psiReferences);
}
return psiReferences;
}
}
@@ -1,24 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.make;
/**
* @author Eugene Zhuravlev
* Date: Apr 7, 2004
*/
abstract class ChangeDescription {
public abstract boolean isChanged();
}
@@ -1,370 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* created at Feb 24, 2002
* @author Jeka
*/
package com.intellij.compiler.make;
import com.intellij.compiler.classParsing.FieldInfo;
import com.intellij.compiler.impl.ExitException;
import com.intellij.compiler.impl.ExitStatus;
import com.intellij.lang.StdLanguages;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.search.*;
import com.intellij.psi.util.PsiUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
public class ChangedConstantsDependencyProcessor {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.make.ChangedConstantsDependencyProcessor");
private final Project myProject;
private final CachingSearcher mySearcher;
private final DependencyCache myDependencyCache;
private final int myQName;
private final CompileContext myContext;
private final FieldChangeInfo[] myChangedFields;
private final FieldChangeInfo[] myRemovedFields;
private final int MAX_CONSTANT_SEARCHES = Registry.intValue("compiler.max.static.constants.searches");
public ChangedConstantsDependencyProcessor(Project project,
CachingSearcher searcher,
DependencyCache dependencyCache,
int qName, CompileContext context, FieldChangeInfo[] changedFields,
FieldChangeInfo[] removedFields) {
myProject = project;
mySearcher = searcher;
myDependencyCache = dependencyCache;
myQName = qName;
myContext = context;
myChangedFields = changedFields;
myRemovedFields = removedFields;
}
public void run() throws CacheCorruptedException, ExitException {
final Ref<CacheCorruptedException> _ex = new Ref<CacheCorruptedException>();
final Ref<ExitException> exitException = new Ref<ExitException>(null);
DumbService.getInstance(myProject).runReadActionInSmartMode(new Runnable() {
public void run() {
try {
final String qName = myDependencyCache.resolve(myQName);
PsiClass[] classes = JavaPsiFacade.getInstance(myProject).findClasses(qName.replace('$', '.'), GlobalSearchScope.allScope(myProject));
for (PsiClass aClass : classes) {
PsiField[] psiFields = aClass.getFields();
for (PsiField psiField : psiFields) {
final FieldChangeInfo changeInfo = findChangeInfo(psiField);
if (changeInfo != null) { // this field has been changed
processFieldChanged(psiField, aClass, changeInfo.isAccessibilityChange);
}
}
for (FieldChangeInfo removedField : myRemovedFields) {
processFieldRemoved(removedField.fieldInfo, aClass);
}
}
}
catch (CacheCorruptedException e) {
_ex.set(e);
}
catch (ExitException e) {
exitException.set(e);
}
catch (ProcessCanceledException e) {
// supressed deliberately
}
}
});
if (_ex.get() != null) {
throw _ex.get();
}
if (exitException.get() != null) {
throw exitException.get();
}
}
private void processFieldRemoved(FieldInfo info, final PsiClass aClass) throws CacheCorruptedException {
if (info.isPrivate()) {
return; // optimization: don't need to search, cause may be used only in this class
}
SearchScope searchScope = GlobalSearchScope.projectScope(myProject);
if (info.isPackageLocal()) {
final PsiFile containingFile = aClass.getContainingFile();
if (containingFile instanceof PsiJavaFile) {
final String packageName = ((PsiJavaFile)containingFile).getPackageName();
final PsiPackage aPackage = JavaPsiFacade.getInstance(myProject).findPackage(packageName);
if (aPackage != null) {
searchScope = PackageScope.packageScope(aPackage, false);
searchScope = searchScope.intersectWith(aClass.getUseScope());
}
}
}
final PsiSearchHelper psiSearchHelper = PsiSearchHelper.SERVICE.getInstance(myProject);
final Ref<CacheCorruptedException> exRef = new Ref<CacheCorruptedException>(null);
processIdentifiers(psiSearchHelper, new PsiElementProcessor<PsiIdentifier>() {
@Override
public synchronized boolean execute(@NotNull PsiIdentifier identifier) {
try {
final PsiElement parent = identifier.getParent();
if (parent instanceof PsiReferenceExpression) {
final PsiClass ownerClass = getOwnerClass(parent);
if (ownerClass != null && !ownerClass.equals(aClass)) {
final String _qName = ownerClass.getQualifiedName();
if (_qName != null) {
int qualifiedName = myDependencyCache.getSymbolTable().getId(_qName);
// should force marking of the class no matter was it compiled or not
// This will ensure the class was recompiled _after_ all the constants get their new values
if (myDependencyCache.markClass(qualifiedName, true)) {
if (LOG.isDebugEnabled()) {
LOG.debug("Mark dependent class " + myDependencyCache.resolve(qualifiedName) + "; reason: some constants were removed from " + myDependencyCache.resolve(myQName));
}
}
}
else {
LOG.warn("Class with null qualified name was not expected here: " + ownerClass);
}
}
}
return true;
}
catch (CacheCorruptedException e) {
exRef.set(e);
return false;
}
}
}, myDependencyCache.resolve(info.getName()), searchScope, UsageSearchContext.IN_CODE);
final CacheCorruptedException cacheCorruptedException = exRef.get();
if (cacheCorruptedException != null) {
throw cacheCorruptedException;
}
}
private static boolean processIdentifiers(PsiSearchHelper helper,
@NotNull final PsiElementProcessor<PsiIdentifier> processor,
@NotNull final String identifier,
@NotNull SearchScope searchScope,
short searchContext) {
TextOccurenceProcessor processor1 = new TextOccurenceProcessor() {
public boolean execute(PsiElement element, int offsetInElement) {
return !(element instanceof PsiIdentifier) || processor.execute((PsiIdentifier)element);
}
};
return helper.processElementsWithWord(processor1, searchScope, identifier, searchContext, true);
}
private void processFieldChanged(PsiField field, PsiClass aClass, final boolean isAccessibilityChange)
throws CacheCorruptedException, ExitException {
if (!isAccessibilityChange && field.hasModifierProperty(PsiModifier.PRIVATE)) {
return; // optimization: don't need to search, cause may be used only in this class
}
Set<PsiElement> usages = new HashSet<PsiElement>();
addUsages(field, usages, isAccessibilityChange);
if (LOG.isDebugEnabled()) {
LOG.debug("++++++++++++++++++++++++++++++++++++++++++++++++");
LOG.debug("Processing changed field: " + aClass.getQualifiedName() + "." + field.getName());
}
for (final PsiElement usage : usages) {
PsiClass ownerClass = getOwnerClass(usage);
if (LOG.isDebugEnabled()) {
if (ownerClass != null) {
LOG.debug("Usage " + usage + " found in class: " + ownerClass.getQualifiedName());
}
else {
LOG.debug("Usage " + usage + " found in class: null");
}
}
if (ownerClass != null && !ownerClass.equals(aClass)) {
int qualifiedName = myDependencyCache.getSymbolTable().getId(ownerClass.getQualifiedName());
// should force marking of the class no matter was it compiled or not
// This will ensure the class was recompiled _after_ all the constants get their new values
if (LOG.isDebugEnabled()) {
LOG.debug("Marking class id = [" + qualifiedName + "], name=[" + myDependencyCache.resolve(qualifiedName) + "]");
}
if (myDependencyCache.markClass(qualifiedName, true)) {
if (LOG.isDebugEnabled()) {
LOG.debug("Marked dependent class " + myDependencyCache.resolve(qualifiedName) + "; reason: constants changed in " +
myDependencyCache.resolve(myQName));
}
}
}
else if (ownerClass == null) {
final PsiFile containingFile = usage.getContainingFile();
if (containingFile != null) {
final VirtualFile file = containingFile.getVirtualFile();
if (file != null) {
myDependencyCache.markFile(file);
}
}
}
}
if (LOG.isDebugEnabled()) {
LOG.debug("+++++++++++++++++++++++++++++++++++++++++++++++");
}
}
private void addUsages(PsiField psiField, Collection<PsiElement> usages, final boolean ignoreAccessScope) throws ExitException {
final int count = getConstantSearchesCount();
if (count > MAX_CONSTANT_SEARCHES) {
myContext.requestRebuildNextTime("Too many changed compile-time constants, project rebuild scheduled");
throw new ExitException(ExitStatus.CANCELLED);
}
Collection<PsiReference> references = mySearcher.findReferences(psiField, ignoreAccessScope)/*doFindReferences(searchHelper, psiField)*/;
incConstantSearchesCount();
for (final PsiReference ref : references) {
if (!(ref instanceof PsiReferenceExpression)) {
continue;
}
PsiElement e = ref.getElement();
usages.add(e);
PsiField ownerField = getOwnerField(e);
if (ownerField != null) {
if (ownerField.hasModifierProperty(PsiModifier.FINAL)) {
PsiExpression initializer = ownerField.getInitializer();
if (initializer != null && PsiUtil.isConstantExpression(initializer)) {
// if the field depends on the compile-time-constant expression and is itself final
addUsages(ownerField, usages, ignoreAccessScope);
}
}
}
}
}
/*
private PsiReference[] doFindReferences(final PsiSearchHelper searchHelper, final PsiField psiField) {
final ProgressManager progressManager = ProgressManager.getInstance();
final ProgressIndicator currentProgress = progressManager.getProgressIndicator();
final PsiReference[][] references = new PsiReference[][] {null};
progressManager.runProcess(new Runnable() {
public void run() {
references[0] = searchHelper.findReferences(psiField, GlobalSearchScope.projectScope(myProject), false);
if (ENABLE_TRACING) {
System.out.println("Finding referencers for " + psiField);
}
}
}, new NonCancellableProgressAdapter(currentProgress));
return references[0];
}
*/
@Nullable
private static PsiField getOwnerField(PsiElement element) {
while (!(element instanceof PsiFile)) {
if (element instanceof PsiClass) {
break;
}
if (element instanceof PsiField) { // top-level class
return (PsiField)element;
}
element = element.getParent();
}
return null;
}
@Nullable
private FieldChangeInfo findChangeInfo(PsiField field) throws CacheCorruptedException {
String name = field.getName();
for (final FieldChangeInfo changeInfo : myChangedFields) {
if (name.equals(myDependencyCache.resolve(changeInfo.fieldInfo.getName()))) {
return changeInfo;
}
}
return null;
}
@Nullable
private static PsiClass getOwnerClass(PsiElement element) {
while (!(element instanceof PsiFile)) {
if (element instanceof PsiClass && element.getParent() instanceof PsiJavaFile) { // top-level class
final PsiClass psiClass = (PsiClass)element;
if (JspPsiUtil.isInJspFile(psiClass)) {
return null;
}
final PsiFile containingFile = psiClass.getContainingFile();
if (containingFile == null) {
return null;
}
return StdLanguages.JAVA.equals(containingFile.getLanguage())? psiClass : null;
}
element = element.getParent();
}
return null;
}
public static class FieldChangeInfo {
final FieldInfo fieldInfo;
final boolean isAccessibilityChange;
public FieldChangeInfo(final FieldInfo fieldId) {
this(fieldId, false);
}
public FieldChangeInfo(final FieldInfo fieldInfo, final boolean accessibilityChange) {
this.fieldInfo = fieldInfo;
isAccessibilityChange = accessibilityChange;
}
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final FieldChangeInfo fieldChangeInfo = (FieldChangeInfo)o;
if (isAccessibilityChange != fieldChangeInfo.isAccessibilityChange) return false;
if (!fieldInfo.equals(fieldChangeInfo.fieldInfo)) return false;
return true;
}
public int hashCode() {
int result;
result = fieldInfo.hashCode();
result = 29 * result + (isAccessibilityChange ? 1 : 0);
return result;
}
}
private static final Key<Integer> CONSTANTS_COUNTER = Key.create("_constant_searches_counter_");
private int getConstantSearchesCount() {
return getConstantSearchesCount(myContext);
}
public static int getConstantSearchesCount(CompileContext context) {
final Integer value = CONSTANTS_COUNTER.get(context);
return value != null? value.intValue() : 0;
}
private void incConstantSearchesCount() {
CONSTANTS_COUNTER.set(myContext, getConstantSearchesCount() + 1);
}
}
@@ -1,107 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.make;
import com.intellij.compiler.SymbolTable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.cls.ClsUtil;
import java.util.Collection;
public class ChangedRetentionPolicyDependencyProcessor {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.make.ChangedConstantsDependencyProcessor");
private final Project myProject;
private final CachingSearcher mySearcher;
private final DependencyCache myDependencyCache;
public ChangedRetentionPolicyDependencyProcessor(Project project, CachingSearcher searcher, DependencyCache dependencyCache) {
myProject = project;
mySearcher = searcher;
myDependencyCache = dependencyCache;
}
public void checkAnnotationRetentionPolicyChanges(final int annotationQName) throws CacheCorruptedException {
final Cache oldCache = myDependencyCache.getCache();
if (!ClsUtil.isAnnotation(oldCache.getFlags(annotationQName))) {
return;
}
if (!hasRetentionPolicyChanged(annotationQName, oldCache, myDependencyCache.getNewClassesCache(), myDependencyCache.getSymbolTable())) {
return;
}
final CacheCorruptedException[] _ex = new CacheCorruptedException[] {null};
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
try {
final String qName = myDependencyCache.resolve(annotationQName);
PsiClass[] classes = JavaPsiFacade.getInstance(myProject).findClasses(qName.replace('$', '.'), GlobalSearchScope.allScope(myProject));
for (final PsiClass aClass : classes) {
if (!aClass.isAnnotationType()) {
continue;
}
final Collection<PsiReference> references = mySearcher.findReferences(aClass, true);
for (PsiReference reference : references) {
final PsiClass ownerClass = getOwnerClass(reference.getElement());
if (ownerClass != null && !ownerClass.equals(aClass)) {
int qualifiedName = myDependencyCache.getSymbolTable().getId(ownerClass.getQualifiedName());
if (myDependencyCache.markClass(qualifiedName, false)) {
if (LOG.isDebugEnabled()) {
LOG.debug("Marked dependent class " + myDependencyCache.resolve(qualifiedName) +
"; reason: annotation's retention policy changed from SOURCE to CLASS or RUNTIME " +
myDependencyCache.resolve(annotationQName));
}
}
}
}
}
}
catch (CacheCorruptedException e) {
_ex[0] = e;
}
catch (ProcessCanceledException e) {
// supressed deliberately
}
}
});
if (_ex[0] != null) {
throw _ex[0];
}
}
private boolean hasRetentionPolicyChanged(int annotationQName, final Cache oldCache, final Cache newCache, SymbolTable symbolTable) throws CacheCorruptedException {
// if retention policy changed from SOURCE to CLASS or RUNTIME, all sources should be recompiled to propagate changes
final int oldPolicy = MakeUtil.getAnnotationRetentionPolicy(annotationQName, oldCache, symbolTable);
final int newPolicy = MakeUtil.getAnnotationRetentionPolicy(annotationQName, newCache, symbolTable);
if ((oldPolicy == RetentionPolicies.SOURCE) && (newPolicy == RetentionPolicies.CLASS || newPolicy == RetentionPolicies.RUNTIME)) {
return true;
}
return false;
}
private static PsiClass getOwnerClass(PsiElement element) {
while (!(element instanceof PsiFile)) {
if (element instanceof PsiClass && element.getParent() instanceof PsiJavaFile) { // top-level class
return (PsiClass)element;
}
element = element.getParent();
}
return null;
}
}
@@ -1,32 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* @author: Eugene Zhuravlev
* Date: May 14, 2003
* Time: 10:42:29 AM
*/
package com.intellij.compiler.make;
public interface ClassInfoProcessor {
/**
* @param classQName of a class info to be processed
* @return true if superclasses of info should be processed and false otherwise
*/
boolean process(int classQName) throws CacheCorruptedException;
}
@@ -1,257 +0,0 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.make;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Ref;
import com.intellij.util.containers.SLRUCache;
import com.intellij.util.io.DataExternalizer;
import com.intellij.util.io.KeyDescriptor;
import com.intellij.util.io.PersistentHashMap;
import gnu.trove.TIntHashSet;
import gnu.trove.TIntProcedure;
import org.jetbrains.annotations.NotNull;
import java.io.*;
/**
* @author Eugene Zhuravlev
* Date: Dec 1, 2008
*/
public class CompilerDependencyStorage<Key> implements Flushable, Disposable {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.make.CompilerDependencyStorage");
protected final PersistentHashMap<Key, int[]> myMap;
protected final SLRUCache<Key, IntSet> myCache;
private Key myKeyToRemove;
public CompilerDependencyStorage(File file, KeyDescriptor<Key> keyDescriptor, final int cacheSize) throws IOException {
myMap = new PersistentHashMap<Key, int[]>(file, keyDescriptor, new DataExternalizer<int[]>() {
public void save(@NotNull DataOutput out, int[] array) throws IOException {
out.writeInt(array.length);
for (int value : array) {
out.writeInt(value);
}
}
public int[] read(@NotNull DataInput in) throws IOException {
final TIntHashSet set = new TIntHashSet();
DataInputStream stream = (DataInputStream)in;
while(stream.available() > 0) {
final int size = stream.readInt();
final int _size = Math.abs(size);
for (int idx = 0; idx < _size; idx++) {
if (size > 0) {
set.add(stream.readInt());
}
else {
set.remove(stream.readInt());
}
}
}
return set.toArray();
}
});
myCache = new SLRUCache<Key, IntSet>(cacheSize * 2, cacheSize) {
@NotNull
public IntSet createValue(Key key) {
return new IntSet(key);
}
protected void onDropFromCache(Key key, final IntSet set) {
if (key == myKeyToRemove || !set.isDirty()) {
return;
}
try {
if (set.needsCompacting()) {
myMap.put(key, set.getValues());
}
else {
myMap.appendData(key, new PersistentHashMap.ValueDataAppender() {
public void append(final DataOutput out) throws IOException {
final Ref<IOException> exception = new Ref<IOException>(null);
final TIntProcedure saveProc = new TIntProcedure() {
public boolean execute(int value) {
try {
out.writeInt(value);
return true;
}
catch (IOException e) {
exception.set(e);
return false;
}
}
};
out.writeInt(-set.getRemovedCount());
set.processRemovedValues(saveProc);
if (exception.get() != null) {
throw exception.get();
}
out.writeInt(set.getAddedCount());
set.processAddedValues(saveProc);
if (exception.get() != null) {
throw exception.get();
}
}
});
}
}
catch (IOException e) {
LOG.error(e);
}
}
};
}
public synchronized void remove(Key key) throws IOException {
myKeyToRemove = key;
try {
myCache.remove(key);
}
finally {
myKeyToRemove = null;
}
myMap.remove(key);
}
public synchronized void removeValue(Key key, int value) throws IOException {
final IntSet set = myCache.get(key);
set.remove(value);
if (set.needsFlushing()) {
flush(key);
}
}
public synchronized void addValue(Key key, int value) throws IOException {
final IntSet set = myCache.get(key);
set.add(value);
if (set.needsFlushing()) {
flush(key);
}
}
public synchronized int[] getValues(Key key) throws IOException {
return myCache.get(key).getValues();
}
public synchronized void flush() throws IOException {
myCache.clear();
myMap.force();
}
private void flush(Key key) {
myCache.remove(key); // makes changes into PersistentHashMap
myMap.force(); // flushes internal caches (which consume memory) and writes unsaved data to disk
}
public synchronized void dispose() {
try {
flush();
}
catch (IOException e) {
LOG.info(e);
}
try {
myMap.close();
}
catch (IOException e) {
LOG.info(e);
}
}
private class IntSet {
private final TIntHashSet myAdded = new TIntHashSet();
private final TIntHashSet myRemoved = new TIntHashSet();
private TIntHashSet myMerged = null;
private final Key myKey;
public IntSet(Key key) {
myKey = key;
}
public void add(int value) {
if (myMerged != null) {
myMerged.add(value);
}
if (!myRemoved.remove(value)) {
myAdded.add(value);
}
}
public void remove(int value) {
if (myMerged != null) {
myMerged.remove(value);
}
if (!myAdded.remove(value)) {
myRemoved.add(value);
}
}
public boolean isDirty() {
return myAdded.size() > 0 || myRemoved.size() > 0;
}
public boolean needsCompacting() {
return myMerged != null;
}
public boolean needsFlushing() {
return myAdded.size() > 3000 || myRemoved.size() > 3000;
}
public int getAddedCount() {
return myAdded.size();
}
public void processAddedValues(final TIntProcedure procedure) {
myAdded.forEach(procedure);
}
public int getRemovedCount() {
return myRemoved.size();
}
public void processRemovedValues(final TIntProcedure procedure) {
myRemoved.forEach(procedure);
}
public int[] getValues() throws IOException {
return getMerged().toArray();
}
private TIntHashSet getMerged() throws IOException {
if (myMerged == null) {
myMerged = new TIntHashSet();
final int[] fromDisk = myMap.get(myKey);
if (fromDisk != null) {
myMerged.addAll(fromDisk);
}
if (myRemoved.size() > 0) {
myMerged.removeAll(myRemoved.toArray());
}
if (myAdded.size() > 0) {
myMerged.addAll(myAdded.toArray());
}
}
return myMerged;
}
}
}
@@ -1,188 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* created at Jan 4, 2002
* @author Jeka
*/
package com.intellij.compiler.make;
import com.intellij.compiler.SymbolTable;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NonNls;
import java.util.*;
public class Dependency {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.make.Dependency");
public static final Dependency[] EMPTY_ARRAY = new Dependency[0];
private final int myClassQualifiedName;
private Set<FieldRef> myUsedFields;
private Set<MethodRef> myUsedMethods;
public static class FieldRef {
public final int name;
public FieldRef(int name) {
this.name = name;
}
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
FieldRef fieldRef = (FieldRef)o;
if (name != fieldRef.name) return false;
return true;
}
public int hashCode() {
return name;
}
}
public static class MethodRef {
public final int name;
public final int descriptor;
private String[] myParameterDescriptors;
public MethodRef(int name, int descriptor) {
this.name = name;
this.descriptor = descriptor;
}
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MethodRef methodRef = (MethodRef)o;
if (descriptor != methodRef.descriptor) return false;
if (name != methodRef.name) return false;
return true;
}
public int hashCode() {
int result = name;
result = 31 * result + descriptor;
return result;
}
public String getDescriptor(SymbolTable symbolTable) throws CacheCorruptedException {
final String descriptorStr = symbolTable.getSymbol(descriptor);
final String nameStr = symbolTable.getSymbol(name);
return CacheUtils.getMethodSignature(nameStr, descriptorStr);
}
public String[] getParameterDescriptors(SymbolTable symbolTable) throws CacheCorruptedException {
if (myParameterDescriptors == null) {
String descriptorStr = symbolTable.getSymbol(descriptor);
int endIndex = descriptorStr.indexOf(')');
if (endIndex <= 0) {
LOG.error("Corrupted method descriptor: " + descriptorStr);
}
myParameterDescriptors = parseParameterDescriptors(descriptorStr.substring(1, endIndex));
}
return myParameterDescriptors;
}
}
public Dependency(int classQualifiedName) {
myClassQualifiedName = classQualifiedName;
}
public int getClassQualifiedName() {
return myClassQualifiedName;
}
public void addMethod(int name, int descriptor) {
if (myUsedMethods == null) {
myUsedMethods = new HashSet<MethodRef>();
}
myUsedMethods.add(new MethodRef(name, descriptor));
}
public void addField(int name) {
if (myUsedFields == null) {
myUsedFields = new HashSet<FieldRef>();
}
myUsedFields.add(new FieldRef(name));
}
public Collection<FieldRef> getFieldRefs() {
return myUsedFields != null? Collections.unmodifiableSet(myUsedFields) : Collections.<FieldRef>emptySet();
}
public Collection<MethodRef> getMethodRefs() {
return myUsedMethods != null? Collections.unmodifiableSet(myUsedMethods) : Collections.<MethodRef>emptySet();
}
private static String[] parseParameterDescriptors(String signature) {
ArrayList<String> list = new ArrayList<String>();
String paramSignature = parseFieldType(signature);
while (paramSignature != null && !paramSignature.isEmpty()) {
list.add(paramSignature);
signature = signature.substring(paramSignature.length());
paramSignature = parseFieldType(signature);
}
return ArrayUtil.toStringArray(list);
}
private static String parseFieldType(@NonNls String signature) {
if (signature.isEmpty()) {
return null;
}
char first = signature.charAt(0);
if (first == 'I') {
return "I";
}
if (first == 'L') {
return signature.substring(0, signature.indexOf(';') + 1);
}
if (first == 'B') {
return "B";
}
if (first == 'C') {
return "C";
}
if (first == 'D') {
return "D";
}
if (first == 'F') {
return "F";
}
if (first == 'J') {
return "J";
}
if (first == 'S') {
return "S";
}
if (first == 'Z') {
return "Z";
}
if (first == '[') {
String s = parseFieldType(signature.substring(1));
return s == null ? null : "[" + s;
}
return null;
}
}

Some files were not shown because too many files have changed in this diff Show More