mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'master' of git.labs.intellij.net:idea/community
This commit is contained in:
@@ -550,6 +550,9 @@ public class CompilerTask extends Task.Backgroundable {
|
||||
|
||||
public boolean canCloseProject(final Project project) {
|
||||
assert project != null;
|
||||
if (!project.equals(myProject)) {
|
||||
return true;
|
||||
}
|
||||
if (shouldAskUser()) {
|
||||
int result = Messages.showOkCancelDialog(
|
||||
myProject,
|
||||
@@ -627,13 +630,15 @@ public class CompilerTask extends Task.Backgroundable {
|
||||
}
|
||||
|
||||
public void projectClosed(Project project) {
|
||||
if (myContent != null) {
|
||||
if (project.equals(myProject) && myContent != null) {
|
||||
myContentManager.removeContent(myContent, true);
|
||||
}
|
||||
}
|
||||
|
||||
public void projectClosing(Project project) {
|
||||
myIsApplicationExitingOrProjectClosing = true;
|
||||
if (project.equals(myProject)) {
|
||||
myIsApplicationExitingOrProjectClosing = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,10 +143,14 @@ public class ExportDialog extends DialogWrapper {
|
||||
}
|
||||
|
||||
public static String getExportThreadsText(VirtualMachineProxyImpl vmProxy) {
|
||||
StringBuffer buffer = new StringBuffer(512);
|
||||
final StringBuffer buffer = new StringBuffer(512);
|
||||
List<ThreadReference> threads = vmProxy.getVirtualMachine().allThreads();
|
||||
for (ThreadReference threadReference : threads) {
|
||||
buffer.append(threadName(threadReference));
|
||||
final String name = threadName(threadReference);
|
||||
if (name == null) {
|
||||
continue;
|
||||
}
|
||||
buffer.append(name);
|
||||
ReferenceType referenceType = threadReference.referenceType();
|
||||
if (referenceType != null) {
|
||||
//noinspection HardCodedStringLiteral
|
||||
@@ -181,7 +185,10 @@ public class ExportDialog extends DialogWrapper {
|
||||
for (ObjectReference reference : list) {
|
||||
final List<ThreadReference> waiting = reference.waitingThreads();
|
||||
for (ThreadReference thread : waiting) {
|
||||
buffer.append("\n\t ").append(DebuggerBundle.message("threads.export.attribute.label.blocks.thread", threadName(thread)));
|
||||
final String waitingThreadName = threadName(thread);
|
||||
if (waitingThreadName != null) {
|
||||
buffer.append("\n\t ").append(DebuggerBundle.message("threads.export.attribute.label.blocks.thread", waitingThreadName));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -191,8 +198,10 @@ public class ExportDialog extends DialogWrapper {
|
||||
if (vmProxy.canGetMonitorInfo()) {
|
||||
ThreadReference waitedThread = waitedMonitor.owningThread();
|
||||
if (waitedThread != null) {
|
||||
buffer.append("\n\t ")
|
||||
.append(DebuggerBundle.message("threads.export.attribute.label.waiting.for.thread", threadName(waitedThread)));
|
||||
final String waitedThreadName = threadName(waitedThread);
|
||||
if (waitedThreadName != null) {
|
||||
buffer.append("\n\t ").append(DebuggerBundle.message("threads.export.attribute.label.waiting.for.thread", waitedThreadName));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -228,7 +237,12 @@ public class ExportDialog extends DialogWrapper {
|
||||
}
|
||||
|
||||
private static String threadName(ThreadReference threadReference) {
|
||||
return threadReference.name() + "@" + threadReference.uniqueID();
|
||||
try {
|
||||
return threadReference.name() + "@" + threadReference.uniqueID();
|
||||
}
|
||||
catch (ObjectCollectedException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private class CopyToClipboardAction extends AbstractAction {
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.codeInsight.completion;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JavadocAutoLookupHandler extends CodeCompletionHandlerBase {
|
||||
public JavadocAutoLookupHandler() {
|
||||
super(CompletionType.BASIC, false, false);
|
||||
}
|
||||
|
||||
protected void doComplete(final int offset1, final int offset2, final CompletionContext context, final FileCopyPatcher dummyIdentifier,
|
||||
final Editor editor, final int invocationCount) {
|
||||
PsiFile file = context.file;
|
||||
int offset = context.getStartOffset();
|
||||
|
||||
PsiElement lastElement = file.findElementAt(offset - 1);
|
||||
if (lastElement == null || !StringUtil.endsWithChar(lastElement.getText(), '@')) return;
|
||||
|
||||
super.doComplete(offset1, offset2, context, dummyIdentifier, editor, invocationCount);
|
||||
}
|
||||
}
|
||||
@@ -17,10 +17,6 @@ package com.intellij.codeInsight.editorActions;
|
||||
|
||||
import com.intellij.codeInsight.AutoPopupController;
|
||||
import com.intellij.codeInsight.CodeInsightSettings;
|
||||
import com.intellij.codeInsight.completion.JavadocAutoLookupHandler;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.command.UndoConfirmationPolicy;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.EditorModificationUtil;
|
||||
import com.intellij.openapi.editor.ScrollType;
|
||||
@@ -30,6 +26,7 @@ import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.filters.ClassFilter;
|
||||
@@ -39,7 +36,6 @@ import com.intellij.psi.jsp.JspFile;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.PsiUtilBase;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
@@ -54,13 +50,45 @@ public class JavaTypedHandler extends TypedHandlerDelegate {
|
||||
return Result.STOP;
|
||||
}
|
||||
if (charTyped == '#' || charTyped == '.') {
|
||||
AutoPopupController.getInstance(project).autoPopupMemberLookup(editor, new MemberAutoLookupCondition());
|
||||
autoPopupMemberLookup(project, editor);
|
||||
return Result.STOP;
|
||||
}
|
||||
|
||||
return Result.CONTINUE;
|
||||
}
|
||||
|
||||
private static void autoPopupMemberLookup(Project project, final Editor editor) {
|
||||
AutoPopupController.getInstance(project).autoPopupMemberLookup(editor, new Condition<PsiFile>() {
|
||||
public boolean value(final PsiFile file) {
|
||||
int offset = editor.getCaretModel().getOffset();
|
||||
|
||||
PsiElement lastElement = file.findElementAt(offset - 1);
|
||||
if (lastElement == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//do not show lookup when typing varargs ellipsis
|
||||
final PsiElement prevSibling = lastElement.getPrevSibling();
|
||||
if (prevSibling == null || ".".equals(prevSibling.getText())) return false;
|
||||
PsiElement parent = prevSibling;
|
||||
do {
|
||||
parent = parent.getParent();
|
||||
} while(parent instanceof PsiJavaCodeReferenceElement || parent instanceof PsiTypeElement);
|
||||
if (parent instanceof PsiParameterList) return false;
|
||||
|
||||
if (!".".equals(lastElement.getText()) && !"#".equals(lastElement.getText())) {
|
||||
return false;
|
||||
}
|
||||
else{
|
||||
final PsiElement element = file.findElementAt(offset);
|
||||
return element == null ||
|
||||
!"#".equals(lastElement.getText()) ||
|
||||
new SuperParentFilter(new ClassFilter(PsiDocComment.class)).isAcceptable(element, element.getParent());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Result beforeCharTyped(final char c, final Project project, final Editor editor, final PsiFile file, final FileType fileType) {
|
||||
final FileType originalFileType = getOriginalFileType(file);
|
||||
|
||||
@@ -217,27 +245,15 @@ public class JavaTypedHandler extends TypedHandlerDelegate {
|
||||
}
|
||||
|
||||
private static void autoPopupJavadocLookup(final Project project, final Editor editor) {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) return;
|
||||
AutoPopupController.getInstance(project).autoPopupMemberLookup(editor, new Condition<PsiFile>() {
|
||||
@Override
|
||||
public boolean value(PsiFile file) {
|
||||
int offset = editor.getCaretModel().getOffset();
|
||||
|
||||
final CodeInsightSettings settings = CodeInsightSettings.getInstance();
|
||||
if (settings.AUTO_POPUP_COMPLETION_LOOKUP) {
|
||||
final PsiFile file = PsiUtilBase.getPsiFileInEditor(editor, project);
|
||||
if (file == null) return;
|
||||
final Runnable request = new Runnable(){
|
||||
public void run(){
|
||||
PsiDocumentManager.getInstance(project).commitAllDocuments();
|
||||
CommandProcessor.getInstance().executeCommand(project, new Runnable() {
|
||||
public void run(){
|
||||
new JavadocAutoLookupHandler().invoke(project, editor, file);
|
||||
}
|
||||
},
|
||||
"",
|
||||
null, UndoConfirmationPolicy.DEFAULT, editor.getDocument()
|
||||
);
|
||||
}
|
||||
};
|
||||
AutoPopupController.getInstance(project).invokeAutoPopupRunnable(request, settings.AUTO_LOOKUP_DELAY);
|
||||
}
|
||||
PsiElement lastElement = file.findElementAt(offset - 1);
|
||||
return lastElement != null && StringUtil.endsWithChar(lastElement.getText(), '@');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static boolean isAfterClassLikeIdentifierOrDot(final int offset, final Editor editor) {
|
||||
@@ -259,38 +275,4 @@ public class JavaTypedHandler extends TypedHandlerDelegate {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static class MemberAutoLookupCondition implements Condition<Editor> {
|
||||
public boolean value(final Editor editor) {
|
||||
final Project project = editor.getProject();
|
||||
if (project == null) return false;
|
||||
PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
|
||||
if (file == null) return false;
|
||||
int offset = editor.getCaretModel().getOffset();
|
||||
|
||||
PsiElement lastElement = file.findElementAt(offset - 1);
|
||||
if (lastElement == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//do not show lookup when typing varargs ellipsis
|
||||
final PsiElement prevSibling = lastElement.getPrevSibling();
|
||||
if (prevSibling == null || ".".equals(prevSibling.getText())) return false;
|
||||
PsiElement parent = prevSibling;
|
||||
do {
|
||||
parent = parent.getParent();
|
||||
} while(parent instanceof PsiJavaCodeReferenceElement || parent instanceof PsiTypeElement);
|
||||
if (parent instanceof PsiParameterList) return false;
|
||||
|
||||
if (!".".equals(lastElement.getText()) && !"#".equals(lastElement.getText())) {
|
||||
return false;
|
||||
}
|
||||
else{
|
||||
final PsiElement element = file.findElementAt(offset);
|
||||
return element == null ||
|
||||
!"#".equals(lastElement.getText()) ||
|
||||
new SuperParentFilter(new ClassFilter(PsiDocComment.class)).isAcceptable(element, element.getParent());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,6 +185,9 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor {
|
||||
else if (myRole2 == ChildRole.ARGUMENT_LIST) {
|
||||
createSpaceInCode(mySettings.SPACE_BEFORE_METHOD_CALL_PARENTHESES);
|
||||
}
|
||||
else if (myRole1 == ChildRole.LBRACKET || myRole2 == ChildRole.RBRACKET) {
|
||||
createSpaceInCode(mySettings.SPACE_WITHIN_BRACKETS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void visitArrayInitializerExpression(PsiArrayInitializerExpression expression) {
|
||||
|
||||
+20
-4
@@ -20,7 +20,6 @@ import com.intellij.pom.PomTarget;
|
||||
import com.intellij.pom.PomTargetPsiElement;
|
||||
import com.intellij.pom.references.PomService;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiTarget;
|
||||
import com.intellij.psi.targets.AliasingPsiTarget;
|
||||
import com.intellij.psi.targets.AliasingPsiTargetMapper;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -31,15 +30,32 @@ public class RenameAliasingPomTargetProcessor extends RenamePsiElementProcessor
|
||||
|
||||
@Override
|
||||
public boolean canProcessElement(@Nullable PsiElement element) {
|
||||
return element instanceof PomTargetPsiElement;
|
||||
return element instanceof PomTarget || element instanceof PomTargetPsiElement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareRenaming(PsiElement element, String newName, Map<PsiElement, String> allRenames) {
|
||||
PomTarget target = null;
|
||||
if (element instanceof PomTargetPsiElement) {
|
||||
target = ((PomTargetPsiElement)element).getTarget();
|
||||
}
|
||||
else if (element instanceof PomTarget) {
|
||||
target = (PomTarget)element;
|
||||
}
|
||||
|
||||
if (target != null) {
|
||||
for (AliasingPsiTargetMapper mapper : Extensions.getExtensions(AliasingPsiTargetMapper.EP_NAME)) {
|
||||
for (AliasingPsiTarget psiTarget : mapper.getTargets(((PomTargetPsiElement)element).getTarget())) {
|
||||
allRenames.put(PomService.convertToPsi(psiTarget), psiTarget.getNameAlias(newName));
|
||||
for (AliasingPsiTarget psiTarget : mapper.getTargets(target)) {
|
||||
PsiElement psiElement = PomService.convertToPsi(psiTarget);
|
||||
String name = psiTarget.getNameAlias(newName);
|
||||
|
||||
String definedName = allRenames.put(psiElement, name);
|
||||
if (definedName != null) {
|
||||
assert definedName.equals(name);
|
||||
}
|
||||
else {
|
||||
prepareRenaming(psiElement, name, allRenames);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,8 +81,16 @@ public class TestIntegrationUtils {
|
||||
|
||||
public static PsiClass findOuterClass(PsiElement element) {
|
||||
PsiClass result = PsiTreeUtil.getParentOfType(element, PsiClass.class, false);
|
||||
if (result == null) {
|
||||
final PsiFile containingFile = element.getContainingFile();
|
||||
if (containingFile instanceof PsiClassOwner){
|
||||
final PsiClass[] classes = ((PsiClassOwner)containingFile).getClasses();
|
||||
if (classes.length == 1) {
|
||||
result = classes[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result == null) return null;
|
||||
|
||||
do {
|
||||
PsiClass nextParent = PsiTreeUtil.getParentOfType(result, PsiClass.class, true);
|
||||
if (nextParent == null) return result;
|
||||
|
||||
@@ -39,6 +39,7 @@ import com.intellij.testIntegration.TestFramework;
|
||||
import com.intellij.testIntegration.TestIntegrationUtils;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@@ -60,17 +61,18 @@ public class CreateTestAction extends PsiElementBaseIntentionAction {
|
||||
|
||||
PsiClass psiClass = getContainingClass(element);
|
||||
|
||||
assert psiClass != null;
|
||||
PsiJavaToken leftBrace = psiClass.getLBrace();
|
||||
if (leftBrace == null) return false;
|
||||
if (element.getTextOffset() >= leftBrace.getTextOffset()) return false;
|
||||
|
||||
TextRange declarationRange = HighlightNamesUtil.getClassDeclarationTextRange(psiClass);
|
||||
if (!declarationRange.contains(element.getTextRange())) return false;
|
||||
//TextRange declarationRange = HighlightNamesUtil.getClassDeclarationTextRange(psiClass);
|
||||
//if (!declarationRange.contains(element.getTextRange())) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isAvailableForElement(PsiElement element) {
|
||||
public static boolean isAvailableForElement(PsiElement element) {
|
||||
if (element == null) return false;
|
||||
|
||||
PsiClass psiClass = getContainingClass(element);
|
||||
@@ -91,7 +93,7 @@ public class CreateTestAction extends PsiElementBaseIntentionAction {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isUnderTestSources(PsiClass c) {
|
||||
private static boolean isUnderTestSources(PsiClass c) {
|
||||
ProjectRootManager rm = ProjectRootManager.getInstance(c.getProject());
|
||||
VirtualFile f = c.getContainingFile().getVirtualFile();
|
||||
if (f == null) return false;
|
||||
@@ -144,7 +146,7 @@ public class CreateTestAction extends PsiElementBaseIntentionAction {
|
||||
});
|
||||
}
|
||||
|
||||
private void showErrorLater(final Project project, final String targetClassName) {
|
||||
private static void showErrorLater(final Project project, final String targetClassName) {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
Messages.showErrorDialog(project,
|
||||
@@ -154,7 +156,7 @@ public class CreateTestAction extends PsiElementBaseIntentionAction {
|
||||
});
|
||||
}
|
||||
|
||||
private void addSuperClass(PsiClass targetClass, Project project, String superClassName) throws IncorrectOperationException {
|
||||
private static void addSuperClass(PsiClass targetClass, Project project, String superClassName) throws IncorrectOperationException {
|
||||
if (superClassName == null) return;
|
||||
|
||||
PsiElementFactory ef = JavaPsiFacade.getInstance(project).getElementFactory();
|
||||
@@ -170,12 +172,13 @@ public class CreateTestAction extends PsiElementBaseIntentionAction {
|
||||
targetClass.getExtendsList().add(superClassRef);
|
||||
}
|
||||
|
||||
private PsiClass findClass(Project project, String fqName) {
|
||||
@Nullable
|
||||
private static PsiClass findClass(Project project, String fqName) {
|
||||
GlobalSearchScope scope = GlobalSearchScope.allScope(project);
|
||||
return JavaPsiFacade.getInstance(project).findClass(fqName, scope);
|
||||
}
|
||||
|
||||
private void addTestMethods(Editor editor,
|
||||
private static void addTestMethods(Editor editor,
|
||||
PsiClass targetClass,
|
||||
TestFramework descriptor,
|
||||
Collection<MemberInfo> methods,
|
||||
@@ -192,14 +195,25 @@ public class CreateTestAction extends PsiElementBaseIntentionAction {
|
||||
}
|
||||
}
|
||||
|
||||
private void generateMethod(TestIntegrationUtils.MethodKind methodKind, TestFramework descriptor, PsiClass targetClass, Editor editor, String name) {
|
||||
private static void generateMethod(TestIntegrationUtils.MethodKind methodKind, TestFramework descriptor, PsiClass targetClass, Editor editor, String name) {
|
||||
PsiMethod method = (PsiMethod)targetClass.add(TestIntegrationUtils.createDummyMethod(targetClass.getProject()));
|
||||
PsiDocumentManager.getInstance(targetClass.getProject()).doPostponedOperationsAndUnblockDocument(editor.getDocument());
|
||||
TestIntegrationUtils.runTestMethodTemplate(methodKind, descriptor, editor, targetClass, method, name, true);
|
||||
}
|
||||
|
||||
private PsiClass getContainingClass(PsiElement element) {
|
||||
return PsiTreeUtil.getParentOfType(element, PsiClass.class, false);
|
||||
@Nullable
|
||||
private static PsiClass getContainingClass(PsiElement element) {
|
||||
final PsiClass psiClass = PsiTreeUtil.getParentOfType(element, PsiClass.class, false);
|
||||
if (psiClass == null) {
|
||||
final PsiFile containingFile = element.getContainingFile();
|
||||
if (containingFile instanceof PsiClassOwner){
|
||||
final PsiClass[] classes = ((PsiClassOwner)containingFile).getClasses();
|
||||
if (classes.length == 1) {
|
||||
return classes[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
return psiClass;
|
||||
}
|
||||
|
||||
public boolean startInWriteAction() {
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
*/
|
||||
package com.intellij.psi;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfoFilter;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.HighlightInfoHolder;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.HighlightVisitorImpl;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.Result;
|
||||
import com.intellij.openapi.application.ex.PathManagerEx;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.projectRoots.impl.JavaSdkImpl;
|
||||
@@ -16,10 +18,10 @@ import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.testFramework.PsiTestCase;
|
||||
import com.intellij.testFramework.PsiTestUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.indexing.StorageException;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class PsiConcurrencyStressTest extends PsiTestCase {
|
||||
|
||||
@@ -47,9 +49,10 @@ public class PsiConcurrencyStressTest extends PsiTestCase {
|
||||
}
|
||||
|
||||
private PsiJavaFile myFile;
|
||||
private volatile boolean writeActionInProgress;
|
||||
public void testStress() throws Exception {
|
||||
int numOfThreads = 10;
|
||||
final int readIterations = 50000;
|
||||
final int readIterations = 100;
|
||||
final int writeIterations = 30;
|
||||
|
||||
synchronized (this) {
|
||||
@@ -71,12 +74,8 @@ public class PsiConcurrencyStressTest extends PsiTestCase {
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
readStep(random);
|
||||
}
|
||||
catch (StorageException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
assertFalse(writeActionInProgress);
|
||||
readStep(random);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -93,15 +92,17 @@ public class PsiConcurrencyStressTest extends PsiTestCase {
|
||||
new WriteCommandAction(myProject, myFile) {
|
||||
@Override
|
||||
protected void run(final Result result) throws Throwable {
|
||||
writeActionInProgress = true;
|
||||
documentManager.commitAllDocuments();
|
||||
writeStep(random);
|
||||
documentManager.commitAllDocuments();
|
||||
assertEquals(document.getText(), myFile.getText());
|
||||
writeActionInProgress = false;
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
reads.await();
|
||||
reads.await(5, TimeUnit.MINUTES);
|
||||
}
|
||||
|
||||
private static void mark(final String s) {
|
||||
@@ -132,62 +133,46 @@ public class PsiConcurrencyStressTest extends PsiTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
private void readStep(final Random random) throws StorageException {
|
||||
private void readStep(final Random random) {
|
||||
PsiClass aClass = getPsiClass();
|
||||
switch (random.nextInt(5)) {
|
||||
case 0 :
|
||||
switch (random.nextInt(4)) {
|
||||
case 0:
|
||||
mark("v");
|
||||
aClass.getContainingFile().accept(new PsiRecursiveElementVisitor() {}); break;
|
||||
aClass.getContainingFile().accept(new PsiRecursiveElementVisitor() {
|
||||
});
|
||||
break;
|
||||
|
||||
case 1 :
|
||||
case 1:
|
||||
mark("m");
|
||||
aClass.getMethods();
|
||||
for (int offset=0; offset<myFile.getTextLength();offset++) {
|
||||
myFile.findElementAt(offset);
|
||||
}
|
||||
break;
|
||||
|
||||
//case 2 : {
|
||||
// mark("h");
|
||||
// psiFile.accept(new PsiRecursiveElementVisitor() {
|
||||
// @Override public void visitElement(final PsiElement element) {
|
||||
// super.visitElement(element);
|
||||
//
|
||||
// final HighlightInfoHolder infoHolder = new HighlightInfoHolder(psiFile, HighlightInfoFilter.EMPTY_ARRAY);
|
||||
// infoHolder.setWritable(true);
|
||||
// new HighlightVisitorImpl(getPsiManager()).visit(element, infoHolder);
|
||||
// }
|
||||
// });
|
||||
// break;
|
||||
//}
|
||||
case 2:
|
||||
mark("h");
|
||||
aClass.accept(new PsiRecursiveElementVisitor() {
|
||||
@Override
|
||||
public void visitElement(final PsiElement element) {
|
||||
super.visitElement(element);
|
||||
|
||||
case 3 :
|
||||
final HighlightInfoHolder infoHolder = new HighlightInfoHolder(myFile, HighlightInfoFilter.EMPTY_ARRAY);
|
||||
new HighlightVisitorImpl(getProject()).visit(element, infoHolder);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case 3:
|
||||
mark("u");
|
||||
//FileBasedIndex.getInstance().ensureUpToDate(StubUpdatingIndex.INDEX_ID);
|
||||
for (PsiMethod method : aClass.getMethods()) {
|
||||
method.getName();
|
||||
}
|
||||
break;
|
||||
case 4 :
|
||||
mark("\n");
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void invokeTestRunnable(final Runnable runnable) throws Exception {
|
||||
final Exception[] e = new Exception[1];
|
||||
Runnable runnable1 = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
runnable.run();
|
||||
}
|
||||
};
|
||||
|
||||
if (myRunCommandForTest) {
|
||||
CommandProcessor.getInstance().executeCommand(myProject, runnable1, "", null);
|
||||
}
|
||||
else {
|
||||
runnable1.run();
|
||||
}
|
||||
|
||||
if (e[0] != null) {
|
||||
throw e[0];
|
||||
}
|
||||
runnable.run();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,4 +163,15 @@ public class JavaFormatterSpaceTest extends AbstractJavaFormatterTest {
|
||||
" }\n" +
|
||||
"}");
|
||||
}
|
||||
|
||||
public void testSpaceWithArrayBrackets() throws Exception {
|
||||
// Inspired by IDEA-58510
|
||||
getSettings().SPACE_WITHIN_BRACKETS = true;
|
||||
doMethodTest(
|
||||
"int[] i = new int[1]\n" +
|
||||
"i[0] = 1;",
|
||||
"int[] i = new int[ 1 ]\n" +
|
||||
"i[ 0 ] = 1;"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ public class ClassloaderUtil {
|
||||
final File libFolder = new File(aFolderPath + File.separator + "lib");
|
||||
addLibraries(classPath, libFolder, selfRootUrl);
|
||||
|
||||
final File extLib = new File(new File(libFolder, "ext"), "lib");
|
||||
final File extLib = new File(libFolder, "ext");
|
||||
addLibraries(classPath, extLib, selfRootUrl);
|
||||
|
||||
final File antLib = new File(new File(libFolder, "ant"), "lib");
|
||||
|
||||
@@ -823,27 +823,7 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
|
||||
public boolean equals(Object other) {
|
||||
if (other instanceof TypeToNameMap) {
|
||||
TypeToNameMap otherMap = (TypeToNameMap)other;
|
||||
if (myPatterns.size() != otherMap.myPatterns.size()) {
|
||||
return false;
|
||||
}
|
||||
if (myNames.size() != otherMap.myNames.size()) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < myPatterns.size(); i++) {
|
||||
String s1 = myPatterns.get(i);
|
||||
String s2 = otherMap.myPatterns.get(i);
|
||||
if (!Comparing.equal(s1, s2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < myNames.size(); i++) {
|
||||
String s1 = myNames.get(i);
|
||||
String s2 = otherMap.myNames.get(i);
|
||||
if (!Comparing.equal(s1, s2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return myPatterns.equals(otherMap.myPatterns) && myNames.equals(otherMap.myNames);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -858,13 +838,12 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void registerAdditionalIndentOptions(FileType fileType, IndentOptions options) {
|
||||
boolean exist = false;
|
||||
for (final FileType existing : myAdditionalIndentOptions.keySet()) {
|
||||
if (existing.getDefaultExtension() == fileType.getDefaultExtension()) {
|
||||
if (Comparing.strEqual(existing.getDefaultExtension(), fileType.getDefaultExtension())) {
|
||||
exist = true;
|
||||
break;
|
||||
}
|
||||
@@ -883,11 +862,13 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
|
||||
}
|
||||
|
||||
private void loadAdditionalIndentOptions() {
|
||||
myLoadedAdditionalIndentOptions = true;
|
||||
final FileTypeIndentOptionsProvider[] providers = Extensions.getExtensions(FileTypeIndentOptionsProvider.EP_NAME);
|
||||
for (final FileTypeIndentOptionsProvider provider : providers) {
|
||||
if (!myAdditionalIndentOptions.containsKey(provider.getFileType())) {
|
||||
registerAdditionalIndentOptions(provider.getFileType(), provider.createIndentOptions());
|
||||
synchronized (myAdditionalIndentOptions) {
|
||||
myLoadedAdditionalIndentOptions = true;
|
||||
final FileTypeIndentOptionsProvider[] providers = Extensions.getExtensions(FileTypeIndentOptionsProvider.EP_NAME);
|
||||
for (final FileTypeIndentOptionsProvider provider : providers) {
|
||||
if (!myAdditionalIndentOptions.containsKey(provider.getFileType())) {
|
||||
registerAdditionalIndentOptions(provider.getFileType(), provider.createIndentOptions());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.containers.FilteringIterator;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
@@ -67,8 +68,9 @@ public class PathsList {
|
||||
addAllLast(chooseFirstTimeItems(path), myPath);
|
||||
}
|
||||
|
||||
public void remove(String path) {
|
||||
public void remove(@NotNull String path) {
|
||||
myPath.remove(path);
|
||||
myPathTail.remove(path);
|
||||
myPathSet.remove(path);
|
||||
}
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ public class AutoPopupController implements Disposable {
|
||||
}, this);
|
||||
}
|
||||
|
||||
public void autoPopupMemberLookup(final Editor editor, @Nullable final Condition<Editor> condition){
|
||||
public void autoPopupMemberLookup(final Editor editor, @Nullable final Condition<PsiFile> condition){
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) return;
|
||||
|
||||
final CodeInsightSettings settings = CodeInsightSettings.getInstance();
|
||||
@@ -92,7 +92,9 @@ public class AutoPopupController implements Disposable {
|
||||
if (editor.isDisposed()) return;
|
||||
|
||||
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
|
||||
if (condition != null && !condition.value(editor)) return;
|
||||
if (!file.isValid()) return;
|
||||
|
||||
if (condition != null && !condition.value(file)) return;
|
||||
new CodeCompletionHandlerBase(CompletionType.BASIC, false, false).invoke(myProject, editor, file);
|
||||
}
|
||||
};
|
||||
|
||||
+5
@@ -31,6 +31,11 @@ public class ComboEditorCompletionContributor extends CompletionContributor{
|
||||
|
||||
@Override
|
||||
public void fillCompletionVariants(final CompletionParameters parameters, final CompletionResultSet result) {
|
||||
final CompletionProcess process = CompletionService.getCompletionService().getCurrentCompletion();
|
||||
if (process != null && process.isAutopopupCompletion()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final PsiFile file = parameters.getOriginalFile();
|
||||
final Document document = PsiDocumentManager.getInstance(file.getProject()).getDocument(file);
|
||||
if (document != null) {
|
||||
|
||||
+10
-7
@@ -42,6 +42,7 @@ import com.intellij.openapi.keymap.KeymapUtil;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.progress.util.ProgressWrapper;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
@@ -49,6 +50,7 @@ import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.Trinity;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
|
||||
import com.intellij.profile.codeInspection.SeverityProvider;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
|
||||
import com.intellij.util.ConcurrencyUtil;
|
||||
@@ -101,9 +103,9 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass
|
||||
else {
|
||||
myShortcutText = "";
|
||||
}
|
||||
mySeverityRegistrar = SeverityRegistrar.getInstance(myProject);
|
||||
InspectionProfileWrapper customProfile = file.getUserData(InspectionProfileWrapper.KEY);
|
||||
myProfileWrapper = customProfile == null ? InspectionProjectProfileManager.getInstance(myProject).getProfileWrapper() : customProfile;
|
||||
mySeverityRegistrar = ((SeverityProvider)myProfileWrapper.getInspectionProfile().getProfileManager()).getSeverityRegistrar();
|
||||
|
||||
// initial guess
|
||||
setProgressLimit(300 * 2);
|
||||
@@ -324,16 +326,17 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass
|
||||
return highlights;
|
||||
}
|
||||
|
||||
private static HighlightInfo highlightInfoFromDescriptor(final ProblemDescriptor problemDescriptor,
|
||||
final HighlightInfoType highlightInfoType,
|
||||
final String message,
|
||||
final String toolTip) {
|
||||
private HighlightInfo highlightInfoFromDescriptor(final ProblemDescriptor problemDescriptor,
|
||||
final HighlightInfoType highlightInfoType,
|
||||
final String message,
|
||||
final String toolTip) {
|
||||
TextRange textRange = ((ProblemDescriptorImpl)problemDescriptor).getTextRange();
|
||||
PsiElement element = problemDescriptor.getPsiElement();
|
||||
boolean isFileLevel = element instanceof PsiFile && textRange.equals(element.getTextRange());
|
||||
|
||||
return new HighlightInfo(null, highlightInfoType, textRange.getStartOffset(), textRange.getEndOffset(), message, toolTip,
|
||||
highlightInfoType.getSeverity(element), problemDescriptor.isAfterEndOfLine(), null, isFileLevel);
|
||||
final HighlightSeverity severity = highlightInfoType.getSeverity(element);
|
||||
return new HighlightInfo(mySeverityRegistrar.getTextAttributesBySeverity(severity), highlightInfoType, textRange.getStartOffset(), textRange.getEndOffset(), message, toolTip,
|
||||
severity, problemDescriptor.isAfterEndOfLine(), null, isFileLevel);
|
||||
}
|
||||
|
||||
private final AtomicBoolean haveInfosToProcess = new AtomicBoolean();
|
||||
|
||||
+7
-6
@@ -158,9 +158,15 @@ public class AutoHardWrapHandler {
|
||||
}
|
||||
|
||||
final int[] wrapIntroducedSymbolsNumber = new int[1];
|
||||
final int[] caretOffsetDiff = new int[1];
|
||||
final int baseCaretOffset = caretModel.getOffset();
|
||||
DocumentListener listener = new DocumentListener() {
|
||||
@Override
|
||||
public void beforeDocumentChange(DocumentEvent event) {
|
||||
if (event.getOffset() <= baseCaretOffset + caretOffsetDiff[0]) {
|
||||
caretOffsetDiff[0] += event.getNewLength() - event.getOldLength();
|
||||
}
|
||||
|
||||
if (event.getNewLength() <= 0) {
|
||||
// There is a possible case that document fragment is removed because of auto-formatting. We don't want to process such events.
|
||||
return;
|
||||
@@ -188,12 +194,7 @@ public class AutoHardWrapHandler {
|
||||
change.change.setStart(wrapOffset);
|
||||
change.change.setEnd(wrapOffset + wrapIntroducedSymbolsNumber[0]);
|
||||
|
||||
int newCaretOffset = caretOffset;
|
||||
if (wrapOffset <= caretOffset && newCaretOffset + wrapIntroducedSymbolsNumber[0] < document.getTextLength()) {
|
||||
newCaretOffset += wrapIntroducedSymbolsNumber[0];
|
||||
}
|
||||
newCaretOffset = Math.min(document.getLineEndOffset(line + 1), newCaretOffset);
|
||||
caretModel.moveToOffset(newCaretOffset);
|
||||
caretModel.moveToOffset(baseCaretOffset + caretOffsetDiff[0]);
|
||||
}
|
||||
|
||||
private static class AutoWrapChange {
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.intellij.execution.process.ProcessAdapter;
|
||||
import com.intellij.execution.process.ProcessEvent;
|
||||
import com.intellij.execution.process.ProcessOutputTypes;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import org.apache.commons.lang.text.StrBuilder;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
@@ -13,6 +14,11 @@ public class OutputListener extends ProcessAdapter {
|
||||
private final StringBuilder out;
|
||||
private final StringBuilder err;
|
||||
|
||||
public OutputListener() {
|
||||
out = new StringBuilder();
|
||||
err = new StringBuilder();
|
||||
}
|
||||
|
||||
public OutputListener(@NotNull final StringBuilder out, @NotNull final StringBuilder err) {
|
||||
this.out = out;
|
||||
this.err = err;
|
||||
@@ -26,4 +32,8 @@ public class OutputListener extends ProcessAdapter {
|
||||
err.append(event.getText());
|
||||
}
|
||||
}
|
||||
|
||||
public Output getOutput() {
|
||||
return new Output(out.toString(), err.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,26 +16,17 @@
|
||||
|
||||
package com.intellij.ide.actions;
|
||||
|
||||
import com.intellij.ide.ui.UISettings;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CustomShortcutSet;
|
||||
import com.intellij.openapi.actionSystem.KeyboardShortcut;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.Trinity;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.ui.ComboboxSpeedSearch;
|
||||
import com.intellij.util.Icons;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
@@ -49,7 +40,7 @@ public class CreateFileFromTemplateDialog extends DialogWrapper {
|
||||
|
||||
private ElementCreator myCreator;
|
||||
|
||||
private CreateFileFromTemplateDialog(@NotNull Project project) {
|
||||
protected CreateFileFromTemplateDialog(@NotNull Project project) {
|
||||
super(project, true);
|
||||
|
||||
myKindLabel.setLabelFor(myKindCombo);
|
||||
@@ -58,8 +49,16 @@ public class CreateFileFromTemplateDialog extends DialogWrapper {
|
||||
init();
|
||||
}
|
||||
|
||||
protected JTextField getNameField() {
|
||||
return myNameField;
|
||||
}
|
||||
|
||||
protected TemplateKindCombo getKindCombo() {
|
||||
return myKindCombo;
|
||||
}
|
||||
|
||||
private String getEnteredName() {
|
||||
return myNameField.getText();
|
||||
return getNameField().getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -77,57 +76,72 @@ public class CreateFileFromTemplateDialog extends DialogWrapper {
|
||||
|
||||
@Override
|
||||
public JComponent getPreferredFocusedComponent() {
|
||||
return myNameField;
|
||||
return getNameField();
|
||||
}
|
||||
|
||||
public static <T extends PsiElement> Builder createDialog(@NotNull final Project project) {
|
||||
public static Builder createDialog(@NotNull final Project project) {
|
||||
final CreateFileFromTemplateDialog dialog = new CreateFileFromTemplateDialog(project);
|
||||
return new BuilderImpl(dialog, project);
|
||||
}
|
||||
|
||||
return new Builder() {
|
||||
protected static class BuilderImpl implements Builder {
|
||||
|
||||
@Override
|
||||
public Builder setTitle(String title) {
|
||||
dialog.setTitle(title);
|
||||
return this;
|
||||
}
|
||||
private final CreateFileFromTemplateDialog myDialog;
|
||||
private final Project myProject;
|
||||
|
||||
public Builder addKind(@NotNull String name, @Nullable Icon icon, @NotNull String templateName) {
|
||||
dialog.myKindCombo.addItem(name, icon, templateName);
|
||||
return this;
|
||||
}
|
||||
public BuilderImpl(CreateFileFromTemplateDialog dialog, Project project) {
|
||||
myDialog = dialog;
|
||||
myProject = project;
|
||||
}
|
||||
|
||||
public <T extends PsiElement> T show(@NotNull String errorTitle, @Nullable String selectedTemplateName,
|
||||
@NotNull final FileCreator<T> creator) {
|
||||
final Ref<T> created = Ref.create(null);
|
||||
dialog.myKindCombo.setSelectedName(selectedTemplateName);
|
||||
dialog.myCreator = new ElementCreator(project, errorTitle) {
|
||||
@Override
|
||||
protected void checkBeforeCreate(String newName) throws IncorrectOperationException {
|
||||
creator.checkBeforeCreate(newName, dialog.myKindCombo.getSelectedName());
|
||||
}
|
||||
@Override
|
||||
public Builder setTitle(String title) {
|
||||
myDialog.setTitle(title);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PsiElement[] create(String newName) throws Exception {
|
||||
final T element = creator.createFile(dialog.getEnteredName(), dialog.myKindCombo.getSelectedName());
|
||||
created.set(element);
|
||||
if (element != null) {
|
||||
return new PsiElement[]{element};
|
||||
}
|
||||
return PsiElement.EMPTY_ARRAY;
|
||||
}
|
||||
public Builder addKind(@NotNull String name, @Nullable Icon icon, @NotNull String templateName) {
|
||||
myDialog.getKindCombo().addItem(name, icon, templateName);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getActionName(String newName) {
|
||||
return creator.getActionName(newName, dialog.myKindCombo.getSelectedName());
|
||||
}
|
||||
};
|
||||
dialog.show();
|
||||
if (dialog.getExitCode() == OK_EXIT_CODE) {
|
||||
return created.get();
|
||||
public <T extends PsiElement> T show(@NotNull String errorTitle, @Nullable String selectedTemplateName,
|
||||
@NotNull final FileCreator<T> creator) {
|
||||
final Ref<T> created = Ref.create(null);
|
||||
myDialog.getKindCombo().setSelectedName(selectedTemplateName);
|
||||
myDialog.myCreator = new ElementCreator(myProject, errorTitle) {
|
||||
@Override
|
||||
protected void checkBeforeCreate(String newName) throws IncorrectOperationException {
|
||||
creator.checkBeforeCreate(newName, myDialog.getKindCombo().getSelectedName());
|
||||
}
|
||||
return null;
|
||||
|
||||
@Override
|
||||
protected PsiElement[] create(String newName) throws Exception {
|
||||
final T element = creator.createFile(myDialog.getEnteredName(), myDialog.getKindCombo().getSelectedName());
|
||||
created.set(element);
|
||||
if (element != null) {
|
||||
return new PsiElement[]{element};
|
||||
}
|
||||
return PsiElement.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getActionName(String newName) {
|
||||
return creator.getActionName(newName, myDialog.getKindCombo().getSelectedName());
|
||||
}
|
||||
};
|
||||
myDialog.show();
|
||||
if (myDialog.getExitCode() == OK_EXIT_CODE) {
|
||||
return created.get();
|
||||
}
|
||||
};
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Map<String,String> getCustomProperties() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public interface Builder {
|
||||
@@ -135,6 +149,8 @@ public class CreateFileFromTemplateDialog extends DialogWrapper {
|
||||
Builder addKind(@NotNull String kind, @Nullable Icon icon, @NotNull String templateName);
|
||||
@Nullable
|
||||
<T extends PsiElement> T show(@NotNull String errorTitle, @Nullable String selectedItem, @NotNull FileCreator<T> creator);
|
||||
@Nullable
|
||||
Map<String,String> getCustomProperties();
|
||||
}
|
||||
|
||||
public interface FileCreator<T> {
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Eugene.Kudelevsky
|
||||
@@ -74,11 +75,11 @@ public abstract class CreateFromTemplateAction<T extends PsiElement> extends AnA
|
||||
});
|
||||
if (createdElement != null) {
|
||||
view.selectElement(createdElement);
|
||||
postProcess(createdElement, selectedTemplateName.get());
|
||||
postProcess(createdElement, selectedTemplateName.get(), builder.getCustomProperties());
|
||||
}
|
||||
}
|
||||
|
||||
protected void postProcess(T createdElement, String templateName) {
|
||||
protected void postProcess(T createdElement, String templateName, Map<String,String> customProperties) {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -24,18 +24,18 @@ import com.intellij.openapi.actionSystem.KeyboardShortcut;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Trinity;
|
||||
import com.intellij.ui.ComboboxSpeedSearch;
|
||||
import com.intellij.ui.ComboboxWithBrowseButton;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.KeyEvent;
|
||||
|
||||
public class TemplateKindCombo extends JComboBox {
|
||||
public class TemplateKindCombo extends ComboboxWithBrowseButton {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.ide.actions.TemplateKindCombo");
|
||||
|
||||
public TemplateKindCombo() {
|
||||
super();
|
||||
|
||||
setRenderer(new ListCellRendererWrapper(getRenderer()) {
|
||||
getComboBox().setRenderer(new ListCellRendererWrapper(getComboBox().getRenderer()) {
|
||||
@Override
|
||||
public void customize(final JList list, final Object value, final int index, final boolean selected, final boolean cellHasFocus) {
|
||||
if (value instanceof Trinity) {
|
||||
@@ -45,7 +45,7 @@ public class TemplateKindCombo extends JComboBox {
|
||||
}
|
||||
});
|
||||
|
||||
new ComboboxSpeedSearch(this) {
|
||||
new ComboboxSpeedSearch(getComboBox()) {
|
||||
@Override
|
||||
protected String getElementText(Object element) {
|
||||
if (element instanceof Trinity) {
|
||||
@@ -54,28 +54,30 @@ public class TemplateKindCombo extends JComboBox {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
setButtonListener(null);
|
||||
}
|
||||
|
||||
public void addItem(String presentableName, Icon icon, String templateName) {
|
||||
addItem(new Trinity<String, Icon, String>(presentableName, icon, templateName));
|
||||
getComboBox().addItem(new Trinity<String, Icon, String>(presentableName, icon, templateName));
|
||||
}
|
||||
|
||||
public String getSelectedName() {
|
||||
//noinspection unchecked
|
||||
final Trinity<String, Icon, String> trinity = (Trinity<String, Icon, String>)getSelectedItem();
|
||||
final Trinity<String, Icon, String> trinity = (Trinity<String, Icon, String>)getComboBox().getSelectedItem();
|
||||
if (trinity == null) {
|
||||
LOG.error("Model: " + getModel());
|
||||
// design time
|
||||
return null;
|
||||
}
|
||||
return trinity.third;
|
||||
}
|
||||
|
||||
public void setSelectedName(@Nullable String name) {
|
||||
if (name == null) return;
|
||||
ComboBoxModel model = getModel();
|
||||
ComboBoxModel model = getComboBox().getModel();
|
||||
for (int i = 0, n = model.getSize(); i < n; i++) {
|
||||
Trinity<String, Icon, String> trinity = (Trinity<String, Icon, String>)model.getElementAt(i);
|
||||
if (name.equals(trinity.third)) {
|
||||
setSelectedItem(trinity);
|
||||
getComboBox().setSelectedItem(trinity);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -97,15 +99,29 @@ public class TemplateKindCombo extends JComboBox {
|
||||
}
|
||||
|
||||
private void scrollBy(int delta) {
|
||||
final int size = getModel().getSize();
|
||||
int next = getSelectedIndex() + delta;
|
||||
if (delta == 0) return;
|
||||
final int size = getComboBox().getModel().getSize();
|
||||
int next = getComboBox().getSelectedIndex() + delta;
|
||||
if (next < 0 || next >= size) {
|
||||
if (!UISettings.getInstance().CYCLE_SCROLLING) {
|
||||
return;
|
||||
}
|
||||
next = (next + size) % size;
|
||||
}
|
||||
setSelectedIndex(next);
|
||||
getComboBox().setSelectedIndex(next);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param listener pass <code>null</code> to hide browse button
|
||||
*/
|
||||
public void setButtonListener(@Nullable ActionListener listener) {
|
||||
getButton().setVisible(listener != null);
|
||||
if (listener != null) {
|
||||
addActionListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
getComboBox().removeAllItems();
|
||||
}
|
||||
}
|
||||
|
||||
+85
-32
@@ -21,12 +21,14 @@
|
||||
package com.intellij.ide.navigationToolbar;
|
||||
|
||||
import com.intellij.ide.ui.UISettings;
|
||||
import com.intellij.ide.ui.UISettingsListener;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.actionSystem.ex.ComboBoxAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.openapi.wm.impl.IdeRootPaneNorthExtension;
|
||||
import com.intellij.ui.ScrollPaneFactory;
|
||||
import com.intellij.ui.components.panels.OpaquePanel;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -37,51 +39,100 @@ import java.awt.event.MouseEvent;
|
||||
public class NavBarRootPaneExtension extends IdeRootPaneNorthExtension {
|
||||
private static final Icon CROSS_ICON = IconLoader.getIcon("/actions/cross.png");
|
||||
|
||||
private JComponent myPanel;
|
||||
private JComponent myWrapperPanel;
|
||||
@NonNls public static final String NAV_BAR = "NavBar";
|
||||
private final Project myProject;
|
||||
private NavBarPanel myNavigationBar;
|
||||
private JPanel myRunPanel;
|
||||
|
||||
public NavBarRootPaneExtension(Project project) {
|
||||
myProject = project;
|
||||
|
||||
UISettings.getInstance().addUISettingsListener(new UISettingsListener() {
|
||||
@Override
|
||||
public void uiSettingsChanged(UISettings source) {
|
||||
toggleRunPanel(!source.SHOW_MAIN_TOOLBAR);
|
||||
}
|
||||
}, project);
|
||||
}
|
||||
|
||||
public JComponent getComponent() {
|
||||
if (myPanel == null) {
|
||||
myPanel = new OpaquePanel.List(new BorderLayout());
|
||||
|
||||
myNavigationBar = new NavBarPanel(myProject);
|
||||
|
||||
JScrollPane scroller = ScrollPaneFactory.createScrollPane(myNavigationBar);
|
||||
scroller.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
|
||||
scroller.setHorizontalScrollBar(null);
|
||||
scroller.setBorder(null);
|
||||
|
||||
myPanel.add(scroller, BorderLayout.CENTER);
|
||||
|
||||
JLabel closeLabel = new JLabel(CROSS_ICON);
|
||||
|
||||
closeLabel.addMouseListener(new MouseAdapter() {
|
||||
public void mouseClicked(final MouseEvent e) {
|
||||
UISettings.getInstance().SHOW_NAVIGATION_BAR = false;
|
||||
uiSettingsChanged(UISettings.getInstance());
|
||||
}
|
||||
});
|
||||
myPanel.add(closeLabel, BorderLayout.EAST);
|
||||
|
||||
myPanel.putClientProperty("NavBarPanel", myNavigationBar);
|
||||
myNavigationBar.installBorder(0, true);
|
||||
myPanel.setBorder(myNavigationBar.getBorder());
|
||||
myNavigationBar.setBorder(null);
|
||||
if (myWrapperPanel == null) {
|
||||
myWrapperPanel = new JPanel(new BorderLayout());
|
||||
myWrapperPanel.add(buildNavBarPanel(), BorderLayout.CENTER);
|
||||
myWrapperPanel.putClientProperty("NavBarPanel", myNavigationBar);
|
||||
toggleRunPanel(!UISettings.getInstance().SHOW_MAIN_TOOLBAR);
|
||||
}
|
||||
|
||||
return myPanel;
|
||||
return myWrapperPanel;
|
||||
}
|
||||
|
||||
private void toggleRunPanel(final boolean show) {
|
||||
if (show && myRunPanel == null) {
|
||||
final ActionManager manager = ActionManager.getInstance();
|
||||
final AnAction toolbarRunGroup = manager.getAction("ToolbarRunGroup");
|
||||
if (toolbarRunGroup instanceof DefaultActionGroup) {
|
||||
final DefaultActionGroup group = (DefaultActionGroup)toolbarRunGroup;
|
||||
boolean needsGap = false;
|
||||
int i = 0;
|
||||
for (final AnAction action : group.getChildActionsOrStubs()) {
|
||||
if (action instanceof ComboBoxAction) {
|
||||
needsGap = i == 0;
|
||||
break;
|
||||
} else if (!(action instanceof Separator)) {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
final ActionToolbar actionToolbar = manager.createActionToolbar(ActionPlaces.UNKNOWN, group, true);
|
||||
final JComponent component = actionToolbar.getComponent();
|
||||
component.setBackground(Color.WHITE);
|
||||
myRunPanel = new JPanel(new BorderLayout());
|
||||
final Color color = myRunPanel.getBackground() != null ? myRunPanel.getBackground().darker() : Color.darkGray;
|
||||
myRunPanel.setBackground(Color.WHITE);
|
||||
myRunPanel.add(component);
|
||||
myRunPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createMatteBorder(0, 1, 1, 0, color),
|
||||
BorderFactory.createEmptyBorder(1, needsGap ? 5 : 1, 0, 0)));
|
||||
myWrapperPanel.add(myRunPanel, BorderLayout.EAST);
|
||||
}
|
||||
}
|
||||
else if (!show && myRunPanel != null) {
|
||||
myWrapperPanel.remove(myRunPanel);
|
||||
myRunPanel = null;
|
||||
}
|
||||
}
|
||||
|
||||
private JComponent buildNavBarPanel() {
|
||||
final JComponent result = new OpaquePanel.List(new BorderLayout());
|
||||
myNavigationBar = new NavBarPanel(myProject);
|
||||
|
||||
JScrollPane scroller = ScrollPaneFactory.createScrollPane(myNavigationBar);
|
||||
scroller.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
|
||||
scroller.setHorizontalScrollBar(null);
|
||||
scroller.setBorder(null);
|
||||
|
||||
result.add(scroller, BorderLayout.CENTER);
|
||||
|
||||
JLabel closeLabel = new JLabel(CROSS_ICON);
|
||||
|
||||
closeLabel.addMouseListener(new MouseAdapter() {
|
||||
public void mouseClicked(final MouseEvent e) {
|
||||
UISettings.getInstance().SHOW_NAVIGATION_BAR = false;
|
||||
uiSettingsChanged(UISettings.getInstance());
|
||||
}
|
||||
});
|
||||
result.add(closeLabel, BorderLayout.EAST);
|
||||
|
||||
myNavigationBar.installBorder(0, true);
|
||||
result.setBorder(myNavigationBar.getBorder());
|
||||
myNavigationBar.setBorder(null);
|
||||
return result;
|
||||
}
|
||||
|
||||
public void uiSettingsChanged(final UISettings settings) {
|
||||
if (myNavigationBar != null) {
|
||||
myNavigationBar.updateState(settings.SHOW_NAVIGATION_BAR);
|
||||
myPanel.setVisible(settings.SHOW_NAVIGATION_BAR);
|
||||
myWrapperPanel.setVisible(settings.SHOW_NAVIGATION_BAR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,9 +141,11 @@ public class NavBarRootPaneExtension extends IdeRootPaneNorthExtension {
|
||||
return NAV_BAR;
|
||||
}
|
||||
|
||||
|
||||
public void dispose() {
|
||||
myPanel.setVisible(false);
|
||||
myPanel = null;
|
||||
myWrapperPanel.setVisible(false);
|
||||
myWrapperPanel = null;
|
||||
myRunPanel = null;
|
||||
myNavigationBar = null;
|
||||
}
|
||||
}
|
||||
|
||||
+13
-14
@@ -33,14 +33,13 @@ import javax.swing.*;
|
||||
public class LangScriptingContextConfigurable implements Configurable {
|
||||
private ScriptingLibrariesPanel myPanel;
|
||||
private LangScriptingContextProvider myProvider;
|
||||
private ModifiableRootModel myRootModel;
|
||||
private ScriptingLibraryManager myLibManager;
|
||||
|
||||
public LangScriptingContextConfigurable(ModifiableRootModel rootModel, LangScriptingContextProvider provider) {
|
||||
LibraryTable libTable = rootModel != null ?
|
||||
rootModel.getModuleLibraryTable() : null;
|
||||
public LangScriptingContextConfigurable(ScriptingLibraryManager libManager, LangScriptingContextProvider provider) {
|
||||
LibraryTable libTable = libManager.getLibraryTable();
|
||||
myPanel = new ScriptingLibrariesPanel(libTable);
|
||||
myProvider = provider;
|
||||
myRootModel = rootModel;
|
||||
myLibManager = libManager;
|
||||
}
|
||||
|
||||
@Nls
|
||||
@@ -71,19 +70,19 @@ public class LangScriptingContextConfigurable implements Configurable {
|
||||
|
||||
@Override
|
||||
public void apply() throws ConfigurationException {
|
||||
if (myRootModel != null) {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myRootModel.commit();
|
||||
}
|
||||
});
|
||||
}
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myLibManager.commitModel();
|
||||
myPanel.resetTable(myLibManager.getLibraryTable());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
//To change body of implemented methods use File | Settings | File Templates.
|
||||
myLibManager.resetModel();
|
||||
myPanel.resetTable(myLibManager.getLibraryTable());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+5
-14
@@ -33,14 +33,12 @@ public class ScriptingContextsConfigurable implements Configurable, Configurable
|
||||
|
||||
private MainScriptingContextsPanel myPanel;
|
||||
private String myLangNames;
|
||||
private Project myProject;
|
||||
private ModifiableRootModel myRootModel;
|
||||
private ScriptingLibraryManager myLibManager;
|
||||
|
||||
public ScriptingContextsConfigurable(Project project) {
|
||||
myPanel = new MainScriptingContextsPanel();
|
||||
myLangNames = getLangNames();
|
||||
myProject = project;
|
||||
myRootModel = ScriptingLibraryManager.getRootModel(project);
|
||||
myLibManager = new ScriptingLibraryManager(project);
|
||||
}
|
||||
|
||||
@Nls
|
||||
@@ -71,9 +69,7 @@ public class ScriptingContextsConfigurable implements Configurable, Configurable
|
||||
|
||||
@Override
|
||||
public void apply() throws ConfigurationException {
|
||||
if (myRootModel != null) {
|
||||
myRootModel.commit();
|
||||
}
|
||||
myLibManager.commitModel();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -83,14 +79,14 @@ public class ScriptingContextsConfigurable implements Configurable, Configurable
|
||||
|
||||
@Override
|
||||
public void disposeUIResources() {
|
||||
disposeModel();
|
||||
myLibManager.disposeModel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Configurable[] getConfigurables() {
|
||||
ArrayList<LangScriptingContextConfigurable> configurables = new ArrayList<LangScriptingContextConfigurable>();
|
||||
for (LangScriptingContextProvider provider : LangScriptingContextProvider.getProviders()) {
|
||||
configurables.add(new LangScriptingContextConfigurable(myRootModel, provider));
|
||||
configurables.add(new LangScriptingContextConfigurable(myLibManager, provider));
|
||||
}
|
||||
return configurables.toArray(new LangScriptingContextConfigurable[configurables.size()]);
|
||||
}
|
||||
@@ -104,9 +100,4 @@ public class ScriptingContextsConfigurable implements Configurable, Configurable
|
||||
return result.substring(0, result.length() - 1);
|
||||
}
|
||||
|
||||
public void disposeModel() {
|
||||
if (myRootModel != null && !myRootModel.isDisposed()) {
|
||||
myRootModel.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+35
-1
@@ -32,8 +32,16 @@ public class ScriptingLibraryManager {
|
||||
|
||||
public static final String WEB_MODULE_TYPE = "WEB_MODULE";
|
||||
|
||||
private ModifiableRootModel myRootModel;
|
||||
private Project myProject;
|
||||
|
||||
public ScriptingLibraryManager(Project project) {
|
||||
myProject = project;
|
||||
myRootModel = getRootModel(project);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static ModifiableRootModel getRootModel(Project project) {
|
||||
private static ModifiableRootModel getRootModel(Project project) {
|
||||
for (Module module : ModuleManager.getInstance(project).getModules()) {
|
||||
if (WEB_MODULE_TYPE.equals(module.getModuleType().getId())) {
|
||||
return ModuleRootManager.getInstance(module).getModifiableModel();
|
||||
@@ -41,4 +49,30 @@ public class ScriptingLibraryManager {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void disposeModel() {
|
||||
if (myRootModel != null && !myRootModel.isDisposed()) {
|
||||
myRootModel.dispose();
|
||||
myRootModel = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void commitModel() {
|
||||
if (myRootModel != null && !myRootModel.isDisposed()) {
|
||||
myRootModel.commit();
|
||||
}
|
||||
}
|
||||
|
||||
public void resetModel() {
|
||||
disposeModel();
|
||||
myRootModel = getRootModel(myProject);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public LibraryTable getLibraryTable() {
|
||||
if (myRootModel != null) {
|
||||
return myRootModel.getModuleLibraryTable();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
+6
@@ -74,4 +74,10 @@ public class ScriptingLibrariesPanel {
|
||||
return myModified;
|
||||
}
|
||||
|
||||
public void resetTable(LibraryTable libTable) {
|
||||
myLibTableModel.resetTable(libTable);
|
||||
myModified = false;
|
||||
myLibraryTable.repaint();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
@@ -36,6 +36,10 @@ public class ScriptingLibraryTableModel extends AbstractTableModel {
|
||||
myLibTable = libTable;
|
||||
}
|
||||
|
||||
public void resetTable(LibraryTable libTable) {
|
||||
myLibTable = libTable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRowCount() {
|
||||
if (myLibTable != null) {
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package com.intellij.refactoring.rename;
|
||||
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
@@ -45,11 +43,9 @@ import org.jetbrains.annotations.TestOnly;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
|
||||
public class RenameDialog extends RefactoringDialog {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.rename.RenameDialog");
|
||||
@@ -126,11 +122,6 @@ public class RenameDialog extends RefactoringDialog {
|
||||
};
|
||||
myNameSuggestionsField.addDataChangedListener(myNameChangedListener);
|
||||
|
||||
myNameSuggestionsField.getComponent().registerKeyboardAction(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
completeVariable(myNameSuggestionsField.getEditor());
|
||||
}
|
||||
}, KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, InputEvent.CTRL_MASK), JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||
}
|
||||
|
||||
public String[] getSuggestedNames() {
|
||||
@@ -146,21 +137,6 @@ public class RenameDialog extends RefactoringDialog {
|
||||
return ArrayUtil.toStringArray(result);
|
||||
}
|
||||
|
||||
private void completeVariable(Editor editor) {
|
||||
final String prefix = myNameSuggestionsField.getEnteredName();
|
||||
Collection<LookupElement> items = null;
|
||||
for(NameSuggestionProvider provider: Extensions.getExtensions(NameSuggestionProvider.EP_NAME)) {
|
||||
items = provider.completeName(myPsiElement, myNameSuggestionContext, prefix);
|
||||
if (items != null) break;
|
||||
}
|
||||
|
||||
if (items != null) {
|
||||
final LookupElement[] lookupItems = items.toArray(new LookupElement[items.size()]);
|
||||
editor.getCaretModel().moveToOffset(prefix.length());
|
||||
editor.getSelectionModel().removeSelection();
|
||||
LookupManager.getInstance(myProject).showLookup(editor, lookupItems, prefix);
|
||||
}
|
||||
}
|
||||
|
||||
public String getNewName() {
|
||||
return myNameSuggestionsField.getEnteredName().trim();
|
||||
|
||||
@@ -210,18 +210,29 @@ public class HintManagerImpl extends HintManager implements Disposable {
|
||||
((ScrollAwareHint)hint.getComponent()).editorScrolled();
|
||||
}
|
||||
|
||||
if (!hint.isVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Editor editor = e.getEditor();
|
||||
if (!editor.getComponent().isShowing() || editor.isOneLineMode()) return;
|
||||
Rectangle newRectangle = e.getOldRectangle();
|
||||
Rectangle oldRectangle = e.getNewRectangle();
|
||||
Rectangle bounds = hint.getBounds();
|
||||
Point location = bounds.getLocation();
|
||||
Point location;
|
||||
|
||||
location = SwingUtilities.convertPoint(
|
||||
editor.getComponent().getRootPane().getLayeredPane(),
|
||||
location,
|
||||
editor.getContentComponent()
|
||||
);
|
||||
final Window window = SwingUtilities.getWindowAncestor(hint.getComponent());
|
||||
final boolean realPopup = window != null && window != SwingUtilities.getWindowAncestor(editor.getComponent());
|
||||
if (realPopup) {
|
||||
location = window.getLocationOnScreen();
|
||||
SwingUtilities.convertPointFromScreen(location, editor.getContentComponent());
|
||||
} else {
|
||||
location = SwingUtilities.convertPoint(
|
||||
editor.getComponent().getRootPane().getLayeredPane(),
|
||||
bounds.getLocation(),
|
||||
editor.getContentComponent()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
int xOffset = location.x - oldRectangle.x;
|
||||
@@ -232,13 +243,18 @@ public class HintManagerImpl extends HintManager implements Disposable {
|
||||
|
||||
final boolean valid = hideIfOutOfEditor ? oldRectangle.contains(newBounds) : oldRectangle.intersects(newBounds);
|
||||
if (valid) {
|
||||
location = SwingUtilities.convertPoint(
|
||||
editor.getContentComponent(),
|
||||
location,
|
||||
editor.getComponent().getRootPane().getLayeredPane()
|
||||
);
|
||||
if (!realPopup) {
|
||||
location = SwingUtilities.convertPoint(
|
||||
editor.getContentComponent(),
|
||||
location,
|
||||
editor.getComponent().getRootPane().getLayeredPane()
|
||||
);
|
||||
hint.updateBounds(location.x, location.y);
|
||||
} else {
|
||||
SwingUtilities.convertPointToScreen(location, editor.getContentComponent());
|
||||
window.setLocation(location);
|
||||
}
|
||||
|
||||
hint.updateBounds(location.x, location.y);
|
||||
}
|
||||
else {
|
||||
hint.hide();
|
||||
|
||||
+10
@@ -363,11 +363,14 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
if (myOrientation == SwingConstants.HORIZONTAL) {
|
||||
int eachX = 0;
|
||||
int eachY = 0;
|
||||
int maxHeight = 0;
|
||||
for (int i = 0; i < componentCount; i++) {
|
||||
final Component eachComp = getComponent(i);
|
||||
final boolean isLast = i == componentCount - 1;
|
||||
|
||||
final Rectangle eachBound = new Rectangle(eachComp.getPreferredSize());
|
||||
maxHeight = Math.max(eachBound.height, maxHeight);
|
||||
|
||||
if (!full) {
|
||||
boolean inside;
|
||||
if (isLast) {
|
||||
@@ -408,6 +411,13 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
|
||||
bounds.get(i).setBounds(eachBound);
|
||||
}
|
||||
|
||||
for (final Rectangle r : bounds) {
|
||||
if (r.height < maxHeight && r.y == 0) {
|
||||
r.y = (maxHeight - r.height) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
int eachX = 0;
|
||||
|
||||
@@ -468,7 +468,9 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
|
||||
return null; // suppress events in shutdown hook
|
||||
}
|
||||
DocumentEvent event = new DocumentEventImpl(this, offset, oldString, newString, myModificationStamp, wholeTextReplaced);
|
||||
|
||||
//System.out.printf("%nbefore change: offset=%d, old text='%s', new text='%s', document modification stamp=%d%nDocument:'%s'%n",
|
||||
// event.getOffset(), event.getOldFragment(), event.getNewFragment(), event.getDocument().getModificationStamp(),
|
||||
// event.getDocument().getText());
|
||||
for (int i = myDocumentListeners.size() - 1; i >= 0; i--) {
|
||||
try {
|
||||
myDocumentListeners.get(i).beforeDocumentChange(event);
|
||||
@@ -484,6 +486,8 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
|
||||
|
||||
@SuppressWarnings({"ForLoopReplaceableByForEach"})
|
||||
private void changedUpdate(DocumentEvent event, long newModificationStamp) {
|
||||
//System.out.printf("after change: new modification stamp=%d%ndocument='%s'%n", event.getDocument().getModificationStamp(),
|
||||
// event.getDocument().getText());
|
||||
if (ShutDownTracker.isShutdownHookRunning()) {
|
||||
return; // suppress events in shutdown hook
|
||||
}
|
||||
|
||||
@@ -116,11 +116,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi
|
||||
}
|
||||
|
||||
Rectangle visibleArea = myEditor.getScrollingModel().getVisibleArea();
|
||||
if (visibleArea.width <= 0 || visibleArea.height <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode() && myEditor.getScrollingModel().getVisibleArea().width <= 0) {
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode() && (visibleArea.width <= 0 || visibleArea.height <= 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ public class ShutDownTracker implements Runnable {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.util.ShutDownTracker");
|
||||
private static ShutDownTracker ourInstance;
|
||||
private final List<Thread> myThreads = new ArrayList<Thread>();
|
||||
private final List<Thread> myShutdownThreads = new ArrayList<Thread>();
|
||||
private final LinkedList<Thread> myShutdownThreads = new LinkedList<Thread>();
|
||||
private final LinkedList<Runnable> myShutdownTasks = new LinkedList<Runnable>();
|
||||
private volatile boolean myIsShutdownHookRunning = false;
|
||||
|
||||
@@ -48,17 +48,6 @@ public class ShutDownTracker implements Runnable {
|
||||
public void run() {
|
||||
myIsShutdownHookRunning = true;
|
||||
|
||||
while (!myShutdownTasks.isEmpty()) {
|
||||
// task can change myShutdownTasks
|
||||
final Runnable task = myShutdownTasks.removeLast();
|
||||
try {
|
||||
task.run();
|
||||
}
|
||||
catch (Throwable e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
Thread[] threads = getStopperThreads();
|
||||
while (threads.length > 0) {
|
||||
Thread thread = threads[0];
|
||||
@@ -77,14 +66,27 @@ public class ShutDownTracker implements Runnable {
|
||||
}
|
||||
threads = getStopperThreads();
|
||||
}
|
||||
|
||||
for (int idx = myShutdownThreads.size() - 1; idx >= 0; idx--) {
|
||||
final Thread thread = myShutdownThreads.remove(idx);
|
||||
thread.start();
|
||||
|
||||
while (!myShutdownTasks.isEmpty()) {
|
||||
// task can change myShutdownTasks
|
||||
final Runnable task = myShutdownTasks.removeLast();
|
||||
try {
|
||||
thread.join();
|
||||
task.run();
|
||||
}
|
||||
catch (Throwable e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (!myShutdownThreads.isEmpty()) {
|
||||
for (Thread thread = myShutdownThreads.removeLast(); thread != null; thread = myShutdownThreads.removeLast()) {
|
||||
thread.start();
|
||||
try {
|
||||
thread.join();
|
||||
}
|
||||
catch (InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
catch (InterruptedException e) { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +107,7 @@ public class ShutDownTracker implements Runnable {
|
||||
}
|
||||
|
||||
public void registerShutdownThread(final Thread thread) {
|
||||
myShutdownThreads.add(thread);
|
||||
myShutdownThreads.addLast(thread);
|
||||
}
|
||||
|
||||
public void registerShutdownThread(int index, final Thread thread) {
|
||||
|
||||
@@ -19,7 +19,6 @@ package com.intellij.openapi.util.io;
|
||||
import com.intellij.CommonBundle;
|
||||
import com.intellij.Patches;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.ShutDownTracker;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.Processor;
|
||||
@@ -429,14 +428,14 @@ public class FileUtil {
|
||||
public void run() {
|
||||
final Thread currentThread = Thread.currentThread();
|
||||
currentThread.setPriority(Thread.MIN_PRIORITY);
|
||||
ShutDownTracker.getInstance().registerStopperThread(currentThread);
|
||||
//ShutDownTracker.getInstance().registerStopperThread(currentThread);
|
||||
try {
|
||||
for (File tempFile : tempFiles) {
|
||||
delete(tempFile);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
ShutDownTracker.getInstance().unregisterStopperThread(currentThread);
|
||||
//ShutDownTracker.getInstance().unregisterStopperThread(currentThread);
|
||||
currentThread.setPriority(Thread.NORM_PRIORITY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.intellij.util.containers;
|
||||
|
||||
import gnu.trove.TObjectHashingStrategy;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
@@ -69,7 +70,7 @@ public class StripedLockConcurrentHashMap<K, V> extends _CHMSegment<K, V> implem
|
||||
|
||||
/* ---------------- Public operations -------------- */
|
||||
|
||||
public StripedLockConcurrentHashMap(TObjectHashingStrategy<K> hashingStrategy) {
|
||||
public StripedLockConcurrentHashMap(@Nullable TObjectHashingStrategy<K> hashingStrategy) {
|
||||
this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, hashingStrategy);
|
||||
}
|
||||
|
||||
@@ -90,7 +91,7 @@ public class StripedLockConcurrentHashMap<K, V> extends _CHMSegment<K, V> implem
|
||||
this(initialCapacity, loadFactor, null);
|
||||
}
|
||||
|
||||
public StripedLockConcurrentHashMap(int initialCapacity, float loadFactor, TObjectHashingStrategy<K> hashingStrategy) {
|
||||
public StripedLockConcurrentHashMap(int initialCapacity, float loadFactor, @Nullable TObjectHashingStrategy<K> hashingStrategy) {
|
||||
super(getInitCap(initialCapacity, loadFactor), loadFactor, hashingStrategy);
|
||||
}
|
||||
|
||||
@@ -138,7 +139,7 @@ public class StripedLockConcurrentHashMap<K, V> extends _CHMSegment<K, V> implem
|
||||
*
|
||||
* @param t the map
|
||||
*/
|
||||
public StripedLockConcurrentHashMap(Map<? extends K, ? extends V> t) {
|
||||
public StripedLockConcurrentHashMap(@NotNull Map<? extends K, ? extends V> t) {
|
||||
this(Math.max((int)(t.size() / DEFAULT_LOAD_FACTOR) + 1, 11), DEFAULT_LOAD_FACTOR);
|
||||
putAll(t);
|
||||
}
|
||||
@@ -166,7 +167,7 @@ public class StripedLockConcurrentHashMap<K, V> extends _CHMSegment<K, V> implem
|
||||
* @throws NullPointerException if the key is
|
||||
* <tt>null</tt>.
|
||||
*/
|
||||
public V get(Object key) {
|
||||
public V get(@NotNull Object key) {
|
||||
K kKey = (K)key;
|
||||
int hash = myHashingStrategy.computeHashCode(kKey); // throws NullPointerException if key null
|
||||
return get(kKey, hash);
|
||||
@@ -182,7 +183,7 @@ public class StripedLockConcurrentHashMap<K, V> extends _CHMSegment<K, V> implem
|
||||
* @throws NullPointerException if the key is
|
||||
* <tt>null</tt>.
|
||||
*/
|
||||
public boolean containsKey(Object key) {
|
||||
public boolean containsKey(@NotNull Object key) {
|
||||
K kKey = (K)key;
|
||||
int hash = myHashingStrategy.computeHashCode(kKey); // throws NullPointerException if key null
|
||||
return containsKey(kKey, hash);
|
||||
@@ -203,7 +204,7 @@ public class StripedLockConcurrentHashMap<K, V> extends _CHMSegment<K, V> implem
|
||||
* <tt>false</tt> otherwise.
|
||||
* @throws NullPointerException if the value is <tt>null</tt>.
|
||||
*/
|
||||
public boolean contains(Object value) {
|
||||
public boolean contains(@NotNull Object value) {
|
||||
return containsValue(value);
|
||||
}
|
||||
|
||||
@@ -262,7 +263,10 @@ public class StripedLockConcurrentHashMap<K, V> extends _CHMSegment<K, V> implem
|
||||
*/
|
||||
public void putAll(@NotNull Map<? extends K, ? extends V> t) {
|
||||
for (Entry<? extends K, ? extends V> e : t.entrySet()) {
|
||||
put(e.getKey(), e.getValue());
|
||||
V value = e.getValue();
|
||||
if (value != null) { // null is possible if the entry has just been removed
|
||||
put(e.getKey(), value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -507,20 +511,24 @@ public class StripedLockConcurrentHashMap<K, V> extends _CHMSegment<K, V> implem
|
||||
}
|
||||
|
||||
final class KeyIterator extends HashIterator implements Iterator<K>, Enumeration<K> {
|
||||
@NotNull
|
||||
public K next() {
|
||||
return nextEntry().key;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public K nextElement() {
|
||||
return nextEntry().key;
|
||||
}
|
||||
}
|
||||
|
||||
final class ValueIterator extends HashIterator implements Iterator<V>, Enumeration<V> {
|
||||
@NotNull
|
||||
public V next() {
|
||||
return nextEntry().value;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public V nextElement() {
|
||||
return nextEntry().value;
|
||||
}
|
||||
@@ -534,11 +542,13 @@ public class StripedLockConcurrentHashMap<K, V> extends _CHMSegment<K, V> implem
|
||||
* itself acts as a forwarding pseudo-entry.
|
||||
*/
|
||||
final class EntryIterator extends HashIterator implements Entry<K, V>, Iterator<Entry<K, V>> {
|
||||
@NotNull
|
||||
public Entry<K, V> next() {
|
||||
nextEntry();
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public K getKey() {
|
||||
if (lastReturned == null) {
|
||||
throw new IllegalStateException("Entry was removed");
|
||||
@@ -546,6 +556,7 @@ public class StripedLockConcurrentHashMap<K, V> extends _CHMSegment<K, V> implem
|
||||
return lastReturned.key;
|
||||
}
|
||||
|
||||
@Nullable("null means the entry has just been removed")
|
||||
public V getValue() {
|
||||
if (lastReturned == null) {
|
||||
throw new IllegalStateException("Entry was removed");
|
||||
@@ -553,7 +564,7 @@ public class StripedLockConcurrentHashMap<K, V> extends _CHMSegment<K, V> implem
|
||||
return get(lastReturned.key);
|
||||
}
|
||||
|
||||
public V setValue(V value) {
|
||||
public V setValue(@NotNull V value) {
|
||||
if (lastReturned == null) {
|
||||
throw new IllegalStateException("Entry was removed");
|
||||
}
|
||||
@@ -571,7 +582,7 @@ public class StripedLockConcurrentHashMap<K, V> extends _CHMSegment<K, V> implem
|
||||
Entry e = (Entry)o;
|
||||
K o1 = getKey();
|
||||
K o2 = (K)e.getKey();
|
||||
return (o1 == null ? o2 == null : myHashingStrategy.equals(o1, o2)) && eq(getValue(), e.getValue());
|
||||
return myHashingStrategy.equals(o1, o2) && getValue().equals(e.getValue());
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
@@ -582,8 +593,7 @@ public class StripedLockConcurrentHashMap<K, V> extends _CHMSegment<K, V> implem
|
||||
|
||||
Object k = getKey();
|
||||
Object v = getValue();
|
||||
return (k == null ? 0 : k.hashCode()) ^
|
||||
(v == null ? 0 : v.hashCode());
|
||||
return k.hashCode() ^ v.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
@@ -591,15 +601,8 @@ public class StripedLockConcurrentHashMap<K, V> extends _CHMSegment<K, V> implem
|
||||
if (lastReturned == null) {
|
||||
return super.toString();
|
||||
}
|
||||
else {
|
||||
return getKey() + "=" + getValue();
|
||||
}
|
||||
return getKey() + "=" + getValue();
|
||||
}
|
||||
|
||||
boolean eq(Object o1, Object o2) {
|
||||
return o1 == null ? o2 == null : o1.equals(o2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
final class KeySet extends AbstractSet<K> {
|
||||
@@ -728,23 +731,25 @@ public class StripedLockConcurrentHashMap<K, V> extends _CHMSegment<K, V> implem
|
||||
* is made accessible.
|
||||
*/
|
||||
final class SimpleEntry implements Entry<K, V> {
|
||||
K key;
|
||||
final K key;
|
||||
V value;
|
||||
|
||||
public SimpleEntry(Entry<K, V> e) {
|
||||
public SimpleEntry(@NotNull Entry<K, V> e) {
|
||||
key = e.getKey();
|
||||
value = e.getValue();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public K getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public V getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public V setValue(V value) {
|
||||
public V setValue(@NotNull V value) {
|
||||
V oldValue = this.value;
|
||||
this.value = value;
|
||||
return oldValue;
|
||||
@@ -756,21 +761,16 @@ public class StripedLockConcurrentHashMap<K, V> extends _CHMSegment<K, V> implem
|
||||
}
|
||||
Entry e = (Entry)o;
|
||||
K o2 = (K)e.getKey();
|
||||
return (key == null ? o2 == null : myHashingStrategy.equals(key, o2)) && eq(value, e.getValue());
|
||||
return myHashingStrategy.equals(key, o2) && value.equals(e.getValue());
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return (key == null ? 0 : key.hashCode()) ^
|
||||
(value == null ? 0 : value.hashCode());
|
||||
return key.hashCode() ^ value.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return key + "=" + value;
|
||||
}
|
||||
|
||||
boolean eq(Object o1, Object o2) {
|
||||
return o1 == null ? o2 == null : o1.equals(o2);
|
||||
}
|
||||
}
|
||||
|
||||
static class CanonicalHashingStrategy<K> implements TObjectHashingStrategy<K> {
|
||||
@@ -790,7 +790,7 @@ public class StripedLockConcurrentHashMap<K, V> extends _CHMSegment<K, V> implem
|
||||
return h;
|
||||
}
|
||||
|
||||
public boolean equals(final K o1, final K o2) {
|
||||
public boolean equals(@NotNull K o1, @NotNull K o2) {
|
||||
return o1.equals(o2);
|
||||
}
|
||||
}
|
||||
@@ -964,9 +964,7 @@ class _CHMSegment<K, V> {
|
||||
HashEntry[] tab = table;
|
||||
int len = tab.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
for (HashEntry<K, V> e = tab[i];
|
||||
e != null;
|
||||
e = e.next) {
|
||||
for (HashEntry<K, V> e = tab[i]; e != null; e = e.next) {
|
||||
V v = e.value;
|
||||
if (v == null) // recheck
|
||||
{
|
||||
@@ -1124,7 +1122,7 @@ class _CHMSegment<K, V> {
|
||||
/*
|
||||
* Remove; match on key only if value null, else match both.
|
||||
*/
|
||||
V remove(K key, int hash, Object value) {
|
||||
V remove(@NotNull K key, int hash, @Nullable("null means don't care") Object value) {
|
||||
try {
|
||||
lock();
|
||||
int c = count - 1;
|
||||
@@ -1188,9 +1186,9 @@ class _CHMSegment<K, V> {
|
||||
* an unsynchronized access method.
|
||||
*/
|
||||
static final class HashEntry<K, V> {
|
||||
final K key;
|
||||
@NotNull final K key;
|
||||
final int hash;
|
||||
volatile V value;
|
||||
@NotNull volatile V value;
|
||||
final HashEntry<K, V> next;
|
||||
|
||||
HashEntry(@NotNull K key, int hash, HashEntry<K, V> next, @NotNull V value) {
|
||||
|
||||
@@ -276,24 +276,29 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
|
||||
}
|
||||
}
|
||||
|
||||
private VcsDirtyScopeManagerImpl getVcsManager() {
|
||||
try {
|
||||
return ((VcsDirtyScopeManagerImpl) VcsDirtyScopeManager.getInstance(myProject));
|
||||
}
|
||||
catch(ProcessCanceledException ex) {
|
||||
return null;
|
||||
}
|
||||
catch(Exception ex) {
|
||||
LOG.error(ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void updateImmediately(final AtomicSectionsAware atomicSectionsAware) {
|
||||
FileHolderComposite composite;
|
||||
ChangeListWorker changeListWorker;
|
||||
final FileHolderComposite composite;
|
||||
final ChangeListWorker changeListWorker;
|
||||
|
||||
final ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(myProject);
|
||||
if (! vcsManager.hasActiveVcss()) return;
|
||||
|
||||
final VcsDirtyScopeManagerImpl dirtyScopeManager;
|
||||
try {
|
||||
dirtyScopeManager = ((VcsDirtyScopeManagerImpl) VcsDirtyScopeManager.getInstanceChecked(myProject));
|
||||
}
|
||||
catch(ProcessCanceledException ex) {
|
||||
return;
|
||||
}
|
||||
catch(Exception ex) {
|
||||
LOG.error(ex);
|
||||
return;
|
||||
}
|
||||
final VcsDirtyScopeManagerImpl dirtyScopeManager = getVcsManager();
|
||||
if (dirtyScopeManager == null) return;
|
||||
|
||||
final VcsInvalidated invalidated = dirtyScopeManager.retrieveScopes();
|
||||
if (invalidated == null || invalidated.isEmpty()) {
|
||||
// a hack here; but otherwise everything here should be refactored ;)
|
||||
@@ -305,6 +310,8 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
|
||||
final boolean wasEverythingDirty = invalidated.isEverythingDirty();
|
||||
final List<VcsDirtyScope> scopes = invalidated.getScopes();
|
||||
|
||||
|
||||
|
||||
try {
|
||||
checkIfDisposed();
|
||||
|
||||
|
||||
+21
-15
@@ -22,7 +22,8 @@ import com.intellij.openapi.project.ProjectLocator;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.vcs.FilePath;
|
||||
import com.intellij.openapi.vcs.FilePathImpl;
|
||||
import com.intellij.openapi.vfs.*;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.openapi.vfs.newvfs.BulkFileListener;
|
||||
import com.intellij.openapi.vfs.newvfs.events.*;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
@@ -71,13 +72,15 @@ public class VcsDirtyScopeVfsListener implements ApplicationComponent, BulkFileL
|
||||
// collect files and directories - sources of events
|
||||
for (VFileEvent event : events) {
|
||||
final VirtualFile file = getFileForEvent(event);
|
||||
if (file == null) { continue; }
|
||||
if (file == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (event instanceof VFileDeleteEvent) {
|
||||
if (!file.isInLocalFileSystem()) { continue; }
|
||||
dirtyFilesAndDirs.add(file);
|
||||
dirtyFilesAndDirs.add(file, true);
|
||||
} else if (event instanceof VFileMoveEvent || event instanceof VFilePropertyChangeEvent) {
|
||||
dirtyFilesAndDirs.addToFiles(file);
|
||||
dirtyFilesAndDirs.addToFiles(file, false); // todo ?
|
||||
}
|
||||
}
|
||||
// and notify VCSDirtyScopeManager
|
||||
@@ -90,20 +93,22 @@ public class VcsDirtyScopeVfsListener implements ApplicationComponent, BulkFileL
|
||||
// collect files and directories - sources of events
|
||||
for (VFileEvent event : events) {
|
||||
final VirtualFile file = getFileForEvent(event);
|
||||
if (file == null) { continue; }
|
||||
if (file == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (event instanceof VFileContentChangeEvent || event instanceof VFileCopyEvent || event instanceof VFileCreateEvent) {
|
||||
dirtyFilesAndDirs.addToFiles(file);
|
||||
dirtyFilesAndDirs.add(file, false);
|
||||
} else if (event instanceof VFilePropertyChangeEvent) {
|
||||
final VFilePropertyChangeEvent pce = (VFilePropertyChangeEvent) event;
|
||||
|
||||
if (pce.getPropertyName().equals(VirtualFile.PROP_NAME)) {
|
||||
// if a file was renamed, then the file is dirty and its parent directory is dirty too;
|
||||
// if a directory was renamed, all its children are recursively dirty, the parent dir is also dirty but not recursively.
|
||||
dirtyFilesAndDirs.add(file); // the file is dirty recursively
|
||||
dirtyFilesAndDirs.addToFiles(file.getParent()); // directory is dirty alone. if parent is null - is checked in the method
|
||||
dirtyFilesAndDirs.add(file, false); // the file is dirty recursively
|
||||
dirtyFilesAndDirs.addToFiles(file.getParent(), false); // directory is dirty alone. if parent is null - is checked in the method
|
||||
} else {
|
||||
dirtyFilesAndDirs.addToFiles(file);
|
||||
dirtyFilesAndDirs.addToFiles(file, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -133,11 +138,12 @@ public class VcsDirtyScopeVfsListener implements ApplicationComponent, BulkFileL
|
||||
* @param file file which path is to be added.
|
||||
* @param addToFiles If true, then add to dirty files even if it is a directory. Otherwise add to the proper set.
|
||||
*/
|
||||
private void add(VirtualFile file, boolean addToFiles) {
|
||||
public void add(VirtualFile file, boolean addToFiles, final boolean forDelete) {
|
||||
if (file == null) { return; }
|
||||
final boolean isDirectory = file.isDirectory();
|
||||
// need to create FilePath explicitly without referring to VirtualFile because the path of VirtualFile may change
|
||||
final FilePathImpl path = new FilePathImpl(new File(file.getPath()), isDirectory);
|
||||
final FilePathImpl path = forDelete ? new FilePathImpl(new File(file.getPath()), isDirectory) :
|
||||
new FilePathImpl(file);
|
||||
|
||||
final Collection<VcsDirtyScopeManager> managers = getManagers(file);
|
||||
for (VcsDirtyScopeManager manager : managers) {
|
||||
@@ -158,16 +164,16 @@ public class VcsDirtyScopeVfsListener implements ApplicationComponent, BulkFileL
|
||||
/**
|
||||
* Adds files to the collection of files and directories - to the collection of directories (which are handled recursively).
|
||||
*/
|
||||
void add(VirtualFile file) {
|
||||
add(file, false);
|
||||
void add(VirtualFile file, final boolean forDelete) {
|
||||
add(file, false, forDelete);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds to the collection of files. A file (even if it is a directory) is marked dirty alone (not recursively).
|
||||
* Use this method, when you want directory not to be marked dirty recursively.
|
||||
*/
|
||||
void addToFiles(VirtualFile file) {
|
||||
add(file, true);
|
||||
void addToFiles(VirtualFile file, final boolean forDelete) {
|
||||
add(file, true, forDelete);
|
||||
}
|
||||
|
||||
void markDirty() {
|
||||
|
||||
@@ -562,11 +562,15 @@ public class PsiUtil {
|
||||
|
||||
@Nullable
|
||||
public static PsiClass getContextClass(PsiElement context) {
|
||||
GroovyPsiElement parent = PsiTreeUtil.getParentOfType(context, GrTypeDefinition.class, GroovyFileBase.class);
|
||||
if (parent instanceof GrTypeDefinition) {
|
||||
return (PsiClass)parent;
|
||||
} else if (parent instanceof GroovyFileBase) {
|
||||
return ((GroovyFileBase)parent).getScriptClass();
|
||||
while (context != null) {
|
||||
if (context instanceof GrTypeDefinition) {
|
||||
return (PsiClass)context;
|
||||
}
|
||||
else if (context instanceof GroovyFileBase) {
|
||||
return ((GroovyFileBase)context).getScriptClass();
|
||||
}
|
||||
|
||||
context = context.getContext();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -4,16 +4,22 @@ import com.intellij.ide.startup.impl.StartupManagerImpl;
|
||||
import com.intellij.openapi.components.ProjectComponent;
|
||||
import com.intellij.openapi.startup.StartupManager;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vcs.FileStatus;
|
||||
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
|
||||
import com.intellij.openapi.vcs.changes.ChangeListManager;
|
||||
import com.intellij.openapi.vcs.changes.IgnoredBeanFactory;
|
||||
import com.intellij.openapi.vcs.changes.IgnoredFileBean;
|
||||
import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
|
||||
import com.intellij.openapi.vcs.impl.ProjectLevelVcsManagerImpl;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.testFramework.AbstractVcsTestCase;
|
||||
import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory;
|
||||
import com.intellij.testFramework.fixtures.TempDirTestFixture;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@@ -46,7 +52,7 @@ public class IgnoredFilesTest extends AbstractVcsTestCase {
|
||||
myVcs = SvnVcs.getInstance(myProject);
|
||||
myVcsManager = (ProjectLevelVcsManagerImpl) ProjectLevelVcsManager.getInstance(myProject);
|
||||
myVcsManager.registerVcs(myVcs);
|
||||
myVcsManager.setDirectoryMapping("", myVcs.getName());
|
||||
myVcsManager.setDirectoryMapping(myWorkingCopyDir.getPath(), myVcs.getName());
|
||||
|
||||
((ProjectComponent) myChangeListManager).projectOpened();
|
||||
myVcsDirtyScopeManager = VcsDirtyScopeManager.getInstance(myProject);
|
||||
@@ -72,7 +78,7 @@ public class IgnoredFilesTest extends AbstractVcsTestCase {
|
||||
}
|
||||
|
||||
// they all blink now
|
||||
/*
|
||||
|
||||
@Test
|
||||
public void testFileIsIgnored() throws Exception {
|
||||
final String filePath1 = myClientRoot.getPath() + "/a";
|
||||
@@ -97,8 +103,8 @@ public class IgnoredFilesTest extends AbstractVcsTestCase {
|
||||
|
||||
@Test
|
||||
public void testDirIsIgnored() throws Exception {
|
||||
final String dirPath1 = myClientRoot.getPath() + "/a";
|
||||
final File dir = new File(dirPath1);
|
||||
//final String dirPath1 = myClientRoot.getPath() + "/a";
|
||||
final File dir = new File(myClientRoot, "a");
|
||||
dir.mkdir();
|
||||
final File innerDir = new File(dir, "innerDir");
|
||||
innerDir.mkdir();
|
||||
@@ -111,7 +117,7 @@ public class IgnoredFilesTest extends AbstractVcsTestCase {
|
||||
final VirtualFile vf1 = myLocalFileSystem.refreshAndFindFileByIoFile(file1);
|
||||
final VirtualFile vf2 = myLocalFileSystem.refreshAndFindFileByIoFile(file2);
|
||||
|
||||
final IgnoredFileBean ignoredFileBean = IgnoredBeanFactory.ignoreUnderDirectory(dirPath1, myProject);
|
||||
final IgnoredFileBean ignoredFileBean = IgnoredBeanFactory.ignoreUnderDirectory(FileUtil.toSystemIndependentName(dir.getPath()), myProject);
|
||||
myChangeListManager.addFilesToIgnore(ignoredFileBean);
|
||||
|
||||
dirty();
|
||||
@@ -124,7 +130,7 @@ public class IgnoredFilesTest extends AbstractVcsTestCase {
|
||||
@Test
|
||||
public void testPatternIsIgnored() throws Exception {
|
||||
final String dirPath1 = myClientRoot.getPath() + "/a";
|
||||
final File dir = new File(dirPath1);
|
||||
final File dir = new File(myClientRoot, "a");
|
||||
dir.mkdir();
|
||||
final File innerDir = new File(dir, "innerDir");
|
||||
innerDir.mkdir();
|
||||
@@ -155,5 +161,5 @@ public class IgnoredFilesTest extends AbstractVcsTestCase {
|
||||
Assert.assertNotNull(vf);
|
||||
Assert.assertTrue(myChangeListManager.isIgnoredFile(vf));
|
||||
Assert.assertEquals(FileStatus.IGNORED, myChangeListManager.getStatus(vf));
|
||||
} */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.codeInsight.completion;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.lang.xml.XMLLanguage;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.FileViewProvider;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiWhiteSpace;
|
||||
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
|
||||
import com.intellij.psi.templateLanguages.TemplateLanguageFileViewProvider;
|
||||
import com.intellij.xml.util.XmlUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class XmlAutoLookupHandler extends CodeCompletionHandlerBase {
|
||||
public XmlAutoLookupHandler() {
|
||||
super(CompletionType.BASIC, false, false);
|
||||
}
|
||||
|
||||
protected void doComplete(final int offset1, final int offset2, final CompletionContext context, final FileCopyPatcher dummyIdentifier, Editor editor,
|
||||
final int invocationCount) {
|
||||
PsiFile file = context.file;
|
||||
int offset = context.getStartOffset();
|
||||
|
||||
PsiElement lastElement = InjectedLanguageUtil.findElementAtNoCommit(file, offset - 1);
|
||||
if (lastElement instanceof PsiFile) { //the very end of an injected file
|
||||
lastElement = file.findElementAt(offset - 1);
|
||||
}
|
||||
if (lastElement == null) return;
|
||||
|
||||
if(!doCompleteIfNeeded(offset1, offset2, context, dummyIdentifier, editor, invocationCount, file, lastElement)) {
|
||||
// In template language based file we need to check element from template data language tree, not from base language
|
||||
FileViewProvider fileViewProvider = file.getViewProvider();
|
||||
Language templateDataLanguage;
|
||||
|
||||
final PsiElement parent = lastElement.getParent();
|
||||
if (fileViewProvider instanceof TemplateLanguageFileViewProvider &&
|
||||
(templateDataLanguage = ((TemplateLanguageFileViewProvider)fileViewProvider).getTemplateDataLanguage()) != parent.getLanguage()) {
|
||||
lastElement = fileViewProvider.findElementAt(offset - 1, templateDataLanguage);
|
||||
if (lastElement == null) return;
|
||||
doCompleteIfNeeded(offset1, offset2, context, dummyIdentifier, editor, invocationCount, file, lastElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean doCompleteIfNeeded(int offset1,
|
||||
int offset2,
|
||||
CompletionContext context,
|
||||
FileCopyPatcher dummyIdentifier,
|
||||
Editor editor,
|
||||
int invocationCount, PsiFile file, PsiElement lastElement) {
|
||||
final Ref<Boolean> isRelevantLanguage = new Ref<Boolean>();
|
||||
final Ref<Boolean> isAnt = new Ref<Boolean>();
|
||||
String text = lastElement.getText();
|
||||
final int len = context.getStartOffset() - lastElement.getTextRange().getStartOffset();
|
||||
if (len < text.length()) {
|
||||
text = text.substring(0, len);
|
||||
}
|
||||
if (text.equals("<") && isLanguageRelevant(lastElement, file, isRelevantLanguage, isAnt) ||
|
||||
text.equals(" ") && isLanguageRelevant(lastElement, file, isRelevantLanguage, isAnt) ||
|
||||
text.endsWith("${") && isLanguageRelevant(lastElement, file, isRelevantLanguage, isAnt) && isAnt.get().booleanValue() ||
|
||||
text.endsWith("@{") && isLanguageRelevant(lastElement, file, isRelevantLanguage, isAnt) && isAnt.get().booleanValue() ||
|
||||
text.endsWith("</") && isLanguageRelevant(lastElement, file, isRelevantLanguage, isAnt)) {
|
||||
super.doComplete(offset1, offset2, context, dummyIdentifier, editor, invocationCount);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isLanguageRelevant(final PsiElement element,
|
||||
final PsiFile file,
|
||||
final Ref<Boolean> isRelevantLanguage,
|
||||
final Ref<Boolean> isAnt) {
|
||||
Boolean isAntFile = isAnt.get();
|
||||
if (isAntFile == null) {
|
||||
isAntFile = XmlUtil.isAntFile(file);
|
||||
isAnt.set(isAntFile);
|
||||
}
|
||||
Boolean result = isRelevantLanguage.get();
|
||||
if (result == null) {
|
||||
Language language = element.getLanguage();
|
||||
if (element instanceof PsiWhiteSpace) language = element.getParent().getLanguage();
|
||||
result = language instanceof XMLLanguage || isAntFile.booleanValue();
|
||||
isRelevantLanguage.set(result);
|
||||
}
|
||||
return result.booleanValue();
|
||||
}
|
||||
}
|
||||
@@ -16,17 +16,20 @@
|
||||
package com.intellij.codeInsight.editorActions;
|
||||
|
||||
import com.intellij.codeInsight.AutoPopupController;
|
||||
import com.intellij.codeInsight.CodeInsightSettings;
|
||||
import com.intellij.codeInsight.completion.XmlAutoLookupHandler;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.lang.xml.XMLLanguage;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.FileViewProvider;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.PsiUtilBase;
|
||||
import com.intellij.psi.PsiWhiteSpace;
|
||||
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
|
||||
import com.intellij.psi.templateLanguages.TemplateLanguageFileViewProvider;
|
||||
import com.intellij.psi.xml.XmlTag;
|
||||
import com.intellij.xml.util.XmlUtil;
|
||||
|
||||
public class XmlAutoPopupHandler extends TypedHandlerDelegate {
|
||||
public Result checkAutoPopup(final char charTyped, final Project project, final Editor editor, final PsiFile file) {
|
||||
@@ -53,24 +56,73 @@ public class XmlAutoPopupHandler extends TypedHandlerDelegate {
|
||||
}
|
||||
|
||||
public static void autoPopupXmlLookup(final Project project, final Editor editor){
|
||||
final CodeInsightSettings settings = CodeInsightSettings.getInstance();
|
||||
if (settings.AUTO_POPUP_COMPLETION_LOOKUP) {
|
||||
final Runnable request = new Runnable(){
|
||||
public void run(){
|
||||
PsiDocumentManager.getInstance(project).commitAllDocuments();
|
||||
AutoPopupController.getInstance(project).autoPopupMemberLookup(editor, new Condition<PsiFile>() {
|
||||
@Override
|
||||
public boolean value(PsiFile file) {
|
||||
int offset = editor.getCaretModel().getOffset();
|
||||
|
||||
final PsiFile file = PsiUtilBase.getPsiFileInEditor(editor, project);
|
||||
if (file == null) return;
|
||||
|
||||
CommandProcessor.getInstance().executeCommand(project, new Runnable() {
|
||||
public void run() {
|
||||
new XmlAutoLookupHandler().invoke(project, editor, file);
|
||||
}
|
||||
}, null, null);
|
||||
PsiElement lastElement = InjectedLanguageUtil.findElementAtNoCommit(file, offset - 1);
|
||||
if (lastElement instanceof PsiFile) { //the very end of an injected file
|
||||
lastElement = file.findElementAt(offset - 1);
|
||||
}
|
||||
};
|
||||
AutoPopupController.getInstance(project).invokeAutoPopupRunnable(request, settings.AUTO_LOOKUP_DELAY);
|
||||
}
|
||||
if (lastElement == null) return false;
|
||||
|
||||
if (doCompleteIfNeeded(offset, file, lastElement)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
FileViewProvider fileViewProvider = file.getViewProvider();
|
||||
Language templateDataLanguage;
|
||||
|
||||
final PsiElement parent = lastElement.getParent();
|
||||
if (fileViewProvider instanceof TemplateLanguageFileViewProvider &&
|
||||
(templateDataLanguage = ((TemplateLanguageFileViewProvider)fileViewProvider).getTemplateDataLanguage()) != parent.getLanguage()) {
|
||||
lastElement = fileViewProvider.findElementAt(offset - 1, templateDataLanguage);
|
||||
if (lastElement == null) return false;
|
||||
return doCompleteIfNeeded(offset, file, lastElement);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static boolean doCompleteIfNeeded(int offset, PsiFile file, PsiElement lastElement) {
|
||||
final Ref<Boolean> isRelevantLanguage = new Ref<Boolean>();
|
||||
final Ref<Boolean> isAnt = new Ref<Boolean>();
|
||||
String text = lastElement.getText();
|
||||
final int len = offset - lastElement.getTextRange().getStartOffset();
|
||||
if (len < text.length()) {
|
||||
text = text.substring(0, len);
|
||||
}
|
||||
if (text.equals("<") && isLanguageRelevant(lastElement, file, isRelevantLanguage, isAnt) ||
|
||||
text.equals(" ") && isLanguageRelevant(lastElement, file, isRelevantLanguage, isAnt) ||
|
||||
text.endsWith("${") && isLanguageRelevant(lastElement, file, isRelevantLanguage, isAnt) && isAnt.get().booleanValue() ||
|
||||
text.endsWith("@{") && isLanguageRelevant(lastElement, file, isRelevantLanguage, isAnt) && isAnt.get().booleanValue() ||
|
||||
text.endsWith("</") && isLanguageRelevant(lastElement, file, isRelevantLanguage, isAnt)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isLanguageRelevant(final PsiElement element,
|
||||
final PsiFile file,
|
||||
final Ref<Boolean> isRelevantLanguage,
|
||||
final Ref<Boolean> isAnt) {
|
||||
Boolean isAntFile = isAnt.get();
|
||||
if (isAntFile == null) {
|
||||
isAntFile = XmlUtil.isAntFile(file);
|
||||
isAnt.set(isAntFile);
|
||||
}
|
||||
Boolean result = isRelevantLanguage.get();
|
||||
if (result == null) {
|
||||
Language language = element.getLanguage();
|
||||
if (element instanceof PsiWhiteSpace) language = element.getParent().getLanguage();
|
||||
result = language instanceof XMLLanguage || isAntFile.booleanValue();
|
||||
isRelevantLanguage.set(result);
|
||||
}
|
||||
return result.booleanValue();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user