From 66048ee5482c20ae6b1978dcb4947990e4bbf66c Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Mon, 26 Jul 2010 16:39:56 +0400 Subject: [PATCH 01/28] Fix: IDEA-56788 (Grails, GSP: plugin taglibs are no more resolved from application's .gsp files) --- .../intellij/util/containers/MultiMap.java | 74 ++++++++++++++++++- 1 file changed, 70 insertions(+), 4 deletions(-) diff --git a/platform/util/src/com/intellij/util/containers/MultiMap.java b/platform/util/src/com/intellij/util/containers/MultiMap.java index d8e5dcd4b838..57af35d547d0 100644 --- a/platform/util/src/com/intellij/util/containers/MultiMap.java +++ b/platform/util/src/com/intellij/util/containers/MultiMap.java @@ -25,8 +25,17 @@ import java.util.*; */ public class MultiMap { + public static final MultiMap EMPTY = new MultiMap() { + @Override + protected Map createMap() { + return Collections.emptyMap(); + } + }; + private final Map> myMap; + private Collection values; + public MultiMap() { myMap = createMap(); } @@ -117,11 +126,64 @@ public class MultiMap { } public Collection values() { - ArrayList result = new ArrayList(); - for (Collection vs : myMap.values()) { - result.addAll(vs); + if (values == null) { + values = new AbstractCollection() { + @Override + public Iterator iterator() { + return new Iterator() { + + private Iterator> mapIterator = myMap.values().iterator(); + + private Iterator 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 vs : myMap.values()) { + res += vs.size(); + } + + return res; + } + + // Don't remove this method!!! + @Override + public boolean contains(Object o) { + for (Collection 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 { public Collection remove(K key) { return myMap.remove(key); } + + public static MultiMap emptyInstance() { + return EMPTY; + } } From 12846f12040b308055b74598a2a3ff6ff663f851 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Mon, 26 Jul 2010 16:29:30 +0400 Subject: [PATCH 02/28] dependencies are searched for inside CompileDriver --- .../intellij/compiler/impl/CompileDriver.java | 265 +++++++++++++----- .../impl/TranslatingCompilerFilesMonitor.java | 36 ++- .../javaCompiler/BackendCompilerWrapper.java | 171 ++--------- .../intellij/compiler/make/CacheUtils.java | 19 ++ 4 files changed, 277 insertions(+), 214 deletions(-) diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java b/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java index b1f30cf4e2e5..dff37de3da1f 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java @@ -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,145 @@ public class CompileDriver { final Set generatedTypes = new HashSet(); Collection 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); - } - - DumbService.getInstance(myProject).waitForSmartMode(); - - 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() { - public VirtualFile[] compute() { - return context.getCompileScope().getFiles(null, true); - } - }); - final Map> moduleToFilesMap = CompilerUtil.buildModuleToFilesMap(context, snapshot); - for (Chunk moduleChunk : sortedChunks) { - List files = Collections.emptyList(); - for (Module module : moduleChunk.getNodes()) { - final List moduleFiles = moduleToFilesMap.get(module); - if (moduleFiles != null) { - files = ContainerUtil.concat(files, moduleFiles); - } - } - chunkMap.put(moduleChunk, files); + int round = 0; + final Set filesToRecompile = new HashSet(); + final Set allDependent = new HashSet(); + Collection dependentFiles = Collections.emptyList(); + final Function>, Pair>> 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); } - total = snapshot.length * translatorsLength; - chunkFiles = chunkMap.get(currentChunk); + + 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() { + 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; } - 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); - } - }; + final Set compiledWithSuccess; + final Set compiledWithErrors = CacheUtils.getFilesCompiledWithErrors(context); + if (compiledWithErrors.isEmpty()) { + compiledWithSuccess = sink.getCompiledSources(); } else { - _context = context; + compiledWithSuccess = new HashSet(); + compiledWithSuccess.addAll(sink.getCompiledSources()); + compiledWithSuccess.removeAll(compiledWithErrors); } - 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)); + filesToRecompile.removeAll(compiledWithSuccess); + filesToRecompile.addAll(compiledWithErrors); + + // TODO: use something to obtain additional processor EXTENSION POINT? + dependentFiles = CacheUtils.findDependentFiles(context, compiledWithSuccess, null, dependencyFilter); + + if (ourDebugMode) { + if (!dependentFiles.isEmpty()) { + for (VirtualFile dependentFile : dependentFiles) { + System.out.println("FOUND TO RECOMPILE: " + dependentFile.getPresentableUrl()); + } + } + else { + System.out.println("NO FILES TO RECOMPILE"); + } } - - if (_context.getMessageCount(CompilerMessageCategory.ERROR) > 0) { - throw new ExitException(ExitStatus.ERRORS); + + if (!dependentFiles.isEmpty()) { + filesToRecompile.addAll(dependentFiles); + allDependent.addAll(dependentFiles); + if (context.getProgressIndicator().isCanceled() || context.getMessageCount(CompilerMessageCategory.ERROR) > 0) { + break; + } + final List filesInScope = getFilesInScope(context, currentChunk, dependentFiles); + if (filesInScope.isEmpty()) { + break; + } + context.getDependencyCache().clearTraverseRoots(); + chunkFiles = filesInScope; + total += chunkFiles.size() * translators.length; } - - 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.emptyList(), VfsUtil.toVirtualFileArray(filesToRecompile)); + } + } + catch (CacheCorruptedException e) { + LOG.info(e); + context.requestRebuildNextTime(e.getMessage()); } finally { if (context.getMessageCount(CompilerMessageCategory.ERROR) == 0) { @@ -1059,6 +1132,37 @@ public class CompileDriver { return didSomething; } + private static List getFilesInScope(final CompileContextEx context, final Chunk chunk, final Collection files) { + final List filesInScope = new ArrayList(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> allChunks, VirtualFile[] snapshot, Map, Collection> chunkMap) { + final Map> moduleToFilesMap = CompilerUtil.buildModuleToFilesMap(context, snapshot); + for (Chunk moduleChunk : allChunks) { + List files = Collections.emptyList(); + for (Module module : moduleChunk.getNodes()) { + final List 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 +1271,14 @@ public class CompileDriver { final ArrayList> toDelete = new ArrayList>(); ApplicationManager.getApplication().runReadAction(new Runnable() { public void run() { - TranslatingCompilerFilesMonitor.getInstance() - .collectFiles(context, (TranslatingCompiler)compiler, Arrays.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(), toDelete); + TranslatingCompilerFilesMonitor.getInstance().collectFiles( + context, + (TranslatingCompiler)compiler, Arrays.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(), + toDelete + ); } }); for (Trinity trinity : toDelete) { @@ -2277,6 +2384,7 @@ public class CompileDriver { private final CompileContextEx myContext; private final TranslatingCompiler[] myCompilers; private int myCurrentCompilerIdx; + private final Set myCompiledSources = new HashSet(); //private LinkedBlockingQueue myFutures = new LinkedBlockingQueue(); private TranslatorsOutputSink(CompileContextEx context, TranslatingCompiler[] compilers) { @@ -2288,7 +2396,17 @@ public class CompileDriver { myCurrentCompilerIdx = index; } + public Set getCompiledSources() { + return Collections.unmodifiableSet(myCompiledSources); + } + public void add(final String outputRoot, final Collection 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 +2486,7 @@ public class CompileDriver { } } - private void addItemToMap(Map> map, String outputDir, TranslatingCompiler.OutputItem item) { + private static void addItemToMap(Map> map, String outputDir, TranslatingCompiler.OutputItem item) { Collection collection = map.get(outputDir); if (collection == null) { collection = new ArrayList(); @@ -2392,4 +2510,21 @@ public class CompileDriver { } } } + + private static class DependentClassesCumulativeFilter implements Function>, Pair>> { + + private final TIntHashSet myProcessedNames = new TIntHashSet(); + private final Set myProcessedFiles = new HashSet(); + + public Pair> fun(Pair> deps) { + final TIntHashSet currentDeps = new TIntHashSet(deps.getFirst()); + currentDeps.removeAll(myProcessedNames.toArray()); + myProcessedNames.addAll(deps.getFirst()); + + final Set depFiles = new HashSet(deps.getSecond()); + depFiles.removeAll(myProcessedFiles); + myProcessedFiles.addAll(deps.getSecond()); + return new Pair>(currentDeps.toArray(), depFiles); + } + } } diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/TranslatingCompilerFilesMonitor.java b/java/compiler/impl/src/com/intellij/compiler/impl/TranslatingCompilerFilesMonitor.java index 5c8a5679c08c..f4abe40f4b9d 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/TranslatingCompilerFilesMonitor.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/TranslatingCompilerFilesMonitor.java @@ -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; } diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/BackendCompilerWrapper.java b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/BackendCompilerWrapper.java index ff0ee19259cb..3e41738c0d3e 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/BackendCompilerWrapper.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/BackendCompilerWrapper.java @@ -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 mySuccesfullyCompiledJavaFiles; // VirtualFile private final CompileContextEx myCompileContext; private final List myFilesToCompile; private final TranslatingCompiler.OutputSink mySink; private final Chunk myChunk; private final Project myProject; - private final Set myFilesToRecompile; private final Map myModuleToTempDirMap = new THashMap(); 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> myFileNameToSourceMap= new THashMap>(); - + private final Set myProcessedPackageInfos = new HashSet(); public BackendCompilerWrapper(Chunk chunk, @NotNull final Project project, @NotNull List filesToCompile, @@ -98,44 +96,19 @@ public class BackendCompilerWrapper { myCompiler = compiler; myCompileContext = compileContext; myFilesToCompile = filesToCompile; - myFilesToRecompile = new HashSet(filesToCompile); mySink = sink; myProjectFileIndex = ProjectRootManager.getInstance(myProject).getFileIndex(); - mySuccesfullyCompiledJavaFiles = new HashSet(filesToCompile.size()); } public void compile() throws CompilerException, CacheCorruptedException { Application application = ApplicationManager.getApplication(); - final Set allDependent = new HashSet(); - COMPILE: try { if (!myFilesToCompile.isEmpty()) { if (application.isUnitTestMode()) { saveTestData(); } - compileModules(buildModuleToFilesMap(myFilesToCompile)); } - - Collection 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 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 outputs = new ArrayList(); + 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 outputs = processPackageInfoFiles(); - if (myFilesToRecompile.size() > 0 || outputs.size() > 0) { - mySink.add(null, outputs, VfsUtil.toVirtualFileArray(myFilesToRecompile)); - } } private Map> buildModuleToFilesMap(final List filesToCompile) { @@ -190,51 +151,6 @@ public class BackendCompilerWrapper { return CompilerUtil.buildModuleToFilesMap(myCompileContext, filesToCompile); } - // package-info.java hack - private List processPackageInfoFiles() { - if (myFilesToRecompile.isEmpty()) { - return Collections.emptyList(); - } - final List outputs = new ArrayList(); - ApplicationManager.getApplication().runReadAction(new Runnable() { - public void run() { - final List packageInfoFiles = new ArrayList(myFilesToRecompile.size()); - for (final VirtualFile file : myFilesToRecompile) { - if (PACKAGE_ANNOTATION_FILE_NAME.equals(file.getName())) { - packageInfoFiles.add(file); - } - } - if (!packageInfoFiles.isEmpty()) { - final Set badFiles = getFilesCompiledWithErrors(); - for (final VirtualFile packageInfoFile : packageInfoFiles) { - if (!badFiles.contains(packageInfoFile)) { - outputs.add(new OutputItemImpl(packageInfoFile)); - myFilesToRecompile.remove(packageInfoFile); - } - } - } - } - }); - return outputs; - } - - private List getFilesInScope(final Collection files) { - final List filesInScope = new ArrayList(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> moduleToFilesMap) throws CompilerException { myProcessedFilesCount = 0; try { @@ -347,21 +263,6 @@ public class BackendCompilerWrapper { }); } - private final TIntHashSet myProcessedNames = new TIntHashSet(); - private final Set myProcessedFiles = new HashSet(); - private final Function>, Pair>> DEPENDENCY_FILTER = new Function>, Pair>>() { - public Pair> fun(Pair> deps) { - final TIntHashSet currentDeps = new TIntHashSet(deps.getFirst()); - currentDeps.removeAll(myProcessedNames.toArray()); - myProcessedNames.addAll(deps.getFirst()); - - final Set depFiles = new HashSet(deps.getSecond()); - depFiles.removeAll(myProcessedFiles); - myProcessedFiles.addAll(deps.getSecond()); - return new Pair>(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 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 getFilesCompiledWithErrors() { - CompilerMessage[] messages = myCompileContext.getMessages(CompilerMessageCategory.ERROR); - Set compiledWithErrors = Collections.emptySet(); - if (messages.length > 0) { - compiledWithErrors = new HashSet(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 compiledWithErrors, final VirtualFile sourceRoot, final String packagePrefix, final List filesToRefresh, final Map> results) throws CacheCorruptedException { final Ref exRef = new Ref(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 compiledWithErrors, + private void updateOutputItemsList(final String outputDir, VirtualFile srcFile, VirtualFile sourceRoot, final String packagePrefix, final List filesToRefresh, Map> 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, '/'); } diff --git a/java/compiler/impl/src/com/intellij/compiler/make/CacheUtils.java b/java/compiler/impl/src/com/intellij/compiler/make/CacheUtils.java index e2ce0fa640d7..4dbae4ca626d 100644 --- a/java/compiler/impl/src/com/intellij/compiler/make/CacheUtils.java +++ b/java/compiler/impl/src/com/intellij/compiler/make/CacheUtils.java @@ -22,6 +22,8 @@ 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 +33,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.*; @@ -187,4 +190,20 @@ public class CacheUtils { return dependentFiles; } + + @NotNull + public static Set getFilesCompiledWithErrors(final CompileContextEx context) { + CompilerMessage[] messages = context.getMessages(CompilerMessageCategory.ERROR); + Set compiledWithErrors = Collections.emptySet(); + if (messages.length > 0) { + compiledWithErrors = new HashSet(messages.length); + for (CompilerMessage message : messages) { + final VirtualFile file = message.getVirtualFile(); + if (file != null) { + compiledWithErrors.add(file); + } + } + } + return compiledWithErrors; + } } From 38d3091442a66a52a7e5ba7051667c2311dfdb1e Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Mon, 26 Jul 2010 16:49:37 +0400 Subject: [PATCH 03/28] IDEA-53596 Soft wrap for editors Corrected editor navigation in case of document with tab symbols (cases when tabulations are on soft-wrapped lines and occupy various number of visual columns) --- .../editor/actions/EditorActionUtil.java | 57 +++++---- .../openapi/editor/ex/util/EditorUtil.java | 114 ++++++++---------- .../openapi/editor/impl/CaretModelImpl.java | 27 +++-- .../openapi/editor/impl/EditorImpl.java | 58 ++++++--- .../editor/impl/SoftWrapModelImpl.java | 15 ++- .../impl/softwrap/SoftWrapDataMapper.java | 4 +- 6 files changed, 158 insertions(+), 117 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/EditorActionUtil.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/EditorActionUtil.java index 80932b63a6d8..2a801fde55be 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/EditorActionUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/EditorActionUtil.java @@ -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; } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java index e0e517dbbad9..61895d40e15a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java @@ -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; } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java index b62353d3467d..6f4d4290843a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java @@ -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); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index 6a64a132032b..b3a4b5d666c3 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -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 { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java index f0fdd6eda822..90b592a2112d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java @@ -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 diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapDataMapper.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapDataMapper.java index 96a840e27902..dbc9c6070f7e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapDataMapper.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapDataMapper.java @@ -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. From e5e13267d3ad4f3bd0de3af3efbf44cc896fae2b Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Mon, 26 Jul 2010 18:26:24 +0400 Subject: [PATCH 04/28] DependencyProcessor extension point --- .../javaCompiler => }/DependencyProcessor.java | 5 ++++- .../com/intellij/compiler/impl/CompileDriver.java | 5 ++--- .../impl/javaCompiler/BackendCompiler.java | 2 -- .../impl/javaCompiler/ExternalCompiler.java | 4 ---- .../impl/javaCompiler/api/CompilerAPICompiler.java | 5 ----- .../eclipse/EclipseEmbeddedCompiler.java | 5 ----- .../src/com/intellij/compiler/make/CacheUtils.java | 11 ++++++----- .../intellij/compiler/make/DependencyCache.java | 14 ++++++-------- resources/src/META-INF/IdeaPlugin.xml | 3 +++ 9 files changed, 21 insertions(+), 33 deletions(-) rename java/compiler/impl/src/com/intellij/compiler/{impl/javaCompiler => }/DependencyProcessor.java (78%) diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/DependencyProcessor.java b/java/compiler/impl/src/com/intellij/compiler/DependencyProcessor.java similarity index 78% rename from java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/DependencyProcessor.java rename to java/compiler/impl/src/com/intellij/compiler/DependencyProcessor.java index 5f09a8c25d53..dbf3703c2337 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/DependencyProcessor.java +++ b/java/compiler/impl/src/com/intellij/compiler/DependencyProcessor.java @@ -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 EXTENSION_POINT_NAME = ExtensionPointName.create("com.intellij.compiler.makeDependencyProcessor"); + void processDependencies(CompileContext context, int classQualifiedName); } diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java b/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java index dff37de3da1f..5a0d69840443 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java @@ -1032,8 +1032,7 @@ public class CompileDriver { filesToRecompile.removeAll(compiledWithSuccess); filesToRecompile.addAll(compiledWithErrors); - // TODO: use something to obtain additional processor EXTENSION POINT? - dependentFiles = CacheUtils.findDependentFiles(context, compiledWithSuccess, null, dependencyFilter); + dependentFiles = CacheUtils.findDependentFiles(context, compiledWithSuccess, dependencyFilter); if (ourDebugMode) { if (!dependentFiles.isEmpty()) { @@ -1107,7 +1106,7 @@ public class CompileDriver { ProgressManager.getInstance().executeNonCancelableSection(new Runnable() { public void run() { try { - final Collection deps = CacheUtils.findDependentFiles(context, Collections.emptySet(), null, null); + final Collection deps = CacheUtils.findDependentFiles(context, Collections.emptySet(), null); if (deps.size() > 0) { TranslatingCompilerFilesMonitor.getInstance().update(context, null, Collections.emptyList(), VfsUtil.toVirtualFileArray(deps)); diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/BackendCompiler.java b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/BackendCompiler.java index 7659c56a3927..9da4a3952baf 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/BackendCompiler.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/BackendCompiler.java @@ -47,6 +47,4 @@ public interface BackendCompiler { void compileFinished(); - @Nullable - DependencyProcessor getDependencyProcessor(); } diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/ExternalCompiler.java b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/ExternalCompiler.java index 22a9f66d715c..c882cc2c27de 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/ExternalCompiler.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/ExternalCompiler.java @@ -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); diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/api/CompilerAPICompiler.java b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/api/CompilerAPICompiler.java index a70bd9418afe..110b05a05edc 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/api/CompilerAPICompiler.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/api/CompilerAPICompiler.java @@ -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; } diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/eclipse/EclipseEmbeddedCompiler.java b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/eclipse/EclipseEmbeddedCompiler.java index 29febbecc1ea..550543ec2779 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/eclipse/EclipseEmbeddedCompiler.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/eclipse/EclipseEmbeddedCompiler.java @@ -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); } diff --git a/java/compiler/impl/src/com/intellij/compiler/make/CacheUtils.java b/java/compiler/impl/src/com/intellij/compiler/make/CacheUtils.java index 4dbae4ca626d..69bfd9d5254d 100644 --- a/java/compiler/impl/src/com/intellij/compiler/make/CacheUtils.java +++ b/java/compiler/impl/src/com/intellij/compiler/make/CacheUtils.java @@ -19,7 +19,6 @@ 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; @@ -129,9 +128,11 @@ public class CacheUtils { return true; } - public static Collection findDependentFiles(final CompileContextEx context, final Set succesfullyCompiledJavaFiles, - final @Nullable DependencyProcessor additionalDependencyProcessor, - final @Nullable Function>, Pair>> filter) throws CacheCorruptedException { + public static Collection findDependentFiles( + final CompileContextEx context, + final Set succesfullyCompiledJavaFiles, + final @Nullable Function>, Pair>> filter) throws CacheCorruptedException { + if (!CompilerConfiguration.MAKE_ENABLED) { return Collections.emptyList(); } @@ -140,7 +141,7 @@ public class CacheUtils { final DependencyCache dependencyCache = context.getDependencyCache(); final Pair> deps = - dependencyCache.findDependentClasses(context, context.getProject(), succesfullyCompiledJavaFiles, additionalDependencyProcessor); + dependencyCache.findDependentClasses(context, context.getProject(), succesfullyCompiledJavaFiles); final Pair> filteredDeps = filter != null? filter.fun(deps) : deps; final Set dependentFiles = new HashSet(); diff --git a/java/compiler/impl/src/com/intellij/compiler/make/DependencyCache.java b/java/compiler/impl/src/com/intellij/compiler/make/DependencyCache.java index f58f6b6df770..05fd42531799 100644 --- a/java/compiler/impl/src/com/intellij/compiler/make/DependencyCache.java +++ b/java/compiler/impl/src/com/intellij/compiler/make/DependencyCache.java @@ -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> findDependentClasses(CompileContext context, Project project, Set successfullyCompiled, @Nullable final DependencyProcessor additionalProcessor) - throws CacheCorruptedException { + public Pair> findDependentClasses(CompileContext context, Project project, Set successfullyCompiled) + throws CacheCorruptedException { - markDependencies(context, project, successfullyCompiled, additionalProcessor); + markDependencies(context, project, successfullyCompiled); return new Pair>(myMarkedInfos.toArray(), Collections.unmodifiableSet(myMarkedFiles)); } - private void markDependencies(CompileContext context, Project project, final Set successfullyCompiled, - @Nullable final DependencyProcessor additionalProcessor) throws CacheCorruptedException { + private void markDependencies(CompileContext context, Project project, final Set 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); } } diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index 3798aaae98e2..987ca08568ee 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -72,6 +72,9 @@ + + From f88a1c4787e8271446555bfe30e498790d1946ec Mon Sep 17 00:00:00 2001 From: "sergey.vasiliev" Date: Mon, 26 Jul 2010 18:31:19 +0400 Subject: [PATCH 05/28] Spring: 1. "insert bean dependency" action(IDEA-56620) and 2. Generate @Qualifier quick fix --- .../com/intellij/codeInsight/template/TemplateBuilder.java | 7 +++++++ .../intellij/codeInsight/template/TemplateBuilderImpl.java | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/platform/lang-api/src/com/intellij/codeInsight/template/TemplateBuilder.java b/platform/lang-api/src/com/intellij/codeInsight/template/TemplateBuilder.java index 565e50870ac1..c921ac1da354 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/template/TemplateBuilder.java +++ b/platform/lang-api/src/com/intellij/codeInsight/template/TemplateBuilder.java @@ -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. */ diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/TemplateBuilderImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/template/TemplateBuilderImpl.java index 3f50d8b4642f..1b2fb89b798f 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/TemplateBuilderImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/TemplateBuilderImpl.java @@ -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 */ From 5ce2891148812392d996d4041e194358d8d278c6 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Mon, 26 Jul 2010 19:01:08 +0400 Subject: [PATCH 06/28] do not search dependencies in rebuild mode and when nothing was compiled before --- .../intellij/compiler/impl/CompileDriver.java | 86 ++++++++++--------- 1 file changed, 44 insertions(+), 42 deletions(-) diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java b/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java index 5a0d69840443..230c9e999ec9 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java @@ -1019,47 +1019,52 @@ public class CompileDriver { didSomething |= compiledSomething; } - final Set compiledWithSuccess; - final Set compiledWithErrors = CacheUtils.getFilesCompiledWithErrors(context); - if (compiledWithErrors.isEmpty()) { - compiledWithSuccess = sink.getCompiledSources(); - } - else { - compiledWithSuccess = new HashSet(); - compiledWithSuccess.addAll(sink.getCompiledSources()); - compiledWithSuccess.removeAll(compiledWithErrors); - } - filesToRecompile.removeAll(compiledWithSuccess); - filesToRecompile.addAll(compiledWithErrors); - - dependentFiles = CacheUtils.findDependentFiles(context, compiledWithSuccess, dependencyFilter); - - if (ourDebugMode) { - if (!dependentFiles.isEmpty()) { - for (VirtualFile dependentFile : dependentFiles) { - System.out.println("FOUND TO RECOMPILE: " + dependentFile.getPresentableUrl()); - } + final boolean hasUnprocessedTraverseRoots = context.getDependencyCache().hasUnprocessedTraverseRoots(); + if (!isRebuild && (didSomething || hasUnprocessedTraverseRoots)) { + final Set compiledWithSuccess; + final Set compiledWithErrors = CacheUtils.getFilesCompiledWithErrors(context); + if (compiledWithErrors.isEmpty()) { + compiledWithSuccess = sink.getCompiledSources(); } else { - System.out.println("NO FILES TO RECOMPILE"); + compiledWithSuccess = new HashSet(); + compiledWithSuccess.addAll(sink.getCompiledSources()); + compiledWithSuccess.removeAll(compiledWithErrors); } + filesToRecompile.removeAll(compiledWithSuccess); + filesToRecompile.addAll(compiledWithErrors); + + dependentFiles = CacheUtils.findDependentFiles(context, compiledWithSuccess, dependencyFilter); + + if (ourDebugMode) { + if (!dependentFiles.isEmpty()) { + for (VirtualFile dependentFile : dependentFiles) { + System.out.println("FOUND TO RECOMPILE: " + dependentFile.getPresentableUrl()); + } + } + else { + System.out.println("NO FILES TO RECOMPILE"); + } + } + + if (!dependentFiles.isEmpty()) { + filesToRecompile.addAll(dependentFiles); + allDependent.addAll(dependentFiles); + if (context.getProgressIndicator().isCanceled() || context.getMessageCount(CompilerMessageCategory.ERROR) > 0) { + break; + } + final List filesInScope = getFilesInScope(context, currentChunk, dependentFiles); + if (filesInScope.isEmpty()) { + break; + } + context.getDependencyCache().clearTraverseRoots(); + chunkFiles = filesInScope; + total += chunkFiles.size() * translators.length; + } + + didSomething |= (hasUnprocessedTraverseRoots != context.getDependencyCache().hasUnprocessedTraverseRoots()); } - - if (!dependentFiles.isEmpty()) { - filesToRecompile.addAll(dependentFiles); - allDependent.addAll(dependentFiles); - if (context.getProgressIndicator().isCanceled() || context.getMessageCount(CompilerMessageCategory.ERROR) > 0) { - break; - } - final List filesInScope = getFilesInScope(context, currentChunk, dependentFiles); - if (filesInScope.isEmpty()) { - break; - } - context.getDependencyCache().clearTraverseRoots(); - chunkFiles = filesInScope; - total += chunkFiles.size() * translators.length; - } - + round++; } while (!dependentFiles.isEmpty() && context.getMessageCount(CompilerMessageCategory.ERROR) == 0); @@ -1638,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() { @@ -1695,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> toDelete) throws CacheCorruptedException { From 83fe33b137ddeee619697c4560242bee3a9f8ef2 Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Mon, 26 Jul 2010 18:59:56 +0400 Subject: [PATCH 07/28] Fix NPE in GroovyNameSuggestionProvider. --- .../groovy/refactoring/GroovyNameSuggestionProvider.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyNameSuggestionProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyNameSuggestionProvider.java index 08a0a2ff85dc..2e1afdbbff02 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyNameSuggestionProvider.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyNameSuggestionProvider.java @@ -22,6 +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.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; @@ -34,8 +35,8 @@ import java.util.Set; */ public class GroovyNameSuggestionProvider implements NameSuggestionProvider { @Override - public SuggestedNameInfo getSuggestedNames(final PsiElement element, PsiElement nameSuggestionContext, Set result) { - if (!(element instanceof GroovyPsiElement)) return null; + public SuggestedNameInfo getSuggestedNames(final PsiElement element, @Nullable PsiElement nameSuggestionContext, Set result) { + if (nameSuggestionContext == null || !(element instanceof GroovyPsiElement)) return null; if (element instanceof GrVariable) { final PsiType type = ((GrVariable)element).getTypeGroovy(); if (type != null) { @@ -56,7 +57,7 @@ public class GroovyNameSuggestionProvider implements NameSuggestionProvider { } @Override - public Collection completeName(PsiElement element, PsiElement nameSuggestionContext, String prefix) { + public Collection completeName(PsiElement element, @Nullable PsiElement nameSuggestionContext, String prefix) { return null; } } From cea9846cee76bbd4099eb14d476bd6c47bf012c6 Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Mon, 26 Jul 2010 19:08:26 +0400 Subject: [PATCH 08/28] Fix NPE in GroovyNameSuggestionProvider. --- .../intellij/refactoring/rename/NameSuggestionProvider.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/lang-api/src/com/intellij/refactoring/rename/NameSuggestionProvider.java b/platform/lang-api/src/com/intellij/refactoring/rename/NameSuggestionProvider.java index 456d583038c6..21e8ed12dc36 100644 --- a/platform/lang-api/src/com/intellij/refactoring/rename/NameSuggestionProvider.java +++ b/platform/lang-api/src/com/intellij/refactoring/rename/NameSuggestionProvider.java @@ -32,8 +32,8 @@ public interface NameSuggestionProvider { ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.nameSuggestionProvider"); @Nullable - SuggestedNameInfo getSuggestedNames(PsiElement element, PsiElement nameSuggestionContext, Set result); + SuggestedNameInfo getSuggestedNames(PsiElement element, @Nullable PsiElement nameSuggestionContext, Set result); @Nullable - Collection completeName(PsiElement element, final PsiElement nameSuggestionContext, final String prefix); + Collection completeName(PsiElement element, @Nullable final PsiElement nameSuggestionContext, final String prefix); } From 1b4e4575ce26b4a97d51e838add0ba9e9c27895a Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Mon, 26 Jul 2010 19:17:17 +0400 Subject: [PATCH 09/28] IDEA-56356 Soft wrap: varargs type declaration could be considered as a whole Soft wrap appliance point selection algorithm is corrected --- .../DefaultSoftWrapApplianceManager.java | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/DefaultSoftWrapApplianceManager.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/DefaultSoftWrapApplianceManager.java index 36b90dd4f12a..876d7bd3ea71 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/DefaultSoftWrapApplianceManager.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/DefaultSoftWrapApplianceManager.java @@ -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) { From eb96c914edec100b620a83a714518cb01cbce102 Mon Sep 17 00:00:00 2001 From: "Kirill.Safonov" Date: Mon, 26 Jul 2010 19:24:55 +0400 Subject: [PATCH 10/28] 'Extract Interface' and 'Extract Module' are now two separate first-class actions --- .../java/JavaRefactoringSupportProvider.java | 2 +- .../DefaultRefactoringSupportProvider.java | 4 +++ .../RefactoringSupportProvider.java | 6 ++++ .../actions/ExtractInterfaceAction.java | 35 +++++++++++++++++++ .../actions/ExtractModuleAction.java | 16 ++++----- ...ction.java => ExtractSuperActionBase.java} | 26 +++++++------- .../actions/ExtractSuperclassAction.java | 34 +++--------------- .../src/messages/ActionsBundle.properties | 2 ++ .../src/idea/LangActions.xml | 4 ++- resources/src/idea/IdeaActions.xml | 4 --- 10 files changed, 76 insertions(+), 57 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/refactoring/actions/ExtractInterfaceAction.java rename java/java-impl/src/com/intellij/refactoring/extractInterface/ExtractInterfaceAction.java => platform/lang-impl/src/com/intellij/refactoring/actions/ExtractModuleAction.java (62%) rename platform/lang-impl/src/com/intellij/refactoring/actions/{BaseExtractModuleAction.java => ExtractSuperActionBase.java} (62%) diff --git a/java/java-impl/src/com/intellij/lang/java/JavaRefactoringSupportProvider.java b/java/java-impl/src/com/intellij/lang/java/JavaRefactoringSupportProvider.java index 59dd9463b2d4..aa153df182ab 100644 --- a/java/java-impl/src/com/intellij/lang/java/JavaRefactoringSupportProvider.java +++ b/java/java-impl/src/com/intellij/lang/java/JavaRefactoringSupportProvider.java @@ -78,7 +78,7 @@ public class JavaRefactoringSupportProvider extends DefaultRefactoringSupportPro return new JavaPushDownHandler(); } - public RefactoringActionHandler getExtractModuleHandler() { + public RefactoringActionHandler getExtractInterfaceHandler() { return new ExtractInterfaceHandler(); } diff --git a/platform/lang-api/src/com/intellij/lang/refactoring/DefaultRefactoringSupportProvider.java b/platform/lang-api/src/com/intellij/lang/refactoring/DefaultRefactoringSupportProvider.java index 3db3337d1493..5a4cb9c1b077 100644 --- a/platform/lang-api/src/com/intellij/lang/refactoring/DefaultRefactoringSupportProvider.java +++ b/platform/lang-api/src/com/intellij/lang/refactoring/DefaultRefactoringSupportProvider.java @@ -59,6 +59,10 @@ public class DefaultRefactoringSupportProvider implements RefactoringSupportProv return null; } + public RefactoringActionHandler getExtractInterfaceHandler() { + return null; + } + public RefactoringActionHandler getExtractModuleHandler() { return null; } diff --git a/platform/lang-api/src/com/intellij/lang/refactoring/RefactoringSupportProvider.java b/platform/lang-api/src/com/intellij/lang/refactoring/RefactoringSupportProvider.java index 7aa9480d5e7b..ac244743397b 100644 --- a/platform/lang-api/src/com/intellij/lang/refactoring/RefactoringSupportProvider.java +++ b/platform/lang-api/src/com/intellij/lang/refactoring/RefactoringSupportProvider.java @@ -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 diff --git a/platform/lang-impl/src/com/intellij/refactoring/actions/ExtractInterfaceAction.java b/platform/lang-impl/src/com/intellij/refactoring/actions/ExtractInterfaceAction.java new file mode 100644 index 000000000000..88fbf0801347 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/refactoring/actions/ExtractInterfaceAction.java @@ -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(); + } + +} \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/refactoring/extractInterface/ExtractInterfaceAction.java b/platform/lang-impl/src/com/intellij/refactoring/actions/ExtractModuleAction.java similarity index 62% rename from java/java-impl/src/com/intellij/refactoring/extractInterface/ExtractInterfaceAction.java rename to platform/lang-impl/src/com/intellij/refactoring/actions/ExtractModuleAction.java index 401e454ecc32..0715cdcfa350 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractInterface/ExtractInterfaceAction.java +++ b/platform/lang-impl/src/com/intellij/refactoring/actions/ExtractModuleAction.java @@ -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(); } -} +} \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/refactoring/actions/BaseExtractModuleAction.java b/platform/lang-impl/src/com/intellij/refactoring/actions/ExtractSuperActionBase.java similarity index 62% rename from platform/lang-impl/src/com/intellij/refactoring/actions/BaseExtractModuleAction.java rename to platform/lang-impl/src/com/intellij/refactoring/actions/ExtractSuperActionBase.java index d20e83f49be3..8c0a5c83f5bf 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/actions/BaseExtractModuleAction.java +++ b/platform/lang-impl/src/com/intellij/refactoring/actions/ExtractSuperActionBase.java @@ -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); } \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/refactoring/actions/ExtractSuperclassAction.java b/platform/lang-impl/src/com/intellij/refactoring/actions/ExtractSuperclassAction.java index 02290346a898..d9d99b71c95a 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/actions/ExtractSuperclassAction.java +++ b/platform/lang-impl/src/com/intellij/refactoring/actions/ExtractSuperclassAction.java @@ -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(); } } \ No newline at end of file diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties index 527d5e8b0da8..bb4a5d8623d7 100644 --- a/platform/platform-resources-en/src/messages/ActionsBundle.properties +++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties @@ -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... diff --git a/platform/platform-resources/src/idea/LangActions.xml b/platform/platform-resources/src/idea/LangActions.xml index 31398574a513..077cba2d4153 100644 --- a/platform/platform-resources/src/idea/LangActions.xml +++ b/platform/platform-resources/src/idea/LangActions.xml @@ -6,7 +6,7 @@ - + @@ -285,6 +285,8 @@ + + diff --git a/resources/src/idea/IdeaActions.xml b/resources/src/idea/IdeaActions.xml index 57745c3c45dc..c34d1bd90657 100644 --- a/resources/src/idea/IdeaActions.xml +++ b/resources/src/idea/IdeaActions.xml @@ -161,10 +161,6 @@ - - - - From f5d1eb37ed1bbe928fe22c24bb25d239636fd4bf Mon Sep 17 00:00:00 2001 From: Gregory Shrago Date: Mon, 26 Jul 2010 18:39:25 +0400 Subject: [PATCH 11/28] NULL object --- .../src/com/intellij/psi/impl/PsiCachedValueImpl.java | 3 +++ .../intellij/psi/impl/PsiParameterizedCachedValue.java | 3 +++ .../src/com/intellij/util/CachedValueBase.java | 5 +++-- .../src/com/intellij/util/CachedValueImpl.java | 4 ++-- .../com/intellij/util/ParameterizedCachedValueImpl.java | 2 ++ .../src/com/intellij/openapi/util/NullableLazyKey.java | 6 +++--- platform/util/src/com/intellij/util/ObjectUtils.java | 2 ++ .../util/src/com/intellij/util/containers/FactoryMap.java | 3 ++- .../src/com/intellij/util/containers/SoftFactoryMap.java | 8 +++++--- .../src/com/intellij/util/containers/WeakFactoryMap.java | 8 +++++--- 10 files changed, 30 insertions(+), 14 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/PsiCachedValueImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/PsiCachedValueImpl.java index d4af0c93a429..e301e75b77fd 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/PsiCachedValueImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/PsiCachedValueImpl.java @@ -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 */ diff --git a/platform/lang-impl/src/com/intellij/psi/impl/PsiParameterizedCachedValue.java b/platform/lang-impl/src/com/intellij/psi/impl/PsiParameterizedCachedValue.java index 5d93119e8550..778931575c04 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/PsiParameterizedCachedValue.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/PsiParameterizedCachedValue.java @@ -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 extends PsiCachedValue implements ParameterizedCachedValue { private final ParameterizedCachedValueProvider myProvider; diff --git a/platform/platform-impl/src/com/intellij/util/CachedValueBase.java b/platform/platform-impl/src/com/intellij/util/CachedValueBase.java index 80133bde1163..13edf8142a59 100644 --- a/platform/platform-impl/src/com/intellij/util/CachedValueBase.java +++ b/platform/platform-impl/src/com/intellij/util/CachedValueBase.java @@ -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 { - protected static final Object NULL = new Object(); private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.CachedValueImpl"); private final MyTimedReference myData = new MyTimedReference(); @@ -66,7 +67,7 @@ public abstract class CachedValueBase { } protected void setValue(final T value, final CachedValueProvider.Result 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()); } diff --git a/platform/platform-impl/src/com/intellij/util/CachedValueImpl.java b/platform/platform-impl/src/com/intellij/util/CachedValueImpl.java index f6a9890319b4..aef384fae2d7 100644 --- a/platform/platform-impl/src/com/intellij/util/CachedValueImpl.java +++ b/platform/platform-impl/src/com/intellij/util/CachedValueImpl.java @@ -47,7 +47,7 @@ public abstract class CachedValueImpl extends CachedValueBase 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 extends CachedValueBase implements C try { value = getUpToDateOrNull(); if (value != null) { - return value == NULL ? null : value; + return value == ObjectUtils.NULL ? null : value; } CachedValueProvider.Result result = myProvider.compute(); diff --git a/platform/platform-impl/src/com/intellij/util/ParameterizedCachedValueImpl.java b/platform/platform-impl/src/com/intellij/util/ParameterizedCachedValueImpl.java index e83faa460ad2..32aa6f157f11 100644 --- a/platform/platform-impl/src/com/intellij/util/ParameterizedCachedValueImpl.java +++ b/platform/platform-impl/src/com/intellij/util/ParameterizedCachedValueImpl.java @@ -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 extends CachedValueBase implements ParameterizedCachedValue { private final ParameterizedCachedValueProvider myProvider; diff --git a/platform/util/src/com/intellij/openapi/util/NullableLazyKey.java b/platform/util/src/com/intellij/openapi/util/NullableLazyKey.java index 7b17675b3c3c..a4e4924f2eee 100644 --- a/platform/util/src/com/intellij/openapi/util/NullableLazyKey.java +++ b/platform/util/src/com/intellij/openapi/util/NullableLazyKey.java @@ -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 extends Key{ - private static final Object NULL = new Object(); private final NullableFunction myFunction; private NullableLazyKey(@NonNls String name, final NullableFunction function) { @@ -36,9 +36,9 @@ public class NullableLazyKey extends Key{ 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 NullableLazyKey create(@NonNls String name, final NullableFunction function) { diff --git a/platform/util/src/com/intellij/util/ObjectUtils.java b/platform/util/src/com/intellij/util/ObjectUtils.java index 82adc4900eb9..bf0c2de574a9 100644 --- a/platform/util/src/com/intellij/util/ObjectUtils.java +++ b/platform/util/src/com/intellij/util/ObjectUtils.java @@ -25,6 +25,8 @@ public class ObjectUtils { private ObjectUtils() { } + public static final Object NULL = new Object(); + @NotNull public static T assertNotNull(@Nullable final T t) { return _assertNotNull(t); diff --git a/platform/util/src/com/intellij/util/containers/FactoryMap.java b/platform/util/src/com/intellij/util/containers/FactoryMap.java index 0133310a92ca..08395cbd08df 100644 --- a/platform/util/src/com/intellij/util/containers/FactoryMap.java +++ b/platform/util/src/com/intellij/util/containers/FactoryMap.java @@ -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 implements Map { - static final Object NULL = new Object(); protected Map myMap; protected Map createMap() { diff --git a/platform/util/src/com/intellij/util/containers/SoftFactoryMap.java b/platform/util/src/com/intellij/util/containers/SoftFactoryMap.java index 24748e7d9501..17ba065ea122 100644 --- a/platform/util/src/com/intellij/util/containers/SoftFactoryMap.java +++ b/platform/util/src/com/intellij/util/containers/SoftFactoryMap.java @@ -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 { 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 valueRef = new SoftReference(value == null ? (V)FactoryMap.NULL : value); + SoftReference valueRef = new SoftReference(value == null ? (V)NULL : value); SoftReference 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) { diff --git a/platform/util/src/com/intellij/util/containers/WeakFactoryMap.java b/platform/util/src/com/intellij/util/containers/WeakFactoryMap.java index e01baa50b28a..2df74cd24c94 100644 --- a/platform/util/src/com/intellij/util/containers/WeakFactoryMap.java +++ b/platform/util/src/com/intellij/util/containers/WeakFactoryMap.java @@ -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 { 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 valueRef = new WeakReference(value == null ? (V)FactoryMap.NULL : value); + WeakReference valueRef = new WeakReference(value == null ? (V)NULL : value); WeakReference 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) { From adb873e5988520f75d9ddccd047e62d8b5e5d799 Mon Sep 17 00:00:00 2001 From: Gregory Shrago Date: Mon, 26 Jul 2010 18:56:27 +0400 Subject: [PATCH 12/28] better fix for missing binary indexer --- .../intellij/psi/stubs/StubUpdatingIndex.java | 51 +++++++++++-------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java b/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java index f20b020e2681..1d4734a43ac6 100644 --- a/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java +++ b/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java @@ -32,6 +32,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.psi.tree.IFileElementType; import com.intellij.psi.tree.IStubFileElementType; +import com.intellij.util.ObjectUtils; import com.intellij.util.indexing.*; import com.intellij.util.io.DataExternalizer; import com.intellij.util.io.IntInlineKeyDescriptor; @@ -127,37 +128,43 @@ public class StubUpdatingIndex extends CustomImplementationFileBasedIndexExtensi }; } - private static Key stubElementKey = Key.create("stub.tree.for.file.content"); + private static Key stubElementKey = Key.create("stub.tree.for.file.content"); @Nullable public static StubElement buildStubTree(final FileContent inputData) { - StubElement data = inputData.getUserData(stubElementKey); - if (data != null) return data; + Object data = inputData.getUserData(stubElementKey); + if (data == null) { + synchronized (inputData) { + data = inputData.getUserData(stubElementKey); + if (data == null) { + final FileType fileType = inputData.getFileType(); - synchronized (inputData) { - data = inputData.getUserData(stubElementKey); - if (data != null) return data; + if (fileType.isBinary()) { + final BinaryFileStubBuilder builder = BinaryFileStubBuilders.INSTANCE.forFileType(fileType); + if (builder != null) { + data = builder.buildStubTree(inputData.getFile(), inputData.getContent(), inputData.getProject()); + } + else { + data = ObjectUtils.NULL; + } + } + else { + final LanguageFileType filetype = (LanguageFileType)fileType; + Language l = filetype.getLanguage(); + final IFileElementType type = LanguageParserDefinitions.INSTANCE.forLanguage(l).getFileNodeType(); - final FileType fileType = inputData.getFileType(); + PsiFile psi = inputData.getPsiFile(); - if (fileType.isBinary()) { - final BinaryFileStubBuilder builder = BinaryFileStubBuilders.INSTANCE.forFileType(fileType); - assert builder != null; + data = ((IStubFileElementType)type).getBuilder().buildStubTree(psi); + } - data = builder.buildStubTree(inputData.getFile(), inputData.getContent(), inputData.getProject()); - } else { - final LanguageFileType filetype = (LanguageFileType)fileType; - Language l = filetype.getLanguage(); - final IFileElementType type = LanguageParserDefinitions.INSTANCE.forLanguage(l).getFileNodeType(); - - PsiFile psi = inputData.getPsiFile(); - - data = ((IStubFileElementType)type).getBuilder().buildStubTree(psi); + inputData.putUserData(stubElementKey, data); + } } - - inputData.putUserData(stubElementKey, data); - return data; } + if (data == ObjectUtils.NULL) return null; + if (data instanceof StubElement) return (StubElement)data; + throw new AssertionError(data); } public KeyDescriptor getKeyDescriptor() { From f8b6740da8a18221540ccfa7a60c948f2bd0370e Mon Sep 17 00:00:00 2001 From: Alexander Chernikov Date: Mon, 26 Jul 2010 23:58:04 +0400 Subject: [PATCH 13/28] Eclipse integration: lib/var collision test data. --- .../varAddJavadoc/expected/.classpath | 9 +++++++++ .../varAddJavadoc/expected/ws-internals.eml | 8 ++++++++ .../modification/varAddJavadoc/jars/test.jar | Bin 0 -> 840 bytes .../modification/varAddJavadoc/test/.classpath | 5 +++++ .../modification/varAddJavadoc/test/.project | 17 +++++++++++++++++ .../varAddJavadoc/variableidea/test.jar | Bin 0 -> 840 bytes .../EclipseLibrariesModificationsTest.java | 6 ++++++ 7 files changed, 45 insertions(+) create mode 100644 plugins/eclipse/testData/modification/varAddJavadoc/expected/.classpath create mode 100644 plugins/eclipse/testData/modification/varAddJavadoc/expected/ws-internals.eml create mode 100644 plugins/eclipse/testData/modification/varAddJavadoc/jars/test.jar create mode 100644 plugins/eclipse/testData/modification/varAddJavadoc/test/.classpath create mode 100644 plugins/eclipse/testData/modification/varAddJavadoc/test/.project create mode 100644 plugins/eclipse/testData/modification/varAddJavadoc/variableidea/test.jar diff --git a/plugins/eclipse/testData/modification/varAddJavadoc/expected/.classpath b/plugins/eclipse/testData/modification/varAddJavadoc/expected/.classpath new file mode 100644 index 000000000000..f53870069b97 --- /dev/null +++ b/plugins/eclipse/testData/modification/varAddJavadoc/expected/.classpath @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/plugins/eclipse/testData/modification/varAddJavadoc/expected/ws-internals.eml b/plugins/eclipse/testData/modification/varAddJavadoc/expected/ws-internals.eml new file mode 100644 index 000000000000..7025e8384962 --- /dev/null +++ b/plugins/eclipse/testData/modification/varAddJavadoc/expected/ws-internals.eml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/plugins/eclipse/testData/modification/varAddJavadoc/jars/test.jar b/plugins/eclipse/testData/modification/varAddJavadoc/jars/test.jar new file mode 100644 index 0000000000000000000000000000000000000000..69d35ecffe38daa9f5223585d031f42787e479ea GIT binary patch literal 840 zcmWIWW@h1H0D*&D*;Zf%l;C7wVeoYgan$wnbJPEKih&^js+5D_08pvpv?#qOpwcuT z76D?oQeQ_uPdC@#5ItYF&%S3)`*`c>UF7xF)jD_P{N^BoE5;9=7M*bxD%A1tIp-0| z(8Z{F_A5{2&Nakr?==Sg2p zDtA`wgu8`-VKbVuxq)s;P0qCj$a%FO#%hK-c`}?QrKSM!hEq7^&@0(dSlq0?$e0+Da{fl;IC-WIy zOFsln?A;q6t|c8WEMtHESyYOZ&`YOn7nDu%LzaEfU07EnCCFnh@7W~1!snZ~{zjcP zCBM{})76!FT^4%n%aW>E^sJ@XL2c!%v#AS`^v{U9D#=S!E>H~?wfD3=>FyI2zG}-Z z>AS8!gQRu0aPF<2%rW<@S#yP!u&=@Nr$X-G7H+-!85Lv>IW%Waj^tI7*GiVueOD3F znf>?;@0TdgZ4$FXH}lTE_)qY_!7|Yo>&`wGJs!XK^J$Olwxj^j c2(tPCsz&sL5#Y_r22#udg#UrGF%yUf0C~Xuh5!Hn literal 0 HcmV?d00001 diff --git a/plugins/eclipse/testData/modification/varAddJavadoc/test/.classpath b/plugins/eclipse/testData/modification/varAddJavadoc/test/.classpath new file mode 100644 index 000000000000..65e495d45cd3 --- /dev/null +++ b/plugins/eclipse/testData/modification/varAddJavadoc/test/.classpath @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/plugins/eclipse/testData/modification/varAddJavadoc/test/.project b/plugins/eclipse/testData/modification/varAddJavadoc/test/.project new file mode 100644 index 000000000000..3c7030a86519 --- /dev/null +++ b/plugins/eclipse/testData/modification/varAddJavadoc/test/.project @@ -0,0 +1,17 @@ + + + ws-internals + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/plugins/eclipse/testData/modification/varAddJavadoc/variableidea/test.jar b/plugins/eclipse/testData/modification/varAddJavadoc/variableidea/test.jar new file mode 100644 index 0000000000000000000000000000000000000000..69d35ecffe38daa9f5223585d031f42787e479ea GIT binary patch literal 840 zcmWIWW@h1H0D*&D*;Zf%l;C7wVeoYgan$wnbJPEKih&^js+5D_08pvpv?#qOpwcuT z76D?oQeQ_uPdC@#5ItYF&%S3)`*`c>UF7xF)jD_P{N^BoE5;9=7M*bxD%A1tIp-0| z(8Z{F_A5{2&Nakr?==Sg2p zDtA`wgu8`-VKbVuxq)s;P0qCj$a%FO#%hK-c`}?QrKSM!hEq7^&@0(dSlq0?$e0+Da{fl;IC-WIy zOFsln?A;q6t|c8WEMtHESyYOZ&`YOn7nDu%LzaEfU07EnCCFnh@7W~1!snZ~{zjcP zCBM{})76!FT^4%n%aW>E^sJ@XL2c!%v#AS`^v{U9D#=S!E>H~?wfD3=>FyI2zG}-Z z>AS8!gQRu0aPF<2%rW<@S#yP!u&=@Nr$X-G7H+-!85Lv>IW%Waj^tI7*GiVueOD3F znf>?;@0TdgZ4$FXH}lTE_)qY_!7|Yo>&`wGJs!XK^J$Olwxj^j c2(tPCsz&sL5#Y_r22#udg#UrGF%yUf0C~Xuh5!Hn literal 0 HcmV?d00001 diff --git a/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseLibrariesModificationsTest.java b/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseLibrariesModificationsTest.java index 08a2d1c44152..9a6fcdb8b5e0 100644 --- a/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseLibrariesModificationsTest.java +++ b/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseLibrariesModificationsTest.java @@ -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!/"}, From 284d2492473d2b80ebf569908d2f42623c5b247d Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 26 Jul 2010 17:46:59 +0100 Subject: [PATCH 14/28] recompile classes that depend on the changed Groovy classes --- .../groovy/compiler/GroovyCompilerBase.java | 32 +++++++++++++++++++ .../groovy/compiler/GppCompilerTest.groovy | 12 +++---- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerBase.java index a308f70f04f4..e1dca6a60a14 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerBase.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerBase.java @@ -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)); diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GppCompilerTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GppCompilerTest.groovy index 94ccc740d1da..7d951d2ef99d 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GppCompilerTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GppCompilerTest.groovy @@ -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" } } From 04c01a352c30be0a84847c66adb2706fb1534cb9 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Mon, 26 Jul 2010 21:30:31 +0400 Subject: [PATCH 15/28] play nice when swf is not mapped --- .../intellij/psi/stubs/StubUpdatingIndex.java | 51 ++++++++----------- 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java b/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java index 1d4734a43ac6..f20b020e2681 100644 --- a/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java +++ b/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java @@ -32,7 +32,6 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.psi.tree.IFileElementType; import com.intellij.psi.tree.IStubFileElementType; -import com.intellij.util.ObjectUtils; import com.intellij.util.indexing.*; import com.intellij.util.io.DataExternalizer; import com.intellij.util.io.IntInlineKeyDescriptor; @@ -128,43 +127,37 @@ public class StubUpdatingIndex extends CustomImplementationFileBasedIndexExtensi }; } - private static Key stubElementKey = Key.create("stub.tree.for.file.content"); + private static Key stubElementKey = Key.create("stub.tree.for.file.content"); @Nullable public static StubElement buildStubTree(final FileContent inputData) { - Object data = inputData.getUserData(stubElementKey); - if (data == null) { - synchronized (inputData) { - data = inputData.getUserData(stubElementKey); - if (data == null) { - final FileType fileType = inputData.getFileType(); + StubElement data = inputData.getUserData(stubElementKey); + if (data != null) return data; - if (fileType.isBinary()) { - final BinaryFileStubBuilder builder = BinaryFileStubBuilders.INSTANCE.forFileType(fileType); - if (builder != null) { - data = builder.buildStubTree(inputData.getFile(), inputData.getContent(), inputData.getProject()); - } - else { - data = ObjectUtils.NULL; - } - } - else { - final LanguageFileType filetype = (LanguageFileType)fileType; - Language l = filetype.getLanguage(); - final IFileElementType type = LanguageParserDefinitions.INSTANCE.forLanguage(l).getFileNodeType(); + synchronized (inputData) { + data = inputData.getUserData(stubElementKey); + if (data != null) return data; - PsiFile psi = inputData.getPsiFile(); + final FileType fileType = inputData.getFileType(); - data = ((IStubFileElementType)type).getBuilder().buildStubTree(psi); - } + if (fileType.isBinary()) { + final BinaryFileStubBuilder builder = BinaryFileStubBuilders.INSTANCE.forFileType(fileType); + assert builder != null; - inputData.putUserData(stubElementKey, data); - } + data = builder.buildStubTree(inputData.getFile(), inputData.getContent(), inputData.getProject()); + } else { + final LanguageFileType filetype = (LanguageFileType)fileType; + Language l = filetype.getLanguage(); + final IFileElementType type = LanguageParserDefinitions.INSTANCE.forLanguage(l).getFileNodeType(); + + PsiFile psi = inputData.getPsiFile(); + + data = ((IStubFileElementType)type).getBuilder().buildStubTree(psi); } + + inputData.putUserData(stubElementKey, data); + return data; } - if (data == ObjectUtils.NULL) return null; - if (data instanceof StubElement) return (StubElement)data; - throw new AssertionError(data); } public KeyDescriptor getKeyDescriptor() { From 769533685cbd738fb9ac285e9a530ce43d8d00be Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Mon, 26 Jul 2010 21:37:27 +0400 Subject: [PATCH 16/28] fixed race condition in afterStartNotified --- .../execution/process/ProcessHandler.java | 61 +++++++++++++------ 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/platform/platform-api/src/com/intellij/execution/process/ProcessHandler.java b/platform/platform-api/src/com/intellij/execution/process/ProcessHandler.java index dc78a8c950fa..b33dab18a0bb 100644 --- a/platform/platform-api/src/com/intellij/execution/process/ProcessHandler.java +++ b/platform/platform-api/src/com/intellij/execution/process/ProcessHandler.java @@ -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 myPendingTasks = new ArrayList(); + + 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(); + } + } + + } } From 9af2d15c1c365c3ce848165e91e031b9beaf54d8 Mon Sep 17 00:00:00 2001 From: Gregory Shrago Date: Mon, 26 Jul 2010 21:50:22 +0400 Subject: [PATCH 17/28] rename standalone iml --- .../IntelliLang/{IntelliLang.iml => IntelliLang-standalone.iml} | 0 plugins/IntelliLang/IntelliLang-standalone.ipr | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename plugins/IntelliLang/{IntelliLang.iml => IntelliLang-standalone.iml} (100%) diff --git a/plugins/IntelliLang/IntelliLang.iml b/plugins/IntelliLang/IntelliLang-standalone.iml similarity index 100% rename from plugins/IntelliLang/IntelliLang.iml rename to plugins/IntelliLang/IntelliLang-standalone.iml diff --git a/plugins/IntelliLang/IntelliLang-standalone.ipr b/plugins/IntelliLang/IntelliLang-standalone.ipr index 602e7f2214d6..569835e49db6 100644 --- a/plugins/IntelliLang/IntelliLang-standalone.ipr +++ b/plugins/IntelliLang/IntelliLang-standalone.ipr @@ -530,7 +530,7 @@ - + From 00f26797287ca5176a8fa1a449cfde55dcf4da3f Mon Sep 17 00:00:00 2001 From: Gregory Shrago Date: Mon, 26 Jul 2010 21:52:38 +0400 Subject: [PATCH 18/28] rename IntelliLangJava -> IntelliLang --- .idea/modules.xml | 2 +- java/compiler/impl/compiler-impl.iml | 2 -- plugins/IntelliLang/IntelliLang-java.iml | 2 +- plugins/IntelliLang/IntelliLang-javaee.iml | 2 +- plugins/IntelliLang/IntelliLang-xml.iml | 2 +- .../{IntelliLangJava.iml => IntelliLang.iml} | 0 plugins/cvs/cvs-core/cvs-core.iml | 1 - plugins/git4idea/git4idea.iml | 1 - plugins/groovy/jetgroovy.iml | 4 +-- plugins/maven/facade-api/maven-facade-api.iml | 2 -- .../maven/facade-impl/maven-facade-impl.iml | 28 ------------------- plugins/relaxng/relaxng.iml | 7 ----- plugins/svn4idea/svn4idea-tests.iml | 3 -- plugins/svn4idea/svn4idea.iml | 5 ---- 14 files changed, 5 insertions(+), 56 deletions(-) rename plugins/IntelliLang/{IntelliLangJava.iml => IntelliLang.iml} (100%) diff --git a/.idea/modules.xml b/.idea/modules.xml index f5a152e858e6..ea2d70bbde97 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -6,7 +6,7 @@ - + diff --git a/java/compiler/impl/compiler-impl.iml b/java/compiler/impl/compiler-impl.iml index 4f7473c9ff2a..381f3496886b 100644 --- a/java/compiler/impl/compiler-impl.iml +++ b/java/compiler/impl/compiler-impl.iml @@ -23,8 +23,6 @@ - - diff --git a/plugins/IntelliLang/IntelliLang-java.iml b/plugins/IntelliLang/IntelliLang-java.iml index a9a38446a280..998ca93c3ae5 100644 --- a/plugins/IntelliLang/IntelliLang-java.iml +++ b/plugins/IntelliLang/IntelliLang-java.iml @@ -15,7 +15,7 @@ - + diff --git a/plugins/IntelliLang/IntelliLang-javaee.iml b/plugins/IntelliLang/IntelliLang-javaee.iml index bfbccd5a1eac..00e420c8ab6f 100644 --- a/plugins/IntelliLang/IntelliLang-javaee.iml +++ b/plugins/IntelliLang/IntelliLang-javaee.iml @@ -7,7 +7,7 @@ - + diff --git a/plugins/IntelliLang/IntelliLang-xml.iml b/plugins/IntelliLang/IntelliLang-xml.iml index d57e3f2a4b2d..62d3a331f7ee 100644 --- a/plugins/IntelliLang/IntelliLang-xml.iml +++ b/plugins/IntelliLang/IntelliLang-xml.iml @@ -16,7 +16,7 @@ - + diff --git a/plugins/IntelliLang/IntelliLangJava.iml b/plugins/IntelliLang/IntelliLang.iml similarity index 100% rename from plugins/IntelliLang/IntelliLangJava.iml rename to plugins/IntelliLang/IntelliLang.iml diff --git a/plugins/cvs/cvs-core/cvs-core.iml b/plugins/cvs/cvs-core/cvs-core.iml index 53189febbd11..f170b4099106 100644 --- a/plugins/cvs/cvs-core/cvs-core.iml +++ b/plugins/cvs/cvs-core/cvs-core.iml @@ -15,7 +15,6 @@ - diff --git a/plugins/git4idea/git4idea.iml b/plugins/git4idea/git4idea.iml index aa21265058b8..5fa1b17970c1 100644 --- a/plugins/git4idea/git4idea.iml +++ b/plugins/git4idea/git4idea.iml @@ -16,7 +16,6 @@ - diff --git a/plugins/groovy/jetgroovy.iml b/plugins/groovy/jetgroovy.iml index 3b210de157c4..75c0ecccfd80 100644 --- a/plugins/groovy/jetgroovy.iml +++ b/plugins/groovy/jetgroovy.iml @@ -26,13 +26,11 @@ - - - + diff --git a/plugins/maven/facade-api/maven-facade-api.iml b/plugins/maven/facade-api/maven-facade-api.iml index 8ba63b8dc7db..56173f227d95 100644 --- a/plugins/maven/facade-api/maven-facade-api.iml +++ b/plugins/maven/facade-api/maven-facade-api.iml @@ -14,8 +14,6 @@ - - diff --git a/plugins/maven/facade-impl/maven-facade-impl.iml b/plugins/maven/facade-impl/maven-facade-impl.iml index 9240cd8ba91c..ae61f67a346f 100644 --- a/plugins/maven/facade-impl/maven-facade-impl.iml +++ b/plugins/maven/facade-impl/maven-facade-impl.iml @@ -16,8 +16,6 @@ - - @@ -25,8 +23,6 @@ - - @@ -34,8 +30,6 @@ - - @@ -43,8 +37,6 @@ - - @@ -52,8 +44,6 @@ - - @@ -61,8 +51,6 @@ - - @@ -70,8 +58,6 @@ - - @@ -79,8 +65,6 @@ - - @@ -88,8 +72,6 @@ - - @@ -97,8 +79,6 @@ - - @@ -106,8 +86,6 @@ - - @@ -115,8 +93,6 @@ - - @@ -124,8 +100,6 @@ - - @@ -133,8 +107,6 @@ - - diff --git a/plugins/relaxng/relaxng.iml b/plugins/relaxng/relaxng.iml index d7d35d40c904..6ff34b95fc39 100644 --- a/plugins/relaxng/relaxng.iml +++ b/plugins/relaxng/relaxng.iml @@ -18,7 +18,6 @@ - @@ -29,8 +28,6 @@ - - @@ -38,8 +35,6 @@ - - @@ -47,8 +42,6 @@ - - diff --git a/plugins/svn4idea/svn4idea-tests.iml b/plugins/svn4idea/svn4idea-tests.iml index 798757278775..5039b6b4a9f5 100644 --- a/plugins/svn4idea/svn4idea-tests.iml +++ b/plugins/svn4idea/svn4idea-tests.iml @@ -16,7 +16,6 @@ - @@ -30,8 +29,6 @@ - - diff --git a/plugins/svn4idea/svn4idea.iml b/plugins/svn4idea/svn4idea.iml index fd765b400568..e00b72d68d9c 100644 --- a/plugins/svn4idea/svn4idea.iml +++ b/plugins/svn4idea/svn4idea.iml @@ -22,7 +22,6 @@ - @@ -33,8 +32,6 @@ - - @@ -43,8 +40,6 @@ - - From dddad0f9794d54b6556e7e0028d0bb39933eec5c Mon Sep 17 00:00:00 2001 From: Gregory Shrago Date: Mon, 26 Jul 2010 21:57:41 +0400 Subject: [PATCH 19/28] rename IntelliLangJava->IntelliLang --- .idea/modules.xml | 4 ++-- .idea/runConfigurations/IDEA.xml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.idea/modules.xml b/.idea/modules.xml index ea2d70bbde97..6c7b87a32dd8 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -3,15 +3,14 @@ + - - @@ -68,6 +67,7 @@ + diff --git a/.idea/runConfigurations/IDEA.xml b/.idea/runConfigurations/IDEA.xml index 75c3b359ab37..16d0af8f13ff 100644 --- a/.idea/runConfigurations/IDEA.xml +++ b/.idea/runConfigurations/IDEA.xml @@ -1,6 +1,6 @@ - + diff --git a/plugins/maven/facade-impl/maven-facade-impl.iml b/plugins/maven/facade-impl/maven-facade-impl.iml index ae61f67a346f..9240cd8ba91c 100644 --- a/plugins/maven/facade-impl/maven-facade-impl.iml +++ b/plugins/maven/facade-impl/maven-facade-impl.iml @@ -16,6 +16,8 @@ + + @@ -23,6 +25,8 @@ + + @@ -30,6 +34,8 @@ + + @@ -37,6 +43,8 @@ + + @@ -44,6 +52,8 @@ + + @@ -51,6 +61,8 @@ + + @@ -58,6 +70,8 @@ + + @@ -65,6 +79,8 @@ + + @@ -72,6 +88,8 @@ + + @@ -79,6 +97,8 @@ + + @@ -86,6 +106,8 @@ + + @@ -93,6 +115,8 @@ + + @@ -100,6 +124,8 @@ + + @@ -107,6 +133,8 @@ + + diff --git a/plugins/relaxng/relaxng.iml b/plugins/relaxng/relaxng.iml index 6ff34b95fc39..d7d35d40c904 100644 --- a/plugins/relaxng/relaxng.iml +++ b/plugins/relaxng/relaxng.iml @@ -18,6 +18,7 @@ + @@ -28,6 +29,8 @@ + + @@ -35,6 +38,8 @@ + + @@ -42,6 +47,8 @@ + + diff --git a/plugins/svn4idea/svn4idea-tests.iml b/plugins/svn4idea/svn4idea-tests.iml index 5039b6b4a9f5..798757278775 100644 --- a/plugins/svn4idea/svn4idea-tests.iml +++ b/plugins/svn4idea/svn4idea-tests.iml @@ -16,6 +16,7 @@ + @@ -29,6 +30,8 @@ + + diff --git a/plugins/svn4idea/svn4idea.iml b/plugins/svn4idea/svn4idea.iml index e00b72d68d9c..fd765b400568 100644 --- a/plugins/svn4idea/svn4idea.iml +++ b/plugins/svn4idea/svn4idea.iml @@ -22,6 +22,7 @@ + @@ -32,6 +33,8 @@ + + @@ -40,6 +43,8 @@ + + From 9ada5b49244247daef20ea6471d8567425a90736 Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Tue, 27 Jul 2010 13:52:32 +0400 Subject: [PATCH 26/28] IDEA-56795 Groovy method does not resolve --- .../jetbrains/plugins/groovy/gpp/GppTypeConverter.java | 2 +- .../plugins/groovy/lang/psi/impl/GrMapType.java | 2 ++ .../plugins/groovy/lang/GroovyHighlightingTest.java | 6 +++++- .../highlighting/MapNotAcceptedAsStringParameter.groovy | 7 +++++++ .../method/mapNotAcceptedAsStringParameter/A.groovy | 9 +++++++++ 5 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 plugins/groovy/testdata/highlighting/MapNotAcceptedAsStringParameter.groovy create mode 100644 plugins/groovy/testdata/resolve/method/mapNotAcceptedAsStringParameter/A.groovy diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/gpp/GppTypeConverter.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/gpp/GppTypeConverter.java index b03125b76fd1..a41d82ebd46e 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/gpp/GppTypeConverter.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/gpp/GppTypeConverter.java @@ -71,7 +71,7 @@ public class GppTypeConverter extends GrTypeConverter { return true; } - if (hasDefaultConstructor(lType)) { + if (!isMethodCallConversion(context) && hasDefaultConstructor(lType)) { return true; } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrMapType.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrMapType.java index 3fbe912f1cc7..2d92fec1267d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrMapType.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrMapType.java @@ -109,6 +109,8 @@ public class GrMapType extends GrLiteralClassType { } public String getInternalCanonicalText() { + if (myStringEntries.size() == 0) return "[:]"; + List components = new ArrayList(); for (String s : myStringEntries.keySet()) { components.add("'" + s + "':" + getInternalCanonicalText(myStringEntries.get(s))); diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.java index 6a29d6fb27f8..63a106b42e52 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.java @@ -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(); + } } \ No newline at end of file diff --git a/plugins/groovy/testdata/highlighting/MapNotAcceptedAsStringParameter.groovy b/plugins/groovy/testdata/highlighting/MapNotAcceptedAsStringParameter.groovy new file mode 100644 index 000000000000..8126990df539 --- /dev/null +++ b/plugins/groovy/testdata/highlighting/MapNotAcceptedAsStringParameter.groovy @@ -0,0 +1,7 @@ +class A { + void method(String m) {} + + { + method([:]) + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/resolve/method/mapNotAcceptedAsStringParameter/A.groovy b/plugins/groovy/testdata/resolve/method/mapNotAcceptedAsStringParameter/A.groovy new file mode 100644 index 000000000000..502c53f40771 --- /dev/null +++ b/plugins/groovy/testdata/resolve/method/mapNotAcceptedAsStringParameter/A.groovy @@ -0,0 +1,9 @@ +class A { + void method(Map m, Closure e ) {} + void method(String m) {} + +{ +method([:]) +} + +} \ No newline at end of file From 0d493420efe5125d29ecb009ea10a98810ca05f4 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Tue, 27 Jul 2010 14:08:28 +0400 Subject: [PATCH 27/28] cosmetics --- .../indexing/FileBasedIndexProjectHandler.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexProjectHandler.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexProjectHandler.java index 73604f7878d7..ad5e603357b1 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexProjectHandler.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexProjectHandler.java @@ -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); } }); From bde13841d71cb956459f0147c953822e0e57cf42 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Tue, 27 Jul 2010 14:10:11 +0400 Subject: [PATCH 28/28] do not defer dumb mode start to ensure changed files are processed in dumb mode if needed --- .../openapi/roots/impl/ProjectRootManagerImpl.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java index 39d89a5f576e..1034ec9e6e20 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java @@ -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() {