<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" />
<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" />
<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 " />
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",
* 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);
}
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;
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;
+ context.getDependencyCache().clearTraverseRoots();
+ chunkFiles = filesInScope;
+ total += chunkFiles.size() * translators.length;
+ }
+
+ didSomething |= (hasUnprocessedTraverseRoots != context.getDependencyCache().hasUnprocessedTraverseRoots());
}
- final boolean compiledSomething =
- compileSources(_context, currentChunk, compiler, chunkFiles, forceCompile, isRebuild, trackDependencies, onlyCheckStatus, sink);
- processed += chunkFiles.size();
- _context.getProgressIndicator().setFraction(((double)processed) / total);
+ round++;
+ }
+ while (!dependentFiles.isEmpty() && context.getMessageCount(CompilerMessageCategory.ERROR) == 0);
- if (compiledSomething) {
- generatedTypes.addAll(compilerManager.getRegisteredOutputTypes(compiler));
- }
+ 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();
- if (_context.getMessageCount(CompilerMessageCategory.ERROR) > 0) {
- throw new ExitException(ExitStatus.ERRORS);
- }
+ indicator.pushState();
+ indicator.setText(CompilerBundle.message("progress.updating.caches"));
+ indicator.setText2("");
+
+ cache.update();
+
+ indicator.setText(CompilerBundle.message("progress.saving.caches"));
+ cache.resetState();
- didSomething |= compiledSomething;
+ 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) {
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));
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);
}
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) {
context.getProgressIndicator().pushState();
final boolean[] wereFilesDeleted = new boolean[]{false};
- boolean traverseRootsProcessed = false;
try {
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
}
}
- 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 {
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) {
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();
}
}
- 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>();
}
}
}
+
+ 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);
+ }
+ }
}
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);
+ }
}
}
}
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);
System.out.println(message);
}
}
- removeSourceForRecompilation(projectId, Math.abs(getFileId(file)));
+ removeSourceForRecompilation(projectId, sourceFileId);
}
}
}
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;
}
void compileFinished();
- @Nullable
- DependencyProcessor getDependencyProcessor();
}
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;
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;
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;
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,
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);
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) {
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 {
});
}
- 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 {
}
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);
}
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 {
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);
}
}
}
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);
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;
}
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 {
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());
}
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);
* @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, '/');
}
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);
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;
myProject = project;
}
- public DependencyProcessor getDependencyProcessor() {
- return null;
- }
-
public boolean checkCompiler(final CompileScope scope) {
return true;
}
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;
myEclipseCompilerDriver = new EclipseCompilerDriver();
}
- public DependencyProcessor getDependencyProcessor() {
- return null;
- }
-
public boolean checkCompiler(final CompileScope scope) {
return myEclipseCompilerDriver != null && myEclipseExternalCompiler.checkCompiler(scope);
}
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;
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.*;
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();
}
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>();
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;
+ }
}
*/
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;
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;
/**
* @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=====================");
).run();
}
changedRetentionPolicyDependencyProcessor.checkAnnotationRetentionPolicyChanges(qName);
- if (additionalProcessor != null) {
+ for (DependencyProcessor additionalProcessor : DependencyProcessor.EXTENSION_POINT_NAME.getExtensions()) {
additionalProcessor.processDependencies(context, qName);
}
}
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;
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)) {
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);
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;
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) {
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();
return new JavaPushDownHandler();
}
- public RefactoringActionHandler getExtractModuleHandler() {
+ public RefactoringActionHandler getExtractInterfaceHandler() {
return new ExtractInterfaceHandler();
}
}
break;
case SUBTYPE:
- if (PsiType.NULL.equals(upperBound)) {
+ if (PsiType.NULL.equals(upperBound) || TypeConversionUtil.isAssignable(upperBound, type)) {
upperBound = type;
}
}
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));
}
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);
!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);
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()) {
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;
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;
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>();
}
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) {
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;
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);
}
break;
}
}
- if (!anyOverridingRefs && isMultipleInterfacesImplementation(overridingMethod, allElementsToDelete)) {
+ if (!anyOverridingRefs && isMultipleInterfacesImplementation(overridingMethod, originalMethod, allElementsToDelete)) {
anyOverridingRefs = true;
multipleInterfaceImplementations.add(overridingMethod);
}
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;
}
}
--- /dev/null
+
+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;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+// "Create Getter" "true"
+public class Test {
+ Integer field;
+ public foo() {
+ getField();
+ }
+
+ public Integer getField() {
+ return field;
+ }
+}
--- /dev/null
+// "Create Getter" "true"
+public class Test {
+ Integer field;
+ public foo() {
+ get<caret>Field();
+ }
+}
<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>
\ No newline at end of file
+ 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>
\ No newline at end of file
--- /dev/null
+public class Super {
+
+}
+
+class Child extends Super {
+ }
+
+class ChildChild extends Child {
+ }
\ No newline at end of file
--- /dev/null
+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");
+ }
+}
\ No newline at end of file
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);}
}
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 {
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;
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);
}
doTest("Super");
}
+ public void testMethodDeepHierarchy() throws Exception {
+ myDoCompare = false;
+ doTest("Super");
+ }
+
public void testLocalVariableSideEffect() throws Exception {
myDoCompare = false;
try {
"<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);
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() {
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();
}
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,
@NotNull
JspxFileViewProvider getViewProvider();
-}
\ No newline at end of file
+}
*/
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.
*/
return null;
}
+ public RefactoringActionHandler getExtractInterfaceHandler() {
+ return null;
+ }
+
public RefactoringActionHandler getExtractModuleHandler() {
return null;
}
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.Nullable;
/**
* @author yole
return canInlineElement(element);
}
- public boolean isEnabledOnElement(PsiElement element, Editor editor) {
+ public boolean isEnabledOnElement(PsiElement element, @Nullable Editor editor) {
return isEnabledOnElement(element);
}
*/
@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
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
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;
- //}
}
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;
}
@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());
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);
}
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>() {
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) {
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;
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();
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){
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;
@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];
}
}
}
- else {
- resolvedElement = ref.resolve();
- }
return resolvedElement;
}
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
*/
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;
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();
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);
}
}
public Icon getIcon(boolean open) {
- return open ? myIconOpen.getIcon() : myIconClosed.getIcon();
+ final ComputableIcon computableIcon = open ? myIconOpen : myIconClosed;
+ return computableIcon == null? null : computableIcon.getIcon();
}
}
}
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.
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) {
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()) {
}
}
- 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) {
}
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();
// 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;
}
}
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) {
iterator.advance();
}
} finally {
- while(iterator.getStart() != offset) iterator.retreat();
+ while (!iterator.atEnd() && iterator.getStart() != offset) iterator.retreat();
}
return false;
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;
}
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) {
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));
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() {
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()) {
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() {
}
}
+ private boolean isInjected(PsiFile psiFile) {
+ return InjectedLanguageManager.getInstance(myProject).isInjectedFragment(psiFile);
+ }
+
private void queueRefreshScope(final NamedScope scope) {
myUpdateQueue.cancelAllUpdates();
queueUpdate(new Runnable() {
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;
}
}
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;
}
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();
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;
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);
}
}
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;
}
}
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);
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>() {
}
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;
}
};
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);
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 {
void commit() throws IOException;
+ void listModifiedFiles(List<VirtualFile> list);
}
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;
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
*/
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;
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;
};
}
+ 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();
- final LanguageFileType filetype = (LanguageFileType)fileType;
- Language l = filetype.getLanguage();
- final IFileElementType type = LanguageParserDefinitions.INSTANCE.forLanguage(l).getFileNodeType();
+ PsiFile psi = inputData.getPsiFile();
- PsiFile psi = inputData.getPsiFile();
+ data = ((IStubFileElementType)type).getBuilder().buildStubTree(psi);
+ }
- return ((IStubFileElementType)type).getBuilder().buildStubTree(psi);
+ inputData.putUserData(stubElementKey, data);
+ return data;
+ }
}
public KeyDescriptor<Integer> getKeyDescriptor() {
* 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();
}
-}
-
+}
\ No newline at end of file
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.intellij.refactoring.extractInterface;
-import com.intellij.refactoring.actions.BaseExtractModuleAction;
-import com.intellij.lang.Language;
-import com.intellij.lang.java.JavaLanguage;
+package com.intellij.refactoring.actions;
+
+import com.intellij.lang.refactoring.RefactoringSupportProvider;
+import com.intellij.refactoring.RefactoringActionHandler;
/**
* @author Dennis.Ushakov
*/
-public class ExtractInterfaceAction extends BaseExtractModuleAction {
+public class ExtractModuleAction extends ExtractSuperActionBase {
@Override
- protected boolean isEnabledOnLanguage(Language language) {
- return language instanceof JavaLanguage;
+ protected RefactoringActionHandler getRefactoringHandler(RefactoringSupportProvider supportProvider) {
+ return supportProvider.getExtractModuleHandler();
}
-}
+}
\ No newline at end of file
/*
- * 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.
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;
}
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);
}
\ No newline at end of file
package com.intellij.refactoring.actions;
-import com.intellij.lang.Language;
-import com.intellij.lang.LanguageRefactoringSupport;
import com.intellij.lang.refactoring.RefactoringSupportProvider;
-import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.LangDataKeys;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiFile;
import com.intellij.refactoring.RefactoringActionHandler;
-import com.intellij.refactoring.lang.ElementsHandler;
-public class ExtractSuperclassAction extends BasePlatformRefactoringAction {
- public boolean isAvailableInEditorOnly() {
- return false;
- }
-
- public boolean isEnabledOnElements(PsiElement[] elements) {
- if (elements.length > 0) {
- final Language language = elements[0].getLanguage();
- final RefactoringActionHandler handler = LanguageRefactoringSupport.INSTANCE.forLanguage(language).getExtractModuleHandler();
- return handler instanceof ElementsHandler && ((ElementsHandler)handler).isEnabledOnElements(elements);
- }
- return false;
- }
-
- public RefactoringActionHandler getHandler(DataContext dataContext) {
- PsiFile file = LangDataKeys.PSI_FILE.getData(dataContext);
- if (file == null) return null;
- final RefactoringSupportProvider supportProvider = LanguageRefactoringSupport.INSTANCE.forLanguage(file.getViewProvider().getBaseLanguage());
- return supportProvider != null ? supportProvider.getExtractSuperClassHandler() : null;
- }
-
- protected boolean isAvailableForLanguage(final Language language) {
- return LanguageRefactoringSupport.INSTANCE.forLanguage(language).getExtractSuperClassHandler() != null;
+public class ExtractSuperclassAction extends ExtractSuperActionBase {
+ @Override
+ protected RefactoringActionHandler getRefactoringHandler(RefactoringSupportProvider supportProvider) {
+ return supportProvider.getExtractSuperClassHandler();
}
}
\ No newline at end of file
final ButtonGroup buttonGroup = new ButtonGroup();
buttonGroup.add(myRbExtractSuperclass);
buttonGroup.add(myRbExtractSubclass);
+ customizeRadiobuttons(box, buttonGroup);
myRbExtractSuperclass.setSelected(true);
ItemListener listener = new ItemListener() {
return box;
}
+ protected void customizeRadiobuttons(Box box, ButtonGroup buttonGroup) {
+ }
+
protected JComponent createNorthPanel() {
Box box = Box.createVerticalBox();
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() {
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) {
}
protected String getNameLabel() {
- return RefactoringBundle.message("name.for.extracted.include.file");
+ return RefactoringBundle.message("name.for.extracted.include.file", myExtension);
}
private void validateOKButton() {
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) {
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;
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;
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 {
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,
return false;
}
}
- Set<UsageInfo> usagesSet = new HashSet<UsageInfo>(Arrays.asList(usagesIn));
- RenameUtil.removeConflictUsages(usagesSet);
final List<UsageInfo> variableUsages = new ArrayList<UsageInfo>();
if (!myRenamers.isEmpty()) {
}
}
- 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;
final Runnable runnable = new Runnable() {
public void run() {
for (final AutomaticRenamer renamer : myRenamers) {
- renamer.findUsages(variableUsages, mySearchInComments, mySearchTextOccurrences);
+ renamer.findUsages(variableUsages, mySearchInComments, mySearchTextOccurrences, mySkippedUsages);
}
}
};
}
}
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() {
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) {
}
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();
}
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);
}
public class RefactoringDescriptionLocation extends ElementDescriptionLocation {
private final boolean myWithParent;
- private RefactoringDescriptionLocation(boolean withParent) {
+ protected RefactoringDescriptionLocation(boolean withParent) {
myWithParent = withParent;
}
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;
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() {
}
public void destroyProcess() {
- afterStartNotified(new Runnable() {
+ myAfterStartNotifiedRunner.execute(new Runnable() {
public void run() {
if (myState.compareAndSet(STATE_RUNNING, STATE_TERMINATING)) {
fireProcessWillTerminate(true);
}
public void detachProcess() {
- afterStartNotified(new Runnable() {
+ myAfterStartNotifiedRunner.execute(new Runnable() {
public void run() {
if (myState.compareAndSet(STATE_RUNNING, STATE_TERMINATING)) {
fireProcessWillTerminate(false);
}
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");
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;
}
}
});
}
+
+ 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();
+ }
+ }
+
+ }
}
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();
public abstract boolean isIgnoredMacroName(@NotNull final String macro);
public abstract void removeAllMacros();
+
+ public abstract Collection<String> getLegacyMacroNames();
}
}
@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 {
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;
}
public void setHyperlinkText(String text) {
+ myUseIconAsLink = true;
setHyperlinkText("", text, "");
}
adjustSize();
}
+ public void setUseIconAsLink(boolean useIconAsLink) {
+ myUseIconAsLink = useIconAsLink;
+ }
+
private void adjustSize() {
final Dimension preferredSize = this.getPreferredSize();
this.setMinimumSize(preferredSize);
}
private boolean isOnLink(int x) {
+ if (myUseIconAsLink && myIcon != null && x < myIcon.getIconWidth()) {
+ return true;
+ }
return findRegionByX(x) != null;
}
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;
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:";
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;
*/
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>();
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>();
}
}
+ @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 {
}
}
+ @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();
}
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);
}
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();
+ }
}
}
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"};
* @author mike
*/
public class ApplicationPathMacroManager extends BasePathMacroManager {
- public ApplicationPathMacroManager() {
- super(true);
- }
}
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;
+
+ 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;
+ }
- public BasePathMacroManager() {
- this(true);
+ 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;
}
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;
}
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;
public class ProjectPathMacroManager extends BasePathMacroManager {
private final ProjectEx myProject;
-
public ProjectPathMacroManager(final ProjectEx project) {
myProject = project;
}
}
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));
}
@Nullable
- private String getProjectDir() {
+ public static String getProjectDir(Project myProject) {
final VirtualFile baseDir = myProject.getBaseDir();
return baseDir != null ? baseDir.getPath() : null;
}
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;
}
}
// 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;
LogicalPosition blockSelectionStart = selectionModel.hasBlockSelection()
? selectionModel.getBlockStart()
: caretModel.getLogicalPosition();
+ SoftWrapModel softWrapModel = editor.getSoftWrapModel();
int lineNumber = editor.getCaretModel().getLogicalPosition().line;
if (lineNumber >= document.getLineCount()) {
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
// 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;
}
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;
}
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;
- boolean hasNonTabs = false;
- boolean hasTabs = false;
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;
+
+ for (int i = start; i < end; i++) {
if (text.charAt(i) == '\t') {
hasTabs = true;
if (hasNonTabs) {
- useOptimization = false;
break;
}
} else {
}
}
- if (editor == null || useOptimization) {
- 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;
- }
+ if (!hasTabs) return Math.min(start + columnNumber, end);
- 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;
}
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;
}
}
* @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;
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;
}
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);
int spaceSize = EditorUtil.getSpaceWidth(fontType, this);
int x = 0;
+ int charWidth;
outer:
while (true) {
+ charWidth = -1;
if (offset >= textLength) {
break;
}
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;
}
// 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;
}
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) {
}
}
- 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 {
if (c != '\t') {
return 1;
}
- return (x - prevX) / spaceSize;
+ int result = (x - prevX) / spaceSize;
+ if ((x - prevX) % spaceSize > 0) {
+ result++;
+ }
+ return result;
}
@NotNull
}
}
- 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);
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);
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 {
mySelectionMarker.release();
mySelectionMarker = null;
fireSelectionChanged(startOffset, endOffset, myLastSelectionStart, myLastSelectionStart);
- updateSystemSelection();
}
}
// 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
// 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)) {
// 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) {
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.
}
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());
}
import java.util.ArrayList;
import java.util.List;
+import static com.intellij.util.ObjectUtils.*;
+
/**
* @author Dmitry Avdeev
*/
public abstract class CachedValueBase<T> {
- protected static final Object NULL = new Object();
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.CachedValueImpl");
private final MyTimedReference<T> myData = new MyTimedReference<T>();
}
protected void setValue(final T value, final CachedValueProvider.Result<T> result) {
- myData.setData(computeData(value == null ? (T) NULL : value, getDependencies(result)));
+ myData.setData(computeData(value == null ? (T)NULL : value, getDependencies(result)));
if (result != null) {
myData.setIsLocked(result.isLockValue());
}
try {
value = getUpToDateOrNull();
if (value != null) {
- return value == NULL ? null : value;
+ return value == ObjectUtils.NULL ? null : value;
}
} finally {
r.unlock();
try {
value = getUpToDateOrNull();
if (value != null) {
- return value == NULL ? null : value;
+ return value == ObjectUtils.NULL ? null : value;
}
CachedValueProvider.Result<T> result = myProvider.compute();
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import static com.intellij.util.ObjectUtils.*;
+
public abstract class ParameterizedCachedValueImpl<T,P> extends CachedValueBase<T> implements ParameterizedCachedValue<T,P> {
private final ParameterizedCachedValueProvider<T,P> myProvider;
action.IntroduceParameter.description=Turn the selected expression into method parameter
action.ExtractInterface.text=Extract _Interface...
action.ExtractInterface.description=Extract interface from the selected class
+action.ExtractModule.text=Extract _Module...
+action.ExtractModule.description=Extract module from the selected class
action.ExtractSuperclass.text=Extract S_uperclass...
action.ExtractSuperclass.description=Extract superclass from the selected class
action.TurnRefsToSuper.text=Use Interface _Where Possible...
extractIncludeFile.name=Extract Include File
file.already.exist=File {0} already exists
file.already.exist.title=Extract Include File
-name.for.extracted.include.file=&Name for extracted include file (without extension):
+name.for.extracted.include.file=&Name for extracted include file (default extension: {0})
extract.to.directory=Extract to &directory:
select.target.directory=Select target directory
select.target.directory.description=The file will be created in this directory
method.has.an.empty.body=Method {0} has an empty body.
idea.has.not.found.any.code.that.can.be.replaced.with.method.call={0} has not found any code that can be replaced with method call
method.duplicates.found.message={0, choice, 1#1 code fragment|2#{0,number} code fragments} found
-0.with.1.visibility.is.not.accesible.from.2={0} with {1} visibility won''t be accesible from {2}
+0.with.1.visibility.is.not.accessible.from.2={0} with {1} visibility won''t be accessible from {2}
0.contains.call.with.null.argument.for.parameter.1={0} contains call with null argument for parameter {1}
no.members.selected=No members selected
0.already.exists.in.the.target.class={0} already exists in the target class.
there.is.already.a.0.it.will.conflict.with.an.introduced.parameter=There is already a {0}. It will conflict with an introduced parameter
introduce.parameter.command=Introducing parameter to {0}
parameter.initializer.contains.0.but.not.all.calls.to.method.are.in.its.class=Parameter initializer contains {0}, but not all calls to method are in its class.
-0.is.not.accesible.from.1.value.for.introduced.parameter.in.that.method.call.will.be.incorrect={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={0} is not accessible from {1}. Value for introduced parameter in that method call will be incorrect.
use.interface.superclass.in.instanceof=Use interface/superclass in instanceof
introduce.parameter.to.method=Introduce parameter to method:
introduced.variable.will.conflict.with.0=Introduced variable will conflict with {0}
xml.parsing.closing.tag.is.not.done=Closing tag is not done
attribute.should.be.preceded.with.space=There should be a space between attribute and previous attribute
cdata.end.should.not.appear.in.content.unless.to.mark.end.of.cdata.section=Character sequence ']]>' must not appear in content unless used to mark the end of a CDATA section
+xml.declaration.should.precede.all.document.content=Xml declaration should precede all document content
<group id="AddAllToFavorites" class="com.intellij.ide.favoritesTreeView.actions.AddAllToFavoritesActionGroup" popup="true"/>
<action id="AddNewFavoritesList" class="com.intellij.ide.favoritesTreeView.actions.AddNewFavoritesListAction"/>
<group id="SendToFavoritesGroup" class="com.intellij.ide.favoritesTreeView.actions.SendToFavoritesGroup" popup="true"/>
-
+
<action id="RunConfiguration" class="com.intellij.execution.actions.RunConfigurationAction"/>
<action id="ChooseRunConfiguration" class="com.intellij.execution.actions.ChooseRunConfigurationAction" text="Run..." icon="/general/toolWindowRun.png"/>
<action id="ChooseDebugConfiguration" class="com.intellij.execution.actions.ChooseDebugConfigurationAction" text="Debug..." icon="/general/debug.png"/>
<action id="MemberPushDown" class="com.intellij.refactoring.actions.PushDownAction"/>
<separator/>
<action id="ExtractInclude" class="com.intellij.refactoring.actions.ExtractIncludeAction"/>
+ <action id="ExtractInterface" class="com.intellij.refactoring.actions.ExtractInterfaceAction"/>
+ <action id="ExtractModule" class="com.intellij.refactoring.actions.ExtractModuleAction"/>
<action id="ExtractSuperclass" class="com.intellij.refactoring.actions.ExtractSuperclassAction"/>
<add-to-group group-id="MainMenu" anchor="after" relative-to-action="CodeMenu"/>
</group>
import com.intellij.execution.testframework.sm.TestsLocationProviderUtil;
import com.intellij.execution.testframework.sm.runner.states.*;
import com.intellij.execution.testframework.sm.runner.ui.TestsPresentationUtil;
-import com.intellij.execution.testframework.ui.PrintableTestProxy;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.ide.util.EditSourceUtil;
import com.intellij.openapi.diagnostic.Logger;
/**
* @author: Roman Chernyatchik
*/
-public class SMTestProxy extends CompositePrintable implements PrintableTestProxy {
+public class SMTestProxy extends AbstractTestProxy {
private static final Logger LOG = Logger.getInstance(SMTestProxy.class.getName());
private List<SMTestProxy> myChildren;
private boolean myHasErrors = false;
private boolean myHasErrorsCached = false;
- private Printer myPrinter = Printer.DEAF;
-
private final boolean myIsSuite;
public SMTestProxy(final String testName, final boolean isSuite,
child.setParent(this);
// if parent is being printed then all childs output
// should be also send to the same printer
- if (myPrinter != Printer.DEAF) {
- child.setPrintLinstener(myPrinter);
- }
+ child.setPrinter(myPrinter);
}
public String getName() {
return myState.wasLaunched();
}
- public boolean isRoot() {
- return getParent() == null;
- }
-
- public void setPrintLinstener(final Printer printer) {
- myPrinter = printer;
-
- if (myChildren == null) {
- return;
- }
-
- for (ChangingPrintable child : myChildren) {
- child.setPrintLinstener(printer);
- }
- }
/**
* Prints this proxy and all its children on given printer
myState.printOn(printer);
}
- /**
- * Stores printable information in internal buffer and notifies
- * proxy's printer about new text available
- * @param printable Printable info
- */
- @Override
- public void addLast(final Printable printable) {
- super.addLast(printable);
- fireOnNewPrintable(printable);
- }
-
public void addStdOutput(final String output, final Key outputType) {
addLast(new Printable() {
public void printOn(final Printer printer) {
});
}
- private void fireOnNewPrintable(final Printable printable) {
- myPrinter.onNewAvailable(printable);
- }
-
@NotNull
public String getPresentableName() {
return TestsPresentationUtil.getPresentableName(this);
*/
package com.intellij.execution.testframework.sm.runner.states;
+import com.intellij.execution.testframework.CompositePrintable;
import com.intellij.execution.testframework.Printer;
import com.intellij.execution.testframework.sm.SMTestsRunnerBundle;
-import com.intellij.execution.testframework.ui.PrintableTestProxy;
+import com.intellij.execution.testframework.sm.runner.SMTestProxy;
import com.intellij.execution.ui.ConsoleViewContentType;
import org.jetbrains.annotations.NonNls;
public void printOn(final Printer printer) {
super.printOn(printer);
- final String msg = EMPTY_SUITE_TEXT + PrintableTestProxy.NEW_LINE;
+ final String msg = EMPTY_SUITE_TEXT + CompositePrintable.NEW_LINE;
printer.print(msg, ConsoleViewContentType.SYSTEM_OUTPUT);
}
*/
package com.intellij.execution.testframework.sm.runner.states;
+import com.intellij.execution.testframework.CompositePrintable;
import com.intellij.execution.testframework.Printer;
-import com.intellij.execution.testframework.ui.PrintableTestProxy;
+import com.intellij.execution.testframework.sm.runner.SMTestProxy;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
@Nullable final String stackTrace) {
final String text = (StringUtil.isEmptyOrSpaces(localizedMessage)
? ""
- : localizedMessage + PrintableTestProxy.NEW_LINE) +
+ : localizedMessage + CompositePrintable.NEW_LINE) +
(StringUtil.isEmptyOrSpaces(stackTrace)
? ""
- : stackTrace + PrintableTestProxy.NEW_LINE);
+ : stackTrace + CompositePrintable.NEW_LINE);
return StringUtil.isEmptyOrSpaces(text) ? null : text;
}
public static void printError(@NotNull final Printer printer,
@NotNull final String errorPresentationText) {
- printer.print(PrintableTestProxy.NEW_LINE, ConsoleViewContentType.ERROR_OUTPUT);
+ printer.print(CompositePrintable.NEW_LINE, ConsoleViewContentType.ERROR_OUTPUT);
printer.mark();
printer.print(errorPresentationText, ConsoleViewContentType.ERROR_OUTPUT);
}
*/
package com.intellij.execution.testframework.sm.runner.states;
+import com.intellij.execution.testframework.CompositePrintable;
import com.intellij.execution.testframework.Printer;
import com.intellij.execution.testframework.sm.SMTestsRunnerBundle;
-import com.intellij.execution.testframework.ui.PrintableTestProxy;
+import com.intellij.execution.testframework.sm.runner.SMTestProxy;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NonNls;
public TestIgnoredState(final String ignoredComment, @Nullable final String stackTrace) {
final String ignored_msg = StringUtil.isEmpty(ignoredComment) ? IGNORED_TEST_TEXT : ignoredComment;
- myText = PrintableTestProxy.NEW_LINE + ignored_msg;
- myStacktrace = stackTrace == null ? null : stackTrace + PrintableTestProxy.NEW_LINE;
+ myText = CompositePrintable.NEW_LINE + ignored_msg;
+ myStacktrace = stackTrace == null ? null : stackTrace + CompositePrintable.NEW_LINE;
}
public boolean isInProgress() {
printer.print(myText, ConsoleViewContentType.SYSTEM_OUTPUT);
if (StringUtil.isEmptyOrSpaces(myStacktrace)) {
- printer.print(PrintableTestProxy.NEW_LINE, ConsoleViewContentType.SYSTEM_OUTPUT);
+ printer.print(CompositePrintable.NEW_LINE, ConsoleViewContentType.SYSTEM_OUTPUT);
}
else {
- printer.print(PrintableTestProxy.NEW_LINE, ConsoleViewContentType.ERROR_OUTPUT);
+ printer.print(CompositePrintable.NEW_LINE, ConsoleViewContentType.ERROR_OUTPUT);
printer.mark();
printer.print(myStacktrace, ConsoleViewContentType.ERROR_OUTPUT);
}
import com.intellij.execution.testframework.sm.SMRunnerUtil;
import com.intellij.execution.testframework.sm.runner.SMTestProxy;
import com.intellij.execution.testframework.ui.BaseTestsOutputConsoleView;
-import com.intellij.execution.testframework.ui.PrintableTestProxy;
import com.intellij.execution.testframework.ui.TestResultsPanel;
import com.intellij.openapi.application.ModalityState;
import org.jetbrains.annotations.NotNull;
public SMTRunnerConsoleView(final TestConsoleProperties consoleProperties, final RunnerSettings runnerSettings,
final ConfigurationPerRunnerSettings configurationPerRunnerSettings,
@Nullable final String splitterProperty) {
- super(consoleProperties);
+ super(consoleProperties, null);
myRunnerSettings = runnerSettings;
myConfigurationPerRunnerSettings = configurationPerRunnerSettings;
mySplitterProperty = splitterProperty;
// Do nothing
}
- public void onSelected(@Nullable final PrintableTestProxy selectedTestProxy,
+ public void onSelected(@Nullable final SMTestProxy selectedTestProxy,
@NotNull final TestResultsViewer viewer,
@NotNull final TestFrameworkRunningModel model) {
if (selectedTestProxy == null) {
}
public void attachToProcess(final ProcessHandler processHandler) {
- getPrinter().setCollectOutput(false);
}
}
package com.intellij.execution.testframework.sm.runner.ui;
import com.intellij.execution.testframework.AbstractTestProxy;
-import com.intellij.execution.testframework.Filter;
import com.intellij.execution.testframework.TestConsoleProperties;
import com.intellij.execution.testframework.TestFrameworkRunningModel;
import com.intellij.execution.testframework.sm.runner.ProxyFilters;
-import com.intellij.execution.testframework.ui.PrintableTestProxy;
import com.intellij.execution.testframework.actions.ScrollToTestSourceAction;
import com.intellij