Merge branch 'master' of git.labs.intellij.net:idea/community

This commit is contained in:
irengrig
2010-07-27 14:40:30 +04:00
78 changed files with 916 additions and 545 deletions
+2 -2
View File
@@ -3,15 +3,14 @@
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/plugins/InspectionGadgets/InspectionGadgetsPlugin.iml" filepath="$PROJECT_DIR$/plugins/InspectionGadgets/InspectionGadgetsPlugin.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/plugins/IntelliLang/IntelliLang.iml" filepath="$PROJECT_DIR$/plugins/IntelliLang/IntelliLang.iml" group="plugins/IntelliLang" />
<module fileurl="file://$PROJECT_DIR$/plugins/IntelliLang/IntelliLang-java.iml" filepath="$PROJECT_DIR$/plugins/IntelliLang/IntelliLang-java.iml" group="plugins/IntelliLang" />
<module fileurl="file://$PROJECT_DIR$/plugins/IntelliLang/IntelliLang-javaee.iml" filepath="$PROJECT_DIR$/plugins/IntelliLang/IntelliLang-javaee.iml" group="plugins/IntelliLang" />
<module fileurl="file://$PROJECT_DIR$/plugins/IntelliLang/IntelliLang-xml.iml" filepath="$PROJECT_DIR$/plugins/IntelliLang/IntelliLang-xml.iml" group="plugins/IntelliLang" />
<module fileurl="file://$PROJECT_DIR$/plugins/IntelliLang/IntelliLangJava.iml" filepath="$PROJECT_DIR$/plugins/IntelliLang/IntelliLangJava.iml" group="plugins/IntelliLang" />
<module fileurl="file://$PROJECT_DIR$/plugins/IntentionPowerPak/IntentionPowerPackPlugin.iml" filepath="$PROJECT_DIR$/plugins/IntentionPowerPak/IntentionPowerPackPlugin.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/RegExpSupport/RegExpSupport.iml" filepath="$PROJECT_DIR$/RegExpSupport/RegExpSupport.iml" />
<module fileurl="file://$PROJECT_DIR$/platform/annotations/annotations.iml" filepath="$PROJECT_DIR$/platform/annotations/annotations.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/plugins/ant/ant.iml" filepath="$PROJECT_DIR$/plugins/ant/ant.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/plugins/relaxng/relaxng.iml" filepath="$PROJECT_DIR$/plugins/relaxng/relaxng.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/platform/boot/boot.iml" filepath="$PROJECT_DIR$/platform/boot/boot.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/platform/bootstrap/bootstrap.iml" filepath="$PROJECT_DIR$/platform/bootstrap/bootstrap.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/build/build.iml" filepath="$PROJECT_DIR$/build/build.iml" />
@@ -68,6 +67,7 @@
<module fileurl="file://$PROJECT_DIR$/platform/platform-resources/platform-resources.iml" filepath="$PROJECT_DIR$/platform/platform-resources/platform-resources.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/platform/platform-resources-en/platform-resources-en.iml" filepath="$PROJECT_DIR$/platform/platform-resources-en/platform-resources-en.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/plugins/properties/properties.iml" filepath="$PROJECT_DIR$/plugins/properties/properties.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/plugins/relaxng/relaxng.iml" filepath="$PROJECT_DIR$/plugins/relaxng/relaxng.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/resources/resources.iml" filepath="$PROJECT_DIR$/resources/resources.iml" />
<module fileurl="file://$PROJECT_DIR$/resources-en/resources-en.iml" filepath="$PROJECT_DIR$/resources-en/resources-en.iml" />
<module fileurl="file://$PROJECT_DIR$/platform/smRunner/smRunner.iml" filepath="$PROJECT_DIR$/platform/smRunner/smRunner.iml" group="platform" />
+1 -1
View File
@@ -1,6 +1,6 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="IDEA" type="Application" factoryName="Application">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<extension name="coverage" enabled="false" sample_coverage="true" runner="idea" merge="false" />
<extension name="snapshooter" />
<option name="MAIN_CLASS_NAME" value="com.intellij.idea.Main" />
<option name="VM_PARAMETERS" value=" -ea -Xbootclasspath/p:../out/classes/production/boot -Xmx192m -Didea.is.internal=true -XX:MaxPermSize=150m " />
-2
View File
@@ -23,8 +23,6 @@
<CLASSES>
<root url="jar://$MODULE_DIR$/../../../lib/dev/compilerapi.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module" module-name="lang-impl" />
@@ -13,14 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.javaCompiler;
package com.intellij.compiler;
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);
}
@@ -77,15 +77,13 @@ import com.intellij.psi.PsiCompiledElement;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.util.Chunk;
import com.intellij.util.LocalTimeCounter;
import com.intellij.util.StringBuilderSpinAllocator;
import com.intellij.util.ThrowableRunnable;
import com.intellij.util.*;
import com.intellij.util.concurrency.Semaphore;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.containers.OrderedSet;
import gnu.trove.TIntHashSet;
import gnu.trove.TObjectHashingStrategy;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -957,70 +955,149 @@ public class CompileDriver {
final Set<FileType> generatedTypes = new HashSet<FileType>();
Collection<VirtualFile> chunkFiles = chunkMap.get(currentChunk);
try {
for (int currentCompiler = 0, translatorsLength = translators.length; currentCompiler < translatorsLength; currentCompiler++) {
sink.setCurrentCompilerIndex(currentCompiler);
final TranslatingCompiler compiler = translators[currentCompiler];
if (context.getProgressIndicator().isCanceled()) {
throw new ExitException(ExitStatus.CANCELLED);
int round = 0;
final Set<VirtualFile> filesToRecompile = new HashSet<VirtualFile>();
final Set<VirtualFile> allDependent = new HashSet<VirtualFile>();
Collection<VirtualFile> dependentFiles = Collections.emptyList();
final Function<Pair<int[], Set<VirtualFile>>, Pair<int[], Set<VirtualFile>>> dependencyFilter = new DependentClassesCumulativeFilter();
do {
for (int currentCompiler = 0, translatorsLength = translators.length; currentCompiler < translatorsLength; currentCompiler++) {
sink.setCurrentCompilerIndex(currentCompiler);
final TranslatingCompiler compiler = translators[currentCompiler];
if (context.getProgressIndicator().isCanceled()) {
throw new ExitException(ExitStatus.CANCELLED);
}
DumbService.getInstance(myProject).waitForSmartMode();
if (round == 0) {
if (snapshot == null || ContainerUtil.intersects(generatedTypes, compilerManager.getRegisteredInputTypes(compiler))) {
// rescan snapshot if previously generated files may influence the input of this compiler
snapshot = ApplicationManager.getApplication().runReadAction(new Computable<VirtualFile[]>() {
public VirtualFile[] compute() {
return context.getCompileScope().getFiles(null, true);
}
});
recalculateChunkToFilesMap(context, sortedChunks, snapshot, chunkMap);
chunkFiles = chunkMap.get(currentChunk);
total = snapshot.length * translatorsLength;
}
}
final CompileContextEx _context;
if (compiler instanceof IntermediateOutputCompiler) {
// wrap compile context so that output goes into intermediate directories
final IntermediateOutputCompiler _compiler = (IntermediateOutputCompiler)compiler;
_context = new CompileContextExProxy(context) {
public VirtualFile getModuleOutputDirectory(final Module module) {
return getGenerationOutputDir(_compiler, module, false);
}
public VirtualFile getModuleOutputDirectoryForTests(final Module module) {
return getGenerationOutputDir(_compiler, module, true);
}
};
}
else {
_context = context;
}
final boolean compiledSomething =
compileSources(_context, currentChunk, compiler, chunkFiles, round == 0? forceCompile : true, isRebuild, trackDependencies, onlyCheckStatus, sink);
processed += chunkFiles.size();
_context.getProgressIndicator().setFraction(((double)processed) / total);
if (compiledSomething) {
generatedTypes.addAll(compilerManager.getRegisteredOutputTypes(compiler));
}
if (_context.getMessageCount(CompilerMessageCategory.ERROR) > 0) {
throw new ExitException(ExitStatus.ERRORS);
}
didSomething |= compiledSomething;
}
DumbService.getInstance(myProject).waitForSmartMode();
final boolean hasUnprocessedTraverseRoots = context.getDependencyCache().hasUnprocessedTraverseRoots();
if (!isRebuild && (didSomething || hasUnprocessedTraverseRoots)) {
final Set<VirtualFile> compiledWithSuccess;
final Set<VirtualFile> compiledWithErrors = CacheUtils.getFilesCompiledWithErrors(context);
if (compiledWithErrors.isEmpty()) {
compiledWithSuccess = sink.getCompiledSources();
}
else {
compiledWithSuccess = new HashSet<VirtualFile>();
compiledWithSuccess.addAll(sink.getCompiledSources());
compiledWithSuccess.removeAll(compiledWithErrors);
}
filesToRecompile.removeAll(compiledWithSuccess);
filesToRecompile.addAll(compiledWithErrors);
if (snapshot == null || ContainerUtil.intersects(generatedTypes, compilerManager.getRegisteredInputTypes(compiler))) {
// rescan snapshot if previously generated files may influence the input of this compiler
snapshot = ApplicationManager.getApplication().runReadAction(new Computable<VirtualFile[]>() {
public VirtualFile[] compute() {
return context.getCompileScope().getFiles(null, true);
}
});
final Map<Module, List<VirtualFile>> moduleToFilesMap = CompilerUtil.buildModuleToFilesMap(context, snapshot);
for (Chunk<Module> moduleChunk : sortedChunks) {
List<VirtualFile> files = Collections.emptyList();
for (Module module : moduleChunk.getNodes()) {
final List<VirtualFile> moduleFiles = moduleToFilesMap.get(module);
if (moduleFiles != null) {
files = ContainerUtil.concat(files, moduleFiles);
dependentFiles = CacheUtils.findDependentFiles(context, compiledWithSuccess, dependencyFilter);
if (ourDebugMode) {
if (!dependentFiles.isEmpty()) {
for (VirtualFile dependentFile : dependentFiles) {
System.out.println("FOUND TO RECOMPILE: " + dependentFile.getPresentableUrl());
}
}
chunkMap.put(moduleChunk, files);
else {
System.out.println("NO FILES TO RECOMPILE");
}
}
total = snapshot.length * translatorsLength;
chunkFiles = chunkMap.get(currentChunk);
}
final CompileContextEx _context;
if (compiler instanceof IntermediateOutputCompiler) {
// wrap compile context so that output goes into intermediate directories
final IntermediateOutputCompiler _compiler = (IntermediateOutputCompiler)compiler;
_context = new CompileContextExProxy(context) {
public VirtualFile getModuleOutputDirectory(final Module module) {
return getGenerationOutputDir(_compiler, module, false);
if (!dependentFiles.isEmpty()) {
filesToRecompile.addAll(dependentFiles);
allDependent.addAll(dependentFiles);
if (context.getProgressIndicator().isCanceled() || context.getMessageCount(CompilerMessageCategory.ERROR) > 0) {
break;
}
public VirtualFile getModuleOutputDirectoryForTests(final Module module) {
return getGenerationOutputDir(_compiler, module, true);
final List<VirtualFile> filesInScope = getFilesInScope(context, currentChunk, dependentFiles);
if (filesInScope.isEmpty()) {
break;
}
};
}
else {
_context = context;
}
final boolean compiledSomething =
compileSources(_context, currentChunk, compiler, chunkFiles, forceCompile, isRebuild, trackDependencies, onlyCheckStatus, sink);
processed += chunkFiles.size();
_context.getProgressIndicator().setFraction(((double)processed) / total);
if (compiledSomething) {
generatedTypes.addAll(compilerManager.getRegisteredOutputTypes(compiler));
context.getDependencyCache().clearTraverseRoots();
chunkFiles = filesInScope;
total += chunkFiles.size() * translators.length;
}
didSomething |= (hasUnprocessedTraverseRoots != context.getDependencyCache().hasUnprocessedTraverseRoots());
}
if (_context.getMessageCount(CompilerMessageCategory.ERROR) > 0) {
throw new ExitException(ExitStatus.ERRORS);
}
didSomething |= compiledSomething;
round++;
}
while (!dependentFiles.isEmpty() && context.getMessageCount(CompilerMessageCategory.ERROR) == 0);
if (CompilerConfiguration.MAKE_ENABLED) {
if (!context.getProgressIndicator().isCanceled()) {
// when cancelled pretend nothing was compiled and next compile will compile everything from the scratch
final ProgressIndicator indicator = context.getProgressIndicator();
final DependencyCache cache = context.getDependencyCache();
indicator.pushState();
indicator.setText(CompilerBundle.message("progress.updating.caches"));
indicator.setText2("");
cache.update();
indicator.setText(CompilerBundle.message("progress.saving.caches"));
cache.resetState();
indicator.popState();
}
}
if (context.getMessageCount(CompilerMessageCategory.ERROR) != 0) {
filesToRecompile.addAll(allDependent);
}
if (filesToRecompile.size() > 0) {
sink.add(null, Collections.<TranslatingCompiler.OutputItem>emptyList(), VfsUtil.toVirtualFileArray(filesToRecompile));
}
}
catch (CacheCorruptedException e) {
LOG.info(e);
context.requestRebuildNextTime(e.getMessage());
}
finally {
if (context.getMessageCount(CompilerMessageCategory.ERROR) == 0) {
@@ -1034,7 +1111,7 @@ public class CompileDriver {
ProgressManager.getInstance().executeNonCancelableSection(new Runnable() {
public void run() {
try {
final Collection<VirtualFile> deps = CacheUtils.findDependentFiles(context, Collections.<VirtualFile>emptySet(), null, null);
final Collection<VirtualFile> deps = CacheUtils.findDependentFiles(context, Collections.<VirtualFile>emptySet(), null);
if (deps.size() > 0) {
TranslatingCompilerFilesMonitor.getInstance().update(context, null, Collections.<TranslatingCompiler.OutputItem>emptyList(),
VfsUtil.toVirtualFileArray(deps));
@@ -1059,6 +1136,37 @@ public class CompileDriver {
return didSomething;
}
private static List<VirtualFile> getFilesInScope(final CompileContextEx context, final Chunk<Module> chunk, final Collection<VirtualFile> files) {
final List<VirtualFile> filesInScope = new ArrayList<VirtualFile>(files.size());
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
for (VirtualFile file : files) {
if (context.getCompileScope().belongs(file.getUrl())) {
final Module module = context.getModuleByFile(file);
if (chunk.getNodes().contains(module)) {
filesInScope.add(file);
}
}
}
}
});
return filesInScope;
}
private static void recalculateChunkToFilesMap(CompileContextEx context, List<Chunk<Module>> allChunks, VirtualFile[] snapshot, Map<Chunk<Module>, Collection<VirtualFile>> chunkMap) {
final Map<Module, List<VirtualFile>> moduleToFilesMap = CompilerUtil.buildModuleToFilesMap(context, snapshot);
for (Chunk<Module> moduleChunk : allChunks) {
List<VirtualFile> files = Collections.emptyList();
for (Module module : moduleChunk.getNodes()) {
final List<VirtualFile> moduleFiles = moduleToFilesMap.get(module);
if (moduleFiles != null) {
files = ContainerUtil.concat(files, moduleFiles);
}
}
chunkMap.put(moduleChunk, files);
}
}
private interface FileProcessingCompilerAdapterFactory {
FileProcessingCompilerAdapter create(CompileContext context, FileProcessingCompiler compiler);
}
@@ -1167,11 +1275,14 @@ public class CompileDriver {
final ArrayList<Trinity<File, String, Boolean>> toDelete = new ArrayList<Trinity<File, String, Boolean>>();
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
TranslatingCompilerFilesMonitor.getInstance()
.collectFiles(context, (TranslatingCompiler)compiler, Arrays.<VirtualFile>asList(allSources).iterator(), true
/*pass true to make sure that every source in scope file is processed*/, false
/*important! should pass false to enable collection of files to delete*/,
new ArrayList<VirtualFile>(), toDelete);
TranslatingCompilerFilesMonitor.getInstance().collectFiles(
context,
(TranslatingCompiler)compiler, Arrays.<VirtualFile>asList(allSources).iterator(),
true /*pass true to make sure that every source in scope file is processed*/,
false /*important! should pass false to enable collection of files to delete*/,
new ArrayList<VirtualFile>(),
toDelete
);
}
});
for (Trinity<File, String, Boolean> trinity : toDelete) {
@@ -1532,7 +1643,6 @@ public class CompileDriver {
context.getProgressIndicator().pushState();
final boolean[] wereFilesDeleted = new boolean[]{false};
boolean traverseRootsProcessed = false;
try {
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
@@ -1589,16 +1699,14 @@ public class CompileDriver {
}
}
final boolean hadUnprocessedTraverseRoots = context.getDependencyCache().hasUnprocessedTraverseRoots();
if ((wereFilesDeleted[0] || hadUnprocessedTraverseRoots || !toCompile.isEmpty()) && context.getMessageCount(CompilerMessageCategory.ERROR) == 0) {
if ((wereFilesDeleted[0] || !toCompile.isEmpty()) && context.getMessageCount(CompilerMessageCategory.ERROR) == 0) {
compiler.compile(context, moduleChunk, VfsUtil.toVirtualFileArray(toCompile), sink);
traverseRootsProcessed = hadUnprocessedTraverseRoots != context.getDependencyCache().hasUnprocessedTraverseRoots();
}
}
finally {
context.getProgressIndicator().popState();
}
return !toCompile.isEmpty() || traverseRootsProcessed || wereFilesDeleted[0];
return !toCompile.isEmpty() || wereFilesDeleted[0];
}
private static boolean syncOutputDir(final CompileContextEx context, final Collection<Trinity<File, String, Boolean>> toDelete) throws CacheCorruptedException {
@@ -2277,6 +2385,7 @@ public class CompileDriver {
private final CompileContextEx myContext;
private final TranslatingCompiler[] myCompilers;
private int myCurrentCompilerIdx;
private final Set<VirtualFile> myCompiledSources = new HashSet<VirtualFile>();
//private LinkedBlockingQueue<Future> myFutures = new LinkedBlockingQueue<Future>();
private TranslatorsOutputSink(CompileContextEx context, TranslatingCompiler[] compilers) {
@@ -2288,7 +2397,17 @@ public class CompileDriver {
myCurrentCompilerIdx = index;
}
public Set<VirtualFile> getCompiledSources() {
return Collections.unmodifiableSet(myCompiledSources);
}
public void add(final String outputRoot, final Collection<TranslatingCompiler.OutputItem> items, final VirtualFile[] filesToRecompile) {
for (TranslatingCompiler.OutputItem item : items) {
final VirtualFile file = item.getSourceFile();
if (file != null) {
myCompiledSources.add(file);
}
}
final TranslatingCompiler compiler = myCompilers[myCurrentCompilerIdx];
if (compiler instanceof IntermediateOutputCompiler) {
final LocalFileSystem lfs = LocalFileSystem.getInstance();
@@ -2368,7 +2487,7 @@ public class CompileDriver {
}
}
private void addItemToMap(Map<String, Collection<TranslatingCompiler.OutputItem>> map, String outputDir, TranslatingCompiler.OutputItem item) {
private static void addItemToMap(Map<String, Collection<TranslatingCompiler.OutputItem>> map, String outputDir, TranslatingCompiler.OutputItem item) {
Collection<TranslatingCompiler.OutputItem> collection = map.get(outputDir);
if (collection == null) {
collection = new ArrayList<TranslatingCompiler.OutputItem>();
@@ -2392,4 +2511,21 @@ public class CompileDriver {
}
}
}
private static class DependentClassesCumulativeFilter implements Function<Pair<int[], Set<VirtualFile>>, Pair<int[], Set<VirtualFile>>> {
private final TIntHashSet myProcessedNames = new TIntHashSet();
private final Set<VirtualFile> myProcessedFiles = new HashSet<VirtualFile>();
public Pair<int[], Set<VirtualFile>> fun(Pair<int[], Set<VirtualFile>> deps) {
final TIntHashSet currentDeps = new TIntHashSet(deps.getFirst());
currentDeps.removeAll(myProcessedNames.toArray());
myProcessedNames.addAll(deps.getFirst());
final Set<VirtualFile> depFiles = new HashSet<VirtualFile>(deps.getSecond());
depFiles.removeAll(myProcessedFiles);
myProcessedFiles.addAll(deps.getSecond());
return new Pair<int[], Set<VirtualFile>>(currentDeps.toArray(), depFiles);
}
}
}
@@ -1212,9 +1212,22 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
if (srcFile != null) {
final SourceFileInfo srcInfo = loadSourceInfo(srcFile);
if (srcInfo != null) {
final boolean srcWillBeDeleted = VfsUtil.isAncestor(eventFile, srcFile, false);
for (int projectId : srcInfo.getProjectIds().toArray()) {
if (srcInfo.isAssociated(projectId, filePath)) {
addSourceForRecompilation(projectId, srcFile, srcInfo);
if (srcWillBeDeleted) {
if (LOG.isDebugEnabled() || ourDebugMode) {
final String message = "Unschedule recompilation because of deletion " + srcFile.getPresentableUrl();
LOG.debug(message);
if (ourDebugMode) {
System.out.println(message);
}
}
removeSourceForRecompilation(projectId, Math.abs(getFileId(srcFile)));
}
else {
addSourceForRecompilation(projectId, srcFile, srcInfo);
}
}
}
}
@@ -1226,6 +1239,8 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
final TIntHashSet projects = srcInfo.getProjectIds();
if (!projects.isEmpty()) {
final ScheduleOutputsForDeletionProc deletionProc = new ScheduleOutputsForDeletionProc(file.getUrl());
deletionProc.setRootBeingDeleted(eventFile);
final int sourceFileId = Math.abs(getFileId(file));
for (int projectId : projects.toArray()) {
// mark associated outputs for deletion
srcInfo.processOutputPaths(projectId, deletionProc);
@@ -1236,7 +1251,7 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
System.out.println(message);
}
}
removeSourceForRecompilation(projectId, Math.abs(getFileId(file)));
removeSourceForRecompilation(projectId, sourceFileId);
}
}
}
@@ -1381,18 +1396,29 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
private class ScheduleOutputsForDeletionProc implements Proc {
private final String mySrcUrl;
private final LocalFileSystem myFileSystem;
@Nullable
private VirtualFile myRootBeingDeleted;
private ScheduleOutputsForDeletionProc(final String srcUrl) {
mySrcUrl = srcUrl;
myFileSystem = LocalFileSystem.getInstance();
}
public void setRootBeingDeleted(@Nullable VirtualFile rootBeingDeleted) {
myRootBeingDeleted = rootBeingDeleted;
}
public boolean execute(final int projectId, String outputPath) {
final VirtualFile outFile = myFileSystem.findFileByPath(outputPath);
if (outFile != null) { // not deleted yet
final OutputFileInfo outputInfo = loadOutputInfo(outFile);
final String classname = outputInfo != null? outputInfo.getClassName() : null;
markOutputPathForDeletion(projectId, outputPath, classname, mySrcUrl);
if (myRootBeingDeleted != null && VfsUtil.isAncestor(myRootBeingDeleted, outFile, false)) {
unmarkOutputPathForDeletion(outputPath);
}
else {
final OutputFileInfo outputInfo = loadOutputInfo(outFile);
final String classname = outputInfo != null? outputInfo.getClassName() : null;
markOutputPathForDeletion(projectId, outputPath, classname, mySrcUrl);
}
}
return true;
}
@@ -47,6 +47,4 @@ public interface BackendCompiler {
void compileFinished();
@Nullable
DependencyProcessor getDependencyProcessor();
}
@@ -26,7 +26,10 @@ import com.intellij.compiler.*;
import com.intellij.compiler.classParsing.AnnotationConstantValue;
import com.intellij.compiler.classParsing.MethodInfo;
import com.intellij.compiler.impl.CompilerUtil;
import com.intellij.compiler.make.*;
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.compiler.notNullVerification.NotNullVerifyingInstrumenter;
import com.intellij.ide.util.projectWizard.JavaModuleBuilder;
import com.intellij.openapi.application.Application;
@@ -38,7 +41,6 @@ import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.module.JavaModuleType;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.JavaSdkType;
import com.intellij.openapi.projectRoots.Sdk;
@@ -52,10 +54,8 @@ import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Chunk;
import com.intellij.util.Function;
import com.intellij.util.cls.ClsFormatException;
import gnu.trove.THashMap;
import gnu.trove.TIntHashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -74,20 +74,18 @@ public class BackendCompilerWrapper {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.javaCompiler.BackendCompilerWrapper");
private final BackendCompiler myCompiler;
private final Set<VirtualFile> mySuccesfullyCompiledJavaFiles; // VirtualFile
private final CompileContextEx myCompileContext;
private final List<VirtualFile> myFilesToCompile;
private final TranslatingCompiler.OutputSink mySink;
private final Chunk<Module> myChunk;
private final Project myProject;
private final Set<VirtualFile> myFilesToRecompile;
private final Map<Module, VirtualFile> myModuleToTempDirMap = new THashMap<Module, VirtualFile>();
private final ProjectFileIndex myProjectFileIndex;
@NonNls private static final String PACKAGE_ANNOTATION_FILE_NAME = "package-info.java";
private static final FileObject myStopThreadToken = new FileObject(new File(""), new byte[0]);
public final Map<String, Set<CompiledClass>> myFileNameToSourceMap= new THashMap<String, Set<CompiledClass>>();
private final Set<VirtualFile> myProcessedPackageInfos = new HashSet<VirtualFile>();
public BackendCompilerWrapper(Chunk<Module> chunk, @NotNull final Project project,
@NotNull List<VirtualFile> filesToCompile,
@@ -98,44 +96,19 @@ public class BackendCompilerWrapper {
myCompiler = compiler;
myCompileContext = compileContext;
myFilesToCompile = filesToCompile;
myFilesToRecompile = new HashSet<VirtualFile>(filesToCompile);
mySink = sink;
myProjectFileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
mySuccesfullyCompiledJavaFiles = new HashSet<VirtualFile>(filesToCompile.size());
}
public void compile() throws CompilerException, CacheCorruptedException {
Application application = ApplicationManager.getApplication();
final Set<VirtualFile> allDependent = new HashSet<VirtualFile>();
COMPILE:
try {
if (!myFilesToCompile.isEmpty()) {
if (application.isUnitTestMode()) {
saveTestData();
}
compileModules(buildModuleToFilesMap(myFilesToCompile));
}
Collection<VirtualFile> dependentFiles;
do {
dependentFiles = CacheUtils.findDependentFiles(myCompileContext, mySuccesfullyCompiledJavaFiles, myCompiler.getDependencyProcessor(), DEPENDENCY_FILTER);
if (!dependentFiles.isEmpty()) {
myFilesToRecompile.addAll(dependentFiles);
allDependent.addAll(dependentFiles);
if (myCompileContext.getProgressIndicator().isCanceled() || myCompileContext.getMessageCount(CompilerMessageCategory.ERROR) > 0) {
break COMPILE;
}
final List<VirtualFile> filesInScope = getFilesInScope(dependentFiles);
if (filesInScope.isEmpty()) {
break;
}
myCompileContext.getDependencyCache().clearTraverseRoots();
compileModules(buildModuleToFilesMap(filesInScope));
}
}
while (!dependentFiles.isEmpty() && myCompileContext.getMessageCount(CompilerMessageCategory.ERROR) == 0);
}
catch (SecurityException e) {
throw new CompilerException(CompilerBundle.message("error.compiler.process.not.started", e.getMessage()), e);
@@ -153,34 +126,22 @@ public class BackendCompilerWrapper {
myModuleToTempDirMap.clear();
}
// do not update caches if cancelled because there is a chance that they will be incomplete
if (CompilerConfiguration.MAKE_ENABLED) {
if (!myCompileContext.getProgressIndicator().isCanceled()) {
// when cancelled pretend nothing was compiled and next compile will compile everything from the scratch
final ProgressIndicator indicator = myCompileContext.getProgressIndicator();
final DependencyCache cache = myCompileContext.getDependencyCache();
indicator.pushState();
indicator.setText(CompilerBundle.message("progress.updating.caches"));
indicator.setText2("");
cache.update();
indicator.setText(CompilerBundle.message("progress.saving.caches"));
cache.resetState();
indicator.popState();
if (!myFilesToCompile.isEmpty() && myCompileContext.getMessageCount(CompilerMessageCategory.ERROR) == 0) {
// package-info.java hack
final List<TranslatingCompiler.OutputItem> outputs = new ArrayList<TranslatingCompiler.OutputItem>();
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
for (final VirtualFile file : myFilesToCompile) {
if (PACKAGE_ANNOTATION_FILE_NAME.equals(file.getName()) && !myProcessedPackageInfos.contains(file)) {
outputs.add(new OutputItemImpl(file));
}
}
}
});
if (!outputs.isEmpty()) {
mySink.add(null, outputs, VirtualFile.EMPTY_ARRAY);
}
}
myFilesToRecompile.removeAll(mySuccesfullyCompiledJavaFiles);
if (myCompileContext.getMessageCount(CompilerMessageCategory.ERROR) != 0) {
myFilesToRecompile.addAll(allDependent);
}
final List<TranslatingCompiler.OutputItem> outputs = processPackageInfoFiles();
if (myFilesToRecompile.size() > 0 || outputs.size() > 0) {
mySink.add(null, outputs, VfsUtil.toVirtualFileArray(myFilesToRecompile));
}
}
private Map<Module, List<VirtualFile>> buildModuleToFilesMap(final List<VirtualFile> filesToCompile) {
@@ -190,51 +151,6 @@ public class BackendCompilerWrapper {
return CompilerUtil.buildModuleToFilesMap(myCompileContext, filesToCompile);
}
// package-info.java hack
private List<TranslatingCompiler.OutputItem> processPackageInfoFiles() {
if (myFilesToRecompile.isEmpty()) {
return Collections.emptyList();
}
final List<TranslatingCompiler.OutputItem> outputs = new ArrayList<TranslatingCompiler.OutputItem>();
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
final List<VirtualFile> packageInfoFiles = new ArrayList<VirtualFile>(myFilesToRecompile.size());
for (final VirtualFile file : myFilesToRecompile) {
if (PACKAGE_ANNOTATION_FILE_NAME.equals(file.getName())) {
packageInfoFiles.add(file);
}
}
if (!packageInfoFiles.isEmpty()) {
final Set<VirtualFile> badFiles = getFilesCompiledWithErrors();
for (final VirtualFile packageInfoFile : packageInfoFiles) {
if (!badFiles.contains(packageInfoFile)) {
outputs.add(new OutputItemImpl(packageInfoFile));
myFilesToRecompile.remove(packageInfoFile);
}
}
}
}
});
return outputs;
}
private List<VirtualFile> getFilesInScope(final Collection<VirtualFile> files) {
final List<VirtualFile> filesInScope = new ArrayList<VirtualFile>(files.size());
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
for (VirtualFile file : files) {
if (myCompileContext.getCompileScope().belongs(file.getUrl())) {
final Module module = myCompileContext.getModuleByFile(file);
if (myChunk.getNodes().contains(module)) {
filesInScope.add(file);
}
}
}
}
});
return filesInScope;
}
private void compileModules(final Map<Module, List<VirtualFile>> moduleToFilesMap) throws CompilerException {
myProcessedFilesCount = 0;
try {
@@ -347,21 +263,6 @@ public class BackendCompilerWrapper {
});
}
private final TIntHashSet myProcessedNames = new TIntHashSet();
private final Set<VirtualFile> myProcessedFiles = new HashSet<VirtualFile>();
private final Function<Pair<int[], Set<VirtualFile>>, Pair<int[], Set<VirtualFile>>> DEPENDENCY_FILTER = new Function<Pair<int[], Set<VirtualFile>>, Pair<int[], Set<VirtualFile>>>() {
public Pair<int[], Set<VirtualFile>> fun(Pair<int[], Set<VirtualFile>> deps) {
final TIntHashSet currentDeps = new TIntHashSet(deps.getFirst());
currentDeps.removeAll(myProcessedNames.toArray());
myProcessedNames.addAll(deps.getFirst());
final Set<VirtualFile> depFiles = new HashSet<VirtualFile>(deps.getSecond());
depFiles.removeAll(myProcessedFiles);
myProcessedFiles.addAll(deps.getSecond());
return new Pair<int[], Set<VirtualFile>>(currentDeps.toArray(), depFiles);
}
};
private final Object lock = new Object();
private class SynchedCompilerParsing extends CompilerParsingThread {
@@ -599,8 +500,7 @@ public class BackendCompilerWrapper {
}
private void compileFinished(int exitValue, final ModuleChunk chunk, final String outputDir) {
if (exitValue != 0 && !myCompileContext.getProgressIndicator().isCanceled() &&
myCompileContext.getMessageCount(CompilerMessageCategory.ERROR) == 0) {
if (exitValue != 0 && !myCompileContext.getProgressIndicator().isCanceled() && myCompileContext.getMessageCount(CompilerMessageCategory.ERROR) == 0) {
myCompileContext.addMessage(CompilerMessageCategory.ERROR, CompilerBundle.message("error.compiler.internal.error", exitValue), null, -1, -1);
}
@@ -610,7 +510,6 @@ public class BackendCompilerWrapper {
try {
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
final Set<VirtualFile> compiledWithErrors = getFilesCompiledWithErrors();
final FileTypeManager typeManager = FileTypeManager.getInstance();
final String outputDirPath = outputDir.replace(File.separatorChar, '/');
try {
@@ -620,7 +519,7 @@ public class BackendCompilerWrapper {
if (LOG.isDebugEnabled()) {
LOG.debug("Building output items for " + root.getPresentableUrl() + "; output dir = " + outputDirPath + "; packagePrefix = \"" + packagePrefix + "\"");
}
buildOutputItemsList(outputDirPath, module, root, typeManager, compiledWithErrors, root, packagePrefix, toRefresh, results);
buildOutputItemsList(outputDirPath, module, root, typeManager, root, packagePrefix, toRefresh, results);
}
}
}
@@ -644,24 +543,8 @@ public class BackendCompilerWrapper {
myFileNameToSourceMap.clear(); // clear the map before the next use
}
private Set<VirtualFile> getFilesCompiledWithErrors() {
CompilerMessage[] messages = myCompileContext.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;
}
private void buildOutputItemsList(final String outputDir, Module module, VirtualFile from,
final FileTypeManager typeManager,
final Set<VirtualFile> compiledWithErrors,
final VirtualFile sourceRoot,
final String packagePrefix, final List<File> filesToRefresh, final Map<String, Collection<TranslatingCompiler.OutputItem>> results) throws CacheCorruptedException {
final Ref<CacheCorruptedException> exRef = new Ref<CacheCorruptedException>(null);
@@ -671,7 +554,7 @@ public class BackendCompilerWrapper {
try {
assert child.isValid();
if (!child.isDirectory() && myCompiler.getCompilableFileTypes().contains(typeManager.getFileTypeByFile(child))) {
updateOutputItemsList(outputDir, child, compiledWithErrors, sourceRoot, packagePrefix, filesToRefresh, results);
updateOutputItemsList(outputDir, child, sourceRoot, packagePrefix, filesToRefresh, results);
}
return true;
}
@@ -720,7 +603,7 @@ public class BackendCompilerWrapper {
paths.add(new CompiledClass(classQName, relativePathToSource, pathToClass));
}
private void updateOutputItemsList(final String outputDir, VirtualFile srcFile, Set<VirtualFile> compiledWithErrors,
private void updateOutputItemsList(final String outputDir, VirtualFile srcFile,
VirtualFile sourceRoot,
final String packagePrefix, final List<File> filesToRefresh,
Map<String, Collection<TranslatingCompiler.OutputItem>> results) throws CacheCorruptedException {
@@ -745,6 +628,9 @@ public class BackendCompilerWrapper {
results.put(realLocation.getFirst(), outputs);
}
outputs.add(new OutputItemImpl(realLocation.getSecond(), srcFile));
if (PACKAGE_ANNOTATION_FILE_NAME.equals(srcFile.getName())) {
myProcessedPackageInfos.add(srcFile);
}
if (CompilerConfiguration.MAKE_ENABLED) {
newCache.setPath(cc.qName, realLocation.getSecond());
}
@@ -752,9 +638,6 @@ public class BackendCompilerWrapper {
LOG.debug("Added output item: [outputDir; outputPath; sourceFile] = [" + realLocation.getFirst() + "; " +
realLocation.getSecond() + "; " + srcFile.getPresentableUrl() + "]");
}
if (!compiledWithErrors.contains(srcFile)) {
mySuccesfullyCompiledJavaFiles.add(srcFile);
}
}
else {
myCompileContext.addMessage(CompilerMessageCategory.ERROR, "Failed to copy from temporary location to output directory: " + outputPath + " (see idea.log for details)", null, -1, -1);
@@ -773,7 +656,7 @@ public class BackendCompilerWrapper {
* @param packagePrefix
* @return A 'package'-path to a given src file relative to a specified root. "/" slashes must be used
*/
protected String calcPackagePath(VirtualFile srcFile, VirtualFile sourceRoot, String packagePrefix) {
protected static String calcPackagePath(VirtualFile srcFile, VirtualFile sourceRoot, String packagePrefix) {
final String prefix = packagePrefix != null && packagePrefix.length() > 0 ? packagePrefix.replace('.', '/') + "/" : "";
return prefix + VfsUtil.getRelativePath(srcFile, sourceRoot, '/');
}
@@ -41,10 +41,6 @@ public abstract class ExternalCompiler implements BackendCompiler {
return COMPILABLE_TYPES;
}
public DependencyProcessor getDependencyProcessor() {
return null;
}
@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);
@@ -17,7 +17,6 @@ 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.DependencyProcessor;
import com.intellij.compiler.impl.javaCompiler.ModuleChunk;
import com.intellij.compiler.impl.javaCompiler.javac.JavacCompiler;
import com.intellij.compiler.impl.javaCompiler.javac.JavacConfigurable;
@@ -56,10 +55,6 @@ public class CompilerAPICompiler implements BackendCompiler {
myProject = project;
}
public DependencyProcessor getDependencyProcessor() {
return null;
}
public boolean checkCompiler(final CompileScope scope) {
return true;
}
@@ -17,7 +17,6 @@ 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.DependencyProcessor;
import com.intellij.compiler.impl.javaCompiler.ModuleChunk;
import com.intellij.compiler.impl.javaCompiler.javac.JavacSettings;
import com.intellij.openapi.application.ApplicationManager;
@@ -58,10 +57,6 @@ public class EclipseEmbeddedCompiler implements BackendCompiler {
myEclipseCompilerDriver = new EclipseCompilerDriver();
}
public DependencyProcessor getDependencyProcessor() {
return null;
}
public boolean checkCompiler(final CompileScope scope) {
return myEclipseCompilerDriver != null && myEclipseExternalCompiler.checkCompiler(scope);
}
@@ -19,9 +19,10 @@ 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.javaCompiler.DependencyProcessor;
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;
@@ -31,6 +32,7 @@ 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.*;
@@ -126,9 +128,11 @@ public class CacheUtils {
return true;
}
public static Collection<VirtualFile> findDependentFiles(final CompileContextEx context, final Set<VirtualFile> succesfullyCompiledJavaFiles,
final @Nullable DependencyProcessor additionalDependencyProcessor,
final @Nullable Function<Pair<int[], Set<VirtualFile>>, Pair<int[], Set<VirtualFile>>> filter) throws CacheCorruptedException {
public static Collection<VirtualFile> findDependentFiles(
final CompileContextEx context,
final Set<VirtualFile> succesfullyCompiledJavaFiles,
final @Nullable Function<Pair<int[], Set<VirtualFile>>, Pair<int[], Set<VirtualFile>>> filter) throws CacheCorruptedException {
if (!CompilerConfiguration.MAKE_ENABLED) {
return Collections.emptyList();
}
@@ -137,7 +141,7 @@ public class CacheUtils {
final DependencyCache dependencyCache = context.getDependencyCache();
final Pair<int[], Set<VirtualFile>> deps =
dependencyCache.findDependentClasses(context, context.getProject(), succesfullyCompiledJavaFiles, additionalDependencyProcessor);
dependencyCache.findDependentClasses(context, context.getProject(), succesfullyCompiledJavaFiles);
final Pair<int[], Set<VirtualFile>> filteredDeps = filter != null? filter.fun(deps) : deps;
final Set<VirtualFile> dependentFiles = new HashSet<VirtualFile>();
@@ -187,4 +191,20 @@ public class CacheUtils {
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;
}
}
@@ -20,9 +20,9 @@
*/
package com.intellij.compiler.make;
import com.intellij.compiler.DependencyProcessor;
import com.intellij.compiler.SymbolTable;
import com.intellij.compiler.classParsing.*;
import com.intellij.compiler.impl.javaCompiler.DependencyProcessor;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.diagnostic.Logger;
@@ -37,7 +37,6 @@ import com.intellij.util.cls.ClsUtil;
import gnu.trove.TIntHashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
@@ -390,15 +389,14 @@ public class DependencyCache {
/**
* @return qualified names of the classes that should be additionally recompiled
*/
public Pair<int[], Set<VirtualFile>> findDependentClasses(CompileContext context, Project project, Set<VirtualFile> successfullyCompiled, @Nullable final DependencyProcessor additionalProcessor)
throws CacheCorruptedException {
public Pair<int[], Set<VirtualFile>> findDependentClasses(CompileContext context, Project project, Set<VirtualFile> successfullyCompiled)
throws CacheCorruptedException {
markDependencies(context, project, successfullyCompiled, additionalProcessor);
markDependencies(context, project, successfullyCompiled);
return new Pair<int[], Set<VirtualFile>>(myMarkedInfos.toArray(), Collections.unmodifiableSet(myMarkedFiles));
}
private void markDependencies(CompileContext context, Project project, final Set<VirtualFile> successfullyCompiled,
@Nullable final DependencyProcessor additionalProcessor) throws CacheCorruptedException {
private void markDependencies(CompileContext context, Project project, final Set<VirtualFile> successfullyCompiled) throws CacheCorruptedException {
try {
if (LOG.isDebugEnabled()) {
LOG.debug("====================Marking dependent files=====================");
@@ -427,7 +425,7 @@ public class DependencyCache {
).run();
}
changedRetentionPolicyDependencyProcessor.checkAnnotationRetentionPolicyChanges(qName);
if (additionalProcessor != null) {
for (DependencyProcessor additionalProcessor : DependencyProcessor.EXTENSION_POINT_NAME.getExtensions()) {
additionalProcessor.processDependencies(context, qName);
}
}
@@ -78,7 +78,7 @@ public class JavaRefactoringSupportProvider extends DefaultRefactoringSupportPro
return new JavaPushDownHandler();
}
public RefactoringActionHandler getExtractModuleHandler() {
public RefactoringActionHandler getExtractInterfaceHandler() {
return new ExtractInterfaceHandler();
}
@@ -53,6 +53,13 @@ public interface TemplateBuilder {
*/
void replaceRange(TextRange rangeWithinElement, String replacementText);
/**
* Creates a replacement box for the specified text range within the container element.
* @param rangeWithinElement range within the container element.
* @param expression the replacement expression.
*/
public void replaceRange(TextRange rangeWithinElement, Expression expression);
/**
* Shows the live template and initiates editing process.
*/
@@ -59,6 +59,10 @@ public class DefaultRefactoringSupportProvider implements RefactoringSupportProv
return null;
}
public RefactoringActionHandler getExtractInterfaceHandler() {
return null;
}
public RefactoringActionHandler getExtractModuleHandler() {
return null;
}
@@ -80,6 +80,12 @@ public interface RefactoringSupportProvider {
*/
@Nullable RefactoringActionHandler getPushDownHandler();
/**
* @return handler for extracting members to an interface in this language
* @see com.intellij.refactoring.RefactoringActionHandler
*/
@Nullable RefactoringActionHandler getExtractInterfaceHandler();
/**
* @return handler for extracting members to some module in this language
* @see com.intellij.refactoring.RefactoringActionHandler
@@ -32,8 +32,8 @@ public interface NameSuggestionProvider {
ExtensionPointName<NameSuggestionProvider> EP_NAME = ExtensionPointName.create("com.intellij.nameSuggestionProvider");
@Nullable
SuggestedNameInfo getSuggestedNames(PsiElement element, PsiElement nameSuggestionContext, Set<String> result);
SuggestedNameInfo getSuggestedNames(PsiElement element, @Nullable PsiElement nameSuggestionContext, Set<String> result);
@Nullable
Collection<LookupElement> completeName(PsiElement element, final PsiElement nameSuggestionContext, final String prefix);
Collection<LookupElement> completeName(PsiElement element, @Nullable final PsiElement nameSuggestionContext, final String prefix);
}
@@ -123,6 +123,12 @@ public class TemplateBuilderImpl implements TemplateBuilder {
myElements.add(key);
}
public void replaceRange(TextRange rangeWithinElement, Expression expression) {
final RangeMarker key = myDocument.createRangeMarker(rangeWithinElement);
myExpressions.put(key, expression);
myElements.add(key);
}
/**
* Adds end variable after the specified element
*/
@@ -28,6 +28,7 @@ import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.actions.EditorActionUtil;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.event.*;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.ex.RangeHighlighterEx;
@@ -109,8 +110,10 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
myEditorDocument = editorFactory.createDocument("");
setLanguage(language);
myConsoleEditor = (EditorEx)editorFactory.createEditor(myEditorDocument, myProject);
myConsoleEditor.setBackgroundColor(myConsoleEditor.getColorsScheme().getColor(ConsoleViewContentType.CONSOLE_BACKGROUND_KEY));
myCurrentEditor = myConsoleEditor;
myHistoryViewer = (EditorEx)editorFactory.createViewer(((EditorFactoryImpl)editorFactory).createDocument(true), myProject);
myHistoryViewer.setBackgroundColor(myHistoryViewer.getColorsScheme().getColor(ConsoleViewContentType.CONSOLE_BACKGROUND_KEY));
myPanel.add(myHistoryViewer.getComponent(), BorderLayout.NORTH);
myPanel.add(myConsoleEditor.getComponent(), BorderLayout.CENTER);
setupComponents();
@@ -35,7 +35,6 @@ import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.impl.ModuleImpl;
import com.intellij.openapi.module.impl.scopes.JdkScope;
import com.intellij.openapi.module.impl.scopes.LibraryRuntimeClasspathScope;
import com.intellij.openapi.project.DumbAwareRunnable;
import com.intellij.openapi.project.DumbServiceImpl;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ex.ProjectEx;
@@ -619,11 +618,7 @@ public class ProjectRootManagerImpl extends ProjectRootManagerEx implements Proj
return; // in test mode suppress addition to a queue unless project is properly initialized
}
}
myStartupManager.runWhenProjectIsInitialized(new DumbAwareRunnable() {
public void run() {
DumbServiceImpl.getInstance(myProject).queueCacheUpdate(myRefreshCacheUpdaters);
}
});
DumbServiceImpl.getInstance(myProject).queueCacheUpdate(myRefreshCacheUpdaters);
}
private void addRootsToWatch() {
@@ -19,8 +19,11 @@ package com.intellij.psi.impl;
import com.intellij.psi.PsiManager;
import com.intellij.psi.util.CachedValue;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.util.ObjectUtils;
import org.jetbrains.annotations.Nullable;
import static com.intellij.util.ObjectUtils.*;
/**
* @author Dmitry Avdeev
*/
@@ -28,9 +28,12 @@ import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.ParameterizedCachedValueProvider;
import com.intellij.psi.util.ParameterizedCachedValue;
import com.intellij.psi.PsiManager;
import com.intellij.util.ObjectUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import static com.intellij.util.ObjectUtils.*;
public abstract class PsiParameterizedCachedValue<T,P> extends PsiCachedValue<T> implements ParameterizedCachedValue<T,P> {
private final ParameterizedCachedValueProvider<T,P> myProvider;
@@ -0,0 +1,35 @@
/*
* 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.refactoring.actions;
import com.intellij.lang.refactoring.RefactoringSupportProvider;
import com.intellij.refactoring.RefactoringActionHandler;
import org.jetbrains.annotations.Nullable;
public class ExtractInterfaceAction extends ExtractSuperActionBase {
public ExtractInterfaceAction() {
setInjectedContext(true);
}
@Nullable
@Override
protected RefactoringActionHandler getRefactoringHandler(RefactoringSupportProvider supportProvider) {
return supportProvider.getExtractInterfaceHandler();
}
}
@@ -13,19 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.refactoring.extractInterface;
import com.intellij.refactoring.actions.BaseExtractModuleAction;
import com.intellij.lang.Language;
import com.intellij.lang.java.JavaLanguage;
package com.intellij.refactoring.actions;
import com.intellij.lang.refactoring.RefactoringSupportProvider;
import com.intellij.refactoring.RefactoringActionHandler;
/**
* @author Dennis.Ushakov
*/
public class ExtractInterfaceAction extends BaseExtractModuleAction {
public class ExtractModuleAction extends ExtractSuperActionBase {
@Override
protected boolean isEnabledOnLanguage(Language language) {
return language instanceof JavaLanguage;
protected RefactoringActionHandler getRefactoringHandler(RefactoringSupportProvider supportProvider) {
return supportProvider.getExtractModuleHandler();
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* 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.
@@ -25,8 +25,10 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.refactoring.RefactoringActionHandler;
import com.intellij.refactoring.lang.ElementsHandler;
import org.jetbrains.annotations.Nullable;
public abstract class ExtractSuperActionBase extends BasePlatformRefactoringAction {
public abstract class BaseExtractModuleAction extends BaseRefactoringAction {
public boolean isAvailableInEditorOnly() {
return false;
}
@@ -34,27 +36,25 @@ public abstract class BaseExtractModuleAction extends BaseRefactoringAction {
public boolean isEnabledOnElements(PsiElement[] elements) {
if (elements.length > 0) {
final Language language = elements[0].getLanguage();
final RefactoringActionHandler handler = getRefactoringSupport(language).getExtractModuleHandler();
return isEnabledOnLanguage(language) && handler instanceof ElementsHandler && ((ElementsHandler)handler).isEnabledOnElements(elements);
final RefactoringActionHandler handler = getRefactoringHandler(LanguageRefactoringSupport.INSTANCE.forLanguage(language));
return handler instanceof ElementsHandler && ((ElementsHandler)handler).isEnabledOnElements(elements);
}
return false;
}
protected RefactoringSupportProvider getRefactoringSupport(Language language) {
return LanguageRefactoringSupport.INSTANCE.forLanguage(language);
}
public RefactoringActionHandler getHandler(DataContext dataContext) {
PsiFile file = LangDataKeys.PSI_FILE.getData(dataContext);
if (file == null) return null;
final RefactoringSupportProvider supportProvider = getRefactoringSupport(file.getViewProvider().getBaseLanguage());
return supportProvider != null ? supportProvider.getExtractModuleHandler() : null;
final RefactoringSupportProvider supportProvider =
LanguageRefactoringSupport.INSTANCE.forLanguage(file.getViewProvider().getBaseLanguage());
return supportProvider != null ? getRefactoringHandler(supportProvider) : null;
}
@Nullable
protected abstract RefactoringActionHandler getRefactoringHandler(RefactoringSupportProvider supportProvider);
protected boolean isAvailableForLanguage(final Language language) {
return isEnabledOnLanguage(language) && getRefactoringSupport(language).getExtractModuleHandler() != null;
return getRefactoringHandler(LanguageRefactoringSupport.INSTANCE.forLanguage(language)) != null;
}
protected abstract boolean isEnabledOnLanguage(final Language language);
}
@@ -16,38 +16,12 @@
package com.intellij.refactoring.actions;
import com.intellij.lang.Language;
import com.intellij.lang.LanguageRefactoringSupport;
import com.intellij.lang.refactoring.RefactoringSupportProvider;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.refactoring.RefactoringActionHandler;
import com.intellij.refactoring.lang.ElementsHandler;
public class ExtractSuperclassAction extends BasePlatformRefactoringAction {
public boolean isAvailableInEditorOnly() {
return false;
}
public boolean isEnabledOnElements(PsiElement[] elements) {
if (elements.length > 0) {
final Language language = elements[0].getLanguage();
final RefactoringActionHandler handler = LanguageRefactoringSupport.INSTANCE.forLanguage(language).getExtractModuleHandler();
return handler instanceof ElementsHandler && ((ElementsHandler)handler).isEnabledOnElements(elements);
}
return false;
}
public RefactoringActionHandler getHandler(DataContext dataContext) {
PsiFile file = LangDataKeys.PSI_FILE.getData(dataContext);
if (file == null) return null;
final RefactoringSupportProvider supportProvider = LanguageRefactoringSupport.INSTANCE.forLanguage(file.getViewProvider().getBaseLanguage());
return supportProvider != null ? supportProvider.getExtractSuperClassHandler() : null;
}
protected boolean isAvailableForLanguage(final Language language) {
return LanguageRefactoringSupport.INSTANCE.forLanguage(language).getExtractSuperClassHandler() != null;
public class ExtractSuperclassAction extends ExtractSuperActionBase {
@Override
protected RefactoringActionHandler getRefactoringHandler(RefactoringSupportProvider supportProvider) {
return supportProvider.getExtractSuperClassHandler();
}
}
@@ -51,17 +51,17 @@ public class FileBasedIndexProjectHandler extends AbstractProjectComponent imple
if (startupManager != null) {
startupManager.registerPreStartupActivity(new Runnable() {
public void run() {
final RefreshCacheUpdater refreshUpdater = new RefreshCacheUpdater();
final UnindexedFilesUpdater rootsChangeUpdater = new UnindexedFilesUpdater(project, index);
final RefreshCacheUpdater changedFilesUpdater = new RefreshCacheUpdater();
final UnindexedFilesUpdater unindexedFilesUpdater = new UnindexedFilesUpdater(project, index);
startupManager.registerCacheUpdater(rootsChangeUpdater);
rootManager.registerRootsChangeUpdater(rootsChangeUpdater);
rootManager.registerRefreshUpdater(refreshUpdater);
startupManager.registerCacheUpdater(unindexedFilesUpdater);
rootManager.registerRootsChangeUpdater(unindexedFilesUpdater);
rootManager.registerRefreshUpdater(changedFilesUpdater);
myIndex.registerIndexableSet(FileBasedIndexProjectHandler.this, project);
projectManager.addProjectManagerListener(project, new ProjectManagerAdapter() {
public void projectClosing(Project project) {
rootManager.unregisterRefreshUpdater(refreshUpdater);
rootManager.unregisterRootsChangeUpdater(rootsChangeUpdater);
rootManager.unregisterRefreshUpdater(changedFilesUpdater);
rootManager.unregisterRootsChangeUpdater(unindexedFilesUpdater);
myIndex.removeIndexableSet(FileBasedIndexProjectHandler.this);
}
});
@@ -27,6 +27,7 @@ import java.io.OutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
@@ -45,14 +46,16 @@ public abstract class ProcessHandler extends UserDataHolderBase {
private final Semaphore myWaitSemaphore;
private final ProcessListener myEventMulticaster;
private final TasksRunner myAfterStartNotifiedRunner;
protected ProcessHandler() {
myEventMulticaster = createEventMulticaster();
myWaitSemaphore = new Semaphore();
myWaitSemaphore.down();
addProcessListener(myAfterStartNotifiedRunner = new TasksRunner());
}
public synchronized void startNotify() {
public void startNotify() {
if(myState.compareAndSet(STATE_INITIAL, STATE_RUNNING)) {
myEventMulticaster.startNotified(new ProcessEvent(this));
}
@@ -86,7 +89,7 @@ public abstract class ProcessHandler extends UserDataHolderBase {
}
public void destroyProcess() {
afterStartNotified(new Runnable() {
myAfterStartNotifiedRunner.execute(new Runnable() {
public void run() {
if (myState.compareAndSet(STATE_RUNNING, STATE_TERMINATING)) {
fireProcessWillTerminate(true);
@@ -97,7 +100,7 @@ public abstract class ProcessHandler extends UserDataHolderBase {
}
public void detachProcess() {
afterStartNotified(new Runnable() {
myAfterStartNotifiedRunner.execute(new Runnable() {
public void run() {
if (myState.compareAndSet(STATE_RUNNING, STATE_TERMINATING)) {
fireProcessWillTerminate(false);
@@ -132,7 +135,7 @@ public abstract class ProcessHandler extends UserDataHolderBase {
}
private void notifyTerminated(final int exitCode, final boolean willBeDestroyed) {
afterStartNotified(new Runnable() {
myAfterStartNotifiedRunner.execute(new Runnable() {
public void run() {
LOG.assertTrue(isStartNotified(), "Start notify is not called");
@@ -173,20 +176,6 @@ public abstract class ProcessHandler extends UserDataHolderBase {
myEventMulticaster.processWillTerminate(new ProcessEvent(this), willBeDestroyed);
}
private synchronized void afterStartNotified(final Runnable runnable) {
if (isStartNotified()) {
runnable.run();
}
else {
addProcessListener(new ProcessAdapter() {
public void startNotified(ProcessEvent event) {
removeProcessListener(this);
runnable.run();
}
});
}
}
public boolean isStartNotified() {
return myState.get() > STATE_INITIAL;
}
@@ -207,4 +196,40 @@ public abstract class ProcessHandler extends UserDataHolderBase {
}
});
}
private final class TasksRunner extends ProcessAdapter {
private final List<Runnable> myPendingTasks = new ArrayList<Runnable>();
public void startNotified(ProcessEvent event) {
removeProcessListener(this);
// at this point it is guaranteed that nothing will be added to myPendingTasks
runPendingTasks();
}
public void execute(Runnable task) {
if (isStartNotified()) {
task.run();
}
else {
synchronized (myPendingTasks) {
myPendingTasks.add(task);
}
if (isStartNotified()) {
runPendingTasks();
}
}
}
private void runPendingTasks() {
final Runnable[] tasks;
synchronized (myPendingTasks) {
tasks = myPendingTasks.toArray(new Runnable[myPendingTasks.size()]);
myPendingTasks.clear();
}
for (Runnable task : tasks) {
task.run();
}
}
}
}
@@ -268,16 +268,19 @@ public class EditorActionUtil {
private static void moveCaretToStartOfSoftWrappedLine(Editor editor, VisualPosition currentVisual) {
CaretModel caretModel = editor.getCaretModel();
int line = currentVisual.line;
int column = 0;
if (currentVisual.column == 0) {
// We use default column value as '1' below in assumption that we work with soft-wrapped line and don't want to put cursor
// before 'after soft wrap' drawing.
int column = 1;
if (currentVisual.column <= 1) {
line--;
int nonSpaceColumn = findFirstNonSpaceColumnOnTheLine(editor, line);
column = nonSpaceColumn >= 0 ? nonSpaceColumn : 0;
column = nonSpaceColumn >= 1 ? nonSpaceColumn : 1;
}
else {
int nonSpaceColumn = findFirstNonSpaceColumnOnTheLine(editor, currentVisual.line);
if (nonSpaceColumn > 0 /* current visual line is not empty */ && nonSpaceColumn < currentVisual.column) {
if (nonSpaceColumn > 1 /* current visual line is not empty */ && nonSpaceColumn < currentVisual.column) {
column = nonSpaceColumn;
}
}
@@ -364,18 +367,13 @@ public class EditorActionUtil {
// There are soft wrap-introduced visual lines after the target one
return -1;
}
end = findFirstNonSpaceOffsetInRange(document.getCharsSequence(), softWrap.getStart(), logLineEndOffset);
if (end >= 0) {
// Width of soft wrap virtual text that is located at the target visual line.
int result = EditorUtil.calcColumnNumber(editor, softWrapText, j, softWrapTextLength);
result++; // For column reserved for 'after soft wrap' sign.
result += EditorUtil.calcColumnNumber(editor, document.getCharsSequence(), softWrap.getStart(), end);
return result;
}
else {
return -1;
}
}
int end = findFirstNonSpaceOffsetInRange(document.getCharsSequence(), softWrap.getStart(), logLineEndOffset);
if (end >= 0) {
return EditorUtil.calcColumnNumber(editor, document.getCharsSequence(), softWrap.getStart(), end);
}
else {
return -1;
}
}
return -1;
@@ -415,6 +413,7 @@ public class EditorActionUtil {
LogicalPosition blockSelectionStart = selectionModel.hasBlockSelection()
? selectionModel.getBlockStart()
: caretModel.getLogicalPosition();
SoftWrapModel softWrapModel = editor.getSoftWrapModel();
int lineNumber = editor.getCaretModel().getLogicalPosition().line;
if (lineNumber >= document.getLineCount()) {
@@ -434,7 +433,7 @@ public class EditorActionUtil {
LogicalPosition logical = editor.visualToLogicalPosition(visualEndOfLineWithCaret);
int offset = editor.logicalPositionToOffset(logical);
if (offset < editor.getDocument().getTextLength()) {
SoftWrapModel softWrapModel = editor.getSoftWrapModel();
TextChange softWrap = softWrapModel.getSoftWrap(offset);
if (softWrap == null) {
// Same offset may correspond to positions on different visual lines in case of soft wraps presence
@@ -442,21 +441,33 @@ public class EditorActionUtil {
// Hence, we check for soft wraps presence at two offsets.
softWrap = softWrapModel.getSoftWrap(offset + 1);
}
int line = currentVisualCaret.line;
int column = currentVisualCaret.column;
if (softWrap != null) {
int line = currentVisualCaret.line + 1;
int column = EditorUtil.getLastVisualLineColumnNumber(editor, line);
visualEndOfLineWithCaret = new VisualPosition(line, column);
line++;
column = EditorUtil.getLastVisualLineColumnNumber(editor, line);
}
// There is a possible case that the last visual line of particular logical line contains only white spaces. We want to move
// caret just after 'after soft wrap' drawing then.
else if (line == editor.offsetToVisualPosition(document.getLineEndOffset(lineNumber)).line) {
column = 1;
}
visualEndOfLineWithCaret = new VisualPosition(line, column);
}
}
int offset;
int newOffset;
LogicalPosition logLineEnd = editor.visualToLogicalPosition(visualEndOfLineWithCaret);
int offset = editor.logicalPositionToOffset(logLineEnd);
offset = editor.logicalPositionToOffset(logLineEnd);
lineNumber = logLineEnd.line;
int newOffset = offset;
newOffset = offset;
CharSequence text = document.getCharsSequence();
for (int i = newOffset - 1; i >= document.getLineStartOffset(lineNumber); i--) {
if (softWrapModel.getSoftWrap(i) != null) {
break;
}
if (text.charAt(i) != ' ' && text.charAt(i) != '\t') {
break;
}
@@ -22,7 +22,6 @@ import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.impl.ComplementaryFontsRegistry;
import com.intellij.openapi.editor.impl.FontInfo;
import com.intellij.openapi.editor.impl.IterationState;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
@@ -158,17 +157,42 @@ public class EditorUtil {
}
public static int calcOffset(Editor editor, CharSequence text, int start, int end, int columnNumber, int tabSize) {
// If all tabs here goes before any other chars in the line we may use an optimization here.
boolean useOptimization = true;
final int maxScanIndex = Math.min(start + columnNumber + 1, end);
if (editor == null) {
return calcSoftWrapUnawareOffset(text, start, maxScanIndex, columnNumber, tabSize);
}
int column = 0;
int tabAnchor = 0;
SoftWrapModel softWrapModel = editor.getSoftWrapModel();
for (int i = start; i < maxScanIndex; i++) {
TextChange softWrap = softWrapModel.getSoftWrap(i);
if (softWrap != null) {
tabAnchor = softWrapModel.getSoftWrapIndentWidthInColumns(softWrap);
}
if (column >= columnNumber) {
return i;
}
int diff = textWidthInColumns(editor, text, i, i + 1, tabAnchor);
if (column + diff > columnNumber) {
// We want to return offset that points to the tabulation symbol if it's represented in multiple columns and target visual
// column points inside it.
return i;
}
column += diff;
tabAnchor += diff;
}
return end;
}
private static int calcSoftWrapUnawareOffset(CharSequence text, int start, int end, int columnNumber, int tabSize) {
boolean hasNonTabs = false;
boolean hasTabs = false;
final int maxScanIndex = Math.min(start + columnNumber + 1, end);
for (int i = start; i < maxScanIndex; i++) {
for (int i = start; i < end; i++) {
if (text.charAt(i) == '\t') {
hasTabs = true;
if (hasNonTabs) {
useOptimization = false;
break;
}
} else {
@@ -176,52 +200,18 @@ public class EditorUtil {
}
}
if (editor == null || useOptimization) {
if (!hasTabs) return Math.min(start + columnNumber, end);
if (!hasTabs) return Math.min(start + columnNumber, end);
int shift = 0;
int offset = start;
for (; offset < end && offset + shift < start + columnNumber; offset++) {
if (text.charAt(offset) == '\t') {
shift += getTabLength(offset + shift - start, tabSize) - 1;
}
}
if (offset + shift > start + columnNumber) {
offset--;
}
return offset;
}
EditorEx editorImpl = (EditorEx)editor;
int shift = 0;
int offset = start;
IterationState state = new IterationState(editorImpl, offset, false);
int fontType = state.getMergedAttributes().getFontType();
int column = 0;
int x = 0;
int spaceSize = getSpaceWidth(fontType, editorImpl);
while (column < columnNumber) {
if (offset >= state.getEndOffset()) {
state.advance();
fontType = state.getMergedAttributes().getFontType();
}
char c = offset < end ? text.charAt(offset++) : ' ';
if (c == '\t') {
int prevX = x;
x = nextTabStop(x, editorImpl);
column += (x - prevX) / spaceSize;
}
else {
x += charWidth(c, fontType, editorImpl);
column++;
for (; offset < end && offset + shift < start + columnNumber; offset++) {
if (text.charAt(offset) == '\t') {
shift += getTabLength(offset + shift - start, tabSize) - 1;
}
}
if (column == columnNumber && offset < end && text.charAt(offset) == '\t' && (nextTabStop(x, editorImpl) - x) / spaceSize == 0) {
offset++;
if (offset + shift > start + columnNumber) {
offset--;
}
if (column > columnNumber) offset--;
return offset;
}
@@ -239,15 +229,21 @@ public class EditorUtil {
public static int calcColumnNumber(Editor editor, CharSequence text, int start, int offset, int tabSize) {
boolean useOptimization = true;
if (editor != null) {
TextChange softWrap = editor.getSoftWrapModel().getSoftWrap(start);
useOptimization = softWrap == null;
}
boolean hasNonTabs = false;
for (int i = start; i < offset; i++) {
if (text.charAt(i) == '\t') {
if (hasNonTabs) {
useOptimization = false;
break;
if (useOptimization) {
for (int i = start; i < offset; i++) {
if (text.charAt(i) == '\t') {
if (hasNonTabs) {
useOptimization = false;
break;
}
} else {
hasNonTabs = true;
}
} else {
hasNonTabs = true;
}
}
@@ -315,9 +311,6 @@ public class EditorUtil {
* @return number of visual columns required to represent tabulation symbols that starts at the given column
*/
public static int tabWidthInColumns(@NotNull Editor editor, int visualColumn) {
if (!editor.getSettings().isWhitespacesShown()) {
return 1;
}
int tabSize = getTabSize(editor);
int tabsNumber = visualColumn / tabSize;
return (tabsNumber + 1) * tabSize - visualColumn;
@@ -365,12 +358,7 @@ public class EditorUtil {
continue;
}
if (editor.getSettings().isWhitespacesShown()) {
result += nextTabStop(x + result, editor) - result - x;
}
else {
result += getSpaceWidth(fontType, editor);
}
result += nextTabStop(x + result, editor) - result - x;
}
return result;
}
@@ -179,34 +179,43 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener {
if (newColumnNumber < 0) newColumnNumber = 0;
if (newLineNumber < 0) newLineNumber = 0;
VisualPosition pos = new VisualPosition(newLineNumber, newColumnNumber);
int lastColumnNumber = newColumnNumber;
if (!editorSettings.isCaretInsideTabs()) {
if (!editorSettings.isCaretInsideTabs() && !myEditor.getSoftWrapModel().isInsideSoftWrap(pos)) {
LogicalPosition log = myEditor.visualToLogicalPosition(new VisualPosition(newLineNumber, newColumnNumber));
int offset = myEditor.logicalPositionToOffset(log);
CharSequence text = myEditor.getDocument().getCharsSequence();
if (offset >= 0 && offset < myEditor.getDocument().getTextLength()) {
if (text.charAt(offset) == '\t') {
if (text.charAt(offset) == '\t' && (columnShift <= 0 || offset == myOffset)) {
if (columnShift <= 0) {
newColumnNumber = myEditor.offsetToVisualPosition(offset).column;
}
else {
if (myEditor.offsetToVisualPosition(offset).column < newColumnNumber) {
TextChange softWrap = myEditor.getSoftWrapModel().getSoftWrap(offset + 1);
// There is a possible case that tabulation symbol is the last document symbol represented on a visual line before
// soft wrap. We can't just use column from 'offset + 1' because it would point on a next visual line.
if (softWrap == null) {
newColumnNumber = myEditor.offsetToVisualPosition(offset + 1).column;
}
else {
newColumnNumber = EditorUtil.getLastVisualLineColumnNumber(myEditor, newLineNumber);
}
}
}
}
}
VisualPosition pos = new VisualPosition(newLineNumber, newColumnNumber);
pos = new VisualPosition(newLineNumber, newColumnNumber);
if (columnShift != 0 && lineShift == 0 && myEditor.getSoftWrapModel().isInsideSoftWrap(pos)) {
LogicalPosition logical = myEditor.visualToLogicalPosition(pos);
int offsetToUse = myEditor.logicalPositionToOffset(logical);
if (columnShift < 0) {
offsetToUse--;
int softWrapOffset = myEditor.logicalPositionToOffset(logical);
if (columnShift >= 0) {
moveToOffset(softWrapOffset);
}
else {
int line = myEditor.offsetToVisualPosition(softWrapOffset - 1).line;
moveToVisualPosition(new VisualPosition(line, EditorUtil.getLastVisualLineColumnNumber(myEditor, line)));
}
moveToOffset(offsetToUse);
}
else {
moveToVisualPosition(pos);
@@ -839,8 +839,10 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
int spaceSize = EditorUtil.getSpaceWidth(fontType, this);
int x = 0;
int charWidth;
outer:
while (true) {
charWidth = -1;
if (offset >= textLength) {
break;
}
@@ -879,12 +881,12 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
continue;
}
prevX = x;
int diff = charToVisibleWidth(c, fontType, x);
if (diff == 0) {
charWidth = charToVisibleWidth(c, fontType, x);
if (charWidth == 0) {
break outer;
}
x += diff;
x += charWidth;
if (x >= px) {
break outer;
}
@@ -894,7 +896,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
// Process 'after soft wrap' sign.
prevX = x;
x += mySoftWrapModel.getMinDrawingWidth(SoftWrapDrawingType.AFTER_SOFT_WRAP);
charWidth = mySoftWrapModel.getMinDrawingWidth(SoftWrapDrawingType.AFTER_SOFT_WRAP);
x += charWidth;
if (x >= px) {
break outer;
}
@@ -903,11 +906,11 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
prevX = x;
c = text.charAt(offset);
int diff = charToVisibleWidth(c, fontType, x);
if (diff == 0) {
charWidth = charToVisibleWidth(c, fontType, x);
if (charWidth == 0) {
break;
} else {
x += diff;
x += charWidth;
}
if (x >= px) {
@@ -919,17 +922,17 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
}
int charWidth = EditorUtil.charWidth(c, fontType, this);
if (charWidth < 0) {
charWidth = EditorUtil.charWidth(c, fontType, this);
}
if (x >= px && c == '\t') {
if (mySettings.isCaretInsideTabs()) {
column += (px - prevX) / spaceSize;
if ((px - prevX) % spaceSize > spaceSize / 2) column++;
}
else {
if ((x - px) * 2 < x - prevX) {
column += (x - prevX) / spaceSize;
}
else if ((x - px) * 2 < x - prevX) {
column += columnsNumber(c, x, prevX, spaceSize);
}
}
else {
@@ -977,7 +980,11 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
if (c != '\t') {
return 1;
}
return (x - prevX) / spaceSize;
int result = (x - prevX) / spaceSize;
if ((x - prevX) % spaceSize > 0) {
result++;
}
return result;
}
@NotNull
@@ -1080,12 +1087,12 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
}
int x = getTabbedTextWidth(lineStartOffset, column);
return new Point(x + reserved, y);
int x = getTabbedTextWidth(lineStartOffset, column, reserved);
return new Point(x, y);
}
private int getTabbedTextWidth(int startOffset, int length) {
int x = 0;
private int getTabbedTextWidth(int startOffset, int length, int xOffset) {
int x = xOffset;
if (startOffset == 0 && myPrefixText != null) {
for (char c : myPrefixText) {
x += EditorUtil.charWidth(c, myPrefixAttributes.getFontType(), this);
@@ -1128,7 +1135,14 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
if (c == '\t') {
int prevX = x;
x = EditorUtil.nextTabStop(x, this);
column += (x - prevX) / spaceSize;
int columnDiff = (x - prevX) / spaceSize;
if ((x - prevX) % spaceSize > 0) {
// There is a possible case that tabulation symbol takes more than one visual column to represent and it's shown at
// soft-wrapped line. Soft wrap sign width may be not divisible by space size, hence, part of tabulation symbol represented
// as a separate visual column may take less space than space width.
columnDiff++;
}
column += columnDiff;
}
else {
x += EditorUtil.charWidth(c, fontType, this);
@@ -4843,11 +4857,17 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
fontType = state.getMergedAttributes().getFontType();
}
TextChange softWrap = getSoftWrapModel().getSoftWrap(i);
if (softWrap != null) {
column++; // For 'after soft wrap' drawing.
x = getSoftWrapModel().getMinDrawingWidth(SoftWrapDrawingType.AFTER_SOFT_WRAP);
}
char c = text.charAt(i);
if (c == '\t') {
int prevX = x;
x = EditorUtil.nextTabStop(x, this);
column += (x - prevX) / spaceSize;
column += columnsNumber(c, x, prevX, spaceSize);
//column += Math.max(1, (x - prevX) / spaceSize);
}
else {
@@ -253,12 +253,23 @@ public class SoftWrapModelImpl implements SoftWrapModelEx {
// We consider visual positions that point after the last symbol before soft wrap and the first symbol after soft wrap to not
// belong to soft wrap-introduced virtual space.
VisualPosition visualAfterSoftWrap = myEditor.offsetToVisualPosition(offset);
if (visualAfterSoftWrap.equals(visual)) {
if (visualAfterSoftWrap.line == visual.line && visualAfterSoftWrap.column <= visual.column) {
return false;
}
VisualPosition visualBeforeSoftWrap = myEditor.offsetToVisualPosition(offset - 1);
return visual.line > visualBeforeSoftWrap.line || visual.column > visualBeforeSoftWrap.column + 1;
int columnOffset = 0;
LogicalPosition logLineStart = myEditor.visualToLogicalPosition(new VisualPosition(visualBeforeSoftWrap.line, 0));
if (logLineStart.softWrapLinesOnCurrentLogicalLine > 0) {
int offsetLineStart = myEditor.logicalPositionToOffset(logLineStart);
softWrap = getSoftWrap(offsetLineStart);
if (softWrap != null) {
columnOffset = getSoftWrapIndentWidthInColumns(softWrap);
}
}
int width = EditorUtil.textWidthInColumns(myEditor, myEditor.getDocument().getCharsSequence(), offset - 1, offset, columnOffset);
int softWrapStartColumn = visualBeforeSoftWrap.column + width;
return visual.line > visualBeforeSoftWrap.line || visual.column > softWrapStartColumn;
}
@Override
@@ -269,7 +269,17 @@ public class DefaultSoftWrapApplianceManager implements SoftWrapApplianceManager
// Try to find target offset that is not greater than preferred position.
for (int i = preferred; i > min; i--) {
char c = text[i];
if ((i < preferred) && (SPECIAL_SYMBOLS_TO_WRAP_AFTER.contains(c) || WHITE_SPACES.contains(c))) {
if (i < preferred && WHITE_SPACES.contains(c)) {
return i + 1;
}
// Don't wrap on the non-id symbol preceded by another non-id symbol. E.g. consider that we have a statement
// like 'foo(int... args)'. We don't want to wrap on the second or third dots then.
if (i > min + 1 && !isIdSymbol(c) && !isIdSymbol(text[i - 1])) {
continue;
}
if ((i < preferred) && SPECIAL_SYMBOLS_TO_WRAP_AFTER.contains(c)) {
return i + 1;
}
if (SPECIAL_SYMBOLS_TO_WRAP_BEFORE.contains(c) || WHITE_SPACES.contains(c)) {
@@ -286,7 +296,15 @@ public class DefaultSoftWrapApplianceManager implements SoftWrapApplianceManager
// Try to find target offset that is greater than preferred position.
for (int i = preferred + 1; i < max; i++) {
char c = text[i];
if (SPECIAL_SYMBOLS_TO_WRAP_BEFORE.contains(c) || WHITE_SPACES.contains(c)) {
if (WHITE_SPACES.contains(c)) {
return i;
}
// Don't wrap on the non-id symbol preceded by another non-id symbol. E.g. consider that we have a statement
// like 'foo(int... args)'. We don't want to wrap on the second or third dots then.
if (i < max - 1 && !isIdSymbol(c) && !isIdSymbol(text[i + 1]) && !isIdSymbol(text[i - 1])) {
continue;
}
if (SPECIAL_SYMBOLS_TO_WRAP_BEFORE.contains(c)) {
return i;
}
if (SPECIAL_SYMBOLS_TO_WRAP_AFTER.contains(c) && i < max - 1) {
@@ -114,7 +114,9 @@ public class SoftWrapDataMapper {
return result;
}
}
context.onSoftWrapSymbol('a'); // Emulate 'after soft wrap' sign
// Emulate 'after soft wrap' sign
//int afterSoftWrapColumns = myEditor.getSoftWrapModel().get
context.onSoftWrapSymbol('a');
}
// Process document symbol.
@@ -35,11 +35,12 @@ import java.lang.ref.Reference;
import java.util.ArrayList;
import java.util.List;
import static com.intellij.util.ObjectUtils.*;
/**
* @author Dmitry Avdeev
*/
public abstract class CachedValueBase<T> {
protected static final Object NULL = new Object();
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.CachedValueImpl");
private final MyTimedReference<T> myData = new MyTimedReference<T>();
@@ -66,7 +67,7 @@ public abstract class CachedValueBase<T> {
}
protected void setValue(final T value, final CachedValueProvider.Result<T> result) {
myData.setData(computeData(value == null ? (T) NULL : value, getDependencies(result)));
myData.setData(computeData(value == null ? (T)NULL : value, getDependencies(result)));
if (result != null) {
myData.setIsLocked(result.isLockValue());
}
@@ -47,7 +47,7 @@ public abstract class CachedValueImpl<T> extends CachedValueBase<T> implements C
try {
value = getUpToDateOrNull();
if (value != null) {
return value == NULL ? null : value;
return value == ObjectUtils.NULL ? null : value;
}
} finally {
r.unlock();
@@ -58,7 +58,7 @@ public abstract class CachedValueImpl<T> extends CachedValueBase<T> implements C
try {
value = getUpToDateOrNull();
if (value != null) {
return value == NULL ? null : value;
return value == ObjectUtils.NULL ? null : value;
}
CachedValueProvider.Result<T> result = myProvider.compute();
@@ -30,6 +30,8 @@ import com.intellij.psi.util.ParameterizedCachedValueProvider;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import static com.intellij.util.ObjectUtils.*;
public abstract class ParameterizedCachedValueImpl<T,P> extends CachedValueBase<T> implements ParameterizedCachedValue<T,P> {
private final ParameterizedCachedValueProvider<T,P> myProvider;
@@ -508,6 +508,8 @@ action.IntroduceParameter.text=Introduce _Parameter...
action.IntroduceParameter.description=Turn the selected expression into method parameter
action.ExtractInterface.text=Extract _Interface...
action.ExtractInterface.description=Extract interface from the selected class
action.ExtractModule.text=Extract _Module...
action.ExtractModule.description=Extract module from the selected class
action.ExtractSuperclass.text=Extract S_uperclass...
action.ExtractSuperclass.description=Extract superclass from the selected class
action.TurnRefsToSuper.text=Use Interface _Where Possible...
@@ -6,7 +6,7 @@
<group id="AddAllToFavorites" class="com.intellij.ide.favoritesTreeView.actions.AddAllToFavoritesActionGroup" popup="true"/>
<action id="AddNewFavoritesList" class="com.intellij.ide.favoritesTreeView.actions.AddNewFavoritesListAction"/>
<group id="SendToFavoritesGroup" class="com.intellij.ide.favoritesTreeView.actions.SendToFavoritesGroup" popup="true"/>
<action id="RunConfiguration" class="com.intellij.execution.actions.RunConfigurationAction"/>
<action id="ChooseRunConfiguration" class="com.intellij.execution.actions.ChooseRunConfigurationAction" text="Run..." icon="/general/toolWindowRun.png"/>
<action id="ChooseDebugConfiguration" class="com.intellij.execution.actions.ChooseDebugConfigurationAction" text="Debug..." icon="/general/debug.png"/>
@@ -285,6 +285,8 @@
<action id="MemberPushDown" class="com.intellij.refactoring.actions.PushDownAction"/>
<separator/>
<action id="ExtractInclude" class="com.intellij.refactoring.actions.ExtractIncludeAction"/>
<action id="ExtractInterface" class="com.intellij.refactoring.actions.ExtractInterfaceAction"/>
<action id="ExtractModule" class="com.intellij.refactoring.actions.ExtractModuleAction"/>
<action id="ExtractSuperclass" class="com.intellij.refactoring.actions.ExtractSuperclassAction"/>
<add-to-group group-id="MainMenu" anchor="after" relative-to-action="CodeMenu"/>
</group>
@@ -16,6 +16,7 @@
package com.intellij.openapi.util;
import com.intellij.util.NullableFunction;
import com.intellij.util.ObjectUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
@@ -23,7 +24,6 @@ import org.jetbrains.annotations.Nullable;
* @author peter
*/
public class NullableLazyKey<T,H extends UserDataHolder> extends Key<T>{
private static final Object NULL = new Object();
private final NullableFunction<H,T> myFunction;
private NullableLazyKey(@NonNls String name, final NullableFunction<H, T> function) {
@@ -36,9 +36,9 @@ public class NullableLazyKey<T,H extends UserDataHolder> extends Key<T>{
T data = h.getUserData(this);
if (data == null) {
data = myFunction.fun(h);
h.putUserData(this, data == null ? (T)NULL : data);
h.putUserData(this, data == null ? (T)ObjectUtils.NULL : data);
}
return data == NULL ? null : data;
return data == ObjectUtils.NULL ? null : data;
}
public static <T,H extends UserDataHolder> NullableLazyKey<T,H> create(@NonNls String name, final NullableFunction<H, T> function) {
@@ -25,6 +25,8 @@ public class ObjectUtils {
private ObjectUtils() {
}
public static final Object NULL = new Object();
@NotNull
public static <T> T assertNotNull(@Nullable final T t) {
return _assertNotNull(t);
@@ -21,11 +21,12 @@ import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.HashSet;
import static com.intellij.util.ObjectUtils.NULL;
/**
* @author peter
*/
public abstract class FactoryMap<K,V> implements Map<K, V> {
static final Object NULL = new Object();
protected Map<K,V> myMap;
protected Map<K, V> createMap() {
@@ -25,8 +25,17 @@ import java.util.*;
*/
public class MultiMap<K, V> {
public static final MultiMap EMPTY = new MultiMap() {
@Override
protected Map createMap() {
return Collections.emptyMap();
}
};
private final Map<K, Collection<V>> myMap;
private Collection<V> values;
public MultiMap() {
myMap = createMap();
}
@@ -117,11 +126,64 @@ public class MultiMap<K, V> {
}
public Collection<? extends V> values() {
ArrayList<V> result = new ArrayList<V>();
for (Collection<V> vs : myMap.values()) {
result.addAll(vs);
if (values == null) {
values = new AbstractCollection<V>() {
@Override
public Iterator<V> iterator() {
return new Iterator<V>() {
private Iterator<Collection<V>> mapIterator = myMap.values().iterator();
private Iterator<V> itr = EmptyIterator.getInstance();
@Override
public boolean hasNext() {
do {
if (itr.hasNext()) return true;
if (!mapIterator.hasNext()) return false;
itr = mapIterator.next().iterator();
} while (true);
}
@Override
public V next() {
do {
if (itr.hasNext()) return itr.next();
if (!mapIterator.hasNext()) throw new NoSuchElementException();
itr = mapIterator.next().iterator();
} while (true);
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
@Override
public int size() {
int res = 0;
for (Collection<V> vs : myMap.values()) {
res += vs.size();
}
return res;
}
// Don't remove this method!!!
@Override
public boolean contains(Object o) {
for (Collection<V> vs : myMap.values()) {
if (vs.contains(o)) return true;
}
return false;
}
};
}
return result;
return values;
}
public void clear() {
@@ -131,4 +193,8 @@ public class MultiMap<K, V> {
public Collection<V> remove(K key) {
return myMap.remove(key);
}
public static <K, V> MultiMap<K, V> emptyInstance() {
return EMPTY;
}
}
@@ -19,6 +19,8 @@ package com.intellij.util.containers;
import java.lang.ref.SoftReference;
import java.util.concurrent.ConcurrentMap;
import static com.intellij.util.ObjectUtils.NULL;
/**
* @author peter
*/
@@ -32,15 +34,15 @@ public abstract class SoftFactoryMap<T,V> {
if (reference != null) {
final V v = reference.get();
if (v != null) {
return v == FactoryMap.NULL ? null : v;
return v == NULL ? null : v;
}
}
final V value = create(key);
SoftReference<V> valueRef = new SoftReference<V>(value == null ? (V)FactoryMap.NULL : value);
SoftReference<V> valueRef = new SoftReference<V>(value == null ? (V)NULL : value);
SoftReference<V> prevRef = myMap.putIfAbsent(key, valueRef);
V prev = prevRef == null ? null : prevRef.get();
return prev == null || prev == FactoryMap.NULL? value : prev;
return prev == null || prev == NULL ? value : prev;
}
public final boolean containsKey(T key) {
@@ -18,6 +18,8 @@ package com.intellij.util.containers;
import java.lang.ref.WeakReference;
import java.util.concurrent.ConcurrentMap;
import static com.intellij.util.ObjectUtils.NULL;
/**
* @author peter
*/
@@ -31,15 +33,15 @@ public abstract class WeakFactoryMap<T,V> {
if (reference != null) {
final V v = reference.get();
if (v != null) {
return v == FactoryMap.NULL ? null : v;
return v == NULL ? null : v;
}
}
final V value = create(key);
WeakReference<V> valueRef = new WeakReference<V>(value == null ? (V)FactoryMap.NULL : value);
WeakReference<V> valueRef = new WeakReference<V>(value == null ? (V)NULL : value);
WeakReference<V> prevRef = myMap.putIfAbsent(key, valueRef);
V prev = prevRef == null ? null : prevRef.get();
return prev == null || prev == FactoryMap.NULL? value : prev;
return prev == null || prev == NULL ? value : prev;
}
public final boolean containsKey(T key) {
+1 -1
View File
@@ -15,7 +15,7 @@
<orderEntry type="module" module-name="RegExpSupport" />
<orderEntry type="module" module-name="platform-api" />
<orderEntry type="module" module-name="java-impl" />
<orderEntry type="module" module-name="IntelliLangJava" />
<orderEntry type="module" module-name="IntelliLang" />
</component>
<component name="copyright">
<Base>
+1 -1
View File
@@ -7,7 +7,7 @@
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="IntelliLangJava" />
<orderEntry type="module" module-name="IntelliLang" />
<orderEntry type="module" module-name="lang-api" />
<orderEntry type="module" module-name="jsp-spi" />
</component>
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<module relativePaths="true" type="PLUGIN_MODULE" version="4">
<component name="DevKit.ModuleBuildProperties" url="file://$MODULE_DIR$/src/META-INF/plugin.xml" />
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_5" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/build/classes/production" />
<output-test url="file://$MODULE_DIR$/build/classes/test" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/build" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="annotations" />
<orderEntry type="module" module-name="regexp-lang" />
<orderEntry type="module" module-name="xpath-view" />
</component>
<component name="RetroweaverPlugin">
<setting name="active" value="false" />
<setting name="verbose" value="false" />
<setting name="verifyrefs" value="false" />
<setting name="targetJDK" value="" />
</component>
<component name="copyright">
<Base>
<setting name="state" value="1" />
</Base>
</component>
</module>
@@ -530,7 +530,7 @@
<component name="ProjectFileVersion" converted="true" />
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/IntelliLang.iml" filepath="$PROJECT_DIR$/IntelliLang.iml" />
<module fileurl="file://$PROJECT_DIR$/IntelliLang-standalone.iml" filepath="$PROJECT_DIR$/IntelliLang-standalone.iml" />
<module fileurl="file://$PROJECT_DIR$/../../RegExpSupport/Trunk/regexp-lang.iml" filepath="$PROJECT_DIR$/../../RegExpSupport/Trunk/regexp-lang.iml" />
<module fileurl="file://$PROJECT_DIR$/../../XPathView/Trunk/xpath-lang/xpath-lang-java.iml" filepath="$PROJECT_DIR$/../../XPathView/Trunk/xpath-lang/xpath-lang-java.iml" />
<module fileurl="file://$PROJECT_DIR$/../../XPathView/Trunk/xpath-view/xpath-view.iml" filepath="$PROJECT_DIR$/../../XPathView/Trunk/xpath-view/xpath-view.iml" />
+1 -1
View File
@@ -16,7 +16,7 @@
<orderEntry type="module" module-name="xpath" />
<orderEntry type="module" module-name="platform-api" />
<orderEntry type="library" name="Jaxen" level="project" />
<orderEntry type="module" module-name="IntelliLangJava" />
<orderEntry type="module" module-name="IntelliLang" />
</component>
<component name="copyright">
<Base>
+7 -15
View File
@@ -1,25 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<module relativePaths="true" type="PLUGIN_MODULE" version="4">
<component name="DevKit.ModuleBuildProperties" url="file://$MODULE_DIR$/src/META-INF/plugin.xml" />
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_5" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/build/classes/production" />
<output-test url="file://$MODULE_DIR$/build/classes/test" />
<module relativePaths="true" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/build" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="annotations" />
<orderEntry type="module" module-name="regexp-lang" />
<orderEntry type="module" module-name="xpath-view" />
</component>
<component name="RetroweaverPlugin">
<setting name="active" value="false" />
<setting name="verbose" value="false" />
<setting name="verifyrefs" value="false" />
<setting name="targetJDK" value="" />
<orderEntry type="module" module-name="platform-impl" />
<orderEntry type="module" module-name="lang-impl" />
<orderEntry type="module" module-name="RegExpSupport" />
<orderEntry type="module" module-name="platform-api" />
<orderEntry type="library" name="Jaxen" level="project" />
</component>
<component name="copyright">
<Base>
-22
View File
@@ -1,22 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module relativePaths="true" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="platform-impl" />
<orderEntry type="module" module-name="lang-impl" />
<orderEntry type="module" module-name="RegExpSupport" />
<orderEntry type="module" module-name="platform-api" />
<orderEntry type="library" name="Jaxen" level="project" />
</component>
<component name="copyright">
<Base>
<setting name="state" value="1" />
</Base>
</component>
</module>
-1
View File
@@ -15,7 +15,6 @@
<CLASSES>
<root url="jar://$MODULE_DIR$/../lib/trilead-ssh2-build213.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="file://$MODULE_DIR$/../trilead-ssh2-build213/src" />
</SOURCES>
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="var" path="variable/test.jar" sourcepath="variable/test.jar">
<attributes>
<attribute name="javadoc_location" value="jar:file:/$ROOT$/jars/test.jar!/" />
</attributes>
</classpathentry>
<classpathentry kind="output" path="bin" />
</classpath>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<component>
<exclude-output />
<contentEntry url="file://$MODULE_DIR$" />
<lib name="test.jar" scope="COMPILE">
<srcroot url="jar://$variable$/test.jar!/" />
</lib>
</component>
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="var" path="variable/test.jar" sourcepath="variable/test.jar" />
<classpathentry kind="output" path="bin" />
</classpath>
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>ws-internals</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
@@ -128,6 +128,12 @@ public class EclipseLibrariesModificationsTest extends EclipseVarsTest {
new String[]{});
}
public void testVarAddJavadoc() throws Exception {
doTestExisting(new String[]{"/variableidea/test.jar!/"},
new String[]{"/variableidea/test.jar!/"},
new String[]{"/jars/test.jar!/"});
}
public void testVarAddVarSource() throws Exception {
doTestExisting(new String[]{"/variableidea/test.jar!/"},
new String[]{"/variableidea/test.jar!/", "/srcvariableidea/test.jar!/"},
+1 -1
View File
@@ -32,7 +32,7 @@
</orderEntry>
<orderEntry type="module" module-name="java-impl" />
<orderEntry type="module" module-name="copyright" />
<orderEntry type="module" module-name="IntelliLangJava" />
<orderEntry type="module" module-name="IntelliLang" />
<orderEntry type="module" module-name="ant" />
<orderEntry type="module" module-name="testFramework-java" scope="TEST" />
</component>
@@ -20,6 +20,8 @@ import com.intellij.compiler.CompilerConfiguration;
import com.intellij.compiler.impl.CompilerUtil;
import com.intellij.compiler.impl.FileSetCompileScope;
import com.intellij.compiler.impl.javaCompiler.ModuleChunk;
import com.intellij.compiler.make.CacheCorruptedException;
import com.intellij.compiler.make.DependencyCache;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.configurations.JavaParameters;
@@ -34,6 +36,8 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.JavaSdkType;
import com.intellij.openapi.projectRoots.JdkUtil;
@@ -58,6 +62,7 @@ import com.intellij.util.Chunk;
import com.intellij.util.PathUtil;
import com.intellij.util.PathsList;
import com.intellij.util.SmartList;
import com.intellij.util.cls.ClsFormatException;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -207,6 +212,33 @@ public abstract class GroovyCompilerBase implements TranslatingCompiler {
}
addStubsToCompileScope(outputPaths, compileContext, module);
outputItems = Collections.emptyList();
} else {
final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
if (indicator != null) {
indicator.setText("Updating caches...");
}
final DependencyCache dependencyCache = ((CompileContextEx)compileContext).getDependencyCache();
for (OutputItem outputItem : outputItems) {
if (indicator != null) {
indicator.setText2(outputItem.getSourceFile().getName());
}
final String path = outputItem.getOutputPath();
final File classFile = new File(path);
try {
dependencyCache.reparseClassFile(classFile, FileUtil.loadFileBytes(classFile));
}
catch (ClsFormatException e) {
LOG.error(e);
}
catch (CacheCorruptedException e) {
LOG.error(e);
}
catch (IOException e) {
LOG.error(e);
}
}
}
sink.add(outputDir.getPath(), outputItems, VfsUtil.toVirtualFileArray(toRecompile));
@@ -35,6 +35,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrNewExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
@@ -88,11 +89,19 @@ public class GroovyConstructorUsagesSearchHelper {
@Override
public boolean processInReadAction(PsiReference ref) {
final PsiElement element = ref.getElement();
if (element instanceof GrCodeReferenceElement && element.getParent() instanceof GrNewExpression) {
final GrNewExpression newExpression = (GrNewExpression)element.getParent();
final PsiMethod resolvedConstructor = newExpression.resolveConstructor();
final PsiManager manager = constructor.getManager();
if (manager.areElementsEquivalent(resolvedConstructor, constructor) && !consumer.process(ref)) return false;
if (element instanceof GrCodeReferenceElement) {
GrNewExpression newExpression = null;
if (element.getParent() instanceof GrNewExpression) {
newExpression = (GrNewExpression)element.getParent();
}
else if (element.getParent() instanceof GrAnonymousClassDefinition) {
newExpression = (GrNewExpression)element.getParent().getParent();
}
if (newExpression != null) {
final PsiMethod resolvedConstructor = newExpression.resolveConstructor();
final PsiManager manager = constructor.getManager();
if (manager.areElementsEquivalent(resolvedConstructor, constructor) && !consumer.process(ref)) return false;
}
}
return true;
}
@@ -71,7 +71,7 @@ public class GppTypeConverter extends GrTypeConverter {
return true;
}
if (hasDefaultConstructor(lType)) {
if (!isMethodCallConversion(context) && hasDefaultConstructor(lType)) {
return true;
}
}
@@ -109,6 +109,8 @@ public class GrMapType extends GrLiteralClassType {
}
public String getInternalCanonicalText() {
if (myStringEntries.size() == 0) return "[:]";
List<String> components = new ArrayList<String>();
for (String s : myStringEntries.keySet()) {
components.add("'" + s + "':" + getInternalCanonicalText(myStringEntries.get(s)));
@@ -22,7 +22,7 @@ import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.codeStyle.SuggestedNameInfo;
import com.intellij.psi.statistics.JavaStatisticsManager;
import com.intellij.refactoring.rename.NameSuggestionProvider;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
import java.util.Arrays;
@@ -34,8 +34,8 @@ import java.util.Set;
*/
public class GroovyNameSuggestionProvider implements NameSuggestionProvider {
@Override
public SuggestedNameInfo getSuggestedNames(final PsiElement element, PsiElement nameSuggestionContext, Set<String> result) {
if (!(element instanceof GroovyPsiElement)) return null;
public SuggestedNameInfo getSuggestedNames(final PsiElement element, @Nullable PsiElement nameSuggestionContext, Set<String> result) {
if (nameSuggestionContext == null) nameSuggestionContext = element;
if (element instanceof GrVariable) {
final PsiType type = ((GrVariable)element).getTypeGroovy();
if (type != null) {
@@ -56,7 +56,7 @@ public class GroovyNameSuggestionProvider implements NameSuggestionProvider {
}
@Override
public Collection<LookupElement> completeName(PsiElement element, PsiElement nameSuggestionContext, String prefix) {
public Collection<LookupElement> completeName(PsiElement element, @Nullable PsiElement nameSuggestionContext, String prefix) {
return null;
}
}
@@ -27,8 +27,8 @@ import com.intellij.usageView.UsageInfo;
import com.intellij.util.containers.hash.HashMap;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrConstructorInvocation;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrConstructorCall;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
@@ -110,8 +110,8 @@ public class GrMethodCallUsageInfo extends UsageInfo implements PossiblyIncorrec
return ((GrReferenceExpression)expression).advancedResolve();
}
}
else if (parent instanceof GrConstructorInvocation) {
return ((GrConstructorInvocation)parent).resolveConstructorGenerics();
else if (parent instanceof GrConstructorCall) {
return ((GrConstructorCall)parent).resolveConstructorGenerics();
}
return null;
@@ -59,7 +59,7 @@ class Foo implements SomeTrait {
assertEmpty(make());
}
public void _testRecompileDependentGroovyClasses() throws Exception {
public void testRecompileDependentGroovyClasses() throws Exception {
def a = myFixture.addFileToProject("A.gpp", """
class A {
void foo() {
@@ -85,7 +85,7 @@ class A {
assertOutput "b", "239"
}
public void _testRecompileDependentJavaClasses() throws Exception {
public void testRecompileDependentJavaClasses() throws Exception {
def a = myFixture.addFileToProject("A.gpp", """
class A {
void foo() {
@@ -93,15 +93,15 @@ class A {
}
}
""")
myFixture.addFileToProject("B.gpp", """
myFixture.addFileToProject("B.java", """
public class B {
public static void main() {
public static void main(String[] args) {
new A().foo();
}
}
""")
assertEmpty make()
assertOutput "b", "239"
assertOutput "B", "239"
VfsUtil.saveText a.virtualFile, """
class A {
@@ -112,7 +112,7 @@ class A {
"""
assertEmpty make()
assertOutput "b", "239"
assertOutput "B", "239"
}
}
@@ -68,7 +68,7 @@ public class GroovyHighlightingTest extends LightCodeInsightFixtureTestCase {
doTest();
}
private void doTest(LocalInspectionTool... tools) throws Exception {
private void doTest(LocalInspectionTool... tools) {
myFixture.enableInspections(tools);
myFixture.testHighlighting(true, false, false, getTestName(false) + ".groovy");
}
@@ -280,4 +280,8 @@ public class GroovyHighlightingTest extends LightCodeInsightFixtureTestCase {
}
public void testNumberDuplicatesInMaps() throws Exception {doTest();}
public void testMapNotAcceptedAsStringParameter() {
doTest();
}
}
@@ -152,7 +152,7 @@ public class FindUsagesTest extends LightGroovyTestCase {
assertEquals(1, query.findAll().size());
}
private void doTestImpl(String filePath, int expectedUsagesCount) throws Throwable {
private void doTestImpl(String filePath, int expectedUsagesCount) {
myFixture.configureByFile(filePath);
assertUsageCount(expectedUsagesCount);
}
@@ -197,7 +197,11 @@ public class FindUsagesTest extends LightGroovyTestCase {
assertEquals(2, ReferencesSearch.search(file.getTopStatements()[0]).findAll().size());
}
private void doSuperMethodTest(String... firstParameterTypes) throws Exception {
public void testConstructorUsageInAnonymousClass() {
doTestImpl("A.groovy", 1);
}
private void doSuperMethodTest(String... firstParameterTypes) {
myFixture.configureByFile(getTestName(false) + ".groovy");
final GroovyFile file = (GroovyFile)myFixture.getFile();
final GrTypeDefinition psiClass = (GrTypeDefinition)file.getClasses()[0];
@@ -0,0 +1,8 @@
class Foo {
def Foo(int a) {
}
def F<caret>oo(){}
}
def z = new Foo() {}
@@ -0,0 +1,7 @@
class A {
void method(String m) {}
{
method<warning descr="'method' in 'A' cannot be applied to '([:])'">([:])</warning>
}
}
@@ -0,0 +1,9 @@
class A {
void method(Map m, Closure e ) {}
void method(String m) {}
{
meth<ref>od([:])
}
}
@@ -154,7 +154,12 @@ public class FormReferenceProvider extends PsiReferenceProvider {
classReference = referencesByString[referencesByString.length - 1];
}
processReferences(rootTag, classReference, file, processor);
final PsiReference finalClassReference = classReference;
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
processReferences(rootTag, finalClassReference, file, processor);
}
});
}
private static TextRange getValueRange(final XmlAttribute classToBind) {
+3
View File
@@ -72,6 +72,9 @@
<extensionPoint name="compiler.additionalCompileScopeProvider"
interface="com.intellij.compiler.impl.AdditionalCompileScopeProvider"/>
<extensionPoint name="compiler.makeDependencyProcessor"
interface="com.intellij.compiler.DependencyProcessor"/>
<extensionPoint name="debugger.codeFragmentFactory"
interface="com.intellij.debugger.engine.evaluation.CodeFragmentFactory"/>
-4
View File
@@ -161,10 +161,6 @@
<add-to-group group-id="RefactoringMenu" anchor="before" relative-to-action="IntroduceVariable"/>
</group>
<action id="ExtractInterface" class="com.intellij.refactoring.extractInterface.ExtractInterfaceAction">
<add-to-group group-id="RefactoringMenu" anchor="before" relative-to-action="ExtractSuperclass"/>
</action>
<group id="RefactoringMenu4">
<action id="TurnRefsToSuper" class="com.intellij.refactoring.actions.TurnRefsToSuperAction"/>
<action id="InheritanceToDelegation" class="com.intellij.refactoring.actions.InheritanceToDelegationAction"/>