mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'master' of git@git.labs.intellij.net:idea/community
This commit is contained in:
Generated
+2
-2
@@ -3,15 +3,14 @@
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/InspectionGadgets/InspectionGadgetsPlugin.iml" filepath="$PROJECT_DIR$/plugins/InspectionGadgets/InspectionGadgetsPlugin.iml" group="plugins" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/IntelliLang/IntelliLang.iml" filepath="$PROJECT_DIR$/plugins/IntelliLang/IntelliLang.iml" group="plugins/IntelliLang" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/IntelliLang/IntelliLang-java.iml" filepath="$PROJECT_DIR$/plugins/IntelliLang/IntelliLang-java.iml" group="plugins/IntelliLang" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/IntelliLang/IntelliLang-javaee.iml" filepath="$PROJECT_DIR$/plugins/IntelliLang/IntelliLang-javaee.iml" group="plugins/IntelliLang" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/IntelliLang/IntelliLang-xml.iml" filepath="$PROJECT_DIR$/plugins/IntelliLang/IntelliLang-xml.iml" group="plugins/IntelliLang" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/IntelliLang/IntelliLangJava.iml" filepath="$PROJECT_DIR$/plugins/IntelliLang/IntelliLangJava.iml" group="plugins/IntelliLang" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/IntentionPowerPak/IntentionPowerPackPlugin.iml" filepath="$PROJECT_DIR$/plugins/IntentionPowerPak/IntentionPowerPackPlugin.iml" group="plugins" />
|
||||
<module fileurl="file://$PROJECT_DIR$/RegExpSupport/RegExpSupport.iml" filepath="$PROJECT_DIR$/RegExpSupport/RegExpSupport.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/platform/annotations/annotations.iml" filepath="$PROJECT_DIR$/platform/annotations/annotations.iml" group="platform" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/ant/ant.iml" filepath="$PROJECT_DIR$/plugins/ant/ant.iml" group="plugins" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/relaxng/relaxng.iml" filepath="$PROJECT_DIR$/plugins/relaxng/relaxng.iml" group="plugins" />
|
||||
<module fileurl="file://$PROJECT_DIR$/platform/boot/boot.iml" filepath="$PROJECT_DIR$/platform/boot/boot.iml" group="platform" />
|
||||
<module fileurl="file://$PROJECT_DIR$/platform/bootstrap/bootstrap.iml" filepath="$PROJECT_DIR$/platform/bootstrap/bootstrap.iml" group="platform" />
|
||||
<module fileurl="file://$PROJECT_DIR$/build/build.iml" filepath="$PROJECT_DIR$/build/build.iml" />
|
||||
@@ -68,6 +67,7 @@
|
||||
<module fileurl="file://$PROJECT_DIR$/platform/platform-resources/platform-resources.iml" filepath="$PROJECT_DIR$/platform/platform-resources/platform-resources.iml" group="platform" />
|
||||
<module fileurl="file://$PROJECT_DIR$/platform/platform-resources-en/platform-resources-en.iml" filepath="$PROJECT_DIR$/platform/platform-resources-en/platform-resources-en.iml" group="platform" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/properties/properties.iml" filepath="$PROJECT_DIR$/plugins/properties/properties.iml" group="plugins" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/relaxng/relaxng.iml" filepath="$PROJECT_DIR$/plugins/relaxng/relaxng.iml" group="plugins" />
|
||||
<module fileurl="file://$PROJECT_DIR$/resources/resources.iml" filepath="$PROJECT_DIR$/resources/resources.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/resources-en/resources-en.iml" filepath="$PROJECT_DIR$/resources-en/resources-en.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/platform/smRunner/smRunner.iml" filepath="$PROJECT_DIR$/platform/smRunner/smRunner.iml" group="platform" />
|
||||
|
||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="IDEA" type="Application" factoryName="Application">
|
||||
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
|
||||
<extension name="coverage" enabled="false" sample_coverage="true" runner="idea" merge="false" />
|
||||
<extension name="snapshooter" />
|
||||
<option name="MAIN_CLASS_NAME" value="com.intellij.idea.Main" />
|
||||
<option name="VM_PARAMETERS" value=" -ea -Xbootclasspath/p:../out/classes/production/boot -Xmx192m -Didea.is.internal=true -XX:MaxPermSize=150m " />
|
||||
|
||||
@@ -67,8 +67,8 @@ def wire_build_date(String buildNumber) {
|
||||
target('default': 'The default target') {
|
||||
depends(compile)
|
||||
layoutAll(
|
||||
buildNumber: "IC-90.SNAPSHOT",
|
||||
version: "Maia",
|
||||
buildNumber: "IC-X.SNAPSHOT",
|
||||
version: "IdeaX",
|
||||
system_selector: "IntelliJIdeaCE10",
|
||||
jdk_req: "1.6*",
|
||||
vmoptions: "-Xms128m -Xmx512m -XX:MaxPermSize=250m -ea",
|
||||
|
||||
+4
-1
@@ -13,14 +13,17 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.compiler.impl.javaCompiler;
|
||||
package com.intellij.compiler;
|
||||
|
||||
import com.intellij.openapi.compiler.CompileContext;
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: Aug 19, 2008
|
||||
*/
|
||||
public interface DependencyProcessor {
|
||||
ExtensionPointName<DependencyProcessor> EXTENSION_POINT_NAME = ExtensionPointName.create("com.intellij.compiler.makeDependencyProcessor");
|
||||
|
||||
void processDependencies(CompileContext context, int classQualifiedName);
|
||||
}
|
||||
@@ -77,15 +77,13 @@ import com.intellij.psi.PsiCompiledElement;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.util.Chunk;
|
||||
import com.intellij.util.LocalTimeCounter;
|
||||
import com.intellij.util.StringBuilderSpinAllocator;
|
||||
import com.intellij.util.ThrowableRunnable;
|
||||
import com.intellij.util.*;
|
||||
import com.intellij.util.concurrency.Semaphore;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import com.intellij.util.containers.OrderedSet;
|
||||
import gnu.trove.TIntHashSet;
|
||||
import gnu.trove.TObjectHashingStrategy;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -957,70 +955,149 @@ public class CompileDriver {
|
||||
final Set<FileType> generatedTypes = new HashSet<FileType>();
|
||||
Collection<VirtualFile> chunkFiles = chunkMap.get(currentChunk);
|
||||
try {
|
||||
for (int currentCompiler = 0, translatorsLength = translators.length; currentCompiler < translatorsLength; currentCompiler++) {
|
||||
sink.setCurrentCompilerIndex(currentCompiler);
|
||||
final TranslatingCompiler compiler = translators[currentCompiler];
|
||||
if (context.getProgressIndicator().isCanceled()) {
|
||||
throw new ExitException(ExitStatus.CANCELLED);
|
||||
int round = 0;
|
||||
final Set<VirtualFile> filesToRecompile = new HashSet<VirtualFile>();
|
||||
final Set<VirtualFile> allDependent = new HashSet<VirtualFile>();
|
||||
Collection<VirtualFile> dependentFiles = Collections.emptyList();
|
||||
final Function<Pair<int[], Set<VirtualFile>>, Pair<int[], Set<VirtualFile>>> dependencyFilter = new DependentClassesCumulativeFilter();
|
||||
|
||||
do {
|
||||
for (int currentCompiler = 0, translatorsLength = translators.length; currentCompiler < translatorsLength; currentCompiler++) {
|
||||
sink.setCurrentCompilerIndex(currentCompiler);
|
||||
final TranslatingCompiler compiler = translators[currentCompiler];
|
||||
if (context.getProgressIndicator().isCanceled()) {
|
||||
throw new ExitException(ExitStatus.CANCELLED);
|
||||
}
|
||||
|
||||
DumbService.getInstance(myProject).waitForSmartMode();
|
||||
|
||||
if (round == 0) {
|
||||
if (snapshot == null || ContainerUtil.intersects(generatedTypes, compilerManager.getRegisteredInputTypes(compiler))) {
|
||||
// rescan snapshot if previously generated files may influence the input of this compiler
|
||||
snapshot = ApplicationManager.getApplication().runReadAction(new Computable<VirtualFile[]>() {
|
||||
public VirtualFile[] compute() {
|
||||
return context.getCompileScope().getFiles(null, true);
|
||||
}
|
||||
});
|
||||
recalculateChunkToFilesMap(context, sortedChunks, snapshot, chunkMap);
|
||||
chunkFiles = chunkMap.get(currentChunk);
|
||||
total = snapshot.length * translatorsLength;
|
||||
}
|
||||
}
|
||||
|
||||
final CompileContextEx _context;
|
||||
if (compiler instanceof IntermediateOutputCompiler) {
|
||||
// wrap compile context so that output goes into intermediate directories
|
||||
final IntermediateOutputCompiler _compiler = (IntermediateOutputCompiler)compiler;
|
||||
_context = new CompileContextExProxy(context) {
|
||||
public VirtualFile getModuleOutputDirectory(final Module module) {
|
||||
return getGenerationOutputDir(_compiler, module, false);
|
||||
}
|
||||
|
||||
public VirtualFile getModuleOutputDirectoryForTests(final Module module) {
|
||||
return getGenerationOutputDir(_compiler, module, true);
|
||||
}
|
||||
};
|
||||
}
|
||||
else {
|
||||
_context = context;
|
||||
}
|
||||
final boolean compiledSomething =
|
||||
compileSources(_context, currentChunk, compiler, chunkFiles, round == 0? forceCompile : true, isRebuild, trackDependencies, onlyCheckStatus, sink);
|
||||
|
||||
processed += chunkFiles.size();
|
||||
_context.getProgressIndicator().setFraction(((double)processed) / total);
|
||||
|
||||
if (compiledSomething) {
|
||||
generatedTypes.addAll(compilerManager.getRegisteredOutputTypes(compiler));
|
||||
}
|
||||
|
||||
if (_context.getMessageCount(CompilerMessageCategory.ERROR) > 0) {
|
||||
throw new ExitException(ExitStatus.ERRORS);
|
||||
}
|
||||
|
||||
didSomething |= compiledSomething;
|
||||
}
|
||||
|
||||
DumbService.getInstance(myProject).waitForSmartMode();
|
||||
final boolean hasUnprocessedTraverseRoots = context.getDependencyCache().hasUnprocessedTraverseRoots();
|
||||
if (!isRebuild && (didSomething || hasUnprocessedTraverseRoots)) {
|
||||
final Set<VirtualFile> compiledWithSuccess;
|
||||
final Set<VirtualFile> compiledWithErrors = CacheUtils.getFilesCompiledWithErrors(context);
|
||||
if (compiledWithErrors.isEmpty()) {
|
||||
compiledWithSuccess = sink.getCompiledSources();
|
||||
}
|
||||
else {
|
||||
compiledWithSuccess = new HashSet<VirtualFile>();
|
||||
compiledWithSuccess.addAll(sink.getCompiledSources());
|
||||
compiledWithSuccess.removeAll(compiledWithErrors);
|
||||
}
|
||||
filesToRecompile.removeAll(compiledWithSuccess);
|
||||
filesToRecompile.addAll(compiledWithErrors);
|
||||
|
||||
if (snapshot == null || ContainerUtil.intersects(generatedTypes, compilerManager.getRegisteredInputTypes(compiler))) {
|
||||
// rescan snapshot if previously generated files may influence the input of this compiler
|
||||
snapshot = ApplicationManager.getApplication().runReadAction(new Computable<VirtualFile[]>() {
|
||||
public VirtualFile[] compute() {
|
||||
return context.getCompileScope().getFiles(null, true);
|
||||
}
|
||||
});
|
||||
final Map<Module, List<VirtualFile>> moduleToFilesMap = CompilerUtil.buildModuleToFilesMap(context, snapshot);
|
||||
for (Chunk<Module> moduleChunk : sortedChunks) {
|
||||
List<VirtualFile> files = Collections.emptyList();
|
||||
for (Module module : moduleChunk.getNodes()) {
|
||||
final List<VirtualFile> moduleFiles = moduleToFilesMap.get(module);
|
||||
if (moduleFiles != null) {
|
||||
files = ContainerUtil.concat(files, moduleFiles);
|
||||
dependentFiles = CacheUtils.findDependentFiles(context, compiledWithSuccess, dependencyFilter);
|
||||
|
||||
if (ourDebugMode) {
|
||||
if (!dependentFiles.isEmpty()) {
|
||||
for (VirtualFile dependentFile : dependentFiles) {
|
||||
System.out.println("FOUND TO RECOMPILE: " + dependentFile.getPresentableUrl());
|
||||
}
|
||||
}
|
||||
chunkMap.put(moduleChunk, files);
|
||||
else {
|
||||
System.out.println("NO FILES TO RECOMPILE");
|
||||
}
|
||||
}
|
||||
total = snapshot.length * translatorsLength;
|
||||
chunkFiles = chunkMap.get(currentChunk);
|
||||
}
|
||||
|
||||
final CompileContextEx _context;
|
||||
if (compiler instanceof IntermediateOutputCompiler) {
|
||||
// wrap compile context so that output goes into intermediate directories
|
||||
final IntermediateOutputCompiler _compiler = (IntermediateOutputCompiler)compiler;
|
||||
_context = new CompileContextExProxy(context) {
|
||||
public VirtualFile getModuleOutputDirectory(final Module module) {
|
||||
return getGenerationOutputDir(_compiler, module, false);
|
||||
if (!dependentFiles.isEmpty()) {
|
||||
filesToRecompile.addAll(dependentFiles);
|
||||
allDependent.addAll(dependentFiles);
|
||||
if (context.getProgressIndicator().isCanceled() || context.getMessageCount(CompilerMessageCategory.ERROR) > 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
public VirtualFile getModuleOutputDirectoryForTests(final Module module) {
|
||||
return getGenerationOutputDir(_compiler, module, true);
|
||||
final List<VirtualFile> filesInScope = getFilesInScope(context, currentChunk, dependentFiles);
|
||||
if (filesInScope.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
else {
|
||||
_context = context;
|
||||
}
|
||||
final boolean compiledSomething =
|
||||
compileSources(_context, currentChunk, compiler, chunkFiles, forceCompile, isRebuild, trackDependencies, onlyCheckStatus, sink);
|
||||
|
||||
processed += chunkFiles.size();
|
||||
_context.getProgressIndicator().setFraction(((double)processed) / total);
|
||||
|
||||
if (compiledSomething) {
|
||||
generatedTypes.addAll(compilerManager.getRegisteredOutputTypes(compiler));
|
||||
context.getDependencyCache().clearTraverseRoots();
|
||||
chunkFiles = filesInScope;
|
||||
total += chunkFiles.size() * translators.length;
|
||||
}
|
||||
|
||||
didSomething |= (hasUnprocessedTraverseRoots != context.getDependencyCache().hasUnprocessedTraverseRoots());
|
||||
}
|
||||
|
||||
if (_context.getMessageCount(CompilerMessageCategory.ERROR) > 0) {
|
||||
throw new ExitException(ExitStatus.ERRORS);
|
||||
}
|
||||
|
||||
didSomething |= compiledSomething;
|
||||
round++;
|
||||
}
|
||||
while (!dependentFiles.isEmpty() && context.getMessageCount(CompilerMessageCategory.ERROR) == 0);
|
||||
|
||||
if (CompilerConfiguration.MAKE_ENABLED) {
|
||||
if (!context.getProgressIndicator().isCanceled()) {
|
||||
// when cancelled pretend nothing was compiled and next compile will compile everything from the scratch
|
||||
final ProgressIndicator indicator = context.getProgressIndicator();
|
||||
final DependencyCache cache = context.getDependencyCache();
|
||||
|
||||
indicator.pushState();
|
||||
indicator.setText(CompilerBundle.message("progress.updating.caches"));
|
||||
indicator.setText2("");
|
||||
|
||||
cache.update();
|
||||
|
||||
indicator.setText(CompilerBundle.message("progress.saving.caches"));
|
||||
cache.resetState();
|
||||
|
||||
indicator.popState();
|
||||
}
|
||||
}
|
||||
|
||||
if (context.getMessageCount(CompilerMessageCategory.ERROR) != 0) {
|
||||
filesToRecompile.addAll(allDependent);
|
||||
}
|
||||
if (filesToRecompile.size() > 0) {
|
||||
sink.add(null, Collections.<TranslatingCompiler.OutputItem>emptyList(), VfsUtil.toVirtualFileArray(filesToRecompile));
|
||||
}
|
||||
}
|
||||
catch (CacheCorruptedException e) {
|
||||
LOG.info(e);
|
||||
context.requestRebuildNextTime(e.getMessage());
|
||||
}
|
||||
finally {
|
||||
if (context.getMessageCount(CompilerMessageCategory.ERROR) == 0) {
|
||||
@@ -1034,7 +1111,7 @@ public class CompileDriver {
|
||||
ProgressManager.getInstance().executeNonCancelableSection(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
final Collection<VirtualFile> deps = CacheUtils.findDependentFiles(context, Collections.<VirtualFile>emptySet(), null, null);
|
||||
final Collection<VirtualFile> deps = CacheUtils.findDependentFiles(context, Collections.<VirtualFile>emptySet(), null);
|
||||
if (deps.size() > 0) {
|
||||
TranslatingCompilerFilesMonitor.getInstance().update(context, null, Collections.<TranslatingCompiler.OutputItem>emptyList(),
|
||||
VfsUtil.toVirtualFileArray(deps));
|
||||
@@ -1059,6 +1136,37 @@ public class CompileDriver {
|
||||
return didSomething;
|
||||
}
|
||||
|
||||
private static List<VirtualFile> getFilesInScope(final CompileContextEx context, final Chunk<Module> chunk, final Collection<VirtualFile> files) {
|
||||
final List<VirtualFile> filesInScope = new ArrayList<VirtualFile>(files.size());
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
for (VirtualFile file : files) {
|
||||
if (context.getCompileScope().belongs(file.getUrl())) {
|
||||
final Module module = context.getModuleByFile(file);
|
||||
if (chunk.getNodes().contains(module)) {
|
||||
filesInScope.add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return filesInScope;
|
||||
}
|
||||
|
||||
private static void recalculateChunkToFilesMap(CompileContextEx context, List<Chunk<Module>> allChunks, VirtualFile[] snapshot, Map<Chunk<Module>, Collection<VirtualFile>> chunkMap) {
|
||||
final Map<Module, List<VirtualFile>> moduleToFilesMap = CompilerUtil.buildModuleToFilesMap(context, snapshot);
|
||||
for (Chunk<Module> moduleChunk : allChunks) {
|
||||
List<VirtualFile> files = Collections.emptyList();
|
||||
for (Module module : moduleChunk.getNodes()) {
|
||||
final List<VirtualFile> moduleFiles = moduleToFilesMap.get(module);
|
||||
if (moduleFiles != null) {
|
||||
files = ContainerUtil.concat(files, moduleFiles);
|
||||
}
|
||||
}
|
||||
chunkMap.put(moduleChunk, files);
|
||||
}
|
||||
}
|
||||
|
||||
private interface FileProcessingCompilerAdapterFactory {
|
||||
FileProcessingCompilerAdapter create(CompileContext context, FileProcessingCompiler compiler);
|
||||
}
|
||||
@@ -1167,11 +1275,14 @@ public class CompileDriver {
|
||||
final ArrayList<Trinity<File, String, Boolean>> toDelete = new ArrayList<Trinity<File, String, Boolean>>();
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
TranslatingCompilerFilesMonitor.getInstance()
|
||||
.collectFiles(context, (TranslatingCompiler)compiler, Arrays.<VirtualFile>asList(allSources).iterator(), true
|
||||
/*pass true to make sure that every source in scope file is processed*/, false
|
||||
/*important! should pass false to enable collection of files to delete*/,
|
||||
new ArrayList<VirtualFile>(), toDelete);
|
||||
TranslatingCompilerFilesMonitor.getInstance().collectFiles(
|
||||
context,
|
||||
(TranslatingCompiler)compiler, Arrays.<VirtualFile>asList(allSources).iterator(),
|
||||
true /*pass true to make sure that every source in scope file is processed*/,
|
||||
false /*important! should pass false to enable collection of files to delete*/,
|
||||
new ArrayList<VirtualFile>(),
|
||||
toDelete
|
||||
);
|
||||
}
|
||||
});
|
||||
for (Trinity<File, String, Boolean> trinity : toDelete) {
|
||||
@@ -1532,7 +1643,6 @@ public class CompileDriver {
|
||||
context.getProgressIndicator().pushState();
|
||||
|
||||
final boolean[] wereFilesDeleted = new boolean[]{false};
|
||||
boolean traverseRootsProcessed = false;
|
||||
try {
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
@@ -1589,16 +1699,14 @@ public class CompileDriver {
|
||||
}
|
||||
}
|
||||
|
||||
final boolean hadUnprocessedTraverseRoots = context.getDependencyCache().hasUnprocessedTraverseRoots();
|
||||
if ((wereFilesDeleted[0] || hadUnprocessedTraverseRoots || !toCompile.isEmpty()) && context.getMessageCount(CompilerMessageCategory.ERROR) == 0) {
|
||||
if ((wereFilesDeleted[0] || !toCompile.isEmpty()) && context.getMessageCount(CompilerMessageCategory.ERROR) == 0) {
|
||||
compiler.compile(context, moduleChunk, VfsUtil.toVirtualFileArray(toCompile), sink);
|
||||
traverseRootsProcessed = hadUnprocessedTraverseRoots != context.getDependencyCache().hasUnprocessedTraverseRoots();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
context.getProgressIndicator().popState();
|
||||
}
|
||||
return !toCompile.isEmpty() || traverseRootsProcessed || wereFilesDeleted[0];
|
||||
return !toCompile.isEmpty() || wereFilesDeleted[0];
|
||||
}
|
||||
|
||||
private static boolean syncOutputDir(final CompileContextEx context, final Collection<Trinity<File, String, Boolean>> toDelete) throws CacheCorruptedException {
|
||||
@@ -2277,6 +2385,7 @@ public class CompileDriver {
|
||||
private final CompileContextEx myContext;
|
||||
private final TranslatingCompiler[] myCompilers;
|
||||
private int myCurrentCompilerIdx;
|
||||
private final Set<VirtualFile> myCompiledSources = new HashSet<VirtualFile>();
|
||||
//private LinkedBlockingQueue<Future> myFutures = new LinkedBlockingQueue<Future>();
|
||||
|
||||
private TranslatorsOutputSink(CompileContextEx context, TranslatingCompiler[] compilers) {
|
||||
@@ -2288,7 +2397,17 @@ public class CompileDriver {
|
||||
myCurrentCompilerIdx = index;
|
||||
}
|
||||
|
||||
public Set<VirtualFile> getCompiledSources() {
|
||||
return Collections.unmodifiableSet(myCompiledSources);
|
||||
}
|
||||
|
||||
public void add(final String outputRoot, final Collection<TranslatingCompiler.OutputItem> items, final VirtualFile[] filesToRecompile) {
|
||||
for (TranslatingCompiler.OutputItem item : items) {
|
||||
final VirtualFile file = item.getSourceFile();
|
||||
if (file != null) {
|
||||
myCompiledSources.add(file);
|
||||
}
|
||||
}
|
||||
final TranslatingCompiler compiler = myCompilers[myCurrentCompilerIdx];
|
||||
if (compiler instanceof IntermediateOutputCompiler) {
|
||||
final LocalFileSystem lfs = LocalFileSystem.getInstance();
|
||||
@@ -2368,7 +2487,7 @@ public class CompileDriver {
|
||||
}
|
||||
}
|
||||
|
||||
private void addItemToMap(Map<String, Collection<TranslatingCompiler.OutputItem>> map, String outputDir, TranslatingCompiler.OutputItem item) {
|
||||
private static void addItemToMap(Map<String, Collection<TranslatingCompiler.OutputItem>> map, String outputDir, TranslatingCompiler.OutputItem item) {
|
||||
Collection<TranslatingCompiler.OutputItem> collection = map.get(outputDir);
|
||||
if (collection == null) {
|
||||
collection = new ArrayList<TranslatingCompiler.OutputItem>();
|
||||
@@ -2392,4 +2511,21 @@ public class CompileDriver {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class DependentClassesCumulativeFilter implements Function<Pair<int[], Set<VirtualFile>>, Pair<int[], Set<VirtualFile>>> {
|
||||
|
||||
private final TIntHashSet myProcessedNames = new TIntHashSet();
|
||||
private final Set<VirtualFile> myProcessedFiles = new HashSet<VirtualFile>();
|
||||
|
||||
public Pair<int[], Set<VirtualFile>> fun(Pair<int[], Set<VirtualFile>> deps) {
|
||||
final TIntHashSet currentDeps = new TIntHashSet(deps.getFirst());
|
||||
currentDeps.removeAll(myProcessedNames.toArray());
|
||||
myProcessedNames.addAll(deps.getFirst());
|
||||
|
||||
final Set<VirtualFile> depFiles = new HashSet<VirtualFile>(deps.getSecond());
|
||||
depFiles.removeAll(myProcessedFiles);
|
||||
myProcessedFiles.addAll(deps.getSecond());
|
||||
return new Pair<int[], Set<VirtualFile>>(currentDeps.toArray(), depFiles);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+31
-5
@@ -1212,9 +1212,22 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
|
||||
if (srcFile != null) {
|
||||
final SourceFileInfo srcInfo = loadSourceInfo(srcFile);
|
||||
if (srcInfo != null) {
|
||||
final boolean srcWillBeDeleted = VfsUtil.isAncestor(eventFile, srcFile, false);
|
||||
for (int projectId : srcInfo.getProjectIds().toArray()) {
|
||||
if (srcInfo.isAssociated(projectId, filePath)) {
|
||||
addSourceForRecompilation(projectId, srcFile, srcInfo);
|
||||
if (srcWillBeDeleted) {
|
||||
if (LOG.isDebugEnabled() || ourDebugMode) {
|
||||
final String message = "Unschedule recompilation because of deletion " + srcFile.getPresentableUrl();
|
||||
LOG.debug(message);
|
||||
if (ourDebugMode) {
|
||||
System.out.println(message);
|
||||
}
|
||||
}
|
||||
removeSourceForRecompilation(projectId, Math.abs(getFileId(srcFile)));
|
||||
}
|
||||
else {
|
||||
addSourceForRecompilation(projectId, srcFile, srcInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1226,6 +1239,8 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
|
||||
final TIntHashSet projects = srcInfo.getProjectIds();
|
||||
if (!projects.isEmpty()) {
|
||||
final ScheduleOutputsForDeletionProc deletionProc = new ScheduleOutputsForDeletionProc(file.getUrl());
|
||||
deletionProc.setRootBeingDeleted(eventFile);
|
||||
final int sourceFileId = Math.abs(getFileId(file));
|
||||
for (int projectId : projects.toArray()) {
|
||||
// mark associated outputs for deletion
|
||||
srcInfo.processOutputPaths(projectId, deletionProc);
|
||||
@@ -1236,7 +1251,7 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
|
||||
System.out.println(message);
|
||||
}
|
||||
}
|
||||
removeSourceForRecompilation(projectId, Math.abs(getFileId(file)));
|
||||
removeSourceForRecompilation(projectId, sourceFileId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1381,18 +1396,29 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
|
||||
private class ScheduleOutputsForDeletionProc implements Proc {
|
||||
private final String mySrcUrl;
|
||||
private final LocalFileSystem myFileSystem;
|
||||
@Nullable
|
||||
private VirtualFile myRootBeingDeleted;
|
||||
|
||||
private ScheduleOutputsForDeletionProc(final String srcUrl) {
|
||||
mySrcUrl = srcUrl;
|
||||
myFileSystem = LocalFileSystem.getInstance();
|
||||
}
|
||||
|
||||
public void setRootBeingDeleted(@Nullable VirtualFile rootBeingDeleted) {
|
||||
myRootBeingDeleted = rootBeingDeleted;
|
||||
}
|
||||
|
||||
public boolean execute(final int projectId, String outputPath) {
|
||||
final VirtualFile outFile = myFileSystem.findFileByPath(outputPath);
|
||||
if (outFile != null) { // not deleted yet
|
||||
final OutputFileInfo outputInfo = loadOutputInfo(outFile);
|
||||
final String classname = outputInfo != null? outputInfo.getClassName() : null;
|
||||
markOutputPathForDeletion(projectId, outputPath, classname, mySrcUrl);
|
||||
if (myRootBeingDeleted != null && VfsUtil.isAncestor(myRootBeingDeleted, outFile, false)) {
|
||||
unmarkOutputPathForDeletion(outputPath);
|
||||
}
|
||||
else {
|
||||
final OutputFileInfo outputInfo = loadOutputInfo(outFile);
|
||||
final String classname = outputInfo != null? outputInfo.getClassName() : null;
|
||||
markOutputPathForDeletion(projectId, outputPath, classname, mySrcUrl);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -47,6 +47,4 @@ public interface BackendCompiler {
|
||||
|
||||
void compileFinished();
|
||||
|
||||
@Nullable
|
||||
DependencyProcessor getDependencyProcessor();
|
||||
}
|
||||
|
||||
+27
-144
@@ -26,7 +26,10 @@ import com.intellij.compiler.*;
|
||||
import com.intellij.compiler.classParsing.AnnotationConstantValue;
|
||||
import com.intellij.compiler.classParsing.MethodInfo;
|
||||
import com.intellij.compiler.impl.CompilerUtil;
|
||||
import com.intellij.compiler.make.*;
|
||||
import com.intellij.compiler.make.Cache;
|
||||
import com.intellij.compiler.make.CacheCorruptedException;
|
||||
import com.intellij.compiler.make.DependencyCache;
|
||||
import com.intellij.compiler.make.MakeUtil;
|
||||
import com.intellij.compiler.notNullVerification.NotNullVerifyingInstrumenter;
|
||||
import com.intellij.ide.util.projectWizard.JavaModuleBuilder;
|
||||
import com.intellij.openapi.application.Application;
|
||||
@@ -38,7 +41,6 @@ import com.intellij.openapi.fileTypes.FileTypeManager;
|
||||
import com.intellij.openapi.module.JavaModuleType;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleType;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.JavaSdkType;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
@@ -52,10 +54,8 @@ import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.Chunk;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.cls.ClsFormatException;
|
||||
import gnu.trove.THashMap;
|
||||
import gnu.trove.TIntHashSet;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -74,20 +74,18 @@ public class BackendCompilerWrapper {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.javaCompiler.BackendCompilerWrapper");
|
||||
|
||||
private final BackendCompiler myCompiler;
|
||||
private final Set<VirtualFile> mySuccesfullyCompiledJavaFiles; // VirtualFile
|
||||
|
||||
private final CompileContextEx myCompileContext;
|
||||
private final List<VirtualFile> myFilesToCompile;
|
||||
private final TranslatingCompiler.OutputSink mySink;
|
||||
private final Chunk<Module> myChunk;
|
||||
private final Project myProject;
|
||||
private final Set<VirtualFile> myFilesToRecompile;
|
||||
private final Map<Module, VirtualFile> myModuleToTempDirMap = new THashMap<Module, VirtualFile>();
|
||||
private final ProjectFileIndex myProjectFileIndex;
|
||||
@NonNls private static final String PACKAGE_ANNOTATION_FILE_NAME = "package-info.java";
|
||||
private static final FileObject myStopThreadToken = new FileObject(new File(""), new byte[0]);
|
||||
public final Map<String, Set<CompiledClass>> myFileNameToSourceMap= new THashMap<String, Set<CompiledClass>>();
|
||||
|
||||
private final Set<VirtualFile> myProcessedPackageInfos = new HashSet<VirtualFile>();
|
||||
|
||||
public BackendCompilerWrapper(Chunk<Module> chunk, @NotNull final Project project,
|
||||
@NotNull List<VirtualFile> filesToCompile,
|
||||
@@ -98,44 +96,19 @@ public class BackendCompilerWrapper {
|
||||
myCompiler = compiler;
|
||||
myCompileContext = compileContext;
|
||||
myFilesToCompile = filesToCompile;
|
||||
myFilesToRecompile = new HashSet<VirtualFile>(filesToCompile);
|
||||
mySink = sink;
|
||||
myProjectFileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
|
||||
mySuccesfullyCompiledJavaFiles = new HashSet<VirtualFile>(filesToCompile.size());
|
||||
}
|
||||
|
||||
public void compile() throws CompilerException, CacheCorruptedException {
|
||||
Application application = ApplicationManager.getApplication();
|
||||
final Set<VirtualFile> allDependent = new HashSet<VirtualFile>();
|
||||
COMPILE:
|
||||
try {
|
||||
if (!myFilesToCompile.isEmpty()) {
|
||||
if (application.isUnitTestMode()) {
|
||||
saveTestData();
|
||||
}
|
||||
|
||||
compileModules(buildModuleToFilesMap(myFilesToCompile));
|
||||
}
|
||||
|
||||
Collection<VirtualFile> dependentFiles;
|
||||
do {
|
||||
dependentFiles = CacheUtils.findDependentFiles(myCompileContext, mySuccesfullyCompiledJavaFiles, myCompiler.getDependencyProcessor(), DEPENDENCY_FILTER);
|
||||
|
||||
if (!dependentFiles.isEmpty()) {
|
||||
myFilesToRecompile.addAll(dependentFiles);
|
||||
allDependent.addAll(dependentFiles);
|
||||
if (myCompileContext.getProgressIndicator().isCanceled() || myCompileContext.getMessageCount(CompilerMessageCategory.ERROR) > 0) {
|
||||
break COMPILE;
|
||||
}
|
||||
final List<VirtualFile> filesInScope = getFilesInScope(dependentFiles);
|
||||
if (filesInScope.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
myCompileContext.getDependencyCache().clearTraverseRoots();
|
||||
compileModules(buildModuleToFilesMap(filesInScope));
|
||||
}
|
||||
}
|
||||
while (!dependentFiles.isEmpty() && myCompileContext.getMessageCount(CompilerMessageCategory.ERROR) == 0);
|
||||
}
|
||||
catch (SecurityException e) {
|
||||
throw new CompilerException(CompilerBundle.message("error.compiler.process.not.started", e.getMessage()), e);
|
||||
@@ -153,34 +126,22 @@ public class BackendCompilerWrapper {
|
||||
myModuleToTempDirMap.clear();
|
||||
}
|
||||
|
||||
// do not update caches if cancelled because there is a chance that they will be incomplete
|
||||
if (CompilerConfiguration.MAKE_ENABLED) {
|
||||
if (!myCompileContext.getProgressIndicator().isCanceled()) {
|
||||
// when cancelled pretend nothing was compiled and next compile will compile everything from the scratch
|
||||
final ProgressIndicator indicator = myCompileContext.getProgressIndicator();
|
||||
final DependencyCache cache = myCompileContext.getDependencyCache();
|
||||
|
||||
indicator.pushState();
|
||||
indicator.setText(CompilerBundle.message("progress.updating.caches"));
|
||||
indicator.setText2("");
|
||||
|
||||
cache.update();
|
||||
|
||||
indicator.setText(CompilerBundle.message("progress.saving.caches"));
|
||||
cache.resetState();
|
||||
|
||||
indicator.popState();
|
||||
if (!myFilesToCompile.isEmpty() && myCompileContext.getMessageCount(CompilerMessageCategory.ERROR) == 0) {
|
||||
// package-info.java hack
|
||||
final List<TranslatingCompiler.OutputItem> outputs = new ArrayList<TranslatingCompiler.OutputItem>();
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
for (final VirtualFile file : myFilesToCompile) {
|
||||
if (PACKAGE_ANNOTATION_FILE_NAME.equals(file.getName()) && !myProcessedPackageInfos.contains(file)) {
|
||||
outputs.add(new OutputItemImpl(file));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
if (!outputs.isEmpty()) {
|
||||
mySink.add(null, outputs, VirtualFile.EMPTY_ARRAY);
|
||||
}
|
||||
}
|
||||
|
||||
myFilesToRecompile.removeAll(mySuccesfullyCompiledJavaFiles);
|
||||
if (myCompileContext.getMessageCount(CompilerMessageCategory.ERROR) != 0) {
|
||||
myFilesToRecompile.addAll(allDependent);
|
||||
}
|
||||
final List<TranslatingCompiler.OutputItem> outputs = processPackageInfoFiles();
|
||||
if (myFilesToRecompile.size() > 0 || outputs.size() > 0) {
|
||||
mySink.add(null, outputs, VfsUtil.toVirtualFileArray(myFilesToRecompile));
|
||||
}
|
||||
}
|
||||
|
||||
private Map<Module, List<VirtualFile>> buildModuleToFilesMap(final List<VirtualFile> filesToCompile) {
|
||||
@@ -190,51 +151,6 @@ public class BackendCompilerWrapper {
|
||||
return CompilerUtil.buildModuleToFilesMap(myCompileContext, filesToCompile);
|
||||
}
|
||||
|
||||
// package-info.java hack
|
||||
private List<TranslatingCompiler.OutputItem> processPackageInfoFiles() {
|
||||
if (myFilesToRecompile.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
final List<TranslatingCompiler.OutputItem> outputs = new ArrayList<TranslatingCompiler.OutputItem>();
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
final List<VirtualFile> packageInfoFiles = new ArrayList<VirtualFile>(myFilesToRecompile.size());
|
||||
for (final VirtualFile file : myFilesToRecompile) {
|
||||
if (PACKAGE_ANNOTATION_FILE_NAME.equals(file.getName())) {
|
||||
packageInfoFiles.add(file);
|
||||
}
|
||||
}
|
||||
if (!packageInfoFiles.isEmpty()) {
|
||||
final Set<VirtualFile> badFiles = getFilesCompiledWithErrors();
|
||||
for (final VirtualFile packageInfoFile : packageInfoFiles) {
|
||||
if (!badFiles.contains(packageInfoFile)) {
|
||||
outputs.add(new OutputItemImpl(packageInfoFile));
|
||||
myFilesToRecompile.remove(packageInfoFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return outputs;
|
||||
}
|
||||
|
||||
private List<VirtualFile> getFilesInScope(final Collection<VirtualFile> files) {
|
||||
final List<VirtualFile> filesInScope = new ArrayList<VirtualFile>(files.size());
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
for (VirtualFile file : files) {
|
||||
if (myCompileContext.getCompileScope().belongs(file.getUrl())) {
|
||||
final Module module = myCompileContext.getModuleByFile(file);
|
||||
if (myChunk.getNodes().contains(module)) {
|
||||
filesInScope.add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return filesInScope;
|
||||
}
|
||||
|
||||
private void compileModules(final Map<Module, List<VirtualFile>> moduleToFilesMap) throws CompilerException {
|
||||
myProcessedFilesCount = 0;
|
||||
try {
|
||||
@@ -347,21 +263,6 @@ public class BackendCompilerWrapper {
|
||||
});
|
||||
}
|
||||
|
||||
private final TIntHashSet myProcessedNames = new TIntHashSet();
|
||||
private final Set<VirtualFile> myProcessedFiles = new HashSet<VirtualFile>();
|
||||
private final Function<Pair<int[], Set<VirtualFile>>, Pair<int[], Set<VirtualFile>>> DEPENDENCY_FILTER = new Function<Pair<int[], Set<VirtualFile>>, Pair<int[], Set<VirtualFile>>>() {
|
||||
public Pair<int[], Set<VirtualFile>> fun(Pair<int[], Set<VirtualFile>> deps) {
|
||||
final TIntHashSet currentDeps = new TIntHashSet(deps.getFirst());
|
||||
currentDeps.removeAll(myProcessedNames.toArray());
|
||||
myProcessedNames.addAll(deps.getFirst());
|
||||
|
||||
final Set<VirtualFile> depFiles = new HashSet<VirtualFile>(deps.getSecond());
|
||||
depFiles.removeAll(myProcessedFiles);
|
||||
myProcessedFiles.addAll(deps.getSecond());
|
||||
return new Pair<int[], Set<VirtualFile>>(currentDeps.toArray(), depFiles);
|
||||
}
|
||||
};
|
||||
|
||||
private final Object lock = new Object();
|
||||
|
||||
private class SynchedCompilerParsing extends CompilerParsingThread {
|
||||
@@ -599,8 +500,7 @@ public class BackendCompilerWrapper {
|
||||
}
|
||||
|
||||
private void compileFinished(int exitValue, final ModuleChunk chunk, final String outputDir) {
|
||||
if (exitValue != 0 && !myCompileContext.getProgressIndicator().isCanceled() &&
|
||||
myCompileContext.getMessageCount(CompilerMessageCategory.ERROR) == 0) {
|
||||
if (exitValue != 0 && !myCompileContext.getProgressIndicator().isCanceled() && myCompileContext.getMessageCount(CompilerMessageCategory.ERROR) == 0) {
|
||||
myCompileContext.addMessage(CompilerMessageCategory.ERROR, CompilerBundle.message("error.compiler.internal.error", exitValue), null, -1, -1);
|
||||
}
|
||||
|
||||
@@ -610,7 +510,6 @@ public class BackendCompilerWrapper {
|
||||
try {
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
final Set<VirtualFile> compiledWithErrors = getFilesCompiledWithErrors();
|
||||
final FileTypeManager typeManager = FileTypeManager.getInstance();
|
||||
final String outputDirPath = outputDir.replace(File.separatorChar, '/');
|
||||
try {
|
||||
@@ -620,7 +519,7 @@ public class BackendCompilerWrapper {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Building output items for " + root.getPresentableUrl() + "; output dir = " + outputDirPath + "; packagePrefix = \"" + packagePrefix + "\"");
|
||||
}
|
||||
buildOutputItemsList(outputDirPath, module, root, typeManager, compiledWithErrors, root, packagePrefix, toRefresh, results);
|
||||
buildOutputItemsList(outputDirPath, module, root, typeManager, root, packagePrefix, toRefresh, results);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -644,24 +543,8 @@ public class BackendCompilerWrapper {
|
||||
myFileNameToSourceMap.clear(); // clear the map before the next use
|
||||
}
|
||||
|
||||
private Set<VirtualFile> getFilesCompiledWithErrors() {
|
||||
CompilerMessage[] messages = myCompileContext.getMessages(CompilerMessageCategory.ERROR);
|
||||
Set<VirtualFile> compiledWithErrors = Collections.emptySet();
|
||||
if (messages.length > 0) {
|
||||
compiledWithErrors = new HashSet<VirtualFile>(messages.length);
|
||||
for (CompilerMessage message : messages) {
|
||||
final VirtualFile file = message.getVirtualFile();
|
||||
if (file != null) {
|
||||
compiledWithErrors.add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
return compiledWithErrors;
|
||||
}
|
||||
|
||||
private void buildOutputItemsList(final String outputDir, Module module, VirtualFile from,
|
||||
final FileTypeManager typeManager,
|
||||
final Set<VirtualFile> compiledWithErrors,
|
||||
final VirtualFile sourceRoot,
|
||||
final String packagePrefix, final List<File> filesToRefresh, final Map<String, Collection<TranslatingCompiler.OutputItem>> results) throws CacheCorruptedException {
|
||||
final Ref<CacheCorruptedException> exRef = new Ref<CacheCorruptedException>(null);
|
||||
@@ -671,7 +554,7 @@ public class BackendCompilerWrapper {
|
||||
try {
|
||||
assert child.isValid();
|
||||
if (!child.isDirectory() && myCompiler.getCompilableFileTypes().contains(typeManager.getFileTypeByFile(child))) {
|
||||
updateOutputItemsList(outputDir, child, compiledWithErrors, sourceRoot, packagePrefix, filesToRefresh, results);
|
||||
updateOutputItemsList(outputDir, child, sourceRoot, packagePrefix, filesToRefresh, results);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -720,7 +603,7 @@ public class BackendCompilerWrapper {
|
||||
paths.add(new CompiledClass(classQName, relativePathToSource, pathToClass));
|
||||
}
|
||||
|
||||
private void updateOutputItemsList(final String outputDir, VirtualFile srcFile, Set<VirtualFile> compiledWithErrors,
|
||||
private void updateOutputItemsList(final String outputDir, VirtualFile srcFile,
|
||||
VirtualFile sourceRoot,
|
||||
final String packagePrefix, final List<File> filesToRefresh,
|
||||
Map<String, Collection<TranslatingCompiler.OutputItem>> results) throws CacheCorruptedException {
|
||||
@@ -745,6 +628,9 @@ public class BackendCompilerWrapper {
|
||||
results.put(realLocation.getFirst(), outputs);
|
||||
}
|
||||
outputs.add(new OutputItemImpl(realLocation.getSecond(), srcFile));
|
||||
if (PACKAGE_ANNOTATION_FILE_NAME.equals(srcFile.getName())) {
|
||||
myProcessedPackageInfos.add(srcFile);
|
||||
}
|
||||
if (CompilerConfiguration.MAKE_ENABLED) {
|
||||
newCache.setPath(cc.qName, realLocation.getSecond());
|
||||
}
|
||||
@@ -752,9 +638,6 @@ public class BackendCompilerWrapper {
|
||||
LOG.debug("Added output item: [outputDir; outputPath; sourceFile] = [" + realLocation.getFirst() + "; " +
|
||||
realLocation.getSecond() + "; " + srcFile.getPresentableUrl() + "]");
|
||||
}
|
||||
if (!compiledWithErrors.contains(srcFile)) {
|
||||
mySuccesfullyCompiledJavaFiles.add(srcFile);
|
||||
}
|
||||
}
|
||||
else {
|
||||
myCompileContext.addMessage(CompilerMessageCategory.ERROR, "Failed to copy from temporary location to output directory: " + outputPath + " (see idea.log for details)", null, -1, -1);
|
||||
@@ -773,7 +656,7 @@ public class BackendCompilerWrapper {
|
||||
* @param packagePrefix
|
||||
* @return A 'package'-path to a given src file relative to a specified root. "/" slashes must be used
|
||||
*/
|
||||
protected String calcPackagePath(VirtualFile srcFile, VirtualFile sourceRoot, String packagePrefix) {
|
||||
protected static String calcPackagePath(VirtualFile srcFile, VirtualFile sourceRoot, String packagePrefix) {
|
||||
final String prefix = packagePrefix != null && packagePrefix.length() > 0 ? packagePrefix.replace('.', '/') + "/" : "";
|
||||
return prefix + VfsUtil.getRelativePath(srcFile, sourceRoot, '/');
|
||||
}
|
||||
|
||||
@@ -41,10 +41,6 @@ public abstract class ExternalCompiler implements BackendCompiler {
|
||||
return COMPILABLE_TYPES;
|
||||
}
|
||||
|
||||
public DependencyProcessor getDependencyProcessor() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Process launchProcess(@NotNull final ModuleChunk chunk, @NotNull final String outputDir, @NotNull final CompileContext compileContext) throws IOException {
|
||||
final String[] commands = createStartupCommand(chunk, compileContext, outputDir);
|
||||
|
||||
-5
@@ -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;
|
||||
}
|
||||
|
||||
-5
@@ -17,7 +17,6 @@ package com.intellij.compiler.impl.javaCompiler.eclipse;
|
||||
|
||||
import com.intellij.compiler.OutputParser;
|
||||
import com.intellij.compiler.impl.javaCompiler.BackendCompiler;
|
||||
import com.intellij.compiler.impl.javaCompiler.DependencyProcessor;
|
||||
import com.intellij.compiler.impl.javaCompiler.ModuleChunk;
|
||||
import com.intellij.compiler.impl.javaCompiler.javac.JavacSettings;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
@@ -58,10 +57,6 @@ public class EclipseEmbeddedCompiler implements BackendCompiler {
|
||||
myEclipseCompilerDriver = new EclipseCompilerDriver();
|
||||
}
|
||||
|
||||
public DependencyProcessor getDependencyProcessor() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean checkCompiler(final CompileScope scope) {
|
||||
return myEclipseCompilerDriver != null && myEclipseExternalCompiler.checkCompiler(scope);
|
||||
}
|
||||
|
||||
@@ -19,9 +19,10 @@ import com.intellij.compiler.CompilerConfiguration;
|
||||
import com.intellij.compiler.CompilerManagerImpl;
|
||||
import com.intellij.compiler.SymbolTable;
|
||||
import com.intellij.compiler.classParsing.MethodInfo;
|
||||
import com.intellij.compiler.impl.javaCompiler.DependencyProcessor;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.compiler.CompilerBundle;
|
||||
import com.intellij.openapi.compiler.CompilerMessage;
|
||||
import com.intellij.openapi.compiler.CompilerMessageCategory;
|
||||
import com.intellij.openapi.compiler.ex.CompileContextEx;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
@@ -31,6 +32,7 @@ import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.StringBuilderSpinAllocator;
|
||||
import gnu.trove.TIntHashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
@@ -126,9 +128,11 @@ public class CacheUtils {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static Collection<VirtualFile> findDependentFiles(final CompileContextEx context, final Set<VirtualFile> succesfullyCompiledJavaFiles,
|
||||
final @Nullable DependencyProcessor additionalDependencyProcessor,
|
||||
final @Nullable Function<Pair<int[], Set<VirtualFile>>, Pair<int[], Set<VirtualFile>>> filter) throws CacheCorruptedException {
|
||||
public static Collection<VirtualFile> findDependentFiles(
|
||||
final CompileContextEx context,
|
||||
final Set<VirtualFile> succesfullyCompiledJavaFiles,
|
||||
final @Nullable Function<Pair<int[], Set<VirtualFile>>, Pair<int[], Set<VirtualFile>>> filter) throws CacheCorruptedException {
|
||||
|
||||
if (!CompilerConfiguration.MAKE_ENABLED) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
@@ -137,7 +141,7 @@ public class CacheUtils {
|
||||
final DependencyCache dependencyCache = context.getDependencyCache();
|
||||
|
||||
final Pair<int[], Set<VirtualFile>> deps =
|
||||
dependencyCache.findDependentClasses(context, context.getProject(), succesfullyCompiledJavaFiles, additionalDependencyProcessor);
|
||||
dependencyCache.findDependentClasses(context, context.getProject(), succesfullyCompiledJavaFiles);
|
||||
final Pair<int[], Set<VirtualFile>> filteredDeps = filter != null? filter.fun(deps) : deps;
|
||||
|
||||
final Set<VirtualFile> dependentFiles = new HashSet<VirtualFile>();
|
||||
@@ -187,4 +191,20 @@ public class CacheUtils {
|
||||
|
||||
return dependentFiles;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Set<VirtualFile> getFilesCompiledWithErrors(final CompileContextEx context) {
|
||||
CompilerMessage[] messages = context.getMessages(CompilerMessageCategory.ERROR);
|
||||
Set<VirtualFile> compiledWithErrors = Collections.emptySet();
|
||||
if (messages.length > 0) {
|
||||
compiledWithErrors = new HashSet<VirtualFile>(messages.length);
|
||||
for (CompilerMessage message : messages) {
|
||||
final VirtualFile file = message.getVirtualFile();
|
||||
if (file != null) {
|
||||
compiledWithErrors.add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
return compiledWithErrors;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
*/
|
||||
package com.intellij.compiler.make;
|
||||
|
||||
import com.intellij.compiler.DependencyProcessor;
|
||||
import com.intellij.compiler.SymbolTable;
|
||||
import com.intellij.compiler.classParsing.*;
|
||||
import com.intellij.compiler.impl.javaCompiler.DependencyProcessor;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.compiler.CompileContext;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
@@ -37,7 +37,6 @@ import com.intellij.util.cls.ClsUtil;
|
||||
import gnu.trove.TIntHashSet;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -390,15 +389,14 @@ public class DependencyCache {
|
||||
/**
|
||||
* @return qualified names of the classes that should be additionally recompiled
|
||||
*/
|
||||
public Pair<int[], Set<VirtualFile>> findDependentClasses(CompileContext context, Project project, Set<VirtualFile> successfullyCompiled, @Nullable final DependencyProcessor additionalProcessor)
|
||||
throws CacheCorruptedException {
|
||||
public Pair<int[], Set<VirtualFile>> findDependentClasses(CompileContext context, Project project, Set<VirtualFile> successfullyCompiled)
|
||||
throws CacheCorruptedException {
|
||||
|
||||
markDependencies(context, project, successfullyCompiled, additionalProcessor);
|
||||
markDependencies(context, project, successfullyCompiled);
|
||||
return new Pair<int[], Set<VirtualFile>>(myMarkedInfos.toArray(), Collections.unmodifiableSet(myMarkedFiles));
|
||||
}
|
||||
|
||||
private void markDependencies(CompileContext context, Project project, final Set<VirtualFile> successfullyCompiled,
|
||||
@Nullable final DependencyProcessor additionalProcessor) throws CacheCorruptedException {
|
||||
private void markDependencies(CompileContext context, Project project, final Set<VirtualFile> successfullyCompiled) throws CacheCorruptedException {
|
||||
try {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("====================Marking dependent files=====================");
|
||||
@@ -427,7 +425,7 @@ public class DependencyCache {
|
||||
).run();
|
||||
}
|
||||
changedRetentionPolicyDependencyProcessor.checkAnnotationRetentionPolicyChanges(qName);
|
||||
if (additionalProcessor != null) {
|
||||
for (DependencyProcessor additionalProcessor : DependencyProcessor.EXTENSION_POINT_NAME.getExtensions()) {
|
||||
additionalProcessor.processDependencies(context, qName);
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -16,6 +16,7 @@
|
||||
package com.intellij.codeInsight.completion;
|
||||
|
||||
import com.intellij.codeInsight.*;
|
||||
import com.intellij.codeInsight.ExceptionUtil;
|
||||
import com.intellij.codeInsight.lookup.*;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
|
||||
+3
-2
@@ -187,8 +187,9 @@ public class CreatePropertyFromUsageFix extends CreateFromUsageBaseFix {
|
||||
LOG.assertTrue(callText != null, myMethodCall.getMethodExpression());
|
||||
PsiType[] expectedTypes;
|
||||
PsiType type;
|
||||
PsiField field = targetClass.findFieldByName(fieldName, true);
|
||||
if (callText.startsWith(GET_PREFIX)) {
|
||||
expectedTypes = CreateFromUsageUtils.guessType(myMethodCall, false);
|
||||
expectedTypes = field != null ? new PsiType[]{field.getType()} : CreateFromUsageUtils.guessType(myMethodCall, false);
|
||||
type = expectedTypes[0];
|
||||
}
|
||||
else if (callText.startsWith(IS_PREFIX)) {
|
||||
@@ -206,7 +207,7 @@ public class CreatePropertyFromUsageFix extends CreateFromUsageBaseFix {
|
||||
IdeDocumentHistory.getInstance(project).includeCurrentPlaceAsChangePlace();
|
||||
|
||||
try {
|
||||
PsiField field = targetClass.findFieldByName(fieldName, true);
|
||||
|
||||
if (field == null) {
|
||||
field = factory.createField(fieldName, type);
|
||||
PsiUtil.setModifierProperty(field, PsiModifier.STATIC, isStatic);
|
||||
|
||||
@@ -46,9 +46,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -1290,32 +1288,26 @@ public class JavaDocInfoGenerator {
|
||||
LinkedList<Pair<PsiDocTag, InheritDocProvider<PsiDocTag>>> collectedTags =
|
||||
new LinkedList<Pair<PsiDocTag, InheritDocProvider<PsiDocTag>>>();
|
||||
|
||||
LinkedList<PsiClassType> holder = new LinkedList<PsiClassType>(Arrays.asList(method.getThrowsList().getReferencedTypes()));
|
||||
final List<PsiClassType> declaredThrows = new ArrayList<PsiClassType>(Arrays.asList(method.getThrowsList().getReferencedTypes()));
|
||||
|
||||
for (int i = localTags.length - 1; i > -1; i--) {
|
||||
PsiDocTagValue valueElement = localTags[i].getValueElement();
|
||||
|
||||
if (valueElement != null) {
|
||||
boolean contains = false;
|
||||
for (PsiClassType classType : holder) {
|
||||
for (Iterator<PsiClassType> iterator = declaredThrows.iterator(); iterator.hasNext();) {
|
||||
PsiClassType classType = iterator.next();
|
||||
if (Comparing.strEqual(valueElement.getText(), classType.getClassName())) {
|
||||
contains = true;
|
||||
iterator.remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (contains) continue;
|
||||
try {
|
||||
PsiClassType t = (PsiClassType)JavaPsiFacade.getInstance(method.getProject()).getElementFactory()
|
||||
.createTypeFromText(valueElement.getText(), method);
|
||||
|
||||
if (!holder.contains(t)) {
|
||||
holder.addFirst(t);
|
||||
}
|
||||
} catch(IncorrectOperationException e) {} // nonvalid type
|
||||
collectedTags.addFirst(new Pair<PsiDocTag, InheritDocProvider<PsiDocTag>>(localTags[i], ourEmptyProvider));
|
||||
}
|
||||
}
|
||||
|
||||
PsiClassType[] trousers = holder.toArray(new PsiClassType[holder.size()]);
|
||||
|
||||
PsiClassType[] trousers = declaredThrows.toArray(new PsiClassType[declaredThrows.size()]);
|
||||
|
||||
for (PsiClassType trouser : trousers) {
|
||||
if (trouser != null) {
|
||||
|
||||
@@ -254,7 +254,7 @@ public class LocalCanBeFinal extends BaseLocalInspectionTool {
|
||||
if (!CodeInsightUtilBase.preparePsiElementForWrite(problem.getPsiElement())) return;
|
||||
PsiElement nameIdentifier = problem.getPsiElement();
|
||||
if (nameIdentifier == null) return;
|
||||
PsiVariable psiVariable = (PsiVariable)nameIdentifier.getParent();
|
||||
PsiVariable psiVariable = PsiTreeUtil.getParentOfType(nameIdentifier, PsiVariable.class, false);
|
||||
if (psiVariable == null) return;
|
||||
try {
|
||||
psiVariable.normalizeDeclaration();
|
||||
|
||||
@@ -78,7 +78,7 @@ public class JavaRefactoringSupportProvider extends DefaultRefactoringSupportPro
|
||||
return new JavaPushDownHandler();
|
||||
}
|
||||
|
||||
public RefactoringActionHandler getExtractModuleHandler() {
|
||||
public RefactoringActionHandler getExtractInterfaceHandler() {
|
||||
return new ExtractInterfaceHandler();
|
||||
}
|
||||
|
||||
|
||||
@@ -175,7 +175,7 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
|
||||
}
|
||||
break;
|
||||
case SUBTYPE:
|
||||
if (PsiType.NULL.equals(upperBound)) {
|
||||
if (PsiType.NULL.equals(upperBound) || TypeConversionUtil.isAssignable(upperBound, type)) {
|
||||
upperBound = type;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -819,7 +819,7 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr
|
||||
if (!JavaPsiFacade.getInstance(element.getProject()).getResolveHelper()
|
||||
.isAccessible(method, modifierList, element, accessObjectClass, null)) {
|
||||
String message =
|
||||
RefactoringBundle.message("0.with.1.visibility.is.not.accesible.from.2",
|
||||
RefactoringBundle.message("0.with.1.visibility.is.not.accessible.from.2",
|
||||
RefactoringUIUtil.getDescription(method, true),
|
||||
myChangeInfo.getNewVisibility(),
|
||||
RefactoringUIUtil.getDescription(ConflictsUtil.getContainer(element), true));
|
||||
|
||||
+1
-1
@@ -200,7 +200,7 @@ public class ConvertToInstanceMethodProcessor extends BaseRefactoringProcessor {
|
||||
}
|
||||
if (!JavaResolveUtil.isAccessible(myMethod, myTargetClass, copy, call, accessObjectClass, null)) {
|
||||
final String newVisibility = myNewVisibility == null ? VisibilityUtil.getVisibilityStringToDisplay(myMethod) : myNewVisibility;
|
||||
String message = RefactoringBundle.message("0.with.1.visibility.is.not.accesible.from.2",
|
||||
String message = RefactoringBundle.message("0.with.1.visibility.is.not.accessible.from.2",
|
||||
RefactoringUIUtil.getDescription(myMethod, true), newVisibility,
|
||||
RefactoringUIUtil.getDescription(ConflictsUtil.getContainer(call), true));
|
||||
conflicts.putValue(myMethod, message);
|
||||
|
||||
+1
-1
@@ -268,7 +268,7 @@ public class IntroduceParameterProcessor extends BaseRefactoringProcessor implem
|
||||
!JavaPsiFacade.getInstance(myProject).getResolveHelper().isAccessible((PsiMember)element, place, null)) {
|
||||
String message =
|
||||
RefactoringBundle.message(
|
||||
"0.is.not.accesible.from.1.value.for.introduced.parameter.in.that.method.call.will.be.incorrect",
|
||||
"0.is.not.accessible.from.1.value.for.introduced.parameter.in.that.method.call.will.be.incorrect",
|
||||
RefactoringUIUtil.getDescription(element, true),
|
||||
RefactoringUIUtil.getDescription(ConflictsUtil.getContainer(place), true));
|
||||
conflicts.putValue(element, message);
|
||||
|
||||
@@ -150,8 +150,10 @@ public class JavaPullUpHandler implements RefactoringActionHandler, PullUpDialog
|
||||
final MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>();
|
||||
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
|
||||
public void run() {
|
||||
final PsiDirectory targetDirectory = superClass.getContainingFile().getContainingDirectory();
|
||||
final PsiPackage targetPackage = targetDirectory != null ? JavaDirectoryService.getInstance().getPackage(targetDirectory) : null;
|
||||
conflicts
|
||||
.putAllValues(PullUpConflictsUtil.checkConflicts(infos, mySubclass, superClass, null, null, dialog.getContainmentVerifier()));
|
||||
.putAllValues(PullUpConflictsUtil.checkConflicts(infos, mySubclass, superClass, targetPackage, targetDirectory, dialog.getContainmentVerifier()));
|
||||
}
|
||||
}, "Detecting possible conflicts...", true, myProject)) return false;
|
||||
if (!conflicts.isEmpty()) {
|
||||
|
||||
@@ -28,10 +28,7 @@ import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.searches.ClassInheritorsSearch;
|
||||
import com.intellij.psi.util.MethodSignature;
|
||||
import com.intellij.psi.util.MethodSignatureUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.refactoring.util.CommonRefactoringUtil;
|
||||
import com.intellij.refactoring.util.RefactoringConflictsUtil;
|
||||
@@ -43,6 +40,7 @@ import com.intellij.refactoring.util.classMembers.MemberInfo;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.util.VisibilityUtil;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -56,17 +54,17 @@ public class PullUpConflictsUtil {
|
||||
public static MultiMap<PsiElement, String> checkConflicts(final MemberInfo[] infos,
|
||||
PsiClass subclass,
|
||||
@Nullable PsiClass superClass,
|
||||
PsiPackage targetPackage,
|
||||
PsiDirectory targetDirectory,
|
||||
@NotNull PsiPackage targetPackage,
|
||||
@NotNull PsiDirectory targetDirectory,
|
||||
final InterfaceContainmentVerifier interfaceContainmentVerifier) {
|
||||
return checkConflicts(infos, subclass, superClass, targetPackage, targetDirectory, interfaceContainmentVerifier, true);
|
||||
}
|
||||
|
||||
public static MultiMap<PsiElement, String> checkConflicts(final MemberInfo[] infos,
|
||||
final PsiClass subclass,
|
||||
@NotNull final PsiClass subclass,
|
||||
@Nullable PsiClass superClass,
|
||||
final PsiPackage targetPackage,
|
||||
PsiDirectory targetDirectory,
|
||||
@NotNull final PsiPackage targetPackage,
|
||||
@NotNull PsiDirectory targetDirectory,
|
||||
final InterfaceContainmentVerifier interfaceContainmentVerifier,
|
||||
boolean movedMembers2Super) {
|
||||
final Set<PsiMember> movedMembers = new HashSet<PsiMember>();
|
||||
@@ -143,9 +141,20 @@ public class PullUpConflictsUtil {
|
||||
}
|
||||
RefactoringConflictsUtil.analyzeModuleConflicts(subclass.getProject(), checkModuleConflictsList,
|
||||
new UsageInfo[0], targetRepresentativeElement, conflicts);
|
||||
final String fqName = subclass.getQualifiedName();
|
||||
final String packageName;
|
||||
if (fqName != null) {
|
||||
packageName = StringUtil.getPackageName(fqName);
|
||||
} else {
|
||||
final PsiFile psiFile = PsiTreeUtil.getParentOfType(subclass, PsiFile.class);
|
||||
if (psiFile instanceof PsiClassOwner) {
|
||||
packageName = ((PsiClassOwner)psiFile).getPackageName();
|
||||
} else {
|
||||
packageName = null;
|
||||
}
|
||||
}
|
||||
final boolean toDifferentPackage = !Comparing.strEqual(targetPackage.getQualifiedName(), packageName);
|
||||
for (final PsiMethod abstractMethod : abstractMethods) {
|
||||
final boolean toDifferentPackage =
|
||||
!Comparing.strEqual(targetPackage.getQualifiedName(), StringUtil.getPackageName(subclass.getQualifiedName()));
|
||||
abstractMethod.accept(new ClassMemberReferencesVisitor(subclass) {
|
||||
@Override
|
||||
protected void visitClassMemberReferenceElement(PsiMember classMember, PsiJavaCodeReferenceElement classMemberReference) {
|
||||
|
||||
+1
-2
@@ -21,7 +21,6 @@
|
||||
package com.intellij.refactoring.move.moveMembers;
|
||||
|
||||
import com.intellij.codeInsight.highlighting.ReadWriteAccessDetector;
|
||||
import com.intellij.lang.LanguageExtension;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
@@ -282,7 +281,7 @@ public class MoveMembersProcessor extends BaseRefactoringProcessor {
|
||||
if (!JavaResolveUtil.isAccessible(member, myTargetClass, modifierListCopies.get(member), element, accessObjectClass, null)) {
|
||||
newVisibility = newVisibility == null ? VisibilityUtil.getVisibilityStringToDisplay(member) : newVisibility;
|
||||
String message =
|
||||
CommonRefactoringUtil.capitalize(RefactoringBundle.message("0.with.1.visibility.is.not.accesible.from.2", RefactoringUIUtil.getDescription(member, false),
|
||||
CommonRefactoringUtil.capitalize(RefactoringBundle.message("0.with.1.visibility.is.not.accessible.from.2", RefactoringUIUtil.getDescription(member, false),
|
||||
newVisibility, RefactoringUIUtil.getDescription(ConflictsUtil.getContainer(element), true)));
|
||||
conflicts.putValue(member, message);
|
||||
}
|
||||
|
||||
@@ -427,7 +427,7 @@ public class JavaSafeDeleteProcessor implements SafeDeleteProcessorDelegate {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!anyOverridingRefs && isMultipleInterfacesImplementation(overridingMethod, allElementsToDelete)) {
|
||||
if (!anyOverridingRefs && isMultipleInterfacesImplementation(overridingMethod, originalMethod, allElementsToDelete)) {
|
||||
anyOverridingRefs = true;
|
||||
multipleInterfaceImplementations.add(overridingMethod);
|
||||
}
|
||||
@@ -468,10 +468,12 @@ public class JavaSafeDeleteProcessor implements SafeDeleteProcessorDelegate {
|
||||
return validOverriding;
|
||||
}
|
||||
|
||||
private static boolean isMultipleInterfacesImplementation(final PsiMethod method, final PsiElement[] allElementsToDelete) {
|
||||
private static boolean isMultipleInterfacesImplementation(final PsiMethod method,
|
||||
PsiMethod originalMethod,
|
||||
final PsiElement[] allElementsToDelete) {
|
||||
final PsiMethod[] methods = method.findSuperMethods();
|
||||
for(PsiMethod superMethod: methods) {
|
||||
if (ArrayUtil.find(allElementsToDelete, superMethod) < 0) {
|
||||
if (ArrayUtil.find(allElementsToDelete, superMethod) < 0 && !MethodSignatureUtil.isSuperMethod(originalMethod, superMethod)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
|
||||
public class NestedGenericGoodCodeIsRed {
|
||||
|
||||
public void main( String[] args ) {
|
||||
satisfiesAllOf(isPositive(), isEqualTo(10.9));
|
||||
satisfiesAllOf(isPositive(), isEqualTo(10));
|
||||
|
||||
Number num = null;
|
||||
satisfiesAllOf(isPositive(), isEqualTo(num));
|
||||
|
||||
this.<Number>satisfiesAllOf<error descr="'satisfiesAllOf(NestedGenericGoodCodeIsRed.Predicate<? super java.lang.Number>, NestedGenericGoodCodeIsRed.Predicate<? super java.lang.Number>)' in 'NestedGenericGoodCodeIsRed' cannot be applied to '(NestedGenericGoodCodeIsRed.Predicate<java.lang.Number>, NestedGenericGoodCodeIsRed.Predicate<java.lang.Integer>)'">(isPositive(), isEqualTo(10))</error>;
|
||||
}
|
||||
|
||||
|
||||
public interface Predicate<T> {
|
||||
|
||||
}
|
||||
|
||||
public <ALL> void satisfiesAllOf( Predicate<? super ALL> first, Predicate<? super ALL> second ) {
|
||||
}
|
||||
|
||||
public <POSITIVE extends Number> Predicate<POSITIVE> isPositive() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public <EQUALTO extends Number> Predicate<EQUALTO> isEqualTo( EQUALTO target ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// "Create Getter" "true"
|
||||
public class Test {
|
||||
Integer field;
|
||||
public foo() {
|
||||
getField();
|
||||
}
|
||||
|
||||
public Integer getField() {
|
||||
return field;
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Create Getter" "true"
|
||||
public class Test {
|
||||
Integer field;
|
||||
public foo() {
|
||||
get<caret>Field();
|
||||
}
|
||||
}
|
||||
@@ -1,2 +1,2 @@
|
||||
<html><head> <style type="text/css"> #error { background-color: #eeeeee; margin-bottom: 10px; } </style></head><body><small><b><a href="psi_element://Idea4780"><code>Idea4780</code></a></b></small><PRE>public <a href="psi_element://java.lang.Object"><code>Object</code></a> <b>read</b>()
|
||||
throws <a href="psi_element://java.io.IOException"><code>IOException</code></a></PRE><DD><DL><DT><b>Throws:</b><DD><a href="psi_element://java.io.EOFException"><code>EOFException</code></a> - if this source is already closed when the <code>read()</code> is called, or is closed during the <code>read()</code>. <DD><font color=red>InterruptedIOException</font> - if the reading thread is interrupted.<DD><a href="psi_element://java.io.IOException"><code>IOException</code></a> - if an I/O error occurs while reading. </DD></DL></DD></body></html>
|
||||
throws <a href="psi_element://java.io.IOException"><code>IOException</code></a></PRE><DD><DL><DT><b>Throws:</b><DD><a href="psi_element://java.io.IOException"><code>IOException</code></a> - if an I/O error occurs while reading. <DD><a href="psi_element://java.io.EOFException"><code>EOFException</code></a> - if this source is already closed when the <code>read()</code> is called, or is closed during the <code>read()</code>. <DD><font color=red>InterruptedIOException</font> - if the reading thread is interrupted.</DD></DL></DD></body></html>
|
||||
@@ -0,0 +1,9 @@
|
||||
public class Super {
|
||||
|
||||
}
|
||||
|
||||
class Child extends Super {
|
||||
}
|
||||
|
||||
class ChildChild extends Child {
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
public class Super {
|
||||
void f<caret>oo() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Child extends Super {
|
||||
void foo(){
|
||||
super.foo();
|
||||
System.out.println("do some staff");
|
||||
}
|
||||
}
|
||||
|
||||
class ChildChild extends Child {
|
||||
void foo(){
|
||||
super.foo();
|
||||
System.out.println("here do smth else");
|
||||
}
|
||||
}
|
||||
@@ -50,6 +50,7 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
public void testExplicitMethodParameters1() throws Exception { doTest(false); }
|
||||
public void testInferenceWithBounds() throws Exception {doTest(false);}
|
||||
public void testInferenceWithSuperBounds() throws Exception {doTest(false);}
|
||||
public void testInferenceWithUpperBoundPromotion() throws Exception {doTest(false);}
|
||||
public void testVariance() throws Exception {doTest(false);}
|
||||
public void testForeachTypes() throws Exception {doTest(false);}
|
||||
public void testRawOverridingMethods() throws Exception {doTest(false);}
|
||||
|
||||
@@ -78,7 +78,7 @@ public class IntroduceParameterTest extends LightCodeInsightTestCase {
|
||||
}
|
||||
|
||||
public void testThisSubstitutionInQualifier() throws Exception {
|
||||
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, false, false, "field <b><code>Test.i</code></b> is not accesible from method <b><code>XTest.n()</code></b>. Value for introduced parameter in that method call will be incorrect.");
|
||||
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, false, false, "field <b><code>Test.i</code></b> is not accessible from method <b><code>XTest.n()</code></b>. Value for introduced parameter in that method call will be incorrect.");
|
||||
}
|
||||
|
||||
public void testFieldAccess() throws Exception {
|
||||
|
||||
@@ -24,10 +24,7 @@ import com.intellij.JavaTestUtil;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.projectRoots.impl.JavaSdkImpl;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiField;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.refactoring.memberPullUp.PullUpConflictsUtil;
|
||||
import com.intellij.refactoring.memberPullUp.PullUpHelper;
|
||||
@@ -75,8 +72,10 @@ public class PullUpMultifileTest extends MultiFileTestCase {
|
||||
memberInfo.setChecked(true);
|
||||
membersToMove[0] = memberInfo;
|
||||
|
||||
final PsiDirectory targetDirectory = targetClass.getContainingFile().getContainingDirectory();
|
||||
final PsiPackage targetPackage = targetDirectory != null ? JavaDirectoryService.getInstance().getPackage(targetDirectory) : null;
|
||||
conflictsMap.putAllValues(
|
||||
PullUpConflictsUtil.checkConflicts(membersToMove, srcClass, targetClass, null, null, new InterfaceContainmentVerifier() {
|
||||
PullUpConflictsUtil.checkConflicts(membersToMove, srcClass, targetClass, targetPackage, targetDirectory, new InterfaceContainmentVerifier() {
|
||||
public boolean checkedInterfacesContain(PsiMethod psiMethod) {
|
||||
return PullUpHelper.checkedInterfacesContain(Arrays.asList(membersToMove), psiMethod);
|
||||
}
|
||||
|
||||
@@ -82,6 +82,11 @@ public class SafeDeleteTest extends MultiFileTestCase {
|
||||
doTest("Super");
|
||||
}
|
||||
|
||||
public void testMethodDeepHierarchy() throws Exception {
|
||||
myDoCompare = false;
|
||||
doTest("Super");
|
||||
}
|
||||
|
||||
public void testLocalVariableSideEffect() throws Exception {
|
||||
myDoCompare = false;
|
||||
try {
|
||||
|
||||
@@ -159,11 +159,15 @@ public class ModuleRootsExternalizationTest extends ModuleTestCase {
|
||||
"<orderEntry type=\"module-library\">" +
|
||||
"<library>" +
|
||||
"<CLASSES><root url=\"file://$MODULE_DIR$/unnamedLibClasses\" /></CLASSES>" +
|
||||
"<JAVADOC />" +
|
||||
"<SOURCES />" +
|
||||
"</library>" +
|
||||
"</orderEntry>" +
|
||||
"<orderEntry type=\"module-library\">" +
|
||||
"<library name=\"namedLibrary\">" +
|
||||
"<CLASSES><root url=\"file://$MODULE_DIR$/namedLibClasses\" /></CLASSES>" +
|
||||
"<JAVADOC />" +
|
||||
"<SOURCES />" +
|
||||
"</library>" +
|
||||
"</orderEntry>" +
|
||||
"</root>", module);
|
||||
|
||||
@@ -47,7 +47,7 @@ public class LibraryTest extends IdeaTestCase {
|
||||
|
||||
final Element element = new Element("root");
|
||||
library.writeExternal(element);
|
||||
assertEquals("<root><library name=\"library\"><CLASSES><root url=\"file://x.jar\" /></CLASSES><SOURCES><root url=\"file://x-src.jar\" /></SOURCES></library></root>",
|
||||
assertEquals("<root><library name=\"library\"><CLASSES><root url=\"file://x.jar\" /></CLASSES><JAVADOC /><SOURCES><root url=\"file://x-src.jar\" /></SOURCES></library></root>",
|
||||
new XMLOutputter().outputString(element));
|
||||
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
|
||||
@@ -16,17 +16,12 @@
|
||||
|
||||
package com.intellij.lang.jsp;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author ik
|
||||
*/
|
||||
public interface JspFileViewProvider extends JspxFileViewProvider {
|
||||
@NotNull
|
||||
Language getTemplateDataLanguage();
|
||||
|
||||
Set<String> getKnownTaglibPrefixes();
|
||||
}
|
||||
|
||||
@@ -32,8 +32,12 @@ public interface BaseJspFile extends XmlFile {
|
||||
boolean isTagPage();
|
||||
|
||||
XmlTag[] getDirectiveTags(JspDirectiveKind directiveKind, final boolean searchInIncludes);
|
||||
XmlTag createDirective(XmlTag context, JspDirectiveKind page);
|
||||
XmlTag createDirective(XmlTag context, JspDirectiveKind directiveKind);
|
||||
|
||||
/**
|
||||
* Method with a bad name. Returns file corresponding to getTemplateDataLanguage() method of ViewProvider
|
||||
* @see com.intellij.psi.templateLanguages.TemplateLanguageFileViewProvider#getTemplateDataLanguage()
|
||||
*/
|
||||
PsiFile getBaseLanguageRoot();
|
||||
/**
|
||||
* @return file which the errorPage directive references,
|
||||
@@ -43,4 +47,4 @@ public interface BaseJspFile extends XmlFile {
|
||||
|
||||
@NotNull
|
||||
JspxFileViewProvider getViewProvider();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
+4
@@ -59,6 +59,10 @@ public class DefaultRefactoringSupportProvider implements RefactoringSupportProv
|
||||
return null;
|
||||
}
|
||||
|
||||
public RefactoringActionHandler getExtractInterfaceHandler() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public RefactoringActionHandler getExtractModuleHandler() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
@@ -38,7 +39,7 @@ public abstract class InlineActionHandler {
|
||||
return canInlineElement(element);
|
||||
}
|
||||
|
||||
public boolean isEnabledOnElement(PsiElement element, Editor editor) {
|
||||
public boolean isEnabledOnElement(PsiElement element, @Nullable Editor editor) {
|
||||
return isEnabledOnElement(element);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
+2
@@ -25,12 +25,14 @@ import org.jetbrains.annotations.NotNull;
|
||||
public interface TemplateLanguageFileViewProvider extends FileViewProvider {
|
||||
|
||||
/**
|
||||
* e.g. JSP
|
||||
* @return instanceof {@link com.intellij.psi.templateLanguages.TemplateLanguage}
|
||||
*/
|
||||
@NotNull
|
||||
Language getBaseLanguage();
|
||||
|
||||
/**
|
||||
* e.g. HTML for JSP files
|
||||
* @return not instanceof {@link com.intellij.lang.DependentLanguage}
|
||||
*/
|
||||
@NotNull
|
||||
|
||||
@@ -42,8 +42,4 @@ public class IFileElementType extends ILazyParseableElementType {
|
||||
final PsiParser parser = LanguageParserDefinitions.INSTANCE.forLanguage(getLanguage()).createParser(project);
|
||||
return parser.parse(this, builder).getFirstChildNode();
|
||||
}
|
||||
|
||||
//public boolean isParsable(CharSequence buffer, final Project project) {
|
||||
// return true;
|
||||
//}
|
||||
}
|
||||
|
||||
@@ -175,6 +175,26 @@ public class PsiTreeUtil {
|
||||
return parents;
|
||||
}
|
||||
|
||||
@Nullable public static <T extends PsiElement> T findChildOfType(@NotNull final PsiElement element, @NotNull final Class<T> aClass) {
|
||||
return findChildOfType(element, aClass, true);
|
||||
}
|
||||
|
||||
@Nullable public static <T extends PsiElement> T findChildOfType(@NotNull final PsiElement element, @NotNull final Class<T> aClass, final boolean strict) {
|
||||
PsiElementProcessor.FindElement<PsiElement> processor = new PsiElementProcessor.FindElement<PsiElement>() {
|
||||
@Override
|
||||
public boolean execute(PsiElement each) {
|
||||
if (strict && each == element) return true;
|
||||
if (instanceOf(aClass, each)) {
|
||||
return setFound(each);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
PsiTreeUtil.processElements(element, processor);
|
||||
return (T)processor.getFoundElement();
|
||||
}
|
||||
|
||||
@Nullable public static <T extends PsiElement> T getChildOfType(@NotNull PsiElement element, @NotNull Class<T> aClass) {
|
||||
for(PsiElement child = element.getFirstChild(); child != null; child = child.getNextSibling()){
|
||||
if (instanceOf(aClass, child)) return (T)child;
|
||||
|
||||
@@ -432,7 +432,7 @@ public class PsiUtilBase {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiElement getElementAtCaret(Editor editor) {
|
||||
public static PsiElement getElementAtCaret(@NotNull Editor editor) {
|
||||
Project project = editor.getProject();
|
||||
if (project == null) return null;
|
||||
PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
|
||||
|
||||
@@ -32,8 +32,8 @@ public interface NameSuggestionProvider {
|
||||
ExtensionPointName<NameSuggestionProvider> EP_NAME = ExtensionPointName.create("com.intellij.nameSuggestionProvider");
|
||||
|
||||
@Nullable
|
||||
SuggestedNameInfo getSuggestedNames(PsiElement element, PsiElement nameSuggestionContext, Set<String> result);
|
||||
SuggestedNameInfo getSuggestedNames(PsiElement element, @Nullable PsiElement nameSuggestionContext, Set<String> result);
|
||||
|
||||
@Nullable
|
||||
Collection<LookupElement> completeName(PsiElement element, final PsiElement nameSuggestionContext, final String prefix);
|
||||
Collection<LookupElement> completeName(PsiElement element, @Nullable final PsiElement nameSuggestionContext, final String prefix);
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ public class CompletionData {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String findPrefixStatic(final PsiElement insertedElement, final int offsetInFile) {
|
||||
public static String findPrefixStatic(final PsiElement insertedElement, final int offsetInFile, ElementPattern<Character> prefixStartTrim) {
|
||||
if(insertedElement == null) return "";
|
||||
|
||||
final String prefix = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
|
||||
@@ -221,7 +221,11 @@ public class CompletionData {
|
||||
return CompletionUtil.findJavaIdentifierPrefix(insertedElement, offsetInFile);
|
||||
}
|
||||
|
||||
return findPrefixDefault(insertedElement, offsetInFile, not(character().javaIdentifierPart()));
|
||||
return findPrefixDefault(insertedElement, offsetInFile, prefixStartTrim);
|
||||
}
|
||||
|
||||
public static String findPrefixStatic(final PsiElement insertedElement, final int offsetInFile) {
|
||||
return findPrefixStatic(insertedElement, offsetInFile, not(character().javaIdentifierPart()));
|
||||
}
|
||||
|
||||
protected static String findPrefixDefault(final PsiElement insertedElement, final int offset, @NotNull final ElementPattern trimStart) {
|
||||
|
||||
@@ -149,13 +149,15 @@ public class EnterHandler extends BaseEnterHandler {
|
||||
|
||||
private static boolean isCommentComplete(PsiComment comment, CodeDocumentationAwareCommenter commenter) {
|
||||
String commentText = comment.getText();
|
||||
final String expectedCommentEnd = isDocComment(comment, commenter) ? commenter.getDocumentationCommentSuffix():commenter.getBlockCommentSuffix();
|
||||
final boolean docComment = isDocComment(comment, commenter);
|
||||
final String expectedCommentEnd = docComment ? commenter.getDocumentationCommentSuffix():commenter.getBlockCommentSuffix();
|
||||
if (!commentText.endsWith(expectedCommentEnd)) return false;
|
||||
|
||||
final PsiFile containingFile = comment.getContainingFile();
|
||||
final Language language = comment.getParent().getLanguage();
|
||||
Lexer lexer = LanguageParserDefinitions.INSTANCE.forLanguage(language).createLexer(containingFile.getProject());
|
||||
lexer.start(commentText, commenter.getDocumentationCommentPrefix().length(), commentText.length());
|
||||
final String commentPrefix = docComment? commenter.getDocumentationCommentPrefix() : commenter.getBlockCommentPrefix();
|
||||
lexer.start(commentText, commentPrefix == null? 0 : commentPrefix.length(), commentText.length());
|
||||
QuoteHandler fileTypeHandler = TypedHandler.getQuoteHandler(containingFile);
|
||||
JavaLikeQuoteHandler javaLikeQuoteHandler = fileTypeHandler instanceof JavaLikeQuoteHandler ?
|
||||
(JavaLikeQuoteHandler)fileTypeHandler:null;
|
||||
|
||||
@@ -282,13 +282,13 @@ public class TypedHandler implements TypedActionHandler {
|
||||
if (!iterator.atEnd()) {
|
||||
iterator.advance();
|
||||
|
||||
IElementType tokenType = iterator.atEnd() ? null : iterator.getTokenType();
|
||||
if (!BraceMatchingUtil.isPairedBracesAllowedBeforeTypeInFileType(braceTokenType, tokenType, fileType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!iterator.atEnd() && BraceMatchingUtil.isLBraceToken(iterator, fileText, fileType)) {
|
||||
return;
|
||||
if (!iterator.atEnd()) {
|
||||
if (!BraceMatchingUtil.isPairedBracesAllowedBeforeTypeInFileType(braceTokenType, iterator.getTokenType(), fileType)) {
|
||||
return;
|
||||
}
|
||||
if (BraceMatchingUtil.isLBraceToken(iterator, fileText, fileType)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
iterator.retreat();
|
||||
@@ -393,8 +393,9 @@ public class TypedHandler implements TypedActionHandler {
|
||||
|
||||
int offset = editor.getCaretModel().getOffset();
|
||||
|
||||
CharSequence chars = editor.getDocument().getCharsSequence();
|
||||
int length = editor.getDocument().getTextLength();
|
||||
final Document document = editor.getDocument();
|
||||
CharSequence chars = document.getCharsSequence();
|
||||
int length = document.getTextLength();
|
||||
if (isTypingEscapeQuote(editor, quoteHandler, offset)) return false;
|
||||
|
||||
if (offset < length && chars.charAt(offset) == quote){
|
||||
@@ -424,7 +425,10 @@ public class TypedHandler implements TypedActionHandler {
|
||||
|
||||
if (isOpeningQuote(editor, quoteHandler, offset - 1) &&
|
||||
hasNonClosedLiterals(editor, quoteHandler, offset - 1)) {
|
||||
editor.getDocument().insertString(offset, String.valueOf(quote));
|
||||
if (offset == document.getTextLength() ||
|
||||
!Character.isUnicodeIdentifierPart(document.getCharsSequence().charAt(offset))) { //any better heuristic or an API?
|
||||
document.insertString(offset, String.valueOf(quote));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -401,9 +401,10 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
|
||||
|
||||
@Nullable
|
||||
private static PsiElement resolve(final PsiReference ref) {
|
||||
PsiElement resolvedElement = null;
|
||||
// IDEA-56727 try resolve first as in GotoDeclarationAction
|
||||
PsiElement resolvedElement = ref.resolve();
|
||||
|
||||
if (ref instanceof PsiPolyVariantReference) {
|
||||
if (resolvedElement == null && ref instanceof PsiPolyVariantReference) {
|
||||
final ResolveResult[] psiElements = ((PsiPolyVariantReference)ref).multiResolve(false);
|
||||
if (psiElements.length > 0) {
|
||||
final ResolveResult resolveResult = psiElements[0];
|
||||
@@ -412,9 +413,6 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
resolvedElement = ref.resolve();
|
||||
}
|
||||
return resolvedElement;
|
||||
}
|
||||
|
||||
|
||||
@@ -123,6 +123,12 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
||||
myElements.add(key);
|
||||
}
|
||||
|
||||
public void replaceRange(TextRange rangeWithinElement, Expression expression) {
|
||||
final RangeMarker key = myDocument.createRangeMarker(rangeWithinElement);
|
||||
myExpressions.put(key, expression);
|
||||
myElements.add(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds end variable after the specified element
|
||||
*/
|
||||
|
||||
@@ -28,6 +28,7 @@ import com.intellij.openapi.editor.*;
|
||||
import com.intellij.openapi.editor.actions.EditorActionUtil;
|
||||
import com.intellij.openapi.editor.colors.EditorColors;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsManager;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
import com.intellij.openapi.editor.event.*;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.editor.ex.RangeHighlighterEx;
|
||||
@@ -109,8 +110,10 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
|
||||
myEditorDocument = editorFactory.createDocument("");
|
||||
setLanguage(language);
|
||||
myConsoleEditor = (EditorEx)editorFactory.createEditor(myEditorDocument, myProject);
|
||||
myConsoleEditor.setBackgroundColor(myConsoleEditor.getColorsScheme().getColor(ConsoleViewContentType.CONSOLE_BACKGROUND_KEY));
|
||||
myCurrentEditor = myConsoleEditor;
|
||||
myHistoryViewer = (EditorEx)editorFactory.createViewer(((EditorFactoryImpl)editorFactory).createDocument(true), myProject);
|
||||
myHistoryViewer.setBackgroundColor(myHistoryViewer.getColorsScheme().getColor(ConsoleViewContentType.CONSOLE_BACKGROUND_KEY));
|
||||
myPanel.add(myHistoryViewer.getComponent(), BorderLayout.NORTH);
|
||||
myPanel.add(myConsoleEditor.getComponent(), BorderLayout.CENTER);
|
||||
setupComponents();
|
||||
|
||||
@@ -66,27 +66,6 @@ public abstract class PsiFileBase extends PsiFileImpl {
|
||||
return myLanguage;
|
||||
}
|
||||
|
||||
protected final FileElement createFileElement(final CharSequence docText) {
|
||||
//final ParserDefinition parserDefinition = myLanguage.getParserDefinition();
|
||||
//if (parserDefinition != null && parserDefinition.createParser(getProject()) != PsiUtil.NULL_PARSER) {
|
||||
// return _createFileElement(docText, myLanguage, getProject(), parserDefinition);
|
||||
//}
|
||||
return super.createFileElement(docText);
|
||||
}
|
||||
|
||||
//private static FileElement _createFileElement(final CharSequence docText,
|
||||
// final Language language,
|
||||
// Project project,
|
||||
// final ParserDefinition parserDefinition) {
|
||||
// final PsiParser parser = parserDefinition.createParser(project);
|
||||
// final IElementType root = parserDefinition.getFileNodeType();
|
||||
// final PsiBuilderImpl builder = new PsiBuilderImpl(language, project, null, docText);
|
||||
// final FileElement fileRoot = (FileElement)parser.parse(root, builder);
|
||||
// LOG.assertTrue(fileRoot.getElementType() == root,
|
||||
// "Parsing file text returns rootElement with type different from declared in parser definition");
|
||||
// return fileRoot;
|
||||
//}
|
||||
|
||||
public void accept(@NotNull PsiElementVisitor visitor) {
|
||||
visitor.visitFile(this);
|
||||
}
|
||||
|
||||
+2
-1
@@ -230,7 +230,8 @@ public class PsiElement2UsageTargetAdapter implements PsiElementUsageTarget, Typ
|
||||
}
|
||||
|
||||
public Icon getIcon(boolean open) {
|
||||
return open ? myIconOpen.getIcon() : myIconClosed.getIcon();
|
||||
final ComputableIcon computableIcon = open ? myIconOpen : myIconClosed;
|
||||
return computableIcon == null? null : computableIcon.getIcon();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,6 +85,7 @@ import java.util.regex.Pattern;
|
||||
|
||||
public class FindInProjectUtil {
|
||||
private static final int USAGES_LIMIT = 1000;
|
||||
private static final int USAGES_PER_READ_ACTION = 100;
|
||||
private static final int FILES_SIZE_LIMIT = 70 * 1024 * 1024; // megabytes.
|
||||
private static final int SINGLE_FILE_SIZE_LIMIT = 5 * 1024 * 1024; // megabytes.
|
||||
|
||||
@@ -218,7 +219,7 @@ public class FindInProjectUtil {
|
||||
int i = 0;
|
||||
long totalFilesSize = 0;
|
||||
int count = 0;
|
||||
boolean warningShown = false;
|
||||
final boolean[] warningShown = new boolean[] {false};
|
||||
|
||||
final UsageViewManager usageViewManager = UsageViewManager.getInstance(project);
|
||||
for (final PsiFile psiFile : psiFiles) {
|
||||
@@ -252,22 +253,16 @@ public class FindInProjectUtil {
|
||||
progress.setText2(FindBundle.message("find.searching.for.string.in.file.occurrences.progress", count));
|
||||
}
|
||||
|
||||
int countInFile = processUsagesInFile(psiFile, findModel, consumer);
|
||||
int countInFile = processUsagesInFile(psiFile, findModel, consumer, count, warningShown);
|
||||
|
||||
if (countInFile > 0) {
|
||||
totalFilesSize += fileLength;
|
||||
if (totalFilesSize > FILES_SIZE_LIMIT && !warningShown) {
|
||||
if (totalFilesSize > FILES_SIZE_LIMIT && !warningShown[0]) {
|
||||
showTooManyUsagesWaring(project, FindBundle.message("find.excessive.total.size.prompt", presentableSize(totalFilesSize),
|
||||
ApplicationNamesInfo.getInstance().getProductName()));
|
||||
warningShown = true;
|
||||
warningShown[0] = true;
|
||||
}
|
||||
}
|
||||
|
||||
count += countInFile;
|
||||
if (count > USAGES_LIMIT && !warningShown) {
|
||||
showTooManyUsagesWaring(project, FindBundle.message("find.excessive.usage.count.prompt", count));
|
||||
warningShown = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!largeFiles.isEmpty()) {
|
||||
@@ -317,22 +312,37 @@ public class FindInProjectUtil {
|
||||
}
|
||||
}
|
||||
|
||||
private static int processUsagesInFile(final PsiFile psiFile, final FindModel findModel, final Processor<UsageInfo> consumer) {
|
||||
return ApplicationManager.getApplication().runReadAction(new Computable<Integer>() {
|
||||
public Integer compute() {
|
||||
if (psiFile.isValid()) {
|
||||
VirtualFile virtualFile = psiFile.getVirtualFile();
|
||||
// Check once more if valid and text since we're in new read action and things might have been changed.
|
||||
if (FileTypeManager.getInstance().getFileTypeByFile(virtualFile).isBinary()) return 0; // do not decompile .class files
|
||||
final Document document = FileDocumentManager.getInstance().getDocument(virtualFile);
|
||||
if (document != null) {
|
||||
return addToUsages(document, consumer, findModel, psiFile);
|
||||
}
|
||||
private static int processUsagesInFile(final PsiFile psiFile,
|
||||
final FindModel findModel,
|
||||
final Processor<UsageInfo> consumer,
|
||||
int alreadyCounted,
|
||||
boolean[] warningShown) {
|
||||
final VirtualFile virtualFile = psiFile.getVirtualFile();
|
||||
if (virtualFile == null) return 0;
|
||||
if (FileTypeManager.getInstance().getFileTypeByFile(virtualFile).isBinary()) return 0; // do not decompile .class files
|
||||
final Document document = FileDocumentManager.getInstance().getDocument(virtualFile);
|
||||
if (document == null) return 0;
|
||||
final int[] offset = new int[] {0};
|
||||
int count = 0;
|
||||
int found;
|
||||
do {
|
||||
found = ApplicationManager.getApplication().runReadAction(new Computable<Integer>() {
|
||||
@Override
|
||||
@NotNull
|
||||
public Integer compute() {
|
||||
if (!psiFile.isValid()) return 0;
|
||||
return addToUsages(document, consumer, findModel, psiFile, offset, USAGES_PER_READ_ACTION);
|
||||
}
|
||||
|
||||
return 0;
|
||||
});
|
||||
count += found;
|
||||
if (found > 0 && count + alreadyCounted > USAGES_LIMIT && !warningShown[0]) {
|
||||
showTooManyUsagesWaring(psiFile.getProject(), FindBundle.message("find.excessive.usage.count.prompt", count));
|
||||
warningShown[0] = true;
|
||||
}
|
||||
}).intValue();
|
||||
|
||||
}
|
||||
while (found != 0);
|
||||
return count;
|
||||
}
|
||||
|
||||
private static String getPresentablePath(final VirtualFile virtualFile) {
|
||||
@@ -605,12 +615,11 @@ public class FindInProjectUtil {
|
||||
}
|
||||
|
||||
private static int addToUsages(@NotNull Document document, @NotNull Processor<UsageInfo> consumer, @NotNull FindModel findModel,
|
||||
@NotNull final PsiFile psiFile) {
|
||||
|
||||
@NotNull final PsiFile psiFile, int[] offsetRef, int maxUsages) {
|
||||
int count = 0;
|
||||
CharSequence text = document.getCharsSequence();
|
||||
int textLength = document.getTextLength();
|
||||
int offset = 0;
|
||||
int offset = offsetRef[0];
|
||||
|
||||
Project project = psiFile.getProject();
|
||||
|
||||
@@ -632,7 +641,11 @@ public class FindInProjectUtil {
|
||||
// for regular expr the size of the match could be zero -> could be infinite loop in finding usages!
|
||||
++offset;
|
||||
}
|
||||
if (maxUsages > 0 && count >= maxUsages) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
offsetRef[0] = offset;
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -80,7 +80,7 @@ class CustomFileTypeBraceMatcher implements BraceMatcher {
|
||||
}
|
||||
|
||||
public boolean isPairedBracesAllowedBeforeType(@NotNull final IElementType lbraceType, @Nullable final IElementType contextType) {
|
||||
return true;
|
||||
return contextType == CustomHighlighterTokenType.WHITESPACE;
|
||||
}
|
||||
|
||||
public int getCodeConstructStart(final PsiFile file, final int openingBraceOffset) {
|
||||
|
||||
+1
-1
@@ -73,7 +73,7 @@ class CustomFileTypeQuoteHandler implements QuoteHandler {
|
||||
iterator.advance();
|
||||
}
|
||||
} finally {
|
||||
while(iterator.getStart() != offset) iterator.retreat();
|
||||
while (!iterator.atEnd() && iterator.getStart() != offset) iterator.retreat();
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -33,6 +33,7 @@ import com.intellij.ide.scopeView.nodes.BasePsiNode;
|
||||
import com.intellij.ide.util.DeleteHandler;
|
||||
import com.intellij.ide.util.DirectoryChooserUtil;
|
||||
import com.intellij.ide.util.EditorHelper;
|
||||
import com.intellij.lang.injection.InjectedLanguageManager;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.actionSystem.LangDataKeys;
|
||||
@@ -419,7 +420,7 @@ public class ScopeTreeViewPanel extends JPanel implements JDOMExternalizable, Di
|
||||
}
|
||||
|
||||
private void processNodeCreation(final PsiElement psiElement) {
|
||||
if (psiElement instanceof PsiFile) {
|
||||
if (psiElement instanceof PsiFile && !isInjected((PsiFile)psiElement)) {
|
||||
reload(myBuilder.addFileNode((PsiFile)psiElement));
|
||||
}
|
||||
else if (psiElement instanceof PsiDirectory) {
|
||||
@@ -433,7 +434,7 @@ public class ScopeTreeViewPanel extends JPanel implements JDOMExternalizable, Di
|
||||
public void beforeChildRemoval(final PsiTreeChangeEvent event) {
|
||||
final PsiElement child = event.getChild();
|
||||
final PsiElement parent = event.getParent();
|
||||
if (parent instanceof PsiDirectory && (child instanceof PsiFile || child instanceof PsiDirectory)) {
|
||||
if (parent instanceof PsiDirectory && (child instanceof PsiFile && !isInjected((PsiFile)child) || child instanceof PsiDirectory)) {
|
||||
queueUpdate(new Runnable() {
|
||||
public void run() {
|
||||
collapseExpand(myBuilder.removeNode(child, (PsiDirectory)parent));
|
||||
@@ -447,7 +448,7 @@ public class ScopeTreeViewPanel extends JPanel implements JDOMExternalizable, Di
|
||||
final PsiElement newParent = event.getNewParent();
|
||||
final PsiElement child = event.getChild();
|
||||
if (oldParent instanceof PsiDirectory && newParent instanceof PsiDirectory) {
|
||||
if (child instanceof PsiFile) {
|
||||
if (child instanceof PsiFile && !isInjected((PsiFile)child)) {
|
||||
final PsiFile file = (PsiFile)child;
|
||||
queueUpdate(new Runnable() {
|
||||
public void run() {
|
||||
@@ -470,7 +471,7 @@ public class ScopeTreeViewPanel extends JPanel implements JDOMExternalizable, Di
|
||||
final PsiElement parent = event.getParent();
|
||||
final PsiFile file = parent.getContainingFile();
|
||||
if (file != null && file.getFileType() == StdFileTypes.JAVA) {
|
||||
if (!file.getViewProvider().isPhysical()) return;
|
||||
if (!file.getViewProvider().isPhysical() && !isInjected(file)) return;
|
||||
queueUpdate(new Runnable() {
|
||||
public void run() {
|
||||
if (file.isValid()) {
|
||||
@@ -505,7 +506,7 @@ public class ScopeTreeViewPanel extends JPanel implements JDOMExternalizable, Di
|
||||
final NamedScope scope = getCurrentScope();
|
||||
final PsiElement element = event.getNewChild();
|
||||
final PsiFile psiFile = event.getFile();
|
||||
if (psiFile != null) {
|
||||
if (psiFile != null && !isInjected(psiFile)) {
|
||||
if (psiFile.getLanguage() == psiFile.getViewProvider().getBaseLanguage()) {
|
||||
queueUpdate(new Runnable() {
|
||||
public void run() {
|
||||
@@ -519,6 +520,10 @@ public class ScopeTreeViewPanel extends JPanel implements JDOMExternalizable, Di
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isInjected(PsiFile psiFile) {
|
||||
return InjectedLanguageManager.getInstance(myProject).isInjectedFragment(psiFile);
|
||||
}
|
||||
|
||||
private void queueRefreshScope(final NamedScope scope) {
|
||||
myUpdateQueue.cancelAllUpdates();
|
||||
queueUpdate(new Runnable() {
|
||||
|
||||
+9
-43
@@ -20,24 +20,18 @@ import com.intellij.application.options.PathMacrosImpl;
|
||||
import com.intellij.application.options.ReplacePathToMacroMap;
|
||||
import com.intellij.openapi.components.ExpandMacroToPathMap;
|
||||
import com.intellij.openapi.components.PathMacroMap;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class ModulePathMacroManager extends BasePathMacroManager /*ProjectPathMacroManager*/ {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.components.impl.ModulePathMacroManager");
|
||||
|
||||
public class ModulePathMacroManager extends BasePathMacroManager {
|
||||
private final Module myModule;
|
||||
|
||||
|
||||
public ModulePathMacroManager(final Module module) {
|
||||
//super((ProjectEx) module.getProject());
|
||||
myModule = module;
|
||||
}
|
||||
|
||||
@@ -49,9 +43,14 @@ public class ModulePathMacroManager extends BasePathMacroManager /*ProjectPathMa
|
||||
}
|
||||
|
||||
public ReplacePathToMacroMap getReplacePathMap() {
|
||||
ReplacePathToMacroMap result = new ReplacePathToMacroMap();
|
||||
result.putAll(super.getReplacePathMap());
|
||||
getModuleHomeReplacements(result, true);
|
||||
ReplacePathToMacroMap result = super.getReplacePathMap();
|
||||
if (!myModule.isDisposed()) {
|
||||
String projectDir = ProjectPathMacroManager.getProjectDir(myModule.getProject());
|
||||
if (projectDir != null) {
|
||||
projectDir = projectDir.replace('/', File.separatorChar);
|
||||
}
|
||||
addFileHierarchyReplacements(result, PathMacrosImpl.MODULE_DIR_MACRO_NAME, getModuleDir(myModule.getModuleFilePath()), projectDir);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -76,39 +75,6 @@ public class ModulePathMacroManager extends BasePathMacroManager /*ProjectPathMa
|
||||
result.put(s, path);
|
||||
}
|
||||
|
||||
private void getModuleHomeReplacements(@NonNls ReplacePathToMacroMap result, final boolean addRelativePathMacros) {
|
||||
String moduleDir = myModule.isDisposed() ? null : getModuleDir(myModule.getModuleFilePath());
|
||||
if (moduleDir == null) return;
|
||||
|
||||
File f = new File(moduleDir.replace('/', File.separatorChar));
|
||||
// [dsl]: Q?
|
||||
//if(!f.exists()) return;
|
||||
|
||||
String macro = "$" + PathMacrosImpl.MODULE_DIR_MACRO_NAME + "$";
|
||||
boolean check = false;
|
||||
while (f != null && f.getParentFile() != null) {
|
||||
@NonNls String path = PathMacroMap.quotePath(f.getAbsolutePath());
|
||||
String s = macro;
|
||||
|
||||
if (StringUtil.endsWithChar(path, '/')) s += "/";
|
||||
|
||||
putIfAbsent(result, "file://" + path, "file://" + s, check);
|
||||
putIfAbsent(result, "file:/" + path, "file:/" + s, check);
|
||||
putIfAbsent(result, "file:" + path, "file:" + s, check);
|
||||
putIfAbsent(result, "jar://" + path, "jar://" + s, check);
|
||||
putIfAbsent(result, "jar:/" + path, "jar:/" + s, check);
|
||||
putIfAbsent(result, "jar:" + path, "jar:" + s, check);
|
||||
if (!path.equalsIgnoreCase("e:/") && !path.equalsIgnoreCase("r:/") && !path.equalsIgnoreCase("p:/")) {
|
||||
putIfAbsent(result, path, s, check);
|
||||
}
|
||||
|
||||
if (!addRelativePathMacros) break;
|
||||
macro += "/..";
|
||||
check = true;
|
||||
f = f.getParentFile();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String getModuleDir(String moduleFilePath) {
|
||||
File moduleDirFile = new File(moduleFilePath).getParentFile();
|
||||
|
||||
+31
-7
@@ -20,6 +20,8 @@ import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.roots.*;
|
||||
import com.intellij.openapi.roots.libraries.Library;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
@@ -43,8 +45,21 @@ public class LibraryRuntimeClasspathScope extends GlobalSearchScope {
|
||||
super(project);
|
||||
myModules = modules;
|
||||
myIndex = ProjectRootManager.getInstance(project).getFileIndex();
|
||||
final Set<Sdk> processedSdk = new THashSet<Sdk>();
|
||||
final Set<Library> processedLibraries = new THashSet<Library>();
|
||||
final Set<Module> processedModules = new THashSet<Module>();
|
||||
final Condition<OrderEntry> condition = new Condition<OrderEntry>() {
|
||||
@Override
|
||||
public boolean value(OrderEntry orderEntry) {
|
||||
if (orderEntry instanceof ModuleOrderEntry) {
|
||||
final Module module = ((ModuleOrderEntry)orderEntry).getModule();
|
||||
return module != null && processedModules.add(module);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
for (Module module : modules) {
|
||||
buildEntries(module);
|
||||
buildEntries(module, processedModules, processedLibraries, processedSdk, condition);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,13 +75,20 @@ public class LibraryRuntimeClasspathScope extends GlobalSearchScope {
|
||||
return that.myModules.equals(myModules);
|
||||
}
|
||||
|
||||
private void buildEntries(@NotNull final Module module) {
|
||||
final Set<Sdk> myJDKProcessed = new THashSet<Sdk>();
|
||||
private void buildEntries(@NotNull final Module module,
|
||||
@NotNull final Set<Module> processedModules,
|
||||
@NotNull final Set<Library> processedLibraries,
|
||||
@NotNull final Set<Sdk> processedSdk,
|
||||
Condition<OrderEntry> condition) {
|
||||
if (!processedModules.add(module)) return;
|
||||
|
||||
ModuleRootManager.getInstance(module).orderEntries().recursively().process(new RootPolicy<LinkedHashSet<VirtualFile>>() {
|
||||
ModuleRootManager.getInstance(module).orderEntries().recursively().satisfying(condition).process(new RootPolicy<LinkedHashSet<VirtualFile>>() {
|
||||
public LinkedHashSet<VirtualFile> visitLibraryOrderEntry(final LibraryOrderEntry libraryOrderEntry,
|
||||
final LinkedHashSet<VirtualFile> value) {
|
||||
ContainerUtil.addAll(value, libraryOrderEntry.getRootFiles(OrderRootType.CLASSES));
|
||||
final Library library = libraryOrderEntry.getLibrary();
|
||||
if (library != null && processedLibraries.add(library)) {
|
||||
ContainerUtil.addAll(value, libraryOrderEntry.getRootFiles(OrderRootType.CLASSES));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -77,8 +99,10 @@ public class LibraryRuntimeClasspathScope extends GlobalSearchScope {
|
||||
}
|
||||
|
||||
public LinkedHashSet<VirtualFile> visitJdkOrderEntry(final JdkOrderEntry jdkOrderEntry, final LinkedHashSet<VirtualFile> value) {
|
||||
if (!myJDKProcessed.add(jdkOrderEntry.getJdk())) return value;
|
||||
ContainerUtil.addAll(value, jdkOrderEntry.getRootFiles(OrderRootType.CLASSES));
|
||||
final Sdk jdk = jdkOrderEntry.getJdk();
|
||||
if (jdk != null && processedSdk.add(jdk)) {
|
||||
ContainerUtil.addAll(value, jdkOrderEntry.getRootFiles(OrderRootType.CLASSES));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}, myEntries);
|
||||
|
||||
@@ -277,7 +277,7 @@ public class LibraryImpl implements LibraryEx.ModifiableModelEx, LibraryEx {
|
||||
if (roots.size() == 0 && rootType.skipWriteIfEmpty()) continue; //compatibility iml/ipr
|
||||
final Element rootTypeElement = new Element(rootType.name());
|
||||
roots.writeExternal(rootTypeElement, ROOT_PATH_ELEMENT);
|
||||
if (rootTypeElement.getAttributes().size() > 0 || rootTypeElement.getContent().size() > 0) element.addContent(rootTypeElement);
|
||||
element.addContent(rootTypeElement);
|
||||
}
|
||||
List<String> urls = new ArrayList<String>(myJarDirectories.keySet());
|
||||
Collections.sort(urls, new Comparator<String>() {
|
||||
|
||||
+18
-7
@@ -199,19 +199,23 @@ public class ClasspathStorage implements StateStorage {
|
||||
}
|
||||
|
||||
public Collection<IFile> getStorageFilesToSave() throws StateStorageException {
|
||||
return needsSave() ? getAllStorageFiles() : Collections.<IFile>emptyList();
|
||||
if (needsSave()) {
|
||||
final List<IFile> list = new ArrayList<IFile>();
|
||||
final ArrayList<VirtualFile> virtualFiles = new ArrayList<VirtualFile>();
|
||||
getFileSet().listModifiedFiles(virtualFiles);
|
||||
convert2Io(list, virtualFiles);
|
||||
return list;
|
||||
}
|
||||
else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
public List<IFile> getAllStorageFiles() {
|
||||
final List<IFile> list = new ArrayList<IFile>();
|
||||
final ArrayList<VirtualFile> virtualFiles = new ArrayList<VirtualFile>();
|
||||
getFileSet().listFiles(virtualFiles);
|
||||
|
||||
for (VirtualFile virtualFile : virtualFiles) {
|
||||
final File ioFile = VfsUtil.virtualToIoFile(virtualFile);
|
||||
list.add(FileSystem.FILE_SYSTEM.createFile(ioFile.getAbsolutePath()));
|
||||
}
|
||||
|
||||
convert2Io(list, virtualFiles);
|
||||
return list;
|
||||
}
|
||||
};
|
||||
@@ -220,6 +224,13 @@ public class ClasspathStorage implements StateStorage {
|
||||
return session;
|
||||
}
|
||||
|
||||
private static void convert2Io(List<IFile> list, ArrayList<VirtualFile> virtualFiles) {
|
||||
for (VirtualFile virtualFile : virtualFiles) {
|
||||
final File ioFile = VfsUtil.virtualToIoFile(virtualFile);
|
||||
list.add(FileSystem.FILE_SYSTEM.createFile(ioFile.getAbsolutePath()));
|
||||
}
|
||||
}
|
||||
|
||||
public void finishSave(final SaveSession saveSession) {
|
||||
try {
|
||||
LOG.assertTrue(mySession == saveSession);
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
package com.intellij.openapi.roots.impl.storage;
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.io.fs.IFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public interface FileSet {
|
||||
@@ -28,4 +30,5 @@ public interface FileSet {
|
||||
|
||||
void commit() throws IOException;
|
||||
|
||||
void listModifiedFiles(List<VirtualFile> list);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class PsiReferenceProviderBean extends AbstractExtensionPointBean {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.PsiReferenceProviderBean");
|
||||
@Tag("className")
|
||||
@Attribute("providerClass")
|
||||
public String className;
|
||||
@Tag("description")
|
||||
public String description;
|
||||
|
||||
@@ -19,8 +19,11 @@ package com.intellij.psi.impl;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.util.CachedValue;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import static com.intellij.util.ObjectUtils.*;
|
||||
|
||||
/**
|
||||
* @author Dmitry Avdeev
|
||||
*/
|
||||
|
||||
@@ -28,9 +28,12 @@ import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.util.ParameterizedCachedValueProvider;
|
||||
import com.intellij.psi.util.ParameterizedCachedValue;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import static com.intellij.util.ObjectUtils.*;
|
||||
|
||||
public abstract class PsiParameterizedCachedValue<T,P> extends PsiCachedValue<T> implements ParameterizedCachedValue<T,P> {
|
||||
|
||||
private final ParameterizedCachedValueProvider<T,P> myProvider;
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.FileTypeManager;
|
||||
import com.intellij.openapi.fileTypes.LanguageFileType;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.tree.IFileElementType;
|
||||
@@ -126,24 +127,37 @@ public class StubUpdatingIndex extends CustomImplementationFileBasedIndexExtensi
|
||||
};
|
||||
}
|
||||
|
||||
private static Key<StubElement> stubElementKey = Key.create("stub.tree.for.file.content");
|
||||
|
||||
@Nullable
|
||||
static StubElement buildStubTree(final FileContent inputData) {
|
||||
final FileType fileType = inputData.getFileType();
|
||||
public static StubElement buildStubTree(final FileContent inputData) {
|
||||
StubElement data = inputData.getUserData(stubElementKey);
|
||||
if (data != null) return data;
|
||||
|
||||
if (fileType.isBinary()) {
|
||||
final BinaryFileStubBuilder builder = BinaryFileStubBuilders.INSTANCE.forFileType(fileType);
|
||||
assert builder != null;
|
||||
synchronized (inputData) {
|
||||
data = inputData.getUserData(stubElementKey);
|
||||
if (data != null) return data;
|
||||
|
||||
return builder.buildStubTree(inputData.getFile(), inputData.getContent(), inputData.getProject());
|
||||
final FileType fileType = inputData.getFileType();
|
||||
|
||||
if (fileType.isBinary()) {
|
||||
final BinaryFileStubBuilder builder = BinaryFileStubBuilders.INSTANCE.forFileType(fileType);
|
||||
assert builder != null;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
final LanguageFileType filetype = (LanguageFileType)fileType;
|
||||
Language l = filetype.getLanguage();
|
||||
final IFileElementType type = LanguageParserDefinitions.INSTANCE.forLanguage(l).getFileNodeType();
|
||||
|
||||
PsiFile psi = inputData.getPsiFile();
|
||||
|
||||
return ((IStubFileElementType)type).getBuilder().buildStubTree(psi);
|
||||
}
|
||||
|
||||
public KeyDescriptor<Integer> getKeyDescriptor() {
|
||||
|
||||
+12
-31
@@ -14,41 +14,22 @@
|
||||
* 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;
|
||||
|
||||
package com.intellij.execution.testframework;
|
||||
|
||||
|
||||
|
||||
import com.intellij.execution.ui.ConsoleViewContentType;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public class ExternalOutput implements Printable {
|
||||
|
||||
private final ConsoleViewContentType myType;
|
||||
|
||||
private final String myContents;
|
||||
|
||||
|
||||
|
||||
public ExternalOutput(final String contents, final ConsoleViewContentType type) {
|
||||
|
||||
myType = type;
|
||||
|
||||
myContents = contents;
|
||||
public class ExtractInterfaceAction extends ExtractSuperActionBase {
|
||||
|
||||
public ExtractInterfaceAction() {
|
||||
setInjectedContext(true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void printOn(final Printer printer) {
|
||||
|
||||
printer.print(myContents, myType);
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected RefactoringActionHandler getRefactoringHandler(RefactoringSupportProvider supportProvider) {
|
||||
return supportProvider.getExtractInterfaceHandler();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+8
-8
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
-10
@@ -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,24 +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 = LanguageRefactoringSupport.INSTANCE.forLanguage(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;
|
||||
}
|
||||
|
||||
|
||||
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.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) &&
|
||||
LanguageRefactoringSupport.INSTANCE.forLanguage(language).getExtractModuleHandler() != null;
|
||||
return getRefactoringHandler(LanguageRefactoringSupport.INSTANCE.forLanguage(language)) != null;
|
||||
}
|
||||
|
||||
protected abstract boolean isEnabledOnLanguage(final Language language);
|
||||
}
|
||||
+4
-30
@@ -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();
|
||||
}
|
||||
}
|
||||
+4
@@ -128,6 +128,7 @@ public abstract class ExtractSuperBaseDialog<ClassType extends PsiElement, Membe
|
||||
final ButtonGroup buttonGroup = new ButtonGroup();
|
||||
buttonGroup.add(myRbExtractSuperclass);
|
||||
buttonGroup.add(myRbExtractSubclass);
|
||||
customizeRadiobuttons(box, buttonGroup);
|
||||
myRbExtractSuperclass.setSelected(true);
|
||||
|
||||
ItemListener listener = new ItemListener() {
|
||||
@@ -140,6 +141,9 @@ public abstract class ExtractSuperBaseDialog<ClassType extends PsiElement, Membe
|
||||
return box;
|
||||
}
|
||||
|
||||
protected void customizeRadiobuttons(Box box, ButtonGroup buttonGroup) {
|
||||
}
|
||||
|
||||
protected JComponent createNorthPanel() {
|
||||
Box box = Box.createVerticalBox();
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ public class ExtractIncludeDialog extends DialogWrapper {
|
||||
private JTextField myNameField;
|
||||
private final PsiDirectory myCurrentDirectory;
|
||||
private static final String REFACTORING_NAME = RefactoringBundle.message("extractIncludeFile.name");
|
||||
private final String myExtension;
|
||||
protected final String myExtension;
|
||||
protected JLabel myTargetDirLabel;
|
||||
|
||||
public PsiDirectory getTargetDirectory() {
|
||||
@@ -60,7 +60,8 @@ public class ExtractIncludeDialog extends DialogWrapper {
|
||||
private PsiDirectory myTargetDirectory;
|
||||
|
||||
public String getTargetFileName () {
|
||||
return myNameField.getText().trim() + "." + myExtension;
|
||||
String name = myNameField.getText().trim();
|
||||
return name.contains(".") ? name: name + "." + myExtension;
|
||||
}
|
||||
|
||||
public ExtractIncludeDialog(final PsiDirectory currentDirectory, final String extension) {
|
||||
@@ -116,7 +117,7 @@ public class ExtractIncludeDialog extends DialogWrapper {
|
||||
}
|
||||
|
||||
protected String getNameLabel() {
|
||||
return RefactoringBundle.message("name.for.extracted.include.file");
|
||||
return RefactoringBundle.message("name.for.extracted.include.file", myExtension);
|
||||
}
|
||||
|
||||
private void validateOKButton() {
|
||||
|
||||
@@ -78,12 +78,11 @@ public class FileReferenceContextUtil {
|
||||
if (!range.intersects(element.getTextRange())) return;
|
||||
String text = element.getText();
|
||||
PsiFileSystemItem item = map.get(text);
|
||||
element = bindElement(element, item);
|
||||
if (element != null) {
|
||||
element.acceptChildren(this);
|
||||
}
|
||||
element.putCopyableUserData(REF_FILE_SYSTEM_ITEM_KEY, item);
|
||||
element.acceptChildren(this);
|
||||
}
|
||||
});
|
||||
decodeFileReferences(element);
|
||||
}
|
||||
|
||||
private static PsiElement bindElement(PsiElement element, PsiFileSystemItem item) {
|
||||
|
||||
@@ -17,12 +17,18 @@
|
||||
package com.intellij.refactoring.rename;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.MessageType;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.wm.IdeFrame;
|
||||
import com.intellij.openapi.wm.WindowManager;
|
||||
import com.intellij.openapi.wm.ex.StatusBarEx;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiNamedElement;
|
||||
import com.intellij.psi.impl.light.LightElement;
|
||||
@@ -39,6 +45,7 @@ import com.intellij.refactoring.util.RelatedUsageInfo;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.usageView.UsageViewDescriptor;
|
||||
import com.intellij.usageView.UsageViewUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
@@ -46,6 +53,8 @@ import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.event.HyperlinkEvent;
|
||||
import javax.swing.event.HyperlinkListener;
|
||||
import java.util.*;
|
||||
|
||||
public class RenameProcessor extends BaseRefactoringProcessor {
|
||||
@@ -65,6 +74,7 @@ public class RenameProcessor extends BaseRefactoringProcessor {
|
||||
private NonCodeUsageInfo[] myNonCodeUsages = new NonCodeUsageInfo[0];
|
||||
private final List<AutomaticRenamerFactory> myRenamerFactories = new ArrayList<AutomaticRenamerFactory>();
|
||||
private final List<AutomaticRenamer> myRenamers = new ArrayList<AutomaticRenamer>();
|
||||
private final List<UnresolvableCollisionUsageInfo> mySkippedUsages = new ArrayList<UnresolvableCollisionUsageInfo>();
|
||||
|
||||
public RenameProcessor(Project project,
|
||||
PsiElement element,
|
||||
@@ -139,8 +149,6 @@ public class RenameProcessor extends BaseRefactoringProcessor {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Set<UsageInfo> usagesSet = new HashSet<UsageInfo>(Arrays.asList(usagesIn));
|
||||
RenameUtil.removeConflictUsages(usagesSet);
|
||||
|
||||
final List<UsageInfo> variableUsages = new ArrayList<UsageInfo>();
|
||||
if (!myRenamers.isEmpty()) {
|
||||
@@ -174,10 +182,13 @@ public class RenameProcessor extends BaseRefactoringProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
if (!variableUsages.isEmpty()) {
|
||||
usagesSet.addAll(variableUsages);
|
||||
refUsages.set(usagesSet.toArray(new UsageInfo[usagesSet.size()]));
|
||||
final Set<UsageInfo> usagesSet = new HashSet<UsageInfo>(Arrays.asList(usagesIn));
|
||||
usagesSet.addAll(variableUsages);
|
||||
final List<UnresolvableCollisionUsageInfo> conflictUsages = RenameUtil.removeConflictUsages(usagesSet);
|
||||
if (conflictUsages != null) {
|
||||
mySkippedUsages.addAll(conflictUsages);
|
||||
}
|
||||
refUsages.set(usagesSet.toArray(new UsageInfo[usagesSet.size()]));
|
||||
|
||||
prepareSuccessful();
|
||||
return true;
|
||||
@@ -192,7 +203,7 @@ public class RenameProcessor extends BaseRefactoringProcessor {
|
||||
final Runnable runnable = new Runnable() {
|
||||
public void run() {
|
||||
for (final AutomaticRenamer renamer : myRenamers) {
|
||||
renamer.findUsages(variableUsages, mySearchInComments, mySearchTextOccurrences);
|
||||
renamer.findUsages(variableUsages, mySearchInComments, mySearchTextOccurrences, mySkippedUsages);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -326,6 +337,32 @@ public class RenameProcessor extends BaseRefactoringProcessor {
|
||||
}
|
||||
}
|
||||
myNonCodeUsages = nonCodeUsages.toArray(new NonCodeUsageInfo[nonCodeUsages.size()]);
|
||||
if (!mySkippedUsages.isEmpty()) {
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode() && !ApplicationManager.getApplication().isHeadlessEnvironment()) {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
final IdeFrame ideFrame = WindowManager.getInstance().getIdeFrame(myProject);
|
||||
if (ideFrame != null) {
|
||||
|
||||
StatusBarEx statusBar = (StatusBarEx)ideFrame.getStatusBar();
|
||||
HyperlinkListener listener = new HyperlinkListener() {
|
||||
public void hyperlinkUpdate(HyperlinkEvent e) {
|
||||
if (e.getEventType() != HyperlinkEvent.EventType.ACTIVATED) return;
|
||||
Messages.showMessageDialog("<html>" +
|
||||
StringUtil.join(mySkippedUsages, new Function<UnresolvableCollisionUsageInfo, String>() {
|
||||
public String fun(UnresolvableCollisionUsageInfo unresolvableCollisionUsageInfo) {
|
||||
return unresolvableCollisionUsageInfo.getDescription();
|
||||
}
|
||||
}, "<br>") +
|
||||
"</html>", "Don't panic! They are safe to skip", null);
|
||||
}
|
||||
};
|
||||
statusBar.notifyProgressByBalloon(MessageType.WARNING, "<html><body>Unable to rename certain usages. <a href=\"\">Browse</a></body></html>", null, listener);
|
||||
}
|
||||
}
|
||||
}, ModalityState.NON_MODAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void performPsiSpoilingRefactoring() {
|
||||
|
||||
@@ -239,13 +239,17 @@ public class RenameUtil {
|
||||
ref.handleElementRename(newName);
|
||||
}
|
||||
|
||||
public static void removeConflictUsages(Set<UsageInfo> usages) {
|
||||
@Nullable
|
||||
public static List<UnresolvableCollisionUsageInfo> removeConflictUsages(Set<UsageInfo> usages) {
|
||||
final List<UnresolvableCollisionUsageInfo> result = new ArrayList<UnresolvableCollisionUsageInfo>();
|
||||
for (Iterator<UsageInfo> iterator = usages.iterator(); iterator.hasNext();) {
|
||||
UsageInfo usageInfo = iterator.next();
|
||||
if (usageInfo instanceof UnresolvableCollisionUsageInfo) {
|
||||
result.add((UnresolvableCollisionUsageInfo)usageInfo);
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
return result.isEmpty() ? null : result;
|
||||
}
|
||||
|
||||
public static void addConflictDescriptions(UsageInfo[] usages, MultiMap<PsiElement, String> conflicts) {
|
||||
|
||||
+15
-3
@@ -47,9 +47,16 @@ public abstract class AutomaticRenamer {
|
||||
}
|
||||
|
||||
public void findUsages(List<UsageInfo> result, final boolean searchInStringsAndComments, final boolean searchInNonJavaFiles) {
|
||||
findUsages(result, searchInStringsAndComments, searchInNonJavaFiles, null);
|
||||
}
|
||||
|
||||
public void findUsages(List<UsageInfo> result,
|
||||
final boolean searchInStringsAndComments,
|
||||
final boolean searchInNonJavaFiles,
|
||||
List<UnresolvableCollisionUsageInfo> unresolvedUsages) {
|
||||
for (Iterator<PsiNamedElement> iterator = myElements.iterator(); iterator.hasNext();) {
|
||||
final PsiNamedElement variable = iterator.next();
|
||||
final boolean success = findUsagesForElement(variable, result, searchInStringsAndComments, searchInNonJavaFiles);
|
||||
final boolean success = findUsagesForElement(variable, result, searchInStringsAndComments, searchInNonJavaFiles, unresolvedUsages);
|
||||
if (!success) {
|
||||
iterator.remove();
|
||||
}
|
||||
@@ -59,12 +66,17 @@ public abstract class AutomaticRenamer {
|
||||
private boolean findUsagesForElement(PsiNamedElement element,
|
||||
List<UsageInfo> result,
|
||||
final boolean searchInStringsAndComments,
|
||||
final boolean searchInNonJavaFiles) {
|
||||
final boolean searchInNonJavaFiles, List<UnresolvableCollisionUsageInfo> unresolvedUsages) {
|
||||
final String newName = getNewName(element);
|
||||
if (newName != null) {
|
||||
final UsageInfo[] usages = RenameUtil.findUsages(element, newName, searchInStringsAndComments, searchInNonJavaFiles, myRenames);
|
||||
for (final UsageInfo usage : usages) {
|
||||
if (usage instanceof UnresolvableCollisionUsageInfo) return false;
|
||||
if (usage instanceof UnresolvableCollisionUsageInfo) {
|
||||
if (unresolvedUsages != null) {
|
||||
unresolvedUsages.add((UnresolvableCollisionUsageInfo)usage);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ContainerUtil.addAll(result, usages);
|
||||
}
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ import com.intellij.psi.ElementDescriptionProvider;
|
||||
public class RefactoringDescriptionLocation extends ElementDescriptionLocation {
|
||||
private final boolean myWithParent;
|
||||
|
||||
private RefactoringDescriptionLocation(boolean withParent) {
|
||||
protected RefactoringDescriptionLocation(boolean withParent) {
|
||||
myWithParent = withParent;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,11 +46,13 @@ 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 void startNotify() {
|
||||
@@ -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,21 +176,6 @@ public abstract class ProcessHandler extends UserDataHolderBase {
|
||||
myEventMulticaster.processWillTerminate(new ProcessEvent(this), willBeDestroyed);
|
||||
}
|
||||
|
||||
private void afterStartNotified(final Runnable runnable) {
|
||||
if (isStartNotified()) {
|
||||
runnable.run();
|
||||
}
|
||||
else {
|
||||
addProcessListener(new ProcessAdapter() {
|
||||
public void startNotified(ProcessEvent event) {
|
||||
removeProcessListener(this);
|
||||
runnable.run();
|
||||
}
|
||||
});
|
||||
assert !isStartNotified();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isStartNotified() {
|
||||
return myState.get() > STATE_INITIAL;
|
||||
}
|
||||
@@ -208,4 +196,40 @@ public abstract class ProcessHandler extends UserDataHolderBase {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private final class TasksRunner extends ProcessAdapter {
|
||||
private final List<Runnable> myPendingTasks = new ArrayList<Runnable>();
|
||||
|
||||
public void startNotified(ProcessEvent event) {
|
||||
removeProcessListener(this);
|
||||
// at this point it is guaranteed that nothing will be added to myPendingTasks
|
||||
runPendingTasks();
|
||||
}
|
||||
|
||||
public void execute(Runnable task) {
|
||||
if (isStartNotified()) {
|
||||
task.run();
|
||||
}
|
||||
else {
|
||||
synchronized (myPendingTasks) {
|
||||
myPendingTasks.add(task);
|
||||
}
|
||||
if (isStartNotified()) {
|
||||
runPendingTasks();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void runPendingTasks() {
|
||||
final Runnable[] tasks;
|
||||
synchronized (myPendingTasks) {
|
||||
tasks = myPendingTasks.toArray(new Runnable[myPendingTasks.size()]);
|
||||
myPendingTasks.clear();
|
||||
}
|
||||
for (Runnable task : tasks) {
|
||||
task.run();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,13 @@ public abstract class PathMacros {
|
||||
|
||||
public abstract void setMacro(String name, String value);
|
||||
|
||||
/**
|
||||
* Obsolete macros that are to be removed gently from the project files. They can be read, but not written again. Not persisted.
|
||||
* @param name
|
||||
* @param value
|
||||
*/
|
||||
public abstract void addLegacyMacro(@NotNull String name, @NotNull String value);
|
||||
|
||||
public abstract void removeMacro(String name);
|
||||
|
||||
public abstract Set<String> getUserMacroNames();
|
||||
@@ -47,4 +54,6 @@ public abstract class PathMacros {
|
||||
public abstract boolean isIgnoredMacroName(@NotNull final String macro);
|
||||
|
||||
public abstract void removeAllMacros();
|
||||
|
||||
public abstract Collection<String> getLegacyMacroNames();
|
||||
}
|
||||
|
||||
@@ -658,8 +658,8 @@ public class VfsUtil {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static VirtualFile createDirectoryIfMissing(@NotNull String dir) throws IOException {
|
||||
return doCreateDirectoriesIfMissing(FileUtil.toSystemIndependentName(dir));
|
||||
public static VirtualFile createDirectoryIfMissing(@NotNull String directoryPath) throws IOException {
|
||||
return doCreateDirectoriesIfMissing(FileUtil.toSystemIndependentName(directoryPath));
|
||||
}
|
||||
|
||||
private static VirtualFile doCreateDirectoriesIfMissing(String dir) throws IOException {
|
||||
|
||||
@@ -35,6 +35,7 @@ import java.util.List;
|
||||
public class HyperlinkLabel extends HighlightableComponent {
|
||||
private HighlightedText myHighlightedText;
|
||||
private final List<HyperlinkListener> myListeners = new ArrayList<HyperlinkListener>();
|
||||
private boolean myUseIconAsLink;
|
||||
private final Color myTextForegroundColor;
|
||||
private final Color myTextBackgroundColor;
|
||||
private final Color myTextEffectColor;
|
||||
@@ -62,6 +63,7 @@ public class HyperlinkLabel extends HighlightableComponent {
|
||||
}
|
||||
|
||||
public void setHyperlinkText(String text) {
|
||||
myUseIconAsLink = true;
|
||||
setHyperlinkText("", text, "");
|
||||
}
|
||||
|
||||
@@ -71,6 +73,10 @@ public class HyperlinkLabel extends HighlightableComponent {
|
||||
adjustSize();
|
||||
}
|
||||
|
||||
public void setUseIconAsLink(boolean useIconAsLink) {
|
||||
myUseIconAsLink = useIconAsLink;
|
||||
}
|
||||
|
||||
private void adjustSize() {
|
||||
final Dimension preferredSize = this.getPreferredSize();
|
||||
this.setMinimumSize(preferredSize);
|
||||
@@ -96,6 +102,9 @@ public class HyperlinkLabel extends HighlightableComponent {
|
||||
}
|
||||
|
||||
private boolean isOnLink(int x) {
|
||||
if (myUseIconAsLink && myIcon != null && x < myIcon.getIconWidth()) {
|
||||
return true;
|
||||
}
|
||||
return findRegionByX(x) != null;
|
||||
}
|
||||
|
||||
|
||||
+2
-10
@@ -22,7 +22,6 @@ import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
@@ -37,10 +36,6 @@ public class PathMacrosCollector extends PathMacroMap {
|
||||
|
||||
private final Matcher myMatcher;
|
||||
|
||||
private static final Set<String> ourSystemMacroNames = new HashSet<String>(
|
||||
Arrays.asList(PathMacrosImpl.APPLICATION_HOME_MACRO_NAME, PathMacrosImpl.MODULE_DIR_MACRO_NAME, PathMacrosImpl.PROJECT_DIR_MACRO_NAME
|
||||
//, PathMacrosImpl.USER_HOME_MACRO_NAME
|
||||
));
|
||||
private static final String FILE_PROTOCOL = "file:";
|
||||
private static final String JAR_PROTOCOL = "jar:";
|
||||
|
||||
@@ -48,15 +43,12 @@ public class PathMacrosCollector extends PathMacroMap {
|
||||
myMatcher = MACRO_PATTERN.matcher("");
|
||||
}
|
||||
|
||||
public static Set<String> getMacroNames(Element root, @Nullable final NotNullFunction<Object, Boolean> filter) {
|
||||
return getMacroNames(root, filter, null);
|
||||
}
|
||||
|
||||
public static Set<String> getMacroNames(Element root, @Nullable final NotNullFunction<Object, Boolean> filter, @Nullable final NotNullFunction<Object, Boolean> recursiveFilter, @NotNull final PathMacros pathMacros) {
|
||||
final PathMacrosCollector collector = new PathMacrosCollector();
|
||||
collector.substitute(root, true, false, filter, recursiveFilter);
|
||||
final HashSet<String> result = new HashSet<String>(collector.myMacroMap.keySet());
|
||||
result.removeAll(ourSystemMacroNames);
|
||||
result.removeAll(pathMacros.getSystemMacroNames());
|
||||
result.removeAll(pathMacros.getLegacyMacroNames());
|
||||
result.removeAll(PathMacrosImpl.getToolMacroNames());
|
||||
result.removeAll(pathMacros.getIgnoredMacroNames());
|
||||
return result;
|
||||
|
||||
@@ -39,6 +39,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
||||
*/
|
||||
public class PathMacrosImpl extends PathMacros implements ApplicationComponent, NamedJDOMExternalizable, RoamingTypeDisabled {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.application.options.PathMacrosImpl");
|
||||
private final Map<String,String> myLegacyMacros = new HashMap<String,String>();
|
||||
private final Map<String,String> myMacros = new HashMap<String, String>();
|
||||
private final JBReentrantReadWriteLock myLock = LockFactory.createReadWriteLock();
|
||||
private final List<String> myIgnoredMacros = new CopyOnWriteArrayList<String>();
|
||||
@@ -70,7 +71,7 @@ public class PathMacrosImpl extends PathMacros implements ApplicationComponent,
|
||||
ourSystemMacroNames.add(APPLICATION_HOME_MACRO_NAME);
|
||||
ourSystemMacroNames.add(PROJECT_DIR_MACRO_NAME);
|
||||
ourSystemMacroNames.add(MODULE_DIR_MACRO_NAME);
|
||||
//ourSystemMacroNames.add(USER_HOME_MACRO_NAME);
|
||||
ourSystemMacroNames.add(USER_HOME_MACRO_NAME);
|
||||
}
|
||||
|
||||
private static final Set<String> ourToolsMacros = new HashSet<String>();
|
||||
@@ -213,6 +214,17 @@ public class PathMacrosImpl extends PathMacros implements ApplicationComponent,
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getLegacyMacroNames() {
|
||||
try {
|
||||
myLock.readLock().lock();
|
||||
return myLegacyMacros.keySet();
|
||||
}
|
||||
finally {
|
||||
myLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void setMacro(@NotNull String name, @NotNull String value) {
|
||||
if (value.trim().length() == 0) return;
|
||||
try {
|
||||
@@ -224,6 +236,18 @@ public class PathMacrosImpl extends PathMacros implements ApplicationComponent,
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLegacyMacro(@NotNull String name, @NotNull String value) {
|
||||
try {
|
||||
myLock.writeLock().lock();
|
||||
myLegacyMacros.put(name, value);
|
||||
myMacros.remove(name);
|
||||
}
|
||||
finally {
|
||||
myLock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void removeMacro(String name) {
|
||||
try {
|
||||
myLock.writeLock().lock();
|
||||
@@ -278,8 +302,7 @@ public class PathMacrosImpl extends PathMacros implements ApplicationComponent,
|
||||
}
|
||||
|
||||
public void addMacroReplacements(ReplacePathToMacroMap result) {
|
||||
final Set<String> macroNames = getUserMacroNames();
|
||||
for (final String name : macroNames) {
|
||||
for (final String name : getUserMacroNames()) {
|
||||
final String value = getValue(name);
|
||||
if (value != null && value.trim().length() > 0) result.addMacroReplacement(value, name);
|
||||
}
|
||||
@@ -287,11 +310,20 @@ public class PathMacrosImpl extends PathMacros implements ApplicationComponent,
|
||||
|
||||
|
||||
public void addMacroExpands(ExpandMacroToPathMap result) {
|
||||
final Set<String> macroNames = getUserMacroNames();
|
||||
for (final String name : macroNames) {
|
||||
for (final String name : getUserMacroNames()) {
|
||||
final String value = getValue(name);
|
||||
if (value != null && value.trim().length() > 0) result.addMacroExpand(name, value);
|
||||
}
|
||||
|
||||
myLock.readLock().lock();
|
||||
try {
|
||||
for (Map.Entry<String, String> entry : myLegacyMacros.entrySet()) {
|
||||
result.addMacroExpand(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
finally {
|
||||
myLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+16
-4
@@ -37,16 +37,28 @@ public class ReplacePathToMacroMap extends PathMacroMap {
|
||||
|
||||
if (idx1 != idx2) return idx1 - idx2;
|
||||
|
||||
return o2.getKey().length() - o1.getKey().length();
|
||||
return stripPrefix(o2.getKey()).length() - stripPrefix(o1.getKey()).length();
|
||||
}
|
||||
|
||||
private int getIndex(final Map.Entry<String, String> s) {
|
||||
if (s.getValue().indexOf("..") >= 0) return 3;
|
||||
final String replacement = s.getValue();
|
||||
if (replacement.indexOf("..") >= 0) return 3;
|
||||
if (replacement.indexOf("$" + PathMacrosImpl.USER_HOME_MACRO_NAME + "$") >= 0) return 3;
|
||||
|
||||
if (s.getValue().indexOf("$MODULE_DIR$") >= 0) return 1;
|
||||
if (s.getValue().indexOf("$PROJECT_DIR$") >= 0) return 1;
|
||||
if (replacement.indexOf("$" + PathMacrosImpl.MODULE_DIR_MACRO_NAME + "$") >= 0) return 1;
|
||||
if (replacement.indexOf("$" + PathMacrosImpl.PROJECT_DIR_MACRO_NAME + "$") >= 0) return 1;
|
||||
return 2;
|
||||
}
|
||||
|
||||
private String stripPrefix(String key) {
|
||||
key = StringUtil.trimStart(key, "jar:");
|
||||
key = StringUtil.trimStart(key, "file:");
|
||||
while (key.startsWith("/")) {
|
||||
key = key.substring(1);
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@NonNls private static final String[] PROTOCOLS = new String[]{"file", "jar"};
|
||||
|
||||
-3
@@ -19,7 +19,4 @@ package com.intellij.openapi.components.impl;
|
||||
* @author mike
|
||||
*/
|
||||
public class ApplicationPathMacroManager extends BasePathMacroManager {
|
||||
public ApplicationPathMacroManager() {
|
||||
super(true);
|
||||
}
|
||||
}
|
||||
|
||||
+41
-13
@@ -20,33 +20,63 @@ import com.intellij.application.options.ReplacePathToMacroMap;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.components.ExpandMacroToPathMap;
|
||||
import com.intellij.openapi.components.PathMacroManager;
|
||||
import com.intellij.openapi.components.PathMacroMap;
|
||||
import com.intellij.openapi.components.TrackingPathMacroSubstitutor;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.SystemProperties;
|
||||
import com.intellij.util.containers.FactoryMap;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
public class BasePathMacroManager extends PathMacroManager {
|
||||
private PathMacrosImpl myPathMacros;
|
||||
private boolean myUseUserMacroses;
|
||||
|
||||
protected static void addFileHierarchyReplacements(ReplacePathToMacroMap result,
|
||||
String variableName,
|
||||
@Nullable String _path, @Nullable String stopAt) {
|
||||
if (_path == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
public BasePathMacroManager(boolean useUserMacroses) {
|
||||
myUseUserMacroses = useUserMacroses;
|
||||
}
|
||||
String macro = "$" + variableName + "$";
|
||||
File dir = new File(_path.replace('/', File.separatorChar));
|
||||
boolean check = false;
|
||||
while (dir != null && dir.getParentFile() != null) {
|
||||
@NonNls String path = PathMacroMap.quotePath(dir.getAbsolutePath());
|
||||
String s = macro;
|
||||
|
||||
public BasePathMacroManager() {
|
||||
this(true);
|
||||
if (StringUtil.endsWithChar(path, '/')) s += "/";
|
||||
|
||||
putIfAbsent(result, "file:" + path, "file:" + s, check);
|
||||
putIfAbsent(result, "file:/" + path, "file:/" + s, check);
|
||||
putIfAbsent(result, "file://" + path, "file://" + s, check);
|
||||
putIfAbsent(result, "jar:" + path, "jar:" + s, check);
|
||||
putIfAbsent(result, "jar:/" + path, "jar:/" + s, check);
|
||||
putIfAbsent(result, "jar://" + path, "jar://" + s, check);
|
||||
if (!path.equalsIgnoreCase("e:/") && !path.equalsIgnoreCase("r:/") && !path.equalsIgnoreCase("p:/")) {
|
||||
putIfAbsent(result, path, s, check);
|
||||
}
|
||||
|
||||
if (dir.getPath().equals(stopAt)) {
|
||||
break;
|
||||
}
|
||||
|
||||
macro += "/..";
|
||||
check = true;
|
||||
dir = dir.getParentFile();
|
||||
}
|
||||
}
|
||||
|
||||
public ExpandMacroToPathMap getExpandMacroMap() {
|
||||
ExpandMacroToPathMap result = new ExpandMacroToPathMap();
|
||||
result.addMacroExpand(PathMacrosImpl.APPLICATION_HOME_MACRO_NAME, PathManager.getHomePath());
|
||||
if (myUseUserMacroses) {
|
||||
getPathMacros().addMacroExpands(result);
|
||||
}
|
||||
result.addMacroExpand(PathMacrosImpl.USER_HOME_MACRO_NAME, SystemProperties.getUserHome());
|
||||
getPathMacros().addMacroExpands(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -55,10 +85,8 @@ public class BasePathMacroManager extends PathMacroManager {
|
||||
ReplacePathToMacroMap result = new ReplacePathToMacroMap();
|
||||
|
||||
result.addMacroReplacement(PathManager.getHomePath(), PathMacrosImpl.APPLICATION_HOME_MACRO_NAME);
|
||||
if (myUseUserMacroses) {
|
||||
getPathMacros().addMacroReplacements(result);
|
||||
}
|
||||
|
||||
result.addMacroReplacement(SystemProperties.getUserHome(), PathMacrosImpl.USER_HOME_MACRO_NAME);
|
||||
getPathMacros().addMacroReplacements(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
+5
-40
@@ -19,10 +19,10 @@ import com.intellij.application.options.PathMacrosImpl;
|
||||
import com.intellij.application.options.ReplacePathToMacroMap;
|
||||
import com.intellij.openapi.components.ExpandMacroToPathMap;
|
||||
import com.intellij.openapi.components.PathMacroMap;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ex.ProjectEx;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
@@ -30,7 +30,6 @@ import java.io.File;
|
||||
public class ProjectPathMacroManager extends BasePathMacroManager {
|
||||
private final ProjectEx myProject;
|
||||
|
||||
|
||||
public ProjectPathMacroManager(final ProjectEx project) {
|
||||
myProject = project;
|
||||
}
|
||||
@@ -42,47 +41,13 @@ public class ProjectPathMacroManager extends BasePathMacroManager {
|
||||
}
|
||||
|
||||
public ReplacePathToMacroMap getReplacePathMap() {
|
||||
ReplacePathToMacroMap result = new ReplacePathToMacroMap();
|
||||
result.putAll(super.getReplacePathMap());
|
||||
getProjectHomeReplacements(result, true);
|
||||
ReplacePathToMacroMap result = super.getReplacePathMap();
|
||||
addFileHierarchyReplacements(result, PathMacrosImpl.PROJECT_DIR_MACRO_NAME, getProjectDir(myProject), null);
|
||||
return result;
|
||||
}
|
||||
|
||||
private void getProjectHomeReplacements(@NonNls ReplacePathToMacroMap result, final boolean savePathsRelative) {
|
||||
String projectDir = getProjectDir();
|
||||
if (projectDir == null) return;
|
||||
|
||||
File f = new File(projectDir.replace('/', File.separatorChar));
|
||||
//LOG.assertTrue(f.exists());
|
||||
|
||||
String macro = "$" + PathMacrosImpl.PROJECT_DIR_MACRO_NAME + "$";
|
||||
boolean check = false;
|
||||
while (f != null && f.getParentFile() != null) {
|
||||
String path = PathMacroMap.quotePath(f.getAbsolutePath());
|
||||
String s = macro;
|
||||
|
||||
if (StringUtil.endsWithChar(path, '/')) s += "/";
|
||||
|
||||
putIfAbsent(result, "file://" + path, "file://" + s, check);
|
||||
putIfAbsent(result, "file:/" + path, "file:/" + s, check);
|
||||
putIfAbsent(result, "file:" + path, "file:" + s, check);
|
||||
putIfAbsent(result, "jar://" + path, "jar://" + s, check);
|
||||
putIfAbsent(result, "jar:/" + path, "jar:/" + s, check);
|
||||
putIfAbsent(result, "jar:" + path, "jar:" + s, check);
|
||||
//noinspection HardCodedStringLiteral
|
||||
if (!path.equalsIgnoreCase("e:/") && !path.equalsIgnoreCase("r:/") && !path.equalsIgnoreCase("p:/")) {
|
||||
putIfAbsent(result, path, s, check);
|
||||
}
|
||||
|
||||
if (!savePathsRelative) break;
|
||||
check = true;
|
||||
macro += "/..";
|
||||
f = f.getParentFile();
|
||||
}
|
||||
}
|
||||
|
||||
private void getExpandProjectHomeReplacements(ExpandMacroToPathMap result) {
|
||||
String projectDir = getProjectDir();
|
||||
String projectDir = getProjectDir(myProject);
|
||||
if (projectDir == null) return;
|
||||
|
||||
File f = new File(projectDir.replace('/', File.separatorChar));
|
||||
@@ -103,7 +68,7 @@ public class ProjectPathMacroManager extends BasePathMacroManager {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String getProjectDir() {
|
||||
public static String getProjectDir(Project myProject) {
|
||||
final VirtualFile baseDir = myProject.getBaseDir();
|
||||
return baseDir != null ? baseDir.getPath() : null;
|
||||
}
|
||||
|
||||
+34
-23
@@ -268,16 +268,19 @@ public class EditorActionUtil {
|
||||
private static void moveCaretToStartOfSoftWrappedLine(Editor editor, VisualPosition currentVisual) {
|
||||
CaretModel caretModel = editor.getCaretModel();
|
||||
int line = currentVisual.line;
|
||||
int column = 0;
|
||||
|
||||
if (currentVisual.column == 0) {
|
||||
// We use default column value as '1' below in assumption that we work with soft-wrapped line and don't want to put cursor
|
||||
// before 'after soft wrap' drawing.
|
||||
int column = 1;
|
||||
|
||||
if (currentVisual.column <= 1) {
|
||||
line--;
|
||||
int nonSpaceColumn = findFirstNonSpaceColumnOnTheLine(editor, line);
|
||||
column = nonSpaceColumn >= 0 ? nonSpaceColumn : 0;
|
||||
column = nonSpaceColumn >= 1 ? nonSpaceColumn : 1;
|
||||
}
|
||||
else {
|
||||
int nonSpaceColumn = findFirstNonSpaceColumnOnTheLine(editor, currentVisual.line);
|
||||
if (nonSpaceColumn > 0 /* current visual line is not empty */ && nonSpaceColumn < currentVisual.column) {
|
||||
if (nonSpaceColumn > 1 /* current visual line is not empty */ && nonSpaceColumn < currentVisual.column) {
|
||||
column = nonSpaceColumn;
|
||||
}
|
||||
}
|
||||
@@ -364,18 +367,13 @@ public class EditorActionUtil {
|
||||
// There are soft wrap-introduced visual lines after the target one
|
||||
return -1;
|
||||
}
|
||||
|
||||
end = findFirstNonSpaceOffsetInRange(document.getCharsSequence(), softWrap.getStart(), logLineEndOffset);
|
||||
if (end >= 0) {
|
||||
// Width of soft wrap virtual text that is located at the target visual line.
|
||||
int result = EditorUtil.calcColumnNumber(editor, softWrapText, j, softWrapTextLength);
|
||||
result++; // For column reserved for 'after soft wrap' sign.
|
||||
result += EditorUtil.calcColumnNumber(editor, document.getCharsSequence(), softWrap.getStart(), end);
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
int end = findFirstNonSpaceOffsetInRange(document.getCharsSequence(), softWrap.getStart(), logLineEndOffset);
|
||||
if (end >= 0) {
|
||||
return EditorUtil.calcColumnNumber(editor, document.getCharsSequence(), softWrap.getStart(), end);
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
@@ -415,6 +413,7 @@ public class EditorActionUtil {
|
||||
LogicalPosition blockSelectionStart = selectionModel.hasBlockSelection()
|
||||
? selectionModel.getBlockStart()
|
||||
: caretModel.getLogicalPosition();
|
||||
SoftWrapModel softWrapModel = editor.getSoftWrapModel();
|
||||
|
||||
int lineNumber = editor.getCaretModel().getLogicalPosition().line;
|
||||
if (lineNumber >= document.getLineCount()) {
|
||||
@@ -434,7 +433,7 @@ public class EditorActionUtil {
|
||||
LogicalPosition logical = editor.visualToLogicalPosition(visualEndOfLineWithCaret);
|
||||
int offset = editor.logicalPositionToOffset(logical);
|
||||
if (offset < editor.getDocument().getTextLength()) {
|
||||
SoftWrapModel softWrapModel = editor.getSoftWrapModel();
|
||||
|
||||
TextChange softWrap = softWrapModel.getSoftWrap(offset);
|
||||
if (softWrap == null) {
|
||||
// Same offset may correspond to positions on different visual lines in case of soft wraps presence
|
||||
@@ -442,21 +441,33 @@ public class EditorActionUtil {
|
||||
// Hence, we check for soft wraps presence at two offsets.
|
||||
softWrap = softWrapModel.getSoftWrap(offset + 1);
|
||||
}
|
||||
int line = currentVisualCaret.line;
|
||||
int column = currentVisualCaret.column;
|
||||
if (softWrap != null) {
|
||||
int line = currentVisualCaret.line + 1;
|
||||
int column = EditorUtil.getLastVisualLineColumnNumber(editor, line);
|
||||
visualEndOfLineWithCaret = new VisualPosition(line, column);
|
||||
line++;
|
||||
column = EditorUtil.getLastVisualLineColumnNumber(editor, line);
|
||||
}
|
||||
// There is a possible case that the last visual line of particular logical line contains only white spaces. We want to move
|
||||
// caret just after 'after soft wrap' drawing then.
|
||||
else if (line == editor.offsetToVisualPosition(document.getLineEndOffset(lineNumber)).line) {
|
||||
column = 1;
|
||||
}
|
||||
visualEndOfLineWithCaret = new VisualPosition(line, column);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int offset;
|
||||
int newOffset;
|
||||
LogicalPosition logLineEnd = editor.visualToLogicalPosition(visualEndOfLineWithCaret);
|
||||
int offset = editor.logicalPositionToOffset(logLineEnd);
|
||||
offset = editor.logicalPositionToOffset(logLineEnd);
|
||||
lineNumber = logLineEnd.line;
|
||||
int newOffset = offset;
|
||||
newOffset = offset;
|
||||
|
||||
CharSequence text = document.getCharsSequence();
|
||||
for (int i = newOffset - 1; i >= document.getLineStartOffset(lineNumber); i--) {
|
||||
if (softWrapModel.getSoftWrap(i) != null) {
|
||||
break;
|
||||
}
|
||||
if (text.charAt(i) != ' ' && text.charAt(i) != '\t') {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.editor.impl.ComplementaryFontsRegistry;
|
||||
import com.intellij.openapi.editor.impl.FontInfo;
|
||||
import com.intellij.openapi.editor.impl.IterationState;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -158,17 +157,42 @@ public class EditorUtil {
|
||||
}
|
||||
|
||||
public static int calcOffset(Editor editor, CharSequence text, int start, int end, int columnNumber, int tabSize) {
|
||||
// If all tabs here goes before any other chars in the line we may use an optimization here.
|
||||
boolean useOptimization = true;
|
||||
final int maxScanIndex = Math.min(start + columnNumber + 1, end);
|
||||
if (editor == null) {
|
||||
return calcSoftWrapUnawareOffset(text, start, maxScanIndex, columnNumber, tabSize);
|
||||
}
|
||||
|
||||
int column = 0;
|
||||
int tabAnchor = 0;
|
||||
SoftWrapModel softWrapModel = editor.getSoftWrapModel();
|
||||
for (int i = start; i < maxScanIndex; i++) {
|
||||
TextChange softWrap = softWrapModel.getSoftWrap(i);
|
||||
if (softWrap != null) {
|
||||
tabAnchor = softWrapModel.getSoftWrapIndentWidthInColumns(softWrap);
|
||||
}
|
||||
if (column >= columnNumber) {
|
||||
return i;
|
||||
}
|
||||
int diff = textWidthInColumns(editor, text, i, i + 1, tabAnchor);
|
||||
if (column + diff > columnNumber) {
|
||||
// We want to return offset that points to the tabulation symbol if it's represented in multiple columns and target visual
|
||||
// column points inside it.
|
||||
return i;
|
||||
}
|
||||
column += diff;
|
||||
tabAnchor += diff;
|
||||
}
|
||||
return end;
|
||||
}
|
||||
|
||||
private static int calcSoftWrapUnawareOffset(CharSequence text, int start, int end, int columnNumber, int tabSize) {
|
||||
boolean hasNonTabs = false;
|
||||
boolean hasTabs = false;
|
||||
final int maxScanIndex = Math.min(start + columnNumber + 1, end);
|
||||
|
||||
for (int i = start; i < maxScanIndex; i++) {
|
||||
for (int i = start; i < end; i++) {
|
||||
if (text.charAt(i) == '\t') {
|
||||
hasTabs = true;
|
||||
if (hasNonTabs) {
|
||||
useOptimization = false;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@@ -176,52 +200,18 @@ public class EditorUtil {
|
||||
}
|
||||
}
|
||||
|
||||
if (editor == null || useOptimization) {
|
||||
if (!hasTabs) return Math.min(start + columnNumber, end);
|
||||
if (!hasTabs) return Math.min(start + columnNumber, end);
|
||||
|
||||
int shift = 0;
|
||||
int offset = start;
|
||||
for (; offset < end && offset + shift < start + columnNumber; offset++) {
|
||||
if (text.charAt(offset) == '\t') {
|
||||
shift += getTabLength(offset + shift - start, tabSize) - 1;
|
||||
}
|
||||
}
|
||||
if (offset + shift > start + columnNumber) {
|
||||
offset--;
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
EditorEx editorImpl = (EditorEx)editor;
|
||||
int shift = 0;
|
||||
int offset = start;
|
||||
IterationState state = new IterationState(editorImpl, offset, false);
|
||||
int fontType = state.getMergedAttributes().getFontType();
|
||||
int column = 0;
|
||||
int x = 0;
|
||||
int spaceSize = getSpaceWidth(fontType, editorImpl);
|
||||
while (column < columnNumber) {
|
||||
if (offset >= state.getEndOffset()) {
|
||||
state.advance();
|
||||
|
||||
fontType = state.getMergedAttributes().getFontType();
|
||||
}
|
||||
|
||||
char c = offset < end ? text.charAt(offset++) : ' ';
|
||||
if (c == '\t') {
|
||||
int prevX = x;
|
||||
x = nextTabStop(x, editorImpl);
|
||||
column += (x - prevX) / spaceSize;
|
||||
}
|
||||
else {
|
||||
x += charWidth(c, fontType, editorImpl);
|
||||
column++;
|
||||
for (; offset < end && offset + shift < start + columnNumber; offset++) {
|
||||
if (text.charAt(offset) == '\t') {
|
||||
shift += getTabLength(offset + shift - start, tabSize) - 1;
|
||||
}
|
||||
}
|
||||
if (column == columnNumber && offset < end && text.charAt(offset) == '\t' && (nextTabStop(x, editorImpl) - x) / spaceSize == 0) {
|
||||
offset++;
|
||||
if (offset + shift > start + columnNumber) {
|
||||
offset--;
|
||||
}
|
||||
if (column > columnNumber) offset--;
|
||||
|
||||
return offset;
|
||||
}
|
||||
@@ -239,15 +229,21 @@ public class EditorUtil {
|
||||
|
||||
public static int calcColumnNumber(Editor editor, CharSequence text, int start, int offset, int tabSize) {
|
||||
boolean useOptimization = true;
|
||||
if (editor != null) {
|
||||
TextChange softWrap = editor.getSoftWrapModel().getSoftWrap(start);
|
||||
useOptimization = softWrap == null;
|
||||
}
|
||||
boolean hasNonTabs = false;
|
||||
for (int i = start; i < offset; i++) {
|
||||
if (text.charAt(i) == '\t') {
|
||||
if (hasNonTabs) {
|
||||
useOptimization = false;
|
||||
break;
|
||||
if (useOptimization) {
|
||||
for (int i = start; i < offset; i++) {
|
||||
if (text.charAt(i) == '\t') {
|
||||
if (hasNonTabs) {
|
||||
useOptimization = false;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
hasNonTabs = true;
|
||||
}
|
||||
} else {
|
||||
hasNonTabs = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -315,9 +311,6 @@ public class EditorUtil {
|
||||
* @return number of visual columns required to represent tabulation symbols that starts at the given column
|
||||
*/
|
||||
public static int tabWidthInColumns(@NotNull Editor editor, int visualColumn) {
|
||||
if (!editor.getSettings().isWhitespacesShown()) {
|
||||
return 1;
|
||||
}
|
||||
int tabSize = getTabSize(editor);
|
||||
int tabsNumber = visualColumn / tabSize;
|
||||
return (tabsNumber + 1) * tabSize - visualColumn;
|
||||
@@ -365,12 +358,7 @@ public class EditorUtil {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (editor.getSettings().isWhitespacesShown()) {
|
||||
result += nextTabStop(x + result, editor) - result - x;
|
||||
}
|
||||
else {
|
||||
result += getSpaceWidth(fontType, editor);
|
||||
}
|
||||
result += nextTabStop(x + result, editor) - result - x;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -179,34 +179,43 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener {
|
||||
if (newColumnNumber < 0) newColumnNumber = 0;
|
||||
if (newLineNumber < 0) newLineNumber = 0;
|
||||
|
||||
VisualPosition pos = new VisualPosition(newLineNumber, newColumnNumber);
|
||||
int lastColumnNumber = newColumnNumber;
|
||||
if (!editorSettings.isCaretInsideTabs()) {
|
||||
if (!editorSettings.isCaretInsideTabs() && !myEditor.getSoftWrapModel().isInsideSoftWrap(pos)) {
|
||||
LogicalPosition log = myEditor.visualToLogicalPosition(new VisualPosition(newLineNumber, newColumnNumber));
|
||||
int offset = myEditor.logicalPositionToOffset(log);
|
||||
CharSequence text = myEditor.getDocument().getCharsSequence();
|
||||
if (offset >= 0 && offset < myEditor.getDocument().getTextLength()) {
|
||||
if (text.charAt(offset) == '\t') {
|
||||
if (text.charAt(offset) == '\t' && (columnShift <= 0 || offset == myOffset)) {
|
||||
if (columnShift <= 0) {
|
||||
newColumnNumber = myEditor.offsetToVisualPosition(offset).column;
|
||||
}
|
||||
else {
|
||||
if (myEditor.offsetToVisualPosition(offset).column < newColumnNumber) {
|
||||
TextChange softWrap = myEditor.getSoftWrapModel().getSoftWrap(offset + 1);
|
||||
// There is a possible case that tabulation symbol is the last document symbol represented on a visual line before
|
||||
// soft wrap. We can't just use column from 'offset + 1' because it would point on a next visual line.
|
||||
if (softWrap == null) {
|
||||
newColumnNumber = myEditor.offsetToVisualPosition(offset + 1).column;
|
||||
}
|
||||
else {
|
||||
newColumnNumber = EditorUtil.getLastVisualLineColumnNumber(myEditor, newLineNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VisualPosition pos = new VisualPosition(newLineNumber, newColumnNumber);
|
||||
pos = new VisualPosition(newLineNumber, newColumnNumber);
|
||||
if (columnShift != 0 && lineShift == 0 && myEditor.getSoftWrapModel().isInsideSoftWrap(pos)) {
|
||||
LogicalPosition logical = myEditor.visualToLogicalPosition(pos);
|
||||
int offsetToUse = myEditor.logicalPositionToOffset(logical);
|
||||
if (columnShift < 0) {
|
||||
offsetToUse--;
|
||||
|
||||
int softWrapOffset = myEditor.logicalPositionToOffset(logical);
|
||||
if (columnShift >= 0) {
|
||||
moveToOffset(softWrapOffset);
|
||||
}
|
||||
else {
|
||||
int line = myEditor.offsetToVisualPosition(softWrapOffset - 1).line;
|
||||
moveToVisualPosition(new VisualPosition(line, EditorUtil.getLastVisualLineColumnNumber(myEditor, line)));
|
||||
}
|
||||
moveToOffset(offsetToUse);
|
||||
}
|
||||
else {
|
||||
moveToVisualPosition(pos);
|
||||
|
||||
@@ -839,8 +839,10 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
int spaceSize = EditorUtil.getSpaceWidth(fontType, this);
|
||||
|
||||
int x = 0;
|
||||
int charWidth;
|
||||
outer:
|
||||
while (true) {
|
||||
charWidth = -1;
|
||||
if (offset >= textLength) {
|
||||
break;
|
||||
}
|
||||
@@ -879,12 +881,12 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
continue;
|
||||
}
|
||||
prevX = x;
|
||||
int diff = charToVisibleWidth(c, fontType, x);
|
||||
if (diff == 0) {
|
||||
charWidth = charToVisibleWidth(c, fontType, x);
|
||||
if (charWidth == 0) {
|
||||
break outer;
|
||||
}
|
||||
|
||||
x += diff;
|
||||
x += charWidth;
|
||||
if (x >= px) {
|
||||
break outer;
|
||||
}
|
||||
@@ -894,7 +896,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
|
||||
// Process 'after soft wrap' sign.
|
||||
prevX = x;
|
||||
x += mySoftWrapModel.getMinDrawingWidth(SoftWrapDrawingType.AFTER_SOFT_WRAP);
|
||||
charWidth = mySoftWrapModel.getMinDrawingWidth(SoftWrapDrawingType.AFTER_SOFT_WRAP);
|
||||
x += charWidth;
|
||||
if (x >= px) {
|
||||
break outer;
|
||||
}
|
||||
@@ -903,11 +906,11 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
|
||||
prevX = x;
|
||||
c = text.charAt(offset);
|
||||
int diff = charToVisibleWidth(c, fontType, x);
|
||||
if (diff == 0) {
|
||||
charWidth = charToVisibleWidth(c, fontType, x);
|
||||
if (charWidth == 0) {
|
||||
break;
|
||||
} else {
|
||||
x += diff;
|
||||
x += charWidth;
|
||||
}
|
||||
|
||||
if (x >= px) {
|
||||
@@ -919,17 +922,17 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
}
|
||||
}
|
||||
|
||||
int charWidth = EditorUtil.charWidth(c, fontType, this);
|
||||
if (charWidth < 0) {
|
||||
charWidth = EditorUtil.charWidth(c, fontType, this);
|
||||
}
|
||||
|
||||
if (x >= px && c == '\t') {
|
||||
if (mySettings.isCaretInsideTabs()) {
|
||||
column += (px - prevX) / spaceSize;
|
||||
if ((px - prevX) % spaceSize > spaceSize / 2) column++;
|
||||
}
|
||||
else {
|
||||
if ((x - px) * 2 < x - prevX) {
|
||||
column += (x - prevX) / spaceSize;
|
||||
}
|
||||
else if ((x - px) * 2 < x - prevX) {
|
||||
column += columnsNumber(c, x, prevX, spaceSize);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -977,7 +980,11 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
if (c != '\t') {
|
||||
return 1;
|
||||
}
|
||||
return (x - prevX) / spaceSize;
|
||||
int result = (x - prevX) / spaceSize;
|
||||
if ((x - prevX) % spaceSize > 0) {
|
||||
result++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -1080,12 +1087,12 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
}
|
||||
}
|
||||
|
||||
int x = getTabbedTextWidth(lineStartOffset, column);
|
||||
return new Point(x + reserved, y);
|
||||
int x = getTabbedTextWidth(lineStartOffset, column, reserved);
|
||||
return new Point(x, y);
|
||||
}
|
||||
|
||||
private int getTabbedTextWidth(int startOffset, int length) {
|
||||
int x = 0;
|
||||
private int getTabbedTextWidth(int startOffset, int length, int xOffset) {
|
||||
int x = xOffset;
|
||||
if (startOffset == 0 && myPrefixText != null) {
|
||||
for (char c : myPrefixText) {
|
||||
x += EditorUtil.charWidth(c, myPrefixAttributes.getFontType(), this);
|
||||
@@ -1128,7 +1135,14 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
if (c == '\t') {
|
||||
int prevX = x;
|
||||
x = EditorUtil.nextTabStop(x, this);
|
||||
column += (x - prevX) / spaceSize;
|
||||
int columnDiff = (x - prevX) / spaceSize;
|
||||
if ((x - prevX) % spaceSize > 0) {
|
||||
// There is a possible case that tabulation symbol takes more than one visual column to represent and it's shown at
|
||||
// soft-wrapped line. Soft wrap sign width may be not divisible by space size, hence, part of tabulation symbol represented
|
||||
// as a separate visual column may take less space than space width.
|
||||
columnDiff++;
|
||||
}
|
||||
column += columnDiff;
|
||||
}
|
||||
else {
|
||||
x += EditorUtil.charWidth(c, fontType, this);
|
||||
@@ -4843,11 +4857,17 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
fontType = state.getMergedAttributes().getFontType();
|
||||
}
|
||||
|
||||
TextChange softWrap = getSoftWrapModel().getSoftWrap(i);
|
||||
if (softWrap != null) {
|
||||
column++; // For 'after soft wrap' drawing.
|
||||
x = getSoftWrapModel().getMinDrawingWidth(SoftWrapDrawingType.AFTER_SOFT_WRAP);
|
||||
}
|
||||
|
||||
char c = text.charAt(i);
|
||||
if (c == '\t') {
|
||||
int prevX = x;
|
||||
x = EditorUtil.nextTabStop(x, this);
|
||||
column += (x - prevX) / spaceSize;
|
||||
column += columnsNumber(c, x, prevX, spaceSize);
|
||||
//column += Math.max(1, (x - prevX) / spaceSize);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -277,7 +277,6 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi
|
||||
mySelectionMarker.release();
|
||||
mySelectionMarker = null;
|
||||
fireSelectionChanged(startOffset, endOffset, myLastSelectionStart, myLastSelectionStart);
|
||||
updateSystemSelection();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
+20
-2
@@ -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) {
|
||||
|
||||
+3
-1
@@ -114,7 +114,9 @@ public class SoftWrapDataMapper {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
context.onSoftWrapSymbol('a'); // Emulate 'after soft wrap' sign
|
||||
// Emulate 'after soft wrap' sign
|
||||
//int afterSoftWrapColumns = myEditor.getSoftWrapModel().get
|
||||
context.onSoftWrapSymbol('a');
|
||||
}
|
||||
|
||||
// Process document symbol.
|
||||
|
||||
@@ -266,9 +266,11 @@ public class JarHandler implements FileSystemInterface {
|
||||
}
|
||||
|
||||
final ZipFile zip = getZip();
|
||||
assert zip != null;
|
||||
assert zip != null : file;
|
||||
|
||||
final InputStream stream = zip.getInputStream(entry);
|
||||
assert stream != null : file;
|
||||
|
||||
try {
|
||||
return FileUtil.loadBytes(stream, (int)entry.getSize());
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user