mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'master' of git@git.labs.intellij.net:idea/community
This commit is contained in:
@@ -97,6 +97,8 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class CompileDriver {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.CompileDriver");
|
||||
// to be used in tests only for debug output
|
||||
public static boolean ourDebugMode = false;
|
||||
|
||||
private final Project myProject;
|
||||
private final Map<Pair<IntermediateOutputCompiler, Module>, Pair<VirtualFile, VirtualFile>> myGenerationCompilerModuleToOutputDirMap; // [IntermediateOutputCompiler, Module] -> [ProductionSources, TestSources]
|
||||
@@ -1558,12 +1560,20 @@ public class CompileDriver {
|
||||
if (toDelete.isEmpty() && toCompile.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
if (LOG.isDebugEnabled()) {
|
||||
if (LOG.isDebugEnabled() || ourDebugMode) {
|
||||
if (!toDelete.isEmpty()) {
|
||||
LOG.debug("Found items to delete, compiler " + compiler.getDescription());
|
||||
final String message = "Found items to delete, compiler " + compiler.getDescription();
|
||||
LOG.debug(message);
|
||||
if (ourDebugMode) {
|
||||
System.out.println(message);
|
||||
}
|
||||
}
|
||||
if (!toCompile.isEmpty()) {
|
||||
LOG.debug("Found items to compile, compiler " + compiler.getDescription());
|
||||
final String message = "Found items to compile, compiler " + compiler.getDescription();
|
||||
LOG.debug(message);
|
||||
if (ourDebugMode) {
|
||||
System.out.println(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new ExitException(ExitStatus.CANCELLED);
|
||||
|
||||
+62
-18
@@ -78,6 +78,7 @@ import java.util.*;
|
||||
|
||||
public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.TranslatingCompilerFilesMonitor");
|
||||
public static boolean ourDebugMode = false;
|
||||
@NonNls
|
||||
private static final String PATHS_TO_DELETE_FILENAME = "paths_to_delete.dat";
|
||||
private static final String OUTPUT_ROOTS_FILENAME = "output_roots.dat";
|
||||
@@ -163,8 +164,12 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
|
||||
while (scopeSrcIterator.hasNext()) {
|
||||
final VirtualFile file = scopeSrcIterator.next();
|
||||
if (!file.isValid()) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Skipping invalid file " + file.getPresentableUrl());
|
||||
if (LOG.isDebugEnabled() || ourDebugMode) {
|
||||
final String message = "Skipping invalid file " + file.getPresentableUrl();
|
||||
LOG.debug(message);
|
||||
if (ourDebugMode) {
|
||||
System.out.println(message);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -212,11 +217,22 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
|
||||
//noinspection UnnecessaryBoxing
|
||||
final File file = new File(outputPath);
|
||||
toDelete.add(new Trinity<File, String, Boolean>(file, classNamePair.getClassName(), Boolean.valueOf(sourcePresent)));
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Found file to delete: " + file);
|
||||
if (LOG.isDebugEnabled() || ourDebugMode) {
|
||||
final String message = "Found file to delete: " + file;
|
||||
LOG.debug(message);
|
||||
if (ourDebugMode) {
|
||||
System.out.println(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (LOG.isDebugEnabled() || ourDebugMode) {
|
||||
final String message = "Found zombie entry marked for deletion: " + outputPath;
|
||||
LOG.debug(message);
|
||||
if (ourDebugMode) {
|
||||
System.out.println(message);
|
||||
}
|
||||
}
|
||||
// must be gagbage entry, should cleanup
|
||||
zombieEntries.add(outputPath);
|
||||
}
|
||||
@@ -301,8 +317,12 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
|
||||
final long fileStamp = file.getTimeStamp();
|
||||
info.updateTimestamp(projectId, fileStamp);
|
||||
saveSourceInfo(file, info);
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Unschedule recompilation (successfully compiled) " + file.getPresentableUrl());
|
||||
if (LOG.isDebugEnabled() || ourDebugMode) {
|
||||
final String message = "Unschedule recompilation (successfully compiled) " + file.getPresentableUrl();
|
||||
LOG.debug(message);
|
||||
if (ourDebugMode) {
|
||||
System.out.println(message);
|
||||
}
|
||||
}
|
||||
removeSourceForRecompilation(projectId, Math.abs(getFileId(file)));
|
||||
if ((fileStamp > compilationStartStamp && !((CompileContextEx)context).isGenerated(file)) || forceRecompile.contains(file)) {
|
||||
@@ -365,8 +385,12 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
|
||||
final String outputPath = FileUtil.toSystemIndependentName(CompilerIOUtil.readString(is));
|
||||
final String srcUrl = CompilerIOUtil.readString(is);
|
||||
final String className = CompilerIOUtil.readString(is);
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("INIT path to delete: " + outputPath);
|
||||
if (LOG.isDebugEnabled() || ourDebugMode) {
|
||||
final String message = "INIT path to delete: " + outputPath;
|
||||
LOG.debug(message);
|
||||
if (ourDebugMode) {
|
||||
System.out.println(message);
|
||||
}
|
||||
}
|
||||
map.put(outputPath, new SourceUrlClassNamePair(srcUrl, className));
|
||||
}
|
||||
@@ -1136,8 +1160,12 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
|
||||
|
||||
public void beforeFileDeletion(final VirtualFileEvent event) {
|
||||
final VirtualFile eventFile = event.getFile();
|
||||
if (LOG.isDebugEnabled() && eventFile.isDirectory()) {
|
||||
LOG.debug("Processing file deletion: " + eventFile.getPresentableUrl());
|
||||
if ((LOG.isDebugEnabled() && eventFile.isDirectory()) || ourDebugMode) {
|
||||
final String message = "Processing file deletion: " + eventFile.getPresentableUrl();
|
||||
LOG.debug(message);
|
||||
if (ourDebugMode) {
|
||||
System.out.println(message);
|
||||
}
|
||||
}
|
||||
processRecursively(eventFile, true, new FileProcessor() {
|
||||
public void execute(final VirtualFile file) {
|
||||
@@ -1167,8 +1195,12 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
|
||||
for (int projectId : projects.toArray()) {
|
||||
// mark associated outputs for deletion
|
||||
srcInfo.processOutputPaths(projectId, deletionProc);
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Unschedule recompilation because of deletion " + file.getPresentableUrl());
|
||||
if (LOG.isDebugEnabled() || ourDebugMode) {
|
||||
final String message = "Unschedule recompilation because of deletion " + file.getPresentableUrl();
|
||||
LOG.debug(message);
|
||||
if (ourDebugMode) {
|
||||
System.out.println(message);
|
||||
}
|
||||
}
|
||||
removeSourceForRecompilation(projectId, Math.abs(getFileId(file)));
|
||||
}
|
||||
@@ -1269,8 +1301,12 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
|
||||
mySourcesToRecompile.put(projectId, set);
|
||||
}
|
||||
alreadyMarked = !set.add(Math.abs(getFileId(srcFile)));
|
||||
if (!alreadyMarked && LOG.isDebugEnabled()) {
|
||||
LOG.debug("Scheduled recompilation " + srcFile.getPresentableUrl());
|
||||
if (!alreadyMarked && (LOG.isDebugEnabled() || ourDebugMode)) {
|
||||
final String message = "Scheduled recompilation " + srcFile.getPresentableUrl();
|
||||
LOG.debug(message);
|
||||
if (ourDebugMode) {
|
||||
System.out.println(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1336,8 +1372,12 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
|
||||
myOutputsToDelete.put(projectId, map);
|
||||
}
|
||||
map.put(outputPath, new SourceUrlClassNamePair(srcUrl, classname));
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("ADD path to delete: " + outputPath + "; source: " + srcUrl);
|
||||
if (LOG.isDebugEnabled() || ourDebugMode) {
|
||||
final String message = "ADD path to delete: " + outputPath + "; source: " + srcUrl;
|
||||
LOG.debug(message);
|
||||
if (ourDebugMode) {
|
||||
System.out.println(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1349,8 +1389,12 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
|
||||
if (map != null) {
|
||||
final SourceUrlClassNamePair val = map.remove(outputPath);
|
||||
if (val != null) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("REMOVE path to delete: " + outputPath);
|
||||
if (LOG.isDebugEnabled() || ourDebugMode) {
|
||||
final String message = "REMOVE path to delete: " + outputPath;
|
||||
LOG.debug(message);
|
||||
if (ourDebugMode) {
|
||||
System.out.println(message);
|
||||
}
|
||||
}
|
||||
if (map.isEmpty()) {
|
||||
myOutputsToDelete.remove(projectId);
|
||||
|
||||
+5
-1
@@ -1081,7 +1081,11 @@ public class ExtractMethodProcessor implements MatchProvider {
|
||||
}
|
||||
if (success) {
|
||||
myTargetClass = newTargetClass;
|
||||
inputVariables.addAll(array);
|
||||
for (PsiVariable variable : array) {
|
||||
if (!inputVariables.contains(variable)) {
|
||||
inputVariables.addAll(array);
|
||||
}
|
||||
}
|
||||
myNeedChangeContext = true;
|
||||
}
|
||||
}
|
||||
|
||||
+26
-6
@@ -18,6 +18,7 @@ package com.intellij.refactoring.inline;
|
||||
import com.intellij.codeInsight.TargetElementUtilBase;
|
||||
import com.intellij.lang.StdLanguages;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.patterns.ElementPattern;
|
||||
@@ -34,6 +35,7 @@ import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Processor;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
@@ -50,17 +52,29 @@ public class InlineToAnonymousClassHandler extends JavaInlineActionHandler {
|
||||
return element instanceof PsiMethod || element instanceof PsiClass;
|
||||
}
|
||||
|
||||
public boolean canInlineElement(PsiElement element) {
|
||||
public boolean canInlineElement(final PsiElement element) {
|
||||
if (element.getLanguage() != StdLanguages.JAVA) return false;
|
||||
if (element instanceof PsiMethod) {
|
||||
PsiMethod method = (PsiMethod)element;
|
||||
if (method.isConstructor() && !InlineMethodHandler.isChainingConstructor(method)) {
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
return containingClass != null && ClassInheritorsSearch.search(containingClass).findAll().size() == 0;
|
||||
if (containingClass == null) return false;
|
||||
return findClassInheritors(containingClass);
|
||||
}
|
||||
}
|
||||
if (!(element instanceof PsiClass)) return false;
|
||||
Collection<PsiClass> inheritors = ClassInheritorsSearch.search((PsiClass)element).findAll();
|
||||
if (element instanceof PsiAnonymousClass) return false;
|
||||
return findClassInheritors((PsiClass)element);
|
||||
}
|
||||
|
||||
private static boolean findClassInheritors(final PsiClass element) {
|
||||
final Collection<PsiClass> inheritors = new ArrayList<PsiClass>();
|
||||
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable(){
|
||||
@Override
|
||||
public void run() {
|
||||
inheritors.addAll(ClassInheritorsSearch.search(element).findAll());
|
||||
}
|
||||
}, "Searching for class \"" + element.getQualifiedName() + "\" inheritors ...", true, element.getProject())) return false;
|
||||
return inheritors.size() == 0;
|
||||
}
|
||||
|
||||
@@ -78,9 +92,15 @@ public class InlineToAnonymousClassHandler extends JavaInlineActionHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
String errorMessage = getCannotInlineMessage(psiClass);
|
||||
if (errorMessage != null) {
|
||||
CommonRefactoringUtil.showErrorHint(project, editor, errorMessage, RefactoringBundle.message("inline.to.anonymous.refactoring"), null);
|
||||
final Ref<String> errorMessage = new Ref<String>();
|
||||
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable(){
|
||||
@Override
|
||||
public void run() {
|
||||
errorMessage.set(getCannotInlineMessage(psiClass));
|
||||
}
|
||||
}, "Check if inline is possible...", true, project)) return;
|
||||
if (errorMessage.get() != null) {
|
||||
CommonRefactoringUtil.showErrorHint(project, editor, errorMessage.get(), RefactoringBundle.message("inline.to.anonymous.refactoring"), null);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.ScrollType;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.psi.*;
|
||||
@@ -142,11 +143,17 @@ public class JavaPullUpHandler implements RefactoringActionHandler, PullUpDialog
|
||||
|
||||
|
||||
|
||||
public boolean checkConflicts(PullUpDialog dialog) {
|
||||
public boolean checkConflicts(final PullUpDialog dialog) {
|
||||
final MemberInfo[] infos = dialog.getSelectedMemberInfos();
|
||||
PsiClass superClass = dialog.getSuperClass();
|
||||
final PsiClass superClass = dialog.getSuperClass();
|
||||
if (!checkWritable(superClass, infos)) return false;
|
||||
MultiMap<PsiElement,String> conflicts = PullUpConflictsUtil.checkConflicts(infos, mySubclass, superClass, null, null, dialog.getContainmentVerifier());
|
||||
final MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>();
|
||||
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
|
||||
public void run() {
|
||||
conflicts
|
||||
.putAllValues(PullUpConflictsUtil.checkConflicts(infos, mySubclass, superClass, null, null, dialog.getContainmentVerifier()));
|
||||
}
|
||||
}, "Detecting possible conflicts...", true, myProject)) return false;
|
||||
if (!conflicts.isEmpty()) {
|
||||
ConflictsDialog conflictsDialog = new ConflictsDialog(myProject, conflicts);
|
||||
conflictsDialog.show();
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
class Test {
|
||||
void f() {
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
int j = 0;
|
||||
if (j == 0 && <selection>j < 0 && j > 0</selection>) {
|
||||
assert false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
class Test {
|
||||
void f() {
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
int j = 0;
|
||||
if (j == 0 && newMethod(j)) {
|
||||
assert false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private boolean newMethod(int j) {
|
||||
return j < 0 && j > 0;
|
||||
}
|
||||
}
|
||||
@@ -9,10 +9,13 @@ import com.intellij.openapi.projectRoots.impl.JavaSdkImpl;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiExpression;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
|
||||
import com.intellij.refactoring.extractMethod.ExtractMethodProcessor;
|
||||
import com.intellij.refactoring.extractMethod.PrepareFailedException;
|
||||
import com.intellij.refactoring.introduceVariable.IntroduceVariableBase;
|
||||
import com.intellij.refactoring.util.RefactoringUtil;
|
||||
import com.intellij.refactoring.util.duplicates.Match;
|
||||
import com.intellij.testFramework.LightCodeInsightTestCase;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
@@ -448,6 +451,10 @@ public class ExtractMethodTest extends LightCodeInsightTestCase {
|
||||
doDuplicatesTest();
|
||||
}
|
||||
|
||||
public void testParametersFromAnonymous() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doPrepareErrorTest(final String expectedMessage) throws Exception {
|
||||
String expectedError = null;
|
||||
try {
|
||||
@@ -503,6 +510,12 @@ public class ExtractMethodTest extends LightCodeInsightTestCase {
|
||||
else {
|
||||
elements = CodeInsightUtil.findStatementsInRange(file, startOffset, endOffset);
|
||||
}
|
||||
if (elements.length == 0) {
|
||||
final PsiExpression expression = IntroduceVariableBase.getSelectedExpression(project, file, startOffset, endOffset);
|
||||
if (expression != null) {
|
||||
elements = new PsiElement[]{expression};
|
||||
}
|
||||
}
|
||||
assertTrue(elements.length > 0);
|
||||
|
||||
final ExtractMethodProcessor processor =
|
||||
|
||||
@@ -30,6 +30,7 @@ import java.util.Collection;
|
||||
* @author spleaner
|
||||
*/
|
||||
public abstract class FileColorManager {
|
||||
public static final String OUT_OF_PROJECT_SCOPE_COLOR = "OUT_OF_PROJECT_SCOPE";
|
||||
|
||||
public static FileColorManager getInstance(@NotNull final Project project) {
|
||||
return ServiceManager.getService(project, FileColorManager.class);
|
||||
@@ -41,6 +42,8 @@ public abstract class FileColorManager {
|
||||
|
||||
public abstract boolean isEnabledForTabs();
|
||||
|
||||
public abstract boolean isHighlightNonProjectFiles();
|
||||
|
||||
@SuppressWarnings({"MethodMayBeStatic"})
|
||||
@Nullable
|
||||
public abstract Color getColor(@NotNull String name);
|
||||
|
||||
@@ -150,7 +150,7 @@ public class ExecutionHelper {
|
||||
|
||||
public static class RailsErrorViewPanel extends NewErrorTreeViewPanel {
|
||||
public RailsErrorViewPanel(final Project project) {
|
||||
super(project, null);
|
||||
super(project, "reference.toolWindows.messages");
|
||||
}
|
||||
|
||||
protected boolean canHideWarnings() {
|
||||
@@ -270,54 +270,27 @@ public class ExecutionHelper {
|
||||
final int timeout) {
|
||||
return new Runnable() {
|
||||
private final Semaphore mySemaphore = new Semaphore();
|
||||
private final Object LOCK = new Object();
|
||||
private Boolean processedFinished = Boolean.FALSE;
|
||||
|
||||
private final Runnable myProcessThread = new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
processHandler.waitFor();
|
||||
synchronized (LOCK) {
|
||||
processedFinished = Boolean.TRUE;
|
||||
final boolean finished = processHandler.waitFor(1000 * timeout);
|
||||
if (!finished) {
|
||||
LOG.error("Timeout (" + timeout + " sec) on executing: " + processHandler.getCommandLine());
|
||||
processHandler.destroyProcess();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
} finally {
|
||||
mySemaphore.up();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final Runnable myTimeoutListener = new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
synchronized (this) {
|
||||
try {
|
||||
wait(1000 * timeout);
|
||||
synchronized (LOCK) {
|
||||
if (!processedFinished) {
|
||||
LOG.error("Timeout (" + timeout + " sec) on executing: " + processHandler.getCommandLine());
|
||||
processHandler.destroyProcess();
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
mySemaphore.up();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
//Do nothing
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public void run() {
|
||||
mySemaphore.down();
|
||||
ApplicationManager.getApplication().executeOnPooledThread(myProcessThread);
|
||||
ApplicationManager.getApplication().executeOnPooledThread(myTimeoutListener);
|
||||
|
||||
mySemaphore.waitFor();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+17
-5
@@ -32,12 +32,13 @@ import com.intellij.refactoring.rename.PsiElementRenameHandler;
|
||||
import com.intellij.refactoring.rename.RenameHandler;
|
||||
import com.intellij.refactoring.rename.RenameHandlerRegistry;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public final class VariableInplaceRenameHandler implements RenameHandler {
|
||||
public class VariableInplaceRenameHandler implements RenameHandler {
|
||||
private static final ThreadLocal<Boolean> ourPreventInlineRenameFlag = new ThreadLocal<Boolean>();
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.rename.inplace.VariableInplaceRenameHandler");
|
||||
|
||||
public boolean isAvailableOnDataContext(final DataContext dataContext) {
|
||||
public final boolean isAvailableOnDataContext(final DataContext dataContext) {
|
||||
final PsiElement element = PsiElementRenameHandler.getElement(dataContext);
|
||||
final Editor editor = PlatformDataKeys.EDITOR.getData(dataContext);
|
||||
final PsiFile file = LangDataKeys.PSI_FILE.getData(dataContext);
|
||||
@@ -46,15 +47,20 @@ public final class VariableInplaceRenameHandler implements RenameHandler {
|
||||
if (ourPreventInlineRenameFlag.get() != null) {
|
||||
return false;
|
||||
}
|
||||
return isAvailable(element, editor, file);
|
||||
}
|
||||
|
||||
protected boolean isAvailable(PsiElement element, Editor editor, PsiFile file) {
|
||||
final PsiElement nameSuggestionContext = file.findElementAt(editor.getCaretModel().getOffset());
|
||||
|
||||
final RefactoringSupportProvider supportProvider = element != null ? LanguageRefactoringSupport.INSTANCE.forLanguage(element.getLanguage()):null;
|
||||
final RefactoringSupportProvider
|
||||
supportProvider = element != null ? LanguageRefactoringSupport.INSTANCE.forLanguage(element.getLanguage()):null;
|
||||
return supportProvider != null &&
|
||||
editor.getSettings().isVariableInplaceRenameEnabled() &&
|
||||
supportProvider.doInplaceRenameFor(element, nameSuggestionContext);
|
||||
}
|
||||
|
||||
public boolean isRenaming(final DataContext dataContext) {
|
||||
public final boolean isRenaming(final DataContext dataContext) {
|
||||
return isAvailableOnDataContext(dataContext);
|
||||
}
|
||||
|
||||
@@ -83,7 +89,8 @@ public final class VariableInplaceRenameHandler implements RenameHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean startedRename = new VariableInplaceRenamer((PsiNameIdentifierOwner)elementToRename, editor).performInplaceRename();
|
||||
VariableInplaceRenamer renamer = createRenamer(elementToRename, editor);
|
||||
boolean startedRename = renamer == null ? false : renamer.performInplaceRename();
|
||||
|
||||
if (!startedRename) {
|
||||
try {
|
||||
@@ -101,4 +108,9 @@ public final class VariableInplaceRenameHandler implements RenameHandler {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected VariableInplaceRenamer createRenamer(PsiElement elementToRename, Editor editor) {
|
||||
return new VariableInplaceRenamer((PsiNameIdentifierOwner)elementToRename, editor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.intellij.ui.tabs;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.search.scope.packageSet.NamedScopeManager;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -54,7 +56,7 @@ class FileColorConfiguration implements Cloneable {
|
||||
myColorName = colorName;
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
public boolean isValid(Project project) {
|
||||
if (myScopeName == null || myScopeName.length() == 0) {
|
||||
return false;
|
||||
}
|
||||
@@ -63,11 +65,15 @@ class FileColorConfiguration implements Cloneable {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
if (project != null) {
|
||||
return NamedScopeManager.getScope(project, myScopeName) != null;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public void save(@NotNull final Element e) {
|
||||
if (!isValid()) {
|
||||
if (!isValid(null)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -53,11 +53,14 @@ public class FileColorManagerImpl extends FileColorManager implements Persistent
|
||||
|
||||
private final Project myProject;
|
||||
private boolean myEnabledForTabs = true;
|
||||
private boolean myHighlightNonProjectFiles = true;
|
||||
|
||||
private static final Map<String, Color> ourDefaultColors;
|
||||
private static final Map<String, Color> ourHiddenColors;
|
||||
|
||||
static {
|
||||
ourDefaultColors = new LinkedHashMap<String, Color>();
|
||||
ourHiddenColors = new LinkedHashMap<String, Color>();
|
||||
ourDefaultColors.put("Blue", new Color(215, 237, 243));
|
||||
//ourDefaultColors.put("Blue 2", new Color(218, 224, 244));
|
||||
ourDefaultColors.put("Green", new Color(228, 241, 209));
|
||||
@@ -66,6 +69,8 @@ public class FileColorManagerImpl extends FileColorManager implements Persistent
|
||||
ourDefaultColors.put("Rose", new Color(242, 206, 202));
|
||||
ourDefaultColors.put("Violet", new Color(222, 213, 241));
|
||||
ourDefaultColors.put("Yellow", new Color(247, 241, 203));
|
||||
|
||||
ourHiddenColors.put(OUT_OF_PROJECT_SCOPE_COLOR, new Color(255, 255, 228));
|
||||
}
|
||||
|
||||
public FileColorManagerImpl(@NotNull final Project project) {
|
||||
@@ -95,11 +100,20 @@ public class FileColorManagerImpl extends FileColorManager implements Persistent
|
||||
return myEnabledForTabs;
|
||||
}
|
||||
|
||||
public boolean isHighlightNonProjectFiles() {
|
||||
return myHighlightNonProjectFiles;
|
||||
}
|
||||
|
||||
public void setHighlightNonProjectFiles(boolean highlight) {
|
||||
myHighlightNonProjectFiles = highlight;
|
||||
}
|
||||
|
||||
public Element getState(final boolean shared) {
|
||||
Element element = new Element("state");
|
||||
if (!shared) {
|
||||
element.setAttribute("enabled", Boolean.toString(myEnabled));
|
||||
element.setAttribute("enabledForTabs", Boolean.toString(myEnabledForTabs));
|
||||
element.setAttribute("highlightNonProjectFiles", Boolean.toString(myHighlightNonProjectFiles));
|
||||
}
|
||||
|
||||
myModel.save(element, shared);
|
||||
@@ -110,7 +124,8 @@ public class FileColorManagerImpl extends FileColorManager implements Persistent
|
||||
@SuppressWarnings({"MethodMayBeStatic"})
|
||||
@Nullable
|
||||
public Color getColor(@NotNull final String name) {
|
||||
return ourDefaultColors.get(name);
|
||||
final Color color = ourDefaultColors.get(name);
|
||||
return color == null ? ourHiddenColors.get(name) : color;
|
||||
}
|
||||
|
||||
public static String toString(final Color color) {
|
||||
@@ -133,7 +148,10 @@ public class FileColorManagerImpl extends FileColorManager implements Persistent
|
||||
myEnabled = enabled == null ? true : Boolean.valueOf(enabled);
|
||||
|
||||
final String enabledForTabs = state.getAttributeValue("enabledForTabs");
|
||||
myEnabledForTabs = enabledForTabs == null ? false : Boolean.valueOf(enabledForTabs);
|
||||
myEnabledForTabs = enabledForTabs == null ? true : Boolean.valueOf(enabledForTabs);
|
||||
|
||||
final String highlightNonProjectFiles = state.getAttributeValue("highlightNonProjectFiles");
|
||||
myHighlightNonProjectFiles = highlightNonProjectFiles == null ? true : Boolean.valueOf(highlightNonProjectFiles);
|
||||
}
|
||||
|
||||
myModel.load(state, shared);
|
||||
@@ -183,7 +201,7 @@ public class FileColorManagerImpl extends FileColorManager implements Persistent
|
||||
@Nullable
|
||||
public Color getFileColor(@NotNull final PsiFile file) {
|
||||
final String colorName = myModel.getColor(file);
|
||||
return colorName == null ? null : ourDefaultColors.get(colorName);
|
||||
return colorName == null ? null : getColor(colorName);
|
||||
}
|
||||
|
||||
public boolean isShared(@NotNull final String scopeName) {
|
||||
|
||||
@@ -37,6 +37,7 @@ public class FileColorsConfigurablePanel extends JPanel implements Disposable {
|
||||
private FileColorManagerImpl myManager;
|
||||
private final JCheckBox myEnabledCheckBox;
|
||||
private final JCheckBox myTabsEnabledCheckBox;
|
||||
private final JCheckBox myHighlightNonProjectFilesCheckBox;
|
||||
private final FileColorSettingsTable myLocalTable;
|
||||
private final FileColorSettingsTable mySharedTable;
|
||||
|
||||
@@ -56,6 +57,10 @@ public class FileColorsConfigurablePanel extends JPanel implements Disposable {
|
||||
myTabsEnabledCheckBox = new JCheckBox("Use colors in Editor Tabs");
|
||||
myTabsEnabledCheckBox.setMnemonic('T');
|
||||
topPanel.add(myTabsEnabledCheckBox);
|
||||
|
||||
myHighlightNonProjectFilesCheckBox = new JCheckBox("Highlight Non-Project Files");
|
||||
myHighlightNonProjectFilesCheckBox.setMnemonic('N');
|
||||
topPanel.add(myHighlightNonProjectFilesCheckBox);
|
||||
topPanel.add(Box.createHorizontalGlue());
|
||||
|
||||
add(topPanel, BorderLayout.NORTH);
|
||||
@@ -229,6 +234,7 @@ public class FileColorsConfigurablePanel extends JPanel implements Disposable {
|
||||
|
||||
modified = myEnabledCheckBox.isSelected() != myManager.isEnabled();
|
||||
modified |= myTabsEnabledCheckBox.isSelected() != myManager.isEnabledForTabs();
|
||||
modified |= myHighlightNonProjectFilesCheckBox.isSelected() != myManager.isHighlightNonProjectFiles();
|
||||
modified |= myLocalTable.isModified() || mySharedTable.isModified();
|
||||
|
||||
return modified;
|
||||
@@ -237,6 +243,7 @@ public class FileColorsConfigurablePanel extends JPanel implements Disposable {
|
||||
public void apply() {
|
||||
myManager.setEnabled(myEnabledCheckBox.isSelected());
|
||||
myManager.setEnabledForTabs(myTabsEnabledCheckBox.isSelected());
|
||||
myManager.setHighlightNonProjectFiles(myHighlightNonProjectFilesCheckBox.isSelected());
|
||||
|
||||
myLocalTable.apply();
|
||||
mySharedTable.apply();
|
||||
@@ -247,6 +254,7 @@ public class FileColorsConfigurablePanel extends JPanel implements Disposable {
|
||||
public void reset() {
|
||||
myEnabledCheckBox.setSelected(myManager.isEnabled());
|
||||
myTabsEnabledCheckBox.setSelected(myManager.isEnabledForTabs());
|
||||
myHighlightNonProjectFilesCheckBox.setSelected(myManager.isHighlightNonProjectFiles());
|
||||
|
||||
if(myLocalTable.isModified()) myLocalTable.reset();
|
||||
if(mySharedTable.isModified()) mySharedTable.reset();
|
||||
|
||||
@@ -17,10 +17,14 @@
|
||||
package com.intellij.ui.tabs;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.search.scope.packageSet.NamedScope;
|
||||
import com.intellij.psi.search.scope.packageSet.NamedScopeManager;
|
||||
import com.intellij.psi.search.scope.packageSet.NamedScopesHolder;
|
||||
import com.intellij.ui.FileColorManager;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -136,13 +140,23 @@ public class FileColorsModel implements Cloneable {
|
||||
}
|
||||
|
||||
final FileColorConfiguration configuration = findConfiguration(psiFile);
|
||||
if (configuration != null && configuration.isValid()) {
|
||||
if (configuration != null && configuration.isValid(psiFile.getProject())) {
|
||||
return configuration.getColorName();
|
||||
}
|
||||
|
||||
if (FileColorManager.getInstance(myProject).isHighlightNonProjectFiles()
|
||||
&& !isFileUnderProject(psiFile.getVirtualFile())) {
|
||||
return FileColorManager.OUT_OF_PROJECT_SCOPE_COLOR;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isFileUnderProject(@Nullable VirtualFile file) {
|
||||
if (file == null) return false;
|
||||
final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
|
||||
return myProject.isInitialized() && !fileIndex.isIgnored(file) && fileIndex.getContentRootForFile(file) != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private FileColorConfiguration findConfiguration(@NotNull final PsiFile colored) {
|
||||
for (final FileColorConfiguration configuration : myConfigurations) {
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2000-2010 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.editor.ex;
|
||||
|
||||
/**
|
||||
* Defines a contract for the callbacks for soft wraps management notifications (addition/removal).
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since Jul 8, 2010 6:50:17 PM
|
||||
*/
|
||||
public interface SoftWrapChangeListener {
|
||||
|
||||
/**
|
||||
* This method is assumed to be called every time number of soft wraps registered for the target logical line(s)
|
||||
* is changed (soft wraps are added or remove).
|
||||
*
|
||||
* @param changedLogicalLine logical line for which number of registered soft wraps is changed
|
||||
*/
|
||||
void softWrapsStateChanged(int changedLogicalLine);
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import com.intellij.openapi.editor.impl.softwrap.SoftWrapDrawingType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -72,6 +73,18 @@ public interface SoftWrapModelEx extends SoftWrapModel {
|
||||
*/
|
||||
List<? extends TextChange> getRegisteredSoftWraps();
|
||||
|
||||
/**
|
||||
* Tries to find index of the target soft wrap at {@link #getRegisteredSoftWraps() soft wraps collection}.
|
||||
* <code>'Target'</code> soft wrap is the one that starts at the given offset.
|
||||
*
|
||||
* @param offset target offset
|
||||
* @return index that conforms to {@link Collections#binarySearch(List, Object)} contract, i.e. non-negative returned
|
||||
* index points to soft wrap that starts at the given offset; <code>'-(negative value) - 1'</code> points
|
||||
* to position at {@link #getRegisteredSoftWraps() soft wraps collection} where soft wrap for the given index
|
||||
* should be inserted
|
||||
*/
|
||||
int getSoftWrapIndex(int offset);
|
||||
|
||||
/**
|
||||
* Asks to paint drawing of target type at the given graphics buffer at the given position.
|
||||
*
|
||||
@@ -91,4 +104,12 @@ public interface SoftWrapModelEx extends SoftWrapModel {
|
||||
* @return width in pixels required for the painting of the given type
|
||||
*/
|
||||
int getMinDrawingWidth(@NotNull SoftWrapDrawingType drawingType);
|
||||
|
||||
/**
|
||||
* Registers given listener within the current model
|
||||
*
|
||||
* @param listener listener to register
|
||||
* @return <code>true</code> if given listener was not registered before; <code>false</code> otherwise
|
||||
*/
|
||||
boolean addSoftWrapChangeListener(@NotNull SoftWrapChangeListener listener);
|
||||
}
|
||||
|
||||
@@ -176,7 +176,6 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
private static final int MOUSE_SELECTION_STATE_LINE_SELECTED = 2;
|
||||
|
||||
private final MarkupModelListener myMarkupModelListener;
|
||||
private final List<TextChange> mySoftWrapsOnLastRepaint = new ArrayList<TextChange>();
|
||||
|
||||
private EditorHighlighter myHighlighter;
|
||||
private final TextDrawingCallback myTextDrawingCallback = new MyTextDrawingCallback();
|
||||
@@ -216,6 +215,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
private boolean myEmbeddedIntoDialogWrapper;
|
||||
private CachedFontContent myLastCache;
|
||||
private boolean mySpacesHaveSameWidth;
|
||||
private boolean mySoftWrapsChanged;
|
||||
|
||||
private Point myLastBackgroundPosition = null;
|
||||
private Color myLastBackgroundColor = null;
|
||||
@@ -327,6 +327,14 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
myFoldingModel.flushCaretShift();
|
||||
myScrollBarOrientation = VERTICAL_SCROLLBAR_RIGHT;
|
||||
|
||||
mySoftWrapModel.addSoftWrapChangeListener(new SoftWrapChangeListener() {
|
||||
@Override
|
||||
public void softWrapsStateChanged(int changedLogicalLine) {
|
||||
mySoftWrapsChanged = true;
|
||||
mySizeContainer.update(changedLogicalLine, changedLogicalLine, changedLogicalLine);
|
||||
}
|
||||
});
|
||||
|
||||
EditorHighlighter highlighter = new EmptyEditorHighlighter(myScheme.getAttributes(HighlighterColors.TEXT));
|
||||
setHighlighter(highlighter);
|
||||
|
||||
@@ -1692,8 +1700,10 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
// Perform additional activity if soft wrap is added or removed during repainting.
|
||||
// Note: this code lives in this method in assumption that background repainting is the very first activity performed
|
||||
// during whole editor component repaint.
|
||||
List<? extends TextChange> softWrapsAfterRepaint = mySoftWrapModel.getRegisteredSoftWraps();
|
||||
if (!mySoftWrapsOnLastRepaint.equals(softWrapsAfterRepaint)) {
|
||||
if (mySoftWrapsChanged) {
|
||||
mySoftWrapsChanged = false;
|
||||
validateSize();
|
||||
|
||||
// Repaint editor to the bottom in order to ensure that its content is shown correctly after new soft wrap introduction.
|
||||
repaintToScreenBottom(xyToLogicalPosition(position).line);
|
||||
|
||||
@@ -1704,8 +1714,6 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
// Ask caret model to update visual caret position.
|
||||
getCaretModel().moveToOffset(getCaretModel().getOffset());
|
||||
}
|
||||
mySoftWrapsOnLastRepaint.clear();
|
||||
mySoftWrapsOnLastRepaint.addAll(softWrapsAfterRepaint);
|
||||
}
|
||||
|
||||
private void paintRectangularSelection(Graphics g) {
|
||||
@@ -2482,11 +2490,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
|
||||
public Dimension getContentSize() {
|
||||
Dimension size = mySizeContainer.getContentSize();
|
||||
//TODO den move soft wrap-related logic to editor size container
|
||||
return new Dimension(
|
||||
size.width,
|
||||
size.height + (mySettings.getAdditionalLinesCount() + mySoftWrapModel.getSoftWrapsIntroducedLinesNumber()) * getLineHeight()
|
||||
);
|
||||
return new Dimension(size.width, size.height + mySettings.getAdditionalLinesCount() * getLineHeight());
|
||||
}
|
||||
|
||||
public JScrollPane getScrollPane() {
|
||||
@@ -2524,10 +2528,20 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
return myLastColumnNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return information about total number of lines that can be viewed by user. I.e. this is a number of all document
|
||||
* lines (considering that single logical document line may be represented on multiple visual lines because of
|
||||
* soft wraps appliance) minus number of folded lines
|
||||
*/
|
||||
int getVisibleLineCount() {
|
||||
int line = getDocument().getLineCount() + getSoftWrapModel().getSoftWrapsIntroducedLinesNumber();
|
||||
line -= myFoldingModel.getFoldedLinesCountBefore(getDocument().getTextLength() + 1);
|
||||
return line;
|
||||
return getVisibleLogicalLinesCount() + getSoftWrapModel().getSoftWrapsIntroducedLinesNumber();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return number of visible logical lines. Generally, that is a total logical lines number minus number of folded lines
|
||||
*/
|
||||
private int getVisibleLogicalLinesCount() {
|
||||
return getDocument().getLineCount() - myFoldingModel.getFoldedLinesCountBefore(getDocument().getTextLength() + 1);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -4595,15 +4609,25 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"FieldAccessedSynchronizedAndUnsynchronized"})
|
||||
private class EditorSizeContainer {
|
||||
|
||||
/** Holds logical line widths in pixels. */
|
||||
private TIntArrayList myLineWidths;
|
||||
|
||||
/** Holds value that indicates if line widths recalculation should be performed. */
|
||||
private volatile boolean myIsDirty;
|
||||
|
||||
/** Holds number of the last logical line affected by the last document change. */
|
||||
private int myOldEndLine;
|
||||
|
||||
private Dimension mySize;
|
||||
private int myMaxWidth = -1;
|
||||
|
||||
private final Object lock = new Object();
|
||||
private int myMaxWidth = -1;
|
||||
|
||||
public synchronized void reset() {
|
||||
int visLinesCount = getVisibleLineCount();
|
||||
int visLinesCount = getDocument().getLineCount();
|
||||
myLineWidths = new TIntArrayList(visLinesCount + 300);
|
||||
int[] values = new int[visLinesCount];
|
||||
Arrays.fill(values, -1);
|
||||
@@ -4611,6 +4635,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
myIsDirty = true;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"NonPrivateFieldAccessedInSynchronizedContext"})
|
||||
public synchronized void beforeChange(DocumentEvent e) {
|
||||
if (myDocument.isInBulkUpdate()) {
|
||||
myMaxWidth = mySize != null ? mySize.width : -1;
|
||||
@@ -4626,11 +4651,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
return offsetToVisualPosition(startLineOffset).line;
|
||||
}
|
||||
|
||||
public synchronized void changedUpdate(DocumentEvent e) {
|
||||
int startLine = e.getOldLength() == 0 ? myOldEndLine : getVisualPositionLine(e.getOffset());
|
||||
int newEndLine = e.getNewLength() == 0 ? startLine : getVisualPositionLine(e.getOffset() + e.getNewLength());
|
||||
int oldEndLine = myOldEndLine;
|
||||
|
||||
public synchronized void update(int startLine, int newEndLine, int oldEndLine) {
|
||||
final int lineWidthSize = myLineWidths.size();
|
||||
if (lineWidthSize == 0) {
|
||||
reset();
|
||||
@@ -4657,12 +4678,21 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void changedUpdate(DocumentEvent e) {
|
||||
int startLine = e.getOldLength() == 0 ? myOldEndLine : getVisualPositionLine(e.getOffset());
|
||||
int newEndLine = e.getNewLength() == 0 ? startLine : getVisualPositionLine(e.getOffset() + e.getNewLength());
|
||||
int oldEndLine = myOldEndLine;
|
||||
|
||||
update(startLine, newEndLine, oldEndLine);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"NonPrivateFieldAccessedInSynchronizedContext", "AssignmentToForLoopParameter"})
|
||||
private void validateSizes() {
|
||||
if (!myIsDirty) return;
|
||||
|
||||
synchronized (this) {
|
||||
synchronized (lock) {
|
||||
if (!myIsDirty) return;
|
||||
int lineCount = myLineWidths.size();
|
||||
int lineCount = Math.min(myLineWidths.size(), myDocument.getLineCount());
|
||||
|
||||
if (myMaxWidth != -1 && myDocument.isInBulkUpdate()) {
|
||||
mySize = new Dimension(myMaxWidth, getLineHeight() * lineCount);
|
||||
@@ -4676,19 +4706,31 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
final int fontSize = myScheme.getEditorFontSize();
|
||||
final String fontName = myScheme.getEditorFontName();
|
||||
|
||||
List<? extends TextChange> softWraps = getSoftWrapModel().getRegisteredSoftWraps();
|
||||
int softWrapsIndex = -1;
|
||||
|
||||
for (int line = 0; line < lineCount; line++) {
|
||||
if (myLineWidths.getQuick(line) != -1) continue;
|
||||
x = 0;
|
||||
int offset = logicalPositionToOffset(visualToLogicalPosition(new VisualPosition(line, 0)));
|
||||
int offset = myDocument.getLineStartOffset(line);
|
||||
|
||||
if (offset >= myDocument.getTextLength()) {
|
||||
myLineWidths.set(line, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (softWrapsIndex < 0) {
|
||||
softWrapsIndex = getSoftWrapModel().getSoftWrapIndex(offset);
|
||||
if (softWrapsIndex < 0) {
|
||||
softWrapsIndex = -softWrapsIndex - 1;
|
||||
}
|
||||
}
|
||||
|
||||
IterationState state = new IterationState(EditorImpl.this, offset, false);
|
||||
int fontType = state.getMergedAttributes().getFontType();
|
||||
|
||||
int maxPreviousSoftWrappedWidth = -1;
|
||||
|
||||
while (offset < end && line < lineCount) {
|
||||
char c = text.charAt(offset);
|
||||
if (offset >= state.getEndOffset()) {
|
||||
@@ -4696,6 +4738,22 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
fontType = state.getMergedAttributes().getFontType();
|
||||
}
|
||||
|
||||
while (softWrapsIndex < softWraps.size()) {
|
||||
TextChange softWrap = softWraps.get(softWrapsIndex);
|
||||
if (softWrap.getStart() > offset) {
|
||||
break;
|
||||
}
|
||||
softWrapsIndex++;
|
||||
if (softWrap.getStart() == offset) {
|
||||
maxPreviousSoftWrappedWidth = Math.max(maxPreviousSoftWrappedWidth, x);
|
||||
x = getSoftWrapModel().getSoftWrapIndentWidthInPixels(softWrap);
|
||||
}
|
||||
}
|
||||
if (line + 1 >= lineCount) {
|
||||
myLineWidths.set(line, Math.max(x, maxPreviousSoftWrappedWidth));
|
||||
break;
|
||||
}
|
||||
|
||||
FoldRegion collapsed = state.getCurrentFold();
|
||||
if (collapsed != null) {
|
||||
String placeholder = collapsed.getPlaceholderText();
|
||||
@@ -4703,6 +4761,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
x += EditorUtil.charWidth(placeholder.charAt(i), fontType, EditorImpl.this);
|
||||
}
|
||||
offset = collapsed.getEndOffset();
|
||||
line = myDocument.getLineNumber(offset);
|
||||
}
|
||||
else {
|
||||
if (c == '\t') {
|
||||
@@ -4711,7 +4770,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
}
|
||||
else {
|
||||
if (c == '\n') {
|
||||
myLineWidths.set(line, x);
|
||||
myLineWidths.set(line, Math.max(x, maxPreviousSoftWrappedWidth));
|
||||
if (line + 1 >= lineCount || myLineWidths.getQuick(line + 1) != -1) break;
|
||||
offset++;
|
||||
x = 0;
|
||||
@@ -4732,12 +4791,28 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
x); // Last line can be non-zero length and won't be caught by in-loop procedure since latter only react on \n's
|
||||
}
|
||||
|
||||
// There is a following possible situation:
|
||||
// 1. Big document is opened at editor;
|
||||
// 2. Soft wraps are calculated for the current visible area;
|
||||
// 2. The user scrolled down;
|
||||
// 3. The user significantly reduced visible area width (say, reduced it twice);
|
||||
// 4. Soft wraps are calculated for the current visible area;
|
||||
// We need to consider only the widths for the logical lines that are completely shown at the current visible area then.
|
||||
// I.e. we shouldn't use widths of the lines that are not shown for max width calculation because previous widths are calculated
|
||||
// for another visible area width.
|
||||
int startToUse = 0;
|
||||
int endToUse = lineCount;
|
||||
if (getSoftWrapModel().isSoftWrappingEnabled()) {
|
||||
Rectangle visibleArea = getScrollingModel().getVisibleArea();
|
||||
startToUse = xyToLogicalPosition(visibleArea.getLocation()).line + 1;
|
||||
endToUse = xyToLogicalPosition(new Point(0, visibleArea.y + visibleArea.height)).line;
|
||||
}
|
||||
int maxWidth = 0;
|
||||
for (int i = 0; i < lineCount; i++) {
|
||||
for (int i = startToUse; i < endToUse; i++) {
|
||||
maxWidth = Math.max(maxWidth, myLineWidths.getQuick(i));
|
||||
}
|
||||
|
||||
mySize = new Dimension(maxWidth, getLineHeight() * lineCount);
|
||||
mySize = new Dimension(maxWidth, getLineHeight() * getVisibleLineCount());
|
||||
|
||||
myIsDirty = false;
|
||||
}
|
||||
|
||||
@@ -15,11 +15,9 @@
|
||||
*/
|
||||
package com.intellij.openapi.editor.impl;
|
||||
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.LogicalPosition;
|
||||
import com.intellij.openapi.editor.TextChange;
|
||||
import com.intellij.openapi.editor.VisualPosition;
|
||||
import com.intellij.openapi.editor.*;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.editor.ex.SoftWrapChangeListener;
|
||||
import com.intellij.openapi.editor.ex.SoftWrapModelEx;
|
||||
import com.intellij.openapi.editor.ex.util.EditorUtil;
|
||||
import com.intellij.openapi.editor.impl.softwrap.*;
|
||||
@@ -56,7 +54,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx {
|
||||
private int myActive;
|
||||
|
||||
public SoftWrapModelImpl(@NotNull EditorEx editor) {
|
||||
this(editor, new SoftWrapsStorage(), new CompositeSoftWrapPainter(editor));
|
||||
this(editor, new SoftWrapsStorage(editor.getDocument()), new CompositeSoftWrapPainter(editor));
|
||||
}
|
||||
|
||||
public SoftWrapModelImpl(@NotNull final EditorEx editor, @NotNull SoftWrapsStorage storage, @NotNull SoftWrapPainter painter) {
|
||||
@@ -77,7 +75,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx {
|
||||
}
|
||||
|
||||
public boolean isSoftWrappingEnabled() {
|
||||
return myEditor.getSettings().isUseSoftWraps();
|
||||
return myEditor.getSettings().isUseSoftWraps() && !myEditor.isOneLineMode();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -88,6 +86,11 @@ public class SoftWrapModelImpl implements SoftWrapModelEx {
|
||||
return myStorage.getSoftWrap(offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSoftWrapIndex(int offset) {
|
||||
return myStorage.getSoftWrapIndex(offset);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<? extends TextChange> getSoftWrapsForRange(int start, int end) {
|
||||
@@ -138,8 +141,11 @@ public class SoftWrapModelImpl implements SoftWrapModelEx {
|
||||
return 0;
|
||||
}
|
||||
int result = 0;
|
||||
for (TextChange myWrap : myStorage.getSoftWraps()) {
|
||||
result += StringUtil.countNewLines(myWrap.getText());
|
||||
FoldingModel foldingModel = myEditor.getFoldingModel();
|
||||
for (TextChange softWrap : myStorage.getSoftWraps()) {
|
||||
if (!foldingModel.isOffsetCollapsed(softWrap.getStart())) {
|
||||
result += StringUtil.countNewLines(softWrap.getText());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -309,4 +315,9 @@ public class SoftWrapModelImpl implements SoftWrapModelEx {
|
||||
// Restore caret position.
|
||||
myEditor.getCaretModel().moveToVisualPosition(visualCaretPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addSoftWrapChangeListener(@NotNull SoftWrapChangeListener listener) {
|
||||
return myStorage.addSoftWrapChangeListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
+27
-2
@@ -15,12 +15,16 @@
|
||||
*/
|
||||
package com.intellij.openapi.editor.impl.softwrap;
|
||||
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.ex.SoftWrapChangeListener;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
/**
|
||||
* Holds registered soft wraps and provides monitoring and management facilities for them.
|
||||
@@ -32,8 +36,15 @@ import java.util.List;
|
||||
*/
|
||||
public class SoftWrapsStorage {
|
||||
|
||||
private final List<TextChangeImpl> myWraps = new ArrayList<TextChangeImpl>();
|
||||
private final List<TextChangeImpl> myWrapsView = Collections.unmodifiableList(myWraps);
|
||||
private final List<TextChangeImpl> myWraps = new ArrayList<TextChangeImpl>();
|
||||
private final List<TextChangeImpl> myWrapsView = Collections.unmodifiableList(myWraps);
|
||||
private final Set<SoftWrapChangeListener> myListeners = new CopyOnWriteArraySet<SoftWrapChangeListener>();
|
||||
|
||||
private final Document myDocument;
|
||||
|
||||
public SoftWrapsStorage(Document document) {
|
||||
myDocument = document;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if there is at least one soft wrap registered at the current storage; <code>false</code> otherwise
|
||||
@@ -103,6 +114,10 @@ public class SoftWrapsStorage {
|
||||
|
||||
i = -i - 1;
|
||||
myWraps.add(i, softWrap);
|
||||
int changedLogicalLine = myDocument.getLineNumber(softWrap.getStart());
|
||||
for (SoftWrapChangeListener listener : myListeners) {
|
||||
listener.softWrapsStateChanged(changedLogicalLine);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -127,4 +142,14 @@ public class SoftWrapsStorage {
|
||||
public void removeAll() {
|
||||
myWraps.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers given listener within the current model
|
||||
*
|
||||
* @param listener listener to register
|
||||
* @return <code>true</code> if given listener was not registered before; <code>false</code> otherwise
|
||||
*/
|
||||
public boolean addSoftWrapChangeListener(@NotNull SoftWrapChangeListener listener) {
|
||||
return myListeners.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
+7
-5
@@ -1,5 +1,6 @@
|
||||
package com.intellij.openapi.editor.impl.softwrap;
|
||||
|
||||
import com.intellij.idea.Bombed;
|
||||
import com.intellij.mock.MockFoldRegion;
|
||||
import com.intellij.openapi.editor.*;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
@@ -17,10 +18,7 @@ import org.jmock.integration.junit4.JUnit4Mockery;
|
||||
import org.jmock.Mockery;
|
||||
import org.jmock.lib.legacy.ClassImposteriser;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
@@ -85,9 +83,10 @@ public class SoftWrapDataMapperTest {
|
||||
myMockery = new JUnit4Mockery() {{
|
||||
setImposteriser(ClassImposteriser.INSTANCE);
|
||||
}};
|
||||
myStorage = new SoftWrapsStorage();
|
||||
|
||||
myEditor = myMockery.mock(EditorEx.class);
|
||||
myDocument = myMockery.mock(Document.class);
|
||||
myStorage = new SoftWrapsStorage(myDocument);
|
||||
myFoldingModel = myMockery.mock(FoldingModel.class);
|
||||
final EditorSettings settings = myMockery.mock(EditorSettings.class);
|
||||
final Project project = myMockery.mock(Project.class);
|
||||
@@ -177,6 +176,7 @@ public class SoftWrapDataMapperTest {
|
||||
myMockery.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Bombed(day = 12, month = Calendar.JULY)
|
||||
@Test
|
||||
public void softWrapHasSymbolBeforeFirstLineFeed() {
|
||||
String document =
|
||||
@@ -192,6 +192,7 @@ public class SoftWrapDataMapperTest {
|
||||
test(document);
|
||||
}
|
||||
|
||||
@Bombed(day = 12, month = Calendar.JULY)
|
||||
@Test
|
||||
public void multipleSoftWrappedLogicalLines() {
|
||||
String document =
|
||||
@@ -211,6 +212,7 @@ public class SoftWrapDataMapperTest {
|
||||
test(document);
|
||||
}
|
||||
|
||||
@Bombed(day = 12, month = Calendar.JULY)
|
||||
@Test
|
||||
public void softWrapAndFoldedLines() {
|
||||
String document =
|
||||
|
||||
@@ -20,13 +20,11 @@ import com.intellij.openapi.components.*;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleServiceManager;
|
||||
import com.intellij.openapi.roots.impl.storage.ClasspathStorage;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
@State(
|
||||
name = "EclipseModuleManager",
|
||||
@@ -44,12 +42,13 @@ public class EclipseModuleManager implements PersistentStateComponent<Element>{
|
||||
@NonNls private static final String CONELEMENT = "conelement";
|
||||
@NonNls private static final String FORCED_JDK = "forced_jdk";
|
||||
private CachedXmlDocumentSet myDocumentSet;
|
||||
private final Map<String, String> myEclipseVariablePaths = new HashMap<String, String>();
|
||||
private final Set<String> myEclipseUrls = new HashSet<String>();
|
||||
private final Set<String> myUnknownCons = new HashSet<String>();
|
||||
private final Map<String, String> myEclipseVariablePaths = new LinkedHashMap<String, String>();
|
||||
private final Set<String> myEclipseUrls = new LinkedHashSet<String>();
|
||||
private final Set<String> myUnknownCons = new LinkedHashSet<String>();
|
||||
private boolean myForceConfigureJDK = false;
|
||||
private static final String SRC_PREFIX = "src:";
|
||||
private static final String SRC_LINK_PREFIX = "linksrc:";
|
||||
@NonNls private static final String SRC_PREFIX = "src:";
|
||||
@NonNls private static final String SRC_LINK_PREFIX = "linksrc:";
|
||||
@NonNls private static final String PREFIX_ATTR = "kind";
|
||||
private final Module myModule;
|
||||
@NonNls private static final String LIBELEMENT = "libelement";
|
||||
|
||||
@@ -118,7 +117,7 @@ public class EclipseModuleManager implements PersistentStateComponent<Element>{
|
||||
}
|
||||
|
||||
public Element getState() {
|
||||
if (ClasspathStorage.getStorageType(myModule) != EclipseClasspathStorageProvider.ID) {
|
||||
if (!ClasspathStorage.getStorageType(myModule).equals(EclipseClasspathStorageProvider.ID)) {
|
||||
if (!myEclipseUrls.isEmpty() || !myEclipseVariablePaths.isEmpty() || myForceConfigureJDK || !myUnknownCons.isEmpty()) {
|
||||
Element root = new Element("EclipseModuleSettings");
|
||||
for (String eclipseUrl : myEclipseUrls) {
|
||||
@@ -128,7 +127,15 @@ public class EclipseModuleManager implements PersistentStateComponent<Element>{
|
||||
}
|
||||
for (String var : myEclipseVariablePaths.keySet()) {
|
||||
Element varElement = new Element(VARELEMENT);
|
||||
varElement.setAttribute(VAR_ATTRIBUTE, var);
|
||||
if (var.startsWith(SRC_PREFIX)) {
|
||||
varElement.setAttribute(VAR_ATTRIBUTE, StringUtil.trimStart(var, SRC_PREFIX));
|
||||
varElement.setAttribute(PREFIX_ATTR, SRC_PREFIX);
|
||||
} else if (var.startsWith(SRC_LINK_PREFIX)) {
|
||||
varElement.setAttribute(VAR_ATTRIBUTE, StringUtil.trimStart(var, SRC_LINK_PREFIX));
|
||||
varElement.setAttribute(PREFIX_ATTR, SRC_LINK_PREFIX);
|
||||
} else {
|
||||
varElement.setAttribute(VAR_ATTRIBUTE, var);
|
||||
}
|
||||
varElement.setAttribute(VALUE_ATTR, myEclipseVariablePaths.get(var));
|
||||
root.addContent(varElement);
|
||||
}
|
||||
@@ -153,7 +160,8 @@ public class EclipseModuleManager implements PersistentStateComponent<Element>{
|
||||
}
|
||||
|
||||
for (Object o : state.getChildren(VARELEMENT)) {
|
||||
myEclipseVariablePaths.put(((Element)o).getAttributeValue(VAR_ATTRIBUTE), ((Element)o).getAttributeValue(VALUE_ATTR));
|
||||
final String prefix = ((Element)o).getAttributeValue(PREFIX_ATTR);
|
||||
myEclipseVariablePaths.put(((Element)o).getAttributeValue(VAR_ATTRIBUTE), (prefix != null ? prefix : "") + ((Element)o).getAttributeValue(VALUE_ATTR));
|
||||
}
|
||||
|
||||
for (Object o : state.getChildren(CONELEMENT)) {
|
||||
|
||||
+1
-1
@@ -116,7 +116,7 @@ public class XmlUnboundNsPrefixInspection extends XmlSuppressableInspectionTool
|
||||
if (!HighlightLevelUtil.shouldInspect(containingFile)) return;
|
||||
|
||||
final XmlExtension extension = XmlExtension.getExtension(containingFile);
|
||||
if (extension.isPrefixDeclared(context, namespacePrefix)) {
|
||||
if (extension.getPrefixDeclaration(context, namespacePrefix) != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,11 +16,12 @@
|
||||
package com.intellij.psi.impl.source.xml;
|
||||
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.impl.RenameableFakePsiElement;
|
||||
import com.intellij.psi.search.LocalSearchScope;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.xml.XmlAttribute;
|
||||
import com.intellij.util.Icons;
|
||||
import com.intellij.xml.XmlExtension;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -73,6 +74,11 @@ public class SchemaPrefix extends RenameableFakePsiElement {
|
||||
@NotNull
|
||||
@Override
|
||||
public SearchScope getUseScope() {
|
||||
return new LocalSearchScope(getDeclaration().getParent());
|
||||
return XmlExtension.getExtension(getContainingFile()).getNsPrefixScope(getDeclaration());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(PsiElement another) {
|
||||
return another instanceof SchemaPrefix && ((SchemaPrefix)another).getDeclaration() == getDeclaration();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,13 +19,13 @@ import com.intellij.openapi.util.NullableLazyValue;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiReferenceBase;
|
||||
import com.intellij.psi.xml.XmlAttribute;
|
||||
import com.intellij.psi.xml.XmlElement;
|
||||
import com.intellij.psi.xml.XmlTag;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.xml.*;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.xml.util.XmlUtil;
|
||||
import com.intellij.xml.XmlExtension;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Konstantin Bulenkov
|
||||
@@ -35,19 +35,16 @@ public class SchemaPrefixReference extends PsiReferenceBase<XmlElement> {
|
||||
private final NullableLazyValue<SchemaPrefix> myPrefix = new NullableLazyValue<SchemaPrefix>() {
|
||||
@Override
|
||||
protected SchemaPrefix compute() {
|
||||
if (myElement instanceof XmlAttribute && ((XmlAttribute)myElement).isNamespaceDeclaration()) {
|
||||
if (myElement instanceof XmlAttribute && (((XmlAttribute)myElement).isNamespaceDeclaration())) {
|
||||
return new SchemaPrefix((XmlAttribute)myElement, getRangeInElement(), myName);
|
||||
}
|
||||
else if (myElement instanceof XmlAttributeValue &&
|
||||
((XmlAttribute)((XmlAttributeValue)myElement).getParent()).getLocalName().equals("prefix")) {
|
||||
return new SchemaPrefix((XmlAttribute)myElement.getParent(), getRangeInElement().shiftRight(myElement.getStartOffsetInParent()), myName);
|
||||
}
|
||||
else {
|
||||
final PsiElement declaration = XmlUtil.findNamespaceDeclaration(myElement, myName);
|
||||
if (declaration instanceof XmlAttribute) {
|
||||
final XmlAttribute attribute = (XmlAttribute)declaration;
|
||||
final String prefix = attribute.getNamespacePrefix();
|
||||
final TextRange textRange = TextRange.from(prefix.length() + 1, myName.length());
|
||||
return new SchemaPrefix(attribute, textRange, myName);
|
||||
}
|
||||
return resolvePrefix(myElement, myName);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -56,7 +53,6 @@ public class SchemaPrefixReference extends PsiReferenceBase<XmlElement> {
|
||||
public SchemaPrefixReference(XmlElement element, TextRange range, String name) {
|
||||
super(element, range, true);
|
||||
myName = name;
|
||||
|
||||
}
|
||||
|
||||
public String getNamespacePrefix() {
|
||||
@@ -75,9 +71,7 @@ public class SchemaPrefixReference extends PsiReferenceBase<XmlElement> {
|
||||
@Override
|
||||
public boolean isReferenceTo(PsiElement element) {
|
||||
if (!(element instanceof SchemaPrefix) || !myName.equals(((SchemaPrefix)element).getName())) return false;
|
||||
|
||||
SchemaPrefix prefix = resolve();
|
||||
return prefix != null && ((SchemaPrefix)element).getDeclaration() == prefix.getDeclaration();
|
||||
return super.isReferenceTo(element);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -94,4 +88,16 @@ public class SchemaPrefixReference extends PsiReferenceBase<XmlElement> {
|
||||
}
|
||||
return super.handleElementRename(name);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static SchemaPrefix resolvePrefix(PsiElement element, String name) {
|
||||
XmlExtension extension = XmlExtension.getExtension(element.getContainingFile());
|
||||
final XmlAttribute declaration = extension.getPrefixDeclaration(PsiTreeUtil.getParentOfType(element, XmlTag.class, false), name);
|
||||
if (declaration != null) {
|
||||
final String prefix = declaration.getNamespacePrefix();
|
||||
final TextRange textRange = TextRange.from(prefix.length() + 1, name.length());
|
||||
return new SchemaPrefix(declaration, textRange, name);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,15 +242,16 @@ public class DefaultXmlExtension extends XmlExtension {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isPrefixDeclared(final XmlTag context, String namespacePrefix) {
|
||||
public XmlAttribute getPrefixDeclaration(final XmlTag context, String namespacePrefix) {
|
||||
@NonNls String nsDeclarationAttrName = null;
|
||||
for(XmlTag t = context; t != null; t = t.getParentTag()) {
|
||||
if (t.hasNamespaceDeclarations()) {
|
||||
if (nsDeclarationAttrName == null) nsDeclarationAttrName = namespacePrefix.length() > 0 ? "xmlns:"+namespacePrefix:"xmlns";
|
||||
if (t.getAttributeValue(nsDeclarationAttrName) != null) return true;
|
||||
XmlAttribute attribute = t.getAttribute(nsDeclarationAttrName);
|
||||
if (attribute != null) return attribute;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Set<String> guessNamespace(final PsiFile file, String tagName) {
|
||||
|
||||
@@ -29,6 +29,8 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.impl.source.xml.TagNameReference;
|
||||
import com.intellij.psi.search.LocalSearchScope;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.xml.XmlAttribute;
|
||||
import com.intellij.psi.xml.XmlDocument;
|
||||
import com.intellij.psi.xml.XmlFile;
|
||||
@@ -153,7 +155,12 @@ public abstract class XmlExtension {
|
||||
return HighlightInfoType.ERROR;
|
||||
}
|
||||
|
||||
public abstract boolean isPrefixDeclared(final XmlTag context, String namespacePrefix);
|
||||
@Nullable
|
||||
public abstract XmlAttribute getPrefixDeclaration(final XmlTag context, String namespacePrefix);
|
||||
|
||||
public SearchScope getNsPrefixScope(XmlAttribute declaration) {
|
||||
return new LocalSearchScope(declaration.getParent());
|
||||
}
|
||||
|
||||
public boolean shouldBeHighlightedAsTag(XmlTag tag) {
|
||||
return true;
|
||||
|
||||
@@ -15,20 +15,15 @@
|
||||
*/
|
||||
package com.intellij.xml.refactoring;
|
||||
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.actionSystem.LangDataKeys;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.impl.source.resolve.reference.impl.PsiMultiReference;
|
||||
import com.intellij.psi.impl.source.xml.SchemaPrefix;
|
||||
import com.intellij.psi.impl.source.xml.SchemaPrefixReference;
|
||||
import com.intellij.refactoring.rename.RenameHandler;
|
||||
import com.intellij.refactoring.rename.inplace.VariableInplaceRenameHandler;
|
||||
import com.intellij.refactoring.rename.inplace.VariableInplaceRenamer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -36,24 +31,14 @@ import java.util.Collection;
|
||||
/**
|
||||
* @author Dmitry Avdeev
|
||||
*/
|
||||
public class SchemaPrefixRenameHandler implements RenameHandler {
|
||||
public class SchemaPrefixRenameHandler extends VariableInplaceRenameHandler {
|
||||
|
||||
public boolean isAvailableOnDataContext(DataContext dataContext) {
|
||||
return isRenaming(dataContext);
|
||||
}
|
||||
|
||||
public boolean isRenaming(DataContext dataContext) {
|
||||
SchemaPrefixReference ref = getReference(dataContext);
|
||||
@Override
|
||||
protected boolean isAvailable(PsiElement element, Editor editor, PsiFile file) {
|
||||
SchemaPrefixReference ref = getReference(file, editor);
|
||||
return ref != null && ref.resolve() != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static SchemaPrefixReference getReference(DataContext dataContext) {
|
||||
PsiFile file = LangDataKeys.PSI_FILE.getData(dataContext);
|
||||
Editor editor = PlatformDataKeys.EDITOR.getData(dataContext);
|
||||
return getReference(file, editor);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static SchemaPrefixReference getReference(PsiFile file, Editor editor) {
|
||||
if (file != null && editor != null) {
|
||||
@@ -75,22 +60,19 @@ public class SchemaPrefixRenameHandler implements RenameHandler {
|
||||
|
||||
}
|
||||
|
||||
public void invoke(@NotNull Project project, Editor editor, PsiFile file, DataContext dataContext) {
|
||||
SchemaPrefixReference reference = getReference(file, editor);
|
||||
@Override
|
||||
protected VariableInplaceRenamer createRenamer(PsiElement elementToRename, Editor editor) {
|
||||
SchemaPrefixReference reference = getReference(elementToRename.getContainingFile(), editor);
|
||||
if (reference != null) {
|
||||
SchemaPrefix prefix = reference.resolve();
|
||||
if (prefix != null) {
|
||||
new VariableInplaceRenamer(prefix, editor) {
|
||||
return new VariableInplaceRenamer(prefix, editor) {
|
||||
@Override
|
||||
protected void addReferenceAtCaret(Collection<PsiReference> refs) {
|
||||
protected void addReferenceAtCaret(Collection<PsiReference> refs) {}
|
||||
|
||||
}
|
||||
}.performInplaceRename();
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void invoke(@NotNull Project project, @NotNull PsiElement[] elements, DataContext dataContext) {
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user