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:
@@ -64,7 +64,7 @@ def wire_build_date(String buildNumber) {
|
||||
target('default': 'The default target') {
|
||||
depends(compile)
|
||||
layoutAll(
|
||||
buildNumber: "IC-102.SNAPSHOT",
|
||||
buildNumber: "IC-104.SNAPSHOT",
|
||||
version: "IdeaX",
|
||||
system_selector: "IntelliJIdeaCE10",
|
||||
jdk_req: "1.6*",
|
||||
|
||||
+14
-1
@@ -20,6 +20,7 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.refactoring.util.RefactoringUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -72,11 +73,23 @@ public class AddTypeArgumentsFix extends MethodArgumentFix {
|
||||
|
||||
final PsiElementFactory factory = JavaPsiFacade.getInstance(expression.getProject()).getElementFactory();
|
||||
PsiMethodCallExpression copy = (PsiMethodCallExpression)expression.copy();
|
||||
final PsiReferenceParameterList parameterList = copy.getMethodExpression().getParameterList();
|
||||
final PsiReferenceExpression methodExpression = copy.getMethodExpression();
|
||||
final PsiReferenceParameterList parameterList = methodExpression.getParameterList();
|
||||
LOG.assertTrue(parameterList != null);
|
||||
for (PsiType mapping : mappings) {
|
||||
parameterList.add(factory.createTypeElement(mapping));
|
||||
}
|
||||
if (methodExpression.getQualifierExpression() == null) {
|
||||
final PsiExpression qualifierExpression;
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
LOG.assertTrue(containingClass != null);
|
||||
if (method.hasModifierProperty(PsiModifier.STATIC)) {
|
||||
qualifierExpression = factory.createReferenceExpression(containingClass);
|
||||
} else {
|
||||
qualifierExpression = RefactoringUtil.createThisExpression(method.getManager(), null);
|
||||
}
|
||||
methodExpression.setQualifierExpression(qualifierExpression);
|
||||
}
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
+1
-1
@@ -71,7 +71,7 @@ public class ConvertReturnStatementsVisitor implements ReturnStatementsVisitor {
|
||||
final String value = generateValue(returnStatement);
|
||||
|
||||
latestReplaced = (PsiReturnStatement) myFactory.createStatementFromText("return " + value+";", returnStatement.getParent());
|
||||
returnStatement.replace(latestReplaced);
|
||||
latestReplaced = (PsiReturnStatement)returnStatement.replace(latestReplaced);
|
||||
}
|
||||
|
||||
return latestReplaced;
|
||||
|
||||
+4
@@ -71,6 +71,10 @@ public class PlainEnterProcessor implements EnterProcessor {
|
||||
else if (element instanceof PsiDoWhileStatement) {
|
||||
body = ((PsiDoWhileStatement)element).getBody();
|
||||
}
|
||||
else if (element instanceof PsiMethod) {
|
||||
PsiCodeBlock methodBody = ((PsiMethod)element).getBody();
|
||||
if (methodBody != null) return methodBody;
|
||||
}
|
||||
|
||||
return body instanceof PsiBlockStatement ? ((PsiBlockStatement)body).getCodeBlock() : null;
|
||||
}
|
||||
|
||||
@@ -215,7 +215,8 @@ public class JavaLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSett
|
||||
" x--;\n" +
|
||||
" } while (x > 10) \n" +
|
||||
" }\n" +
|
||||
" public static void test() { \n" +
|
||||
" public static void test() \n" +
|
||||
" throws Exception { \n" +
|
||||
" foo.foo().bar(\"arg1\", \n" +
|
||||
" \"arg2\"); \n" +
|
||||
" } \n" +
|
||||
|
||||
@@ -58,14 +58,15 @@ public class ClassLiteralGetter extends CompletionProvider<JavaSmartCompletionPa
|
||||
return;
|
||||
}
|
||||
|
||||
addClassLiteralLookupElement(classParameter, result, parameters.getPosition());
|
||||
PsiFile file = parameters.getPosition().getContainingFile();
|
||||
addClassLiteralLookupElement(classParameter, result, file);
|
||||
if (addInheritors) {
|
||||
addInheritorClassLiterals(parameters.getPosition(), shortNameCondition, classParameter, result);
|
||||
addInheritorClassLiterals(file, shortNameCondition, classParameter, result);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void addInheritorClassLiterals(PsiElement context,
|
||||
private static void addInheritorClassLiterals(PsiFile context,
|
||||
Condition<String> shortNameCondition,
|
||||
final PsiType classParameter,
|
||||
CompletionResultSet result) {
|
||||
@@ -79,7 +80,7 @@ public class ClassLiteralGetter extends CompletionProvider<JavaSmartCompletionPa
|
||||
}
|
||||
}
|
||||
|
||||
private static void addClassLiteralLookupElement(@Nullable final PsiType type, final CompletionResultSet resultSet, final PsiElement context) {
|
||||
private static void addClassLiteralLookupElement(@Nullable final PsiType type, final CompletionResultSet resultSet, final PsiFile context) {
|
||||
if (type instanceof PsiClassType &&
|
||||
PsiUtil.resolveClassInType(type) != null &&
|
||||
!((PsiClassType)type).hasParameters() &&
|
||||
|
||||
@@ -823,6 +823,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
|
||||
if (role == ChildRole.TYPE_PARAMETER_LIST) return defaultAlignment;
|
||||
if (role == ChildRole.TYPE) return defaultAlignment;
|
||||
if (role == ChildRole.NAME) return defaultAlignment;
|
||||
if (role == ChildRole.THROWS_LIST && mySettings.ALIGN_THROWS_KEYWORD) return defaultAlignment;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -78,10 +78,13 @@ public class InlineUtil {
|
||||
final PsiReferenceExpression methodExpression = ((PsiMethodCallExpression)expr).getMethodExpression();
|
||||
final PsiExpression qualifierExpression = methodExpression.getQualifierExpression();
|
||||
if (qualifierExpression == null) {
|
||||
if (((PsiMethod)resolved).getModifierList().hasModifierProperty(PsiModifier.STATIC)) {
|
||||
methodExpression.setQualifierExpression(elementFactory.createReferenceExpression(thisClass));
|
||||
final PsiMethod method = (PsiMethod)resolved;
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
LOG.assertTrue(containingClass != null);
|
||||
if (method.getModifierList().hasModifierProperty(PsiModifier.STATIC)) {
|
||||
methodExpression.setQualifierExpression(elementFactory.createReferenceExpression(containingClass));
|
||||
} else {
|
||||
methodExpression.setQualifierExpression(createThisExpression(manager, thisClass, refParent));
|
||||
methodExpression.setQualifierExpression(createThisExpression(manager, containingClass, refParent));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
class Foo {
|
||||
@Test
|
||||
public void testValueOf(<caret>)
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
class Foo {
|
||||
@Test
|
||||
public void testValueOf()
|
||||
{
|
||||
<caret>
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Add explicit type arguments" "true"
|
||||
import java.util.*;
|
||||
class Test {
|
||||
<T> List<T> f() { return new ArrayList<T>(); }
|
||||
void g(List<Integer> a) {}
|
||||
void someMethod() { g(this.<Integer>f()); }
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Add explicit type arguments" "true"
|
||||
import java.util.*;
|
||||
class Test {
|
||||
static <T> List<T> f() { return new ArrayList<T>(); }
|
||||
void g(List<Integer> a) {}
|
||||
void someMethod() { g(Test.<Integer>f()); }
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Add explicit type arguments" "true"
|
||||
import java.util.*;
|
||||
class Test {
|
||||
<T> List<T> f() { return new ArrayList<T>(); }
|
||||
void g(List<Integer> a) {}
|
||||
void someMethod() { g(f<caret>()); }
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Add explicit type arguments" "true"
|
||||
import java.util.*;
|
||||
class Test {
|
||||
static <T> List<T> f() { return new ArrayList<T>(); }
|
||||
void g(List<Integer> a) {}
|
||||
void someMethod() { g(<caret>f()); }
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static Statics._emptyList;
|
||||
|
||||
public class Statics {
|
||||
|
||||
public static <T> List<T> _emptyList() {
|
||||
return new ArrayList<T>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Foo {
|
||||
public static void main(String[] args) {
|
||||
List<String> v1 = _emptyList();
|
||||
doSomething(v<caret>1);
|
||||
}
|
||||
|
||||
public static void doSomething(List<String> list) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static Statics._emptyList;
|
||||
|
||||
public class Statics {
|
||||
|
||||
public static <T> List<T> _emptyList() {
|
||||
return new ArrayList<T>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Foo {
|
||||
public static void main(String[] args) {
|
||||
doSomething(Statics.<String>_emptyList());
|
||||
}
|
||||
|
||||
public static void doSomething(List<String> list) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -184,7 +184,15 @@ public class CompleteStatementTest extends EditorActionTestCase {
|
||||
|
||||
public void testIDEADEV40479() throws Exception { doTest(); }
|
||||
|
||||
public void testIDEADEV13019() throws Exception {
|
||||
public void testIDEADEV13019() throws Exception {
|
||||
doTestBracesNextLineStyle();
|
||||
}
|
||||
|
||||
public void testIDEA25139() throws Exception {
|
||||
doTestBracesNextLineStyle();
|
||||
}
|
||||
|
||||
private void doTestBracesNextLineStyle() throws Exception {
|
||||
CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
|
||||
settings.BRACE_STYLE = CodeStyleSettings.NEXT_LINE;
|
||||
settings.METHOD_BRACE_STYLE = CodeStyleSettings.NEXT_LINE;
|
||||
|
||||
+22
@@ -251,4 +251,26 @@ public class JavaFormatterAlignmentTest extends AbstractJavaFormatterTest {
|
||||
"}"
|
||||
);
|
||||
}
|
||||
|
||||
public void testAlignThrowsKeyword() throws Exception {
|
||||
// Inspired by IDEA-63820
|
||||
|
||||
getSettings().ALIGN_THROWS_KEYWORD = true;
|
||||
doClassTest(
|
||||
"public void test()\n" +
|
||||
" throws Exception {}",
|
||||
"public void test()\n" +
|
||||
"throws Exception {\n" +
|
||||
"}"
|
||||
);
|
||||
|
||||
getSettings().ALIGN_THROWS_KEYWORD = false;
|
||||
doClassTest(
|
||||
"public void test()\n" +
|
||||
" throws Exception {}",
|
||||
"public void test()\n" +
|
||||
" throws Exception {\n" +
|
||||
"}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,6 +123,10 @@ public class InlineLocalTest extends LightCodeInsightTestCase {
|
||||
doTest(true);
|
||||
}
|
||||
|
||||
public void testStaticImported() throws Exception {
|
||||
doTest(true);
|
||||
}
|
||||
|
||||
private void doTest(final boolean inlineDef, String conflictMessage) throws Exception {
|
||||
try {
|
||||
doTest(inlineDef);
|
||||
|
||||
@@ -56,7 +56,7 @@ public class LibrariesDownloadAssistant {
|
||||
LOG.error(e);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
// no route to host, unknown host, etc.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -299,6 +299,7 @@ public class CommonCodeStyleSettings {
|
||||
public boolean ALIGN_MULTILINE_ASSIGNMENT = false;
|
||||
public boolean ALIGN_MULTILINE_TERNARY_OPERATION = false;
|
||||
public boolean ALIGN_MULTILINE_THROWS_LIST = false;
|
||||
public boolean ALIGN_THROWS_KEYWORD = false;
|
||||
|
||||
public boolean ALIGN_MULTILINE_EXTENDS_LIST = false;
|
||||
public boolean ALIGN_MULTILINE_METHOD_BRACKETS = false;
|
||||
|
||||
+1
@@ -49,6 +49,7 @@ public class WrappingAndBracesPanel extends OptionTableWithPreviewPanel {
|
||||
|
||||
addOption("THROWS_LIST_WRAP", WRAPPING_THROWS_LIST, WRAP_OPTIONS, WRAP_VALUES);
|
||||
addOption("ALIGN_MULTILINE_THROWS_LIST", ApplicationBundle.message("wrapping.align.when.multiline"), WRAPPING_THROWS_LIST);
|
||||
addOption("ALIGN_THROWS_KEYWORD", ApplicationBundle.message("wrapping.align.throws.keyword"), WRAPPING_THROWS_LIST);
|
||||
addOption("THROWS_KEYWORD_WRAP", WRAPPING_THROWS_KEYWORD, WRAP_OPTIONS_FOR_SINGLETON, WRAP_VALUES_FOR_SINGLETON);
|
||||
|
||||
addOption("METHOD_PARAMETERS_WRAP", WRAPPING_METHOD_PARAMETERS, WRAP_OPTIONS, WRAP_VALUES);
|
||||
|
||||
+22
-2
@@ -24,6 +24,8 @@ import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.FileTypeManager;
|
||||
import com.intellij.openapi.fileTypes.UnknownFileType;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleUtil;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
@@ -33,6 +35,8 @@ import com.intellij.psi.PsiNamedElement;
|
||||
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReference;
|
||||
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceSet;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@@ -70,12 +74,22 @@ public class FileReferenceQuickFixProvider {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
PsiElement element = reference.getElement();
|
||||
Module module = element != null ? ModuleUtil.findModuleForPsiElement(element) : null;
|
||||
|
||||
for (PsiFileSystemItem defaultContext : defaultContexts) {
|
||||
if (defaultContext != null) {
|
||||
final VirtualFile virtualFile = defaultContext.getVirtualFile();
|
||||
if (virtualFile != null && defaultContext.isDirectory() && virtualFile.isInLocalFileSystem()) {
|
||||
context = defaultContext;
|
||||
break;
|
||||
if (context == null) {
|
||||
context = defaultContext;
|
||||
}
|
||||
else if (module != null && module == getModuleForContext(defaultContext)) {
|
||||
// fixes IDEA-64156
|
||||
// todo: fix it on PsiFileReferenceHelper level in 10.X
|
||||
context = defaultContext;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -134,4 +148,10 @@ public class FileReferenceQuickFixProvider {
|
||||
return Arrays.asList(action);
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
private static Module getModuleForContext(@NotNull PsiFileSystemItem context) {
|
||||
VirtualFile file = context.getVirtualFile();
|
||||
return file != null ? ModuleUtil.findModuleForFile(file, context.getProject()) : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,8 @@ public abstract class LookupManager {
|
||||
public abstract Lookup showLookup(Editor editor, @NotNull LookupElement[] items, String prefix, @NotNull LookupArranger arranger);
|
||||
|
||||
public abstract void hideActiveLookup();
|
||||
|
||||
@Nullable
|
||||
public abstract Lookup getActiveLookup();
|
||||
|
||||
@NonNls public static final String PROP_ACTIVE_LOOKUP = "activeLookup";
|
||||
|
||||
@@ -543,6 +543,7 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable {
|
||||
|
||||
final PsiFile file = getPsiFile();
|
||||
if (file != null && !WriteCommandAction.ensureFilesWritable(myProject, Arrays.asList(file))) {
|
||||
fireItemSelected(null, completionChar);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+5
-4
@@ -19,7 +19,6 @@ package com.intellij.codeInsight.lookup.impl.actions;
|
||||
import com.intellij.codeInsight.completion.CodeCompletionFeatures;
|
||||
import com.intellij.codeInsight.completion.CompletionProcess;
|
||||
import com.intellij.codeInsight.completion.CompletionService;
|
||||
import com.intellij.codeInsight.completion.CompletionUtil;
|
||||
import com.intellij.codeInsight.lookup.Lookup;
|
||||
import com.intellij.codeInsight.lookup.LookupManager;
|
||||
import com.intellij.codeInsight.lookup.impl.LookupImpl;
|
||||
@@ -31,6 +30,7 @@ import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.actionSystem.EditorAction;
|
||||
import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiFile;
|
||||
|
||||
@@ -74,9 +74,10 @@ public class ChooseItemReplaceAction extends EditorAction {
|
||||
final Editor editor = lookup.getEditor();
|
||||
PsiDocumentManager.getInstance(file.getProject()).commitDocument(editor.getDocument());
|
||||
|
||||
final int offset = editor.getCaretModel().getOffset();
|
||||
final String prefix = CompletionUtil.findJavaIdentifierPrefix(file, offset);
|
||||
final TemplateImpl template = LiveTemplateCompletionContributor.findApplicableTemplate(file, offset, prefix);
|
||||
final int end = editor.getCaretModel().getOffset();
|
||||
final int start = lookup.getLookupStart();
|
||||
final String prefix = editor.getDocument().getText(TextRange.create(start, end));
|
||||
final TemplateImpl template = LiveTemplateCompletionContributor.findApplicableTemplate(file, end, prefix);
|
||||
return template != null && shortcutChar == TemplateSettings.getInstance().getShortcutChar(template);
|
||||
}
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ public class ExecutionManagerImpl extends ExecutionManager implements ProjectCom
|
||||
return handlers.toArray(new ProcessHandler[handlers.size()]);
|
||||
}
|
||||
|
||||
public void compileAndRun(final Runnable startRunnable, final RunProfile configuration, final RunProfileState state, @Nullable final Runnable onCancelRunnable) {
|
||||
public void compileAndRun(final Runnable startRunnable, final RunProfile configuration, final @Nullable RunProfileState state, @Nullable final Runnable onCancelRunnable) {
|
||||
if (configuration instanceof RunConfiguration) {
|
||||
final RunConfiguration runConfiguration = (RunConfiguration)configuration;
|
||||
final RunManagerImpl runManager = RunManagerImpl.getInstanceImpl(myProject);
|
||||
@@ -112,7 +112,7 @@ public class ExecutionManagerImpl extends ExecutionManager implements ProjectCom
|
||||
if (!activeProviders.isEmpty()) {
|
||||
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
|
||||
public void run() {
|
||||
ConfigurationPerRunnerSettings configurationSettings = state.getConfigurationSettings();
|
||||
ConfigurationPerRunnerSettings configurationSettings = state != null ? state.getConfigurationSettings() : null;
|
||||
DataContext projectContext = SimpleDataContext.getProjectContext(myProject);
|
||||
|
||||
final DataContext dataContext = configurationSettings != null ? SimpleDataContext
|
||||
|
||||
@@ -57,6 +57,7 @@ import com.intellij.ui.components.labels.LinkListener;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.text.BadLocationException;
|
||||
@@ -106,10 +107,14 @@ class FindDialog extends DialogWrapper {
|
||||
private JRadioButton myRbCustomScope;
|
||||
private ScopeChooserCombo myScopeCombo;
|
||||
|
||||
private LivePreviewController myLivePreviewController;
|
||||
|
||||
|
||||
public FindDialog(Project project, FindModel model, Runnable myOkHandler){
|
||||
super(project, true);
|
||||
myProject = project;
|
||||
myModel = model;
|
||||
|
||||
this.myOkHandler = myOkHandler;
|
||||
|
||||
if (myModel.isReplaceState()){
|
||||
@@ -133,6 +138,7 @@ class FindDialog extends DialogWrapper {
|
||||
setOKButtonIcon(IconLoader.getIcon("/actions/find.png"));
|
||||
init();
|
||||
initByModel();
|
||||
myLivePreviewController = new LivePreviewController(this, new LivePreview(myProject), getContentPane());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -141,6 +147,9 @@ class FindDialog extends DialogWrapper {
|
||||
e.getKey().removeDocumentListener(e.getValue());
|
||||
}
|
||||
myComboBoxListeners.clear();
|
||||
if (myLivePreviewController != null) {
|
||||
myLivePreviewController.cleanUp();
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -274,6 +283,22 @@ class FindDialog extends DialogWrapper {
|
||||
validateFindButton();
|
||||
}
|
||||
|
||||
public FindModel getModel() {
|
||||
return myModel;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public FindModel getCurrentModel() {
|
||||
FindModel validateModel = (FindModel)myModel.clone();
|
||||
applyTo(validateModel, false);
|
||||
|
||||
|
||||
if (getValidationInfo(validateModel) == null) {
|
||||
return validateModel;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static int getCaretPosition(JComboBox comboBox) {
|
||||
Component editorComponent = comboBox.getEditor().getEditorComponent();
|
||||
if (editorComponent instanceof JTextField){
|
||||
@@ -293,7 +318,6 @@ class FindDialog extends DialogWrapper {
|
||||
|
||||
private void validateFindButton() {
|
||||
final String toFind = getStringToFind();
|
||||
|
||||
if (toFind == null || toFind.length() == 0){
|
||||
setOKStatus(false);
|
||||
return;
|
||||
@@ -416,76 +440,130 @@ class FindDialog extends DialogWrapper {
|
||||
|
||||
private void doOKAction(boolean findAll) {
|
||||
FindModel validateModel = (FindModel)myModel.clone();
|
||||
applyTo(validateModel);
|
||||
validateModel.setFindAll(findAll);
|
||||
if (validateModel.getDirectoryName() != null) {
|
||||
PsiDirectory directory = FindInProjectUtil.getPsiDirectory(validateModel, myProject);
|
||||
if (directory == null) {
|
||||
applyTo(validateModel, findAll);
|
||||
|
||||
ValidationInfo validationInfo = getValidationInfo(validateModel);
|
||||
|
||||
if (validationInfo == null) {
|
||||
|
||||
myModel.copyFrom(validateModel);
|
||||
updateFindSettings();
|
||||
|
||||
super.doOKAction();
|
||||
myOkHandler.run();
|
||||
} else {
|
||||
String message = validationInfo.message;
|
||||
if (message != null) {
|
||||
Messages.showMessageDialog(
|
||||
myProject,
|
||||
FindBundle.message("find.directory.not.found.error", validateModel.getDirectoryName()),
|
||||
message,
|
||||
CommonBundle.getErrorTitle(),
|
||||
Messages.getErrorIcon()
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (validateModel.isRegularExpressions()) {
|
||||
String toFind = validateModel.getStringToFind();
|
||||
try {
|
||||
Pattern pattern = Pattern.compile(toFind, validateModel.isCaseSensitive() ? Pattern.MULTILINE : Pattern.MULTILINE | Pattern.CASE_INSENSITIVE);
|
||||
if (pattern.matcher("").matches() && !toFind.endsWith("$") && !toFind.startsWith("^")) {
|
||||
throw new PatternSyntaxException(FindBundle.message("find.empty.match.regular.expression.error"),toFind, -1);
|
||||
}
|
||||
}
|
||||
catch(PatternSyntaxException e){
|
||||
Messages.showMessageDialog(
|
||||
myProject,
|
||||
FindBundle.message("find.invalid.regular.expression.error", toFind, e.getDescription()),
|
||||
CommonBundle.getErrorTitle(),
|
||||
Messages.getErrorIcon()
|
||||
);
|
||||
return;
|
||||
}
|
||||
private void updateFindSettings() {
|
||||
FindSettings findSettings = FindSettings.getInstance();
|
||||
findSettings.setCaseSensitive(myModel.isCaseSensitive());
|
||||
if (myModel.isReplaceState()) {
|
||||
findSettings.setPreserveCase(myModel.isPreserveCase());
|
||||
}
|
||||
|
||||
validateModel.setFileFilter( null );
|
||||
FindSettings.getInstance().setFileMask(null);
|
||||
findSettings.setWholeWordsOnly(myModel.isWholeWordsOnly());
|
||||
findSettings.setInStringLiteralsOnly(myModel.isInStringLiteralsOnly());
|
||||
findSettings.setInCommentsOnly(myModel.isInCommentsOnly());
|
||||
|
||||
if (useFileFilter!=null && useFileFilter.isSelected() &&
|
||||
myFileFilter.getSelectedItem()!=null
|
||||
) {
|
||||
final String mask = (String)myFileFilter.getSelectedItem();
|
||||
findSettings.setRegularExpressions(myModel.isRegularExpressions());
|
||||
if (!myModel.isMultipleFiles()){
|
||||
findSettings.setForward(myModel.isForward());
|
||||
findSettings.setFromCursor(myModel.isFromCursor());
|
||||
|
||||
if (mask.length() > 0) {
|
||||
try {
|
||||
FindInProjectUtil.createFileMaskRegExp(mask); // verify that the regexp compiles
|
||||
validateModel.setFileFilter(mask);
|
||||
FindSettings.getInstance().setFileMask(mask);
|
||||
}
|
||||
catch (PatternSyntaxException ex) {
|
||||
Messages.showMessageDialog(myProject, FindBundle.message("find.filter.invalid.file.mask.error", myFileFilter.getSelectedItem()),
|
||||
CommonBundle.getErrorTitle(), Messages.getErrorIcon());
|
||||
return;
|
||||
}
|
||||
findSettings.setGlobal(myModel.isGlobal());
|
||||
} else{
|
||||
String directoryName = myModel.getDirectoryName();
|
||||
if (directoryName != null && !directoryName.isEmpty()) {
|
||||
findSettings.setWithSubdirectories(myModel.isWithSubdirectories());
|
||||
}
|
||||
else {
|
||||
Messages.showMessageDialog(myProject, FindBundle.message("find.filter.empty.file.mask.error"), CommonBundle.getErrorTitle(),
|
||||
Messages.getErrorIcon());
|
||||
return;
|
||||
else if (myRbModule.isSelected()) {
|
||||
}
|
||||
else if (myRbCustomScope.isSelected()) {
|
||||
SearchScope selectedScope = myScopeCombo.getSelectedScope();
|
||||
String customScopeName = selectedScope == null ? null : selectedScope.getDisplayName();
|
||||
findSettings.setCustomScope(customScopeName);
|
||||
}
|
||||
}
|
||||
|
||||
if (myCbToSkipResultsWhenOneUsage != null){
|
||||
FindSettings.getInstance().setSkipResultsWithOneUsage(
|
||||
findSettings.setSkipResultsWithOneUsage(
|
||||
isSkipResultsWhenOneUsage()
|
||||
);
|
||||
}
|
||||
|
||||
myModel.copyFrom(validateModel);
|
||||
super.doOKAction();
|
||||
myOkHandler.run();
|
||||
findSettings.setFileMask(myModel.getFileFilter());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean postponeValidation() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private ValidationInfo getValidationInfo(FindModel model) {
|
||||
if (myRbDirectory != null && myRbDirectory.isEnabled() && myRbDirectory.isSelected()) {
|
||||
PsiDirectory directory = FindInProjectUtil.getPsiDirectory(model, myProject);
|
||||
if (directory == null) {
|
||||
return new ValidationInfo(FindBundle.message("find.directory.not.found.error", getDirectory()), myDirectoryComboBox);
|
||||
}
|
||||
}
|
||||
|
||||
String toFind = (String)myInputComboBox.getSelectedItem();
|
||||
if (toFind != null && toFind.isEmpty()) {
|
||||
return new ValidationInfo("String to find is empty", myInputComboBox);
|
||||
}
|
||||
|
||||
if (myCbRegularExpressions != null && myCbRegularExpressions.isEnabled()) {
|
||||
try {
|
||||
boolean isCaseSensitive = myCbCaseSensitive != null && myCbCaseSensitive.isEnabled();
|
||||
Pattern pattern =
|
||||
Pattern.compile(toFind, isCaseSensitive ? Pattern.MULTILINE : Pattern.MULTILINE | Pattern.CASE_INSENSITIVE);
|
||||
if (pattern.matcher("").matches() && !toFind.endsWith("$") && !toFind.startsWith("^")) {
|
||||
return new ValidationInfo(FindBundle.message("find.empty.match.regular.expression.error"), myInputComboBox);
|
||||
}
|
||||
}
|
||||
catch (PatternSyntaxException e) {
|
||||
return new ValidationInfo(FindBundle.message("find.invalid.regular.expression.error", toFind, e.getDescription()), myInputComboBox);
|
||||
}
|
||||
}
|
||||
|
||||
final String mask = myFileFilter == null ? null : (String)myFileFilter.getSelectedItem();
|
||||
|
||||
if (mask != null) {
|
||||
if (mask.length() == 0) {
|
||||
return new ValidationInfo(FindBundle.message("find.filter.empty.file.mask.error"), myFileFilter);
|
||||
}
|
||||
else {
|
||||
try {
|
||||
FindInProjectUtil.createFileMaskRegExp(mask); // verify that the regexp compiles
|
||||
}
|
||||
catch (PatternSyntaxException ex) {
|
||||
return new ValidationInfo(FindBundle.message("find.filter.invalid.file.mask.error", mask), myFileFilter);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ValidationInfo doValidate() {
|
||||
FindModel validateModel = (FindModel)myModel.clone();
|
||||
applyTo(validateModel, false);
|
||||
|
||||
ValidationInfo result = getValidationInfo(validateModel);
|
||||
|
||||
setOKStatus(result == null);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void doHelpAction() {
|
||||
@@ -768,7 +846,7 @@ class FindDialog extends DialogWrapper {
|
||||
public void consume(final VirtualFile[] files) {
|
||||
if (files.length != 0) {
|
||||
myDirectoryComboBox.setSelectedItem(files[0].getPresentableUrl());
|
||||
validateFindButton();
|
||||
//validateFindButton();
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -845,10 +923,12 @@ class FindDialog extends DialogWrapper {
|
||||
}
|
||||
|
||||
private String getStringToFind() {
|
||||
return (String)myInputComboBox.getEditor().getItem();
|
||||
String string = (String)myInputComboBox.getEditor().getItem();
|
||||
return string == null ? "" : string;
|
||||
}
|
||||
private String getStringToReplace() {
|
||||
return (String)myReplaceComboBox.getEditor().getItem();
|
||||
String item = (String)myReplaceComboBox.getEditor().getItem();
|
||||
return item == null ? "" : item;
|
||||
}
|
||||
|
||||
private String getDirectory() {
|
||||
@@ -886,27 +966,26 @@ class FindDialog extends DialogWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
private void applyTo(FindModel model) {
|
||||
FindSettings findSettings = FindSettings.getInstance();
|
||||
|
||||
|
||||
private void applyTo(FindModel model, boolean findAll) {
|
||||
|
||||
model.setCaseSensitive(myCbCaseSensitive.isSelected());
|
||||
findSettings.setCaseSensitive(myCbCaseSensitive.isSelected());
|
||||
|
||||
if (model.isReplaceState()) {
|
||||
model.setPreserveCase(myCbPreserveCase.isSelected());
|
||||
findSettings.setPreserveCase(myCbPreserveCase.isSelected());
|
||||
}
|
||||
|
||||
model.setWholeWordsOnly(myCbWholeWordsOnly.isSelected());
|
||||
findSettings.setWholeWordsOnly(myCbWholeWordsOnly.isSelected());
|
||||
model.setInStringLiteralsOnly(myCbInStringLiteralsOnly.isSelected());
|
||||
findSettings.setInStringLiteralsOnly(myCbInStringLiteralsOnly.isSelected());
|
||||
|
||||
model.setInCommentsOnly(myCbInCommentsOnly.isSelected());
|
||||
findSettings.setInCommentsOnly(myCbInCommentsOnly.isSelected());
|
||||
|
||||
model.setRegularExpressions(myCbRegularExpressions.isSelected());
|
||||
findSettings.setRegularExpressions(myCbRegularExpressions.isSelected());
|
||||
model.setStringToFind(getStringToFind());
|
||||
String stringToFind = getStringToFind();
|
||||
if (stringToFind.length() > 0) {
|
||||
model.setStringToFind(stringToFind);
|
||||
}
|
||||
|
||||
if (model.isReplaceState()){
|
||||
model.setPromptOnReplace(true);
|
||||
@@ -920,11 +999,8 @@ class FindDialog extends DialogWrapper {
|
||||
|
||||
if (!model.isMultipleFiles()){
|
||||
model.setForward(myRbForward.isSelected());
|
||||
findSettings.setForward(myRbForward.isSelected());
|
||||
model.setFromCursor(myRbFromCursor.isSelected());
|
||||
findSettings.setFromCursor(myRbFromCursor.isSelected());
|
||||
model.setGlobal(myRbGlobal.isSelected());
|
||||
findSettings.setGlobal(myRbGlobal.isSelected());
|
||||
}
|
||||
else{
|
||||
if (myCbToOpenInNewTab != null){
|
||||
@@ -942,7 +1018,6 @@ class FindDialog extends DialogWrapper {
|
||||
String directory = getDirectory();
|
||||
model.setDirectoryName(directory == null ? "" : directory);
|
||||
model.setWithSubdirectories(myCbWithSubdirectories.isSelected());
|
||||
findSettings.setWithSubdirectories(myCbWithSubdirectories.isSelected());
|
||||
}
|
||||
else if (myRbModule.isSelected()) {
|
||||
model.setModuleName((String)myModuleComboBox.getSelectedItem());
|
||||
@@ -953,9 +1028,17 @@ class FindDialog extends DialogWrapper {
|
||||
model.setCustomScopeName(customScopeName);
|
||||
model.setCustomScope(selectedScope == null ? null : selectedScope);
|
||||
model.setCustomScope(true);
|
||||
findSettings.setCustomScope(customScopeName);
|
||||
}
|
||||
}
|
||||
|
||||
model.setFindAll(findAll);
|
||||
|
||||
String mask = null;
|
||||
if (useFileFilter!=null && useFileFilter.isSelected()) {
|
||||
mask = (String)myFileFilter.getSelectedItem();
|
||||
}
|
||||
model.setFileFilter(mask);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1061,7 +1144,7 @@ class FindDialog extends DialogWrapper {
|
||||
setStringsToComboBox(FindSettings.getInstance().getRecentReplaceStrings(), myReplaceComboBox, myModel.getStringToReplace());
|
||||
}
|
||||
updateControls();
|
||||
validateFindButton();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.intellij.find.impl;
|
||||
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
public class LiveOccurrence {
|
||||
private TextRange myPrimaryRange;
|
||||
private Collection<TextRange> mySecondaryRanges = new ArrayList<TextRange>();
|
||||
|
||||
public TextRange getPrimaryRange() {
|
||||
return myPrimaryRange;
|
||||
}
|
||||
|
||||
public Collection<TextRange> getSecondaryRanges() {
|
||||
return mySecondaryRanges;
|
||||
}
|
||||
|
||||
public void setPrimaryRange(TextRange primaryRange) {
|
||||
this.myPrimaryRange = primaryRange;
|
||||
}
|
||||
|
||||
public void setSecondaryRanges(Collection<TextRange> secondaryRanges) {
|
||||
this.mySecondaryRanges = secondaryRanges;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,421 @@
|
||||
package com.intellij.find.impl;
|
||||
|
||||
|
||||
import com.intellij.codeInsight.highlighting.HighlightManager;
|
||||
import com.intellij.ide.IdeTooltipManager;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.ScrollType;
|
||||
import com.intellij.openapi.editor.VisualPosition;
|
||||
import com.intellij.openapi.editor.event.DocumentAdapter;
|
||||
import com.intellij.openapi.editor.event.DocumentEvent;
|
||||
import com.intellij.openapi.editor.event.VisibleAreaEvent;
|
||||
import com.intellij.openapi.editor.event.VisibleAreaListener;
|
||||
import com.intellij.openapi.editor.markup.CustomHighlighterRenderer;
|
||||
import com.intellij.openapi.editor.markup.RangeHighlighter;
|
||||
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.fileEditor.FileEditor;
|
||||
import com.intellij.openapi.fileEditor.TextEditor;
|
||||
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.Balloon;
|
||||
import com.intellij.openapi.ui.popup.BalloonBuilder;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import com.intellij.util.ui.PositionTracker;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public class LivePreview extends DocumentAdapter {
|
||||
|
||||
private final Collection<RangeHighlighter> myHighlighters = new HashSet<RangeHighlighter>();
|
||||
private RangeHighlighter myCursorHighlighter;
|
||||
private final List<VisibleAreaListener> myVisibleAreaListenersToRemove = new ArrayList<VisibleAreaListener>();
|
||||
|
||||
public interface Delegate {
|
||||
@NotNull
|
||||
List<LiveOccurrence> performSearchInBackgroundInReadAction(Editor editor);
|
||||
|
||||
@Nullable
|
||||
String getReplacementPreviewText(Editor editor, LiveOccurrence liveOccurrence);
|
||||
}
|
||||
|
||||
private static final int USER_ACTIVITY_TRIGGERING_DELAY = 300;
|
||||
|
||||
private static final TextAttributes OTHER_TARGETS_ATTRIBUTES = new TextAttributes(Color.BLACK, Color.GREEN, null, null, 0);
|
||||
private static final TextAttributes MAIN_TARGET_ATTRIBUTES = new TextAttributes(Color.BLACK, Color.YELLOW, null, null, 0);
|
||||
|
||||
private final Alarm myLivePreviewAlarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD);
|
||||
|
||||
private final Project myProject;
|
||||
private Editor myEditor;
|
||||
|
||||
private Delegate myDelegate;
|
||||
|
||||
private LiveOccurrence myCursor;
|
||||
private List<LiveOccurrence> mySearchResults;
|
||||
|
||||
private Balloon myReplacementBalloon;
|
||||
|
||||
public LivePreview(Project project) {
|
||||
this.myProject = project;
|
||||
updateEditorReference();
|
||||
}
|
||||
|
||||
public Delegate getDelegate() {
|
||||
return myDelegate;
|
||||
}
|
||||
|
||||
public void setDelegate(Delegate delegate) {
|
||||
this.myDelegate = delegate;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Editor updateEditorReference() {
|
||||
if (myProject == null) return null;
|
||||
FileEditorManagerEx instanceEx = FileEditorManagerEx.getInstanceEx(myProject);
|
||||
if (instanceEx != null) {
|
||||
VirtualFile currentFile = instanceEx.getCurrentFile();
|
||||
if (currentFile != null) {
|
||||
FileEditor[] editors = instanceEx.getEditors(currentFile);
|
||||
if (editors.length > 0) {
|
||||
FileEditor fileEditor = editors[0];
|
||||
boolean focusedFound = false;
|
||||
for (FileEditor e : editors) {
|
||||
if (e instanceof TextEditor && ((TextEditor)e).getEditor().getContentComponent().hasFocus()) {
|
||||
fileEditor = e;
|
||||
focusedFound = true;
|
||||
}
|
||||
}
|
||||
boolean needToUpdate = true;
|
||||
if (!focusedFound) {
|
||||
for (FileEditor e : editors) {
|
||||
if (e instanceof TextEditor && ((TextEditor)e).getEditor() == myEditor) {
|
||||
needToUpdate = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (needToUpdate && fileEditor instanceof TextEditor) {
|
||||
Editor editor1 = ((TextEditor) fileEditor).getEditor();
|
||||
if (editor1 != myEditor) {
|
||||
cleanUp();
|
||||
}
|
||||
if (myEditor != null) {
|
||||
myEditor.getDocument().removeDocumentListener(this);
|
||||
}
|
||||
myEditor = editor1;
|
||||
myEditor.getDocument().addDocumentListener(this);
|
||||
}
|
||||
} else {
|
||||
myEditor = null;
|
||||
}
|
||||
} else {
|
||||
myEditor = null;
|
||||
}
|
||||
}
|
||||
return myEditor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void documentChanged(DocumentEvent e) {
|
||||
update();
|
||||
}
|
||||
|
||||
public void update() {
|
||||
myLivePreviewAlarm.cancelAllRequests();
|
||||
if (updateEditorReference() != null) {
|
||||
myLivePreviewAlarm.addRequest(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateInBackground();
|
||||
}
|
||||
}, USER_ACTIVITY_TRIGGERING_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
public void cleanUp() {
|
||||
if (myReplacementBalloon != null) {
|
||||
myReplacementBalloon.hide();
|
||||
}
|
||||
if (myEditor != null) {
|
||||
for (VisibleAreaListener visibleAreaListener : myVisibleAreaListenersToRemove) {
|
||||
myEditor.getScrollingModel().removeVisibleAreaListener(visibleAreaListener);
|
||||
}
|
||||
myVisibleAreaListenersToRemove.clear();
|
||||
for (RangeHighlighter h : myHighlighters) {
|
||||
HighlightManager.getInstance(myProject).removeSegmentHighlighter(myEditor, h);
|
||||
}
|
||||
if (myCursorHighlighter != null) {
|
||||
HighlightManager.getInstance(myProject).removeSegmentHighlighter(myEditor, myCursorHighlighter);
|
||||
myCursorHighlighter = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateInBackground() {
|
||||
if (myDelegate == null) return;
|
||||
final TextRange oldCursorRange = myCursor != null ? myCursor.getPrimaryRange() : null;
|
||||
mySearchResults = performSearchInBackground();
|
||||
Collections.sort(mySearchResults, new Comparator<LiveOccurrence>() {
|
||||
@Override
|
||||
public int compare(LiveOccurrence liveOccurrence, LiveOccurrence liveOccurence1) {
|
||||
return liveOccurrence.getPrimaryRange().getStartOffset() - liveOccurence1.getPrimaryRange().getStartOffset();
|
||||
}
|
||||
});
|
||||
if (mySearchResults != null) {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
cleanUp();
|
||||
highlightUsages(oldCursorRange);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private List<LiveOccurrence> performSearchInBackground() {
|
||||
final AtomicReference<List<LiveOccurrence>> occurrences = new AtomicReference<List<LiveOccurrence>>();
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
occurrences.set(myDelegate.performSearchInBackgroundInReadAction(myEditor));
|
||||
}
|
||||
});
|
||||
return occurrences.get();
|
||||
}
|
||||
|
||||
private void highlightUsages(TextRange oldCursorRange) {
|
||||
if (myEditor == null) return;
|
||||
LiveOccurrence firstVisibleOccurrence = null;
|
||||
LiveOccurrence firstOccurrence = null;
|
||||
int offset = Integer.MAX_VALUE;
|
||||
for (LiveOccurrence o : mySearchResults) {
|
||||
if (insideVisibleArea(myEditor, o.getPrimaryRange())) {
|
||||
if (firstVisibleOccurrence == null || o.getPrimaryRange().getStartOffset() < firstVisibleOccurrence.getPrimaryRange().getStartOffset()) {
|
||||
firstVisibleOccurrence = o;
|
||||
}
|
||||
}
|
||||
if (o.getPrimaryRange().getStartOffset() < offset) {
|
||||
offset = o.getPrimaryRange().getStartOffset();
|
||||
firstOccurrence = o;
|
||||
}
|
||||
|
||||
for (TextRange textRange : o.getSecondaryRanges()) {
|
||||
highlightRange(textRange, OTHER_TARGETS_ATTRIBUTES, myHighlighters);
|
||||
}
|
||||
highlightRange(o.getPrimaryRange(), MAIN_TARGET_ATTRIBUTES, myHighlighters);
|
||||
}
|
||||
|
||||
if (!tryToRepairOldCursor(oldCursorRange)) {
|
||||
setCursor(firstVisibleOccurrence != null ? firstVisibleOccurrence : firstOccurrence);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean tryToRepairOldCursor(TextRange oldCursorRange) {
|
||||
if (oldCursorRange == null) return false;
|
||||
LiveOccurrence mayBeOldCursor = null;
|
||||
for (LiveOccurrence searchResult : mySearchResults) {
|
||||
if (searchResult.getPrimaryRange().intersects(oldCursorRange)) {
|
||||
mayBeOldCursor = searchResult;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mayBeOldCursor != null && insideVisibleArea(myEditor, mayBeOldCursor.getPrimaryRange())) {
|
||||
setCursor(mayBeOldCursor);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private LiveOccurrence prevOccurrence(LiveOccurrence o) {
|
||||
if (mySearchResults == null) return null;
|
||||
for (int i = 0; i < mySearchResults.size(); ++i) {
|
||||
if (o == mySearchResults.get(i)) {
|
||||
if (i > 0) {
|
||||
return mySearchResults.get(i-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private LiveOccurrence nextOccurrence(LiveOccurrence o) {
|
||||
if (mySearchResults == null) return null;
|
||||
boolean found = false;
|
||||
for (LiveOccurrence occurrence : mySearchResults) {
|
||||
if (found) {
|
||||
return occurrence;
|
||||
}
|
||||
if (o == occurrence) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void prevOccurrence() {
|
||||
LiveOccurrence prev = prevOccurrence(myCursor);
|
||||
if (prev == null && !mySearchResults.isEmpty()) {
|
||||
prev = mySearchResults.get(mySearchResults.size()-1);
|
||||
}
|
||||
moveCursorTo(prev);
|
||||
}
|
||||
|
||||
public void nextOccurrence() {
|
||||
LiveOccurrence next = nextOccurrence(myCursor);
|
||||
if (next == null && !mySearchResults.isEmpty()) {
|
||||
next = mySearchResults.get(0);
|
||||
}
|
||||
moveCursorTo(next);
|
||||
}
|
||||
|
||||
public void moveCursorTo(LiveOccurrence next) {
|
||||
if (next != null) {
|
||||
setCursor(next);
|
||||
} else {
|
||||
showReplacementPreview();
|
||||
}
|
||||
}
|
||||
|
||||
private void setCursor(LiveOccurrence liveOccurrence) {
|
||||
hideBalloon();
|
||||
myCursor = liveOccurrence;
|
||||
|
||||
if (myCursorHighlighter != null) {
|
||||
HighlightManager.getInstance(myProject).removeSegmentHighlighter(myEditor, myCursorHighlighter);
|
||||
myCursorHighlighter = null;
|
||||
}
|
||||
if (myCursor != null) {
|
||||
ArrayList<RangeHighlighter> dummy = new ArrayList<RangeHighlighter>();
|
||||
highlightRange(myCursor.getPrimaryRange(), new TextAttributes(null, null, null, null, 0), dummy);
|
||||
if (!dummy.isEmpty()) {
|
||||
myCursorHighlighter = dummy.get(0);
|
||||
myCursorHighlighter.setCustomRenderer(new CustomHighlighterRenderer() {
|
||||
@Override
|
||||
public void paint(Editor editor, RangeHighlighter highlighter, Graphics g) {
|
||||
Graphics2D g2d = (Graphics2D)g;
|
||||
VisualPosition startVp = editor.offsetToVisualPosition(highlighter.getStartOffset());
|
||||
VisualPosition endVp = editor.offsetToVisualPosition(highlighter.getEndOffset());
|
||||
Point start = editor.visualPositionToXY(startVp);
|
||||
Point end = editor.visualPositionToXY(endVp);
|
||||
g2d.setColor(Color.YELLOW);
|
||||
Point startP = new Point(start.x-5, start.y-5);
|
||||
int lineHeight = editor.getLineHeight();
|
||||
Point endP = new Point(start.x-5, end.y+ lineHeight +10);
|
||||
g2d.setPaint(new GradientPaint(startP, Color.YELLOW, endP, new Color(255, 200, 0)));
|
||||
|
||||
g2d.fillRoundRect(startP.x, startP.y,
|
||||
end.x - start.x+10, lineHeight +10, 10, 10);
|
||||
g2d.setColor(Color.GRAY);
|
||||
g2d.drawRoundRect(start.x - 5, start.y - 5,
|
||||
end.x - start.x + 10, lineHeight + 10, 10, 10);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (!insideVisibleArea(myEditor, myCursor.getPrimaryRange())) {
|
||||
myEditor.getScrollingModel().scrollTo(myEditor.offsetToLogicalPosition(myCursor.getPrimaryRange().getStartOffset()),
|
||||
ScrollType.CENTER);
|
||||
myEditor.getScrollingModel().runActionOnScrollingFinished(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
showReplacementPreview();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
showReplacementPreview();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void showReplacementPreview() {
|
||||
hideBalloon();
|
||||
if (myDelegate != null && myCursor != null) {
|
||||
String replacementPreviewText = myDelegate.getReplacementPreviewText(myEditor, myCursor);
|
||||
if (replacementPreviewText != null) {
|
||||
|
||||
JLabel balloonContent = new JLabel(replacementPreviewText);
|
||||
balloonContent.setForeground(Color.WHITE);
|
||||
|
||||
BalloonBuilder balloonBuilder = JBPopupFactory.getInstance().createBalloonBuilder(balloonContent);
|
||||
balloonBuilder.setFadeoutTime(0);
|
||||
balloonBuilder.setFillColor(IdeTooltipManager.GRAPHITE_COLOR);
|
||||
balloonBuilder.setAnimationCycle(0);
|
||||
balloonBuilder.setHideOnClickOutside(false);
|
||||
balloonBuilder.setHideOnKeyOutside(false);
|
||||
balloonBuilder.setHideOnAction(false);
|
||||
myReplacementBalloon = balloonBuilder.createBalloon();
|
||||
final int startOffset = myCursor.getPrimaryRange().getStartOffset();
|
||||
final int endOffset = myCursor.getPrimaryRange().getEndOffset();
|
||||
|
||||
myReplacementBalloon.show(new PositionTracker<Balloon>(myEditor.getContentComponent()) {
|
||||
@Override
|
||||
public RelativePoint recalculateLocation(final Balloon object) {
|
||||
Point startPoint = myEditor.visualPositionToXY(myEditor.offsetToVisualPosition(startOffset));
|
||||
Point endPoint = myEditor.visualPositionToXY(myEditor.offsetToVisualPosition(endOffset));
|
||||
Point point = new Point((startPoint.x + endPoint.x)/2, startPoint.y);
|
||||
if (!insideVisibleArea(myEditor, myCursor.getPrimaryRange())) {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
object.hide();
|
||||
}
|
||||
});
|
||||
|
||||
VisibleAreaListener visibleAreaListener = new VisibleAreaListener() {
|
||||
@Override
|
||||
public void visibleAreaChanged(VisibleAreaEvent e) {
|
||||
if (insideVisibleArea(myEditor, myCursor.getPrimaryRange())) {
|
||||
showReplacementPreview();
|
||||
final VisibleAreaListener visibleAreaListener = this;
|
||||
myEditor.getScrollingModel().removeVisibleAreaListener(visibleAreaListener);
|
||||
myVisibleAreaListenersToRemove.remove(visibleAreaListener);
|
||||
}
|
||||
}
|
||||
};
|
||||
myEditor.getScrollingModel().addVisibleAreaListener(visibleAreaListener);
|
||||
myVisibleAreaListenersToRemove.add(visibleAreaListener);
|
||||
|
||||
}
|
||||
return new RelativePoint(myEditor.getContentComponent(), point);
|
||||
}
|
||||
}, Balloon.Position.above);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void hideBalloon() {
|
||||
if (myReplacementBalloon != null) {
|
||||
myReplacementBalloon.hide();
|
||||
myReplacementBalloon = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void highlightRange(TextRange textRange, TextAttributes attributes, Collection<RangeHighlighter> highlighters) {
|
||||
HighlightManager highlightManager = HighlightManager.getInstance(myProject);
|
||||
if (highlightManager != null) {
|
||||
highlightManager.addRangeHighlight(myEditor,
|
||||
textRange.getStartOffset(), textRange.getEndOffset(),
|
||||
attributes, true, highlighters);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean insideVisibleArea(Editor e, TextRange r) {
|
||||
Rectangle visibleArea = e.getScrollingModel().getVisibleArea();
|
||||
Point point = e.logicalPositionToXY(e.offsetToLogicalPosition(r.getStartOffset()));
|
||||
|
||||
return visibleArea.contains(point);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
package com.intellij.find.impl;
|
||||
|
||||
import com.intellij.find.FindManager;
|
||||
import com.intellij.find.FindModel;
|
||||
import com.intellij.find.FindResult;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.UserActivityListener;
|
||||
import com.intellij.ui.UserActivityWatcher;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class LivePreviewController implements LivePreview.Delegate, UserActivityListener {
|
||||
|
||||
private static final String EMPTY_STRING_DISPLAY_TEXT = "<Empty string>";
|
||||
private final FindDialog myFindDialog;
|
||||
private final LivePreview myLivePreview;
|
||||
private final UserActivityWatcher myWatcher = new MomentoUserActivityWatcher();
|
||||
private int myMatchesLimit = 100;
|
||||
|
||||
public LivePreviewController(FindDialog findDialog, LivePreview livePreview, Component toWatch) {
|
||||
myFindDialog = findDialog;
|
||||
myLivePreview = livePreview;
|
||||
myLivePreview.setDelegate(this);
|
||||
myWatcher.register(toWatch);
|
||||
myWatcher.addUserActivityListener(this);
|
||||
myFindDialog.getWindow().addWindowFocusListener(new WindowFocusListener() {
|
||||
@Override
|
||||
public void windowGainedFocus(WindowEvent windowEvent) {
|
||||
myLivePreview.update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowLostFocus(WindowEvent windowEvent) {
|
||||
}
|
||||
});
|
||||
|
||||
JComponent contentPane = (JComponent)findDialog.getContentPane();
|
||||
new AnAction() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
myLivePreview.nextOccurrence();
|
||||
}
|
||||
}.registerCustomShortcutSet(KeyEvent.VK_F3, 0, contentPane);
|
||||
|
||||
new AnAction() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
myLivePreview.prevOccurrence();
|
||||
}
|
||||
}.registerCustomShortcutSet(KeyEvent.VK_F3, KeyEvent.SHIFT_MASK, contentPane);
|
||||
}
|
||||
|
||||
public void cleanUp() {
|
||||
myWatcher.removeUserActivityListener(this);
|
||||
myLivePreview.cleanUp();
|
||||
}
|
||||
|
||||
public void setMatchesLimit(int matchesLimit) {
|
||||
myMatchesLimit = matchesLimit;
|
||||
}
|
||||
|
||||
public int getMatchesLimit() {
|
||||
return myMatchesLimit;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<LiveOccurrence> performSearchInBackgroundInReadAction(Editor editor) {
|
||||
ArrayList<LiveOccurrence> occurrences = new ArrayList<LiveOccurrence>();
|
||||
FindModel currentModel = myFindDialog.getCurrentModel();
|
||||
if (currentModel != null) {
|
||||
int offset = 0;
|
||||
VirtualFile virtualFile = FileDocumentManager.getInstance().getFile(editor.getDocument());
|
||||
ArrayList<FindResult> results = new ArrayList<FindResult>();
|
||||
|
||||
while (true) {
|
||||
FindManager findManager = FindManager.getInstance(editor.getProject());
|
||||
FindResult result = findManager.findString(editor.getDocument().getCharsSequence(), offset, currentModel, virtualFile);
|
||||
if (!result.isStringFound()) break;
|
||||
int newOffset = result.getEndOffset();
|
||||
if (offset == newOffset) break;
|
||||
offset = newOffset;
|
||||
results.add(result);
|
||||
|
||||
if (results.size() > myMatchesLimit) break;
|
||||
}
|
||||
if (results.size() < myMatchesLimit) {
|
||||
findResultsToOccurrences(results, occurrences);
|
||||
}
|
||||
}
|
||||
return occurrences;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReplacementPreviewText(Editor editor, LiveOccurrence liveOccurrence) {
|
||||
String foundString = editor.getDocument().getText(liveOccurrence.getPrimaryRange());
|
||||
String documentText = editor.getDocument().getText();
|
||||
FindModel currentModel = myFindDialog.getCurrentModel();
|
||||
String stringToReplace = null;
|
||||
|
||||
if (currentModel != null) {
|
||||
if (currentModel.isReplaceState()) {
|
||||
FindManager findManager = FindManager.getInstance(editor.getProject());
|
||||
stringToReplace = findManager.getStringToReplace(foundString, currentModel,
|
||||
liveOccurrence.getPrimaryRange().getStartOffset(), documentText);
|
||||
if (stringToReplace != null && stringToReplace.isEmpty()) {
|
||||
stringToReplace = EMPTY_STRING_DISPLAY_TEXT;
|
||||
}
|
||||
}
|
||||
}
|
||||
return stringToReplace;
|
||||
}
|
||||
|
||||
private static void findResultsToOccurrences(ArrayList<FindResult> results, Collection<LiveOccurrence> occurrences) {
|
||||
for (FindResult r : results) {
|
||||
LiveOccurrence occurrence = new LiveOccurrence();
|
||||
occurrence.setPrimaryRange(r);
|
||||
occurrences.add(occurrence);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stateChanged() {
|
||||
myLivePreview.update();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.intellij.find.impl;
|
||||
|
||||
import com.intellij.ui.UserActivityWatcher;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
public class MomentoUserActivityWatcher extends UserActivityWatcher {
|
||||
|
||||
Set<Component> components = new HashSet<Component>();
|
||||
|
||||
@Override
|
||||
protected void processComponent(Component parentComponent) {
|
||||
if (!components.contains(parentComponent)) {
|
||||
super.processComponent(parentComponent);
|
||||
components.add(parentComponent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void unprocessComponent(Component component) {
|
||||
components.remove(component);
|
||||
super.unprocessComponent(component);
|
||||
}
|
||||
|
||||
public boolean isWatched(Component c) {
|
||||
return components.contains(c);
|
||||
}
|
||||
}
|
||||
@@ -109,7 +109,9 @@ public abstract class BaseProjectTreeBuilder extends AbstractTreeBuilder {
|
||||
}
|
||||
|
||||
protected final void expandNodeChildren(final DefaultMutableTreeNode node) {
|
||||
Object element = ((NodeDescriptor)node.getUserObject()).getElement();
|
||||
final NodeDescriptor userObject = (NodeDescriptor)node.getUserObject();
|
||||
if (userObject == null) return;
|
||||
Object element = userObject.getElement();
|
||||
VirtualFile virtualFile = getFileToRefresh(element);
|
||||
super.expandNodeChildren(node);
|
||||
if (virtualFile != null) {
|
||||
|
||||
+34
-1
@@ -375,6 +375,24 @@ public class ScriptingLibraryMappings extends LanguagePerFileMappings<ScriptingL
|
||||
myLibraries.clear();
|
||||
myLibraries.putAll(myOldLibraries);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<VirtualFile> getSourceFiles() {
|
||||
Set<VirtualFile> sourceFiles = new HashSet<VirtualFile>();
|
||||
for (ScriptingLibraryTable.LibraryModel libModel : myLibraries.values()) {
|
||||
sourceFiles.addAll(libModel.getSourceFiles());
|
||||
}
|
||||
return sourceFiles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<VirtualFile> getCompactFiles() {
|
||||
Set<VirtualFile> compactFiles = new HashSet<VirtualFile>();
|
||||
for (ScriptingLibraryTable.LibraryModel libModel : myLibraries.values()) {
|
||||
compactFiles.addAll(libModel.getCompactFiles());
|
||||
}
|
||||
return compactFiles;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -400,6 +418,21 @@ public class ScriptingLibraryMappings extends LanguagePerFileMappings<ScriptingL
|
||||
}
|
||||
return isApplicable(libFile, srcFile.getParent());
|
||||
}
|
||||
|
||||
|
||||
public Set<VirtualFile> getLibraryFilesFor(VirtualFile srcFile) {
|
||||
Set<VirtualFile> libFiles = new HashSet<VirtualFile>();
|
||||
collectLibraryFilesFor(srcFile, libFiles);
|
||||
return libFiles;
|
||||
}
|
||||
|
||||
private void collectLibraryFilesFor(VirtualFile file, Set<VirtualFile> libFiles) {
|
||||
if (file == null) return;
|
||||
ScriptingLibraryTable.LibraryModel libraryModel = getMapping(file);
|
||||
if (libraryModel != null) {
|
||||
libFiles.addAll(libraryModel.getCompactFiles());
|
||||
libFiles.addAll(libraryModel.getSourceFiles());
|
||||
}
|
||||
collectLibraryFilesFor(file.getParent(), libFiles);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
|
||||
public class EditLibraryDialog extends DialogWrapper {
|
||||
|
||||
@@ -290,11 +291,11 @@ public class EditLibraryDialog extends DialogWrapper {
|
||||
fireTableDataChanged();
|
||||
}
|
||||
|
||||
public void setFiles(VirtualFile[] sourceFiles, VirtualFile[] compactFiles) {
|
||||
public void setFiles(Set<VirtualFile> sourceFiles, Set<VirtualFile> compactFiles) {
|
||||
myFiles.clear();
|
||||
myFiles.addAll(Arrays.asList(sourceFiles));
|
||||
myFiles.addAll(Arrays.asList(compactFiles));
|
||||
myCompactFiles.addAll(Arrays.asList(compactFiles));
|
||||
myFiles.addAll(sourceFiles);
|
||||
myFiles.addAll(compactFiles);
|
||||
myCompactFiles.addAll(compactFiles);
|
||||
}
|
||||
|
||||
public void setFileType(VirtualFile file, boolean isCompact) {
|
||||
|
||||
+4
-9
@@ -30,7 +30,7 @@ public class ScriptingLibrariesScope extends GlobalSearchScope {
|
||||
|
||||
private GlobalSearchScope myBaseScope;
|
||||
private ScriptingIndexableSetContributor myContributor;
|
||||
private Set<VirtualFile> myLibraryFiles;
|
||||
protected Set<VirtualFile> myLibraryFiles;
|
||||
|
||||
public ScriptingLibrariesScope(GlobalSearchScope baseScope, Class<? extends IndexableSetContributor> providerClass) {
|
||||
super(baseScope.getProject());
|
||||
@@ -38,21 +38,16 @@ public class ScriptingLibrariesScope extends GlobalSearchScope {
|
||||
IndexableSetContributor contributor = IndexableSetContributor.EP_NAME.findExtension(providerClass);
|
||||
if (contributor instanceof ScriptingIndexableSetContributor) {
|
||||
myContributor = (ScriptingIndexableSetContributor)contributor;
|
||||
updateLibraryFiles();
|
||||
setLibraryFiles();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateLibraryFiles() {
|
||||
public void setLibraryFiles() {
|
||||
myLibraryFiles = myContributor.getLibraryFiles(myBaseScope.getProject());
|
||||
}
|
||||
|
||||
public boolean contains(VirtualFile file) {
|
||||
return myBaseScope.contains(file) | contributorContains(file);
|
||||
}
|
||||
|
||||
private boolean contributorContains(VirtualFile file) {
|
||||
if (myContributor == null) return false;
|
||||
return myLibraryFiles.contains(file);
|
||||
return myBaseScope.contains(file) | (myLibraryFiles == null ? false : myLibraryFiles.contains(file));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+9
-9
@@ -79,7 +79,7 @@ public class ScriptingLibraryTable {
|
||||
if (myCompactFilesCache == null) {
|
||||
myCompactFilesCache = new HashSet<VirtualFile>();
|
||||
for (LibraryModel libraryModel : myLibraryModels) {
|
||||
myCompactFilesCache.addAll(Arrays.asList(libraryModel.getCompactFiles()));
|
||||
myCompactFilesCache.addAll(libraryModel.getCompactFiles());
|
||||
}
|
||||
}
|
||||
return myCompactFilesCache.contains(file);
|
||||
@@ -149,8 +149,8 @@ public class ScriptingLibraryTable {
|
||||
|
||||
public static class LibraryModel {
|
||||
private String myName;
|
||||
private ArrayList<VirtualFile> mySourceFiles = new ArrayList<VirtualFile>();
|
||||
private ArrayList<VirtualFile> myCompactFiles = new ArrayList<VirtualFile>();
|
||||
private Set<VirtualFile> mySourceFiles = new HashSet<VirtualFile>();
|
||||
private Set<VirtualFile> myCompactFiles = new HashSet<VirtualFile>();
|
||||
private ArrayList<String> myDocUrls = new ArrayList<String>();
|
||||
|
||||
public LibraryModel(String name, VirtualFile[] sourceFiles, VirtualFile[] compactFiles, String[] docUrls) {
|
||||
@@ -183,12 +183,12 @@ public class ScriptingLibraryTable {
|
||||
myDocUrls.addAll(Arrays.asList(docUrls));
|
||||
}
|
||||
|
||||
public VirtualFile[] getSourceFiles() {
|
||||
return mySourceFiles.toArray(new VirtualFile[mySourceFiles.size()]);
|
||||
public Set<VirtualFile> getSourceFiles() {
|
||||
return mySourceFiles;
|
||||
}
|
||||
|
||||
public VirtualFile[] getCompactFiles() {
|
||||
return myCompactFiles.toArray(new VirtualFile[myCompactFiles.size()]);
|
||||
|
||||
public Set<VirtualFile> getCompactFiles() {
|
||||
return myCompactFiles;
|
||||
}
|
||||
|
||||
public String[] getDocUrls() {
|
||||
@@ -196,7 +196,7 @@ public class ScriptingLibraryTable {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public VirtualFile[] getFiles(OrderRootType rootType) {
|
||||
public Set<VirtualFile> getFiles(OrderRootType rootType) {
|
||||
if (rootType == COMPACT_ROOT_TYPE) {
|
||||
return getCompactFiles();
|
||||
}
|
||||
|
||||
+1
-2
@@ -929,9 +929,8 @@ public class SingleInspectionProfilePanel extends JPanel {
|
||||
if (myShareProfile != (mySelectedProfile.getProfileManager() == myProjectProfileManager)) return true;
|
||||
if (!Comparing.strEqual(myInitialProfile, mySelectedProfile.getName())) return true;
|
||||
if (descriptorsAreChanged()) {
|
||||
return setSelectedProfileModified(true);
|
||||
return true;
|
||||
}
|
||||
setSelectedProfileModified(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+8
-3
@@ -35,14 +35,19 @@ public class DefaultPomTargetDescriptionProvider extends PomDescriptionProvider
|
||||
if (element instanceof PsiElement) return null;
|
||||
|
||||
if (location == UsageViewTypeLocation.INSTANCE) {
|
||||
return TypeNameManager.getTypeName(element.getClass());
|
||||
return getTypeName(element);
|
||||
}
|
||||
if (location == UsageViewNodeTextLocation.INSTANCE) {
|
||||
return TypeNameManager.getTypeName(element.getClass()) + " " + StringUtil.notNullize(element instanceof PomNamedTarget ? ((PomNamedTarget)element).getName() : null, "''");
|
||||
return getTypeName(element) + " " + StringUtil.notNullize(element instanceof PomNamedTarget ? ((PomNamedTarget)element).getName() : null, "''");
|
||||
}
|
||||
if (location instanceof HighlightUsagesDescriptionLocation) {
|
||||
return TypeNameManager.getTypeName(element.getClass());
|
||||
return getTypeName(element);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String getTypeName(PomTarget element) {
|
||||
final String s = TypeNameManager._getTypeName(element.getClass());
|
||||
return s == null ? "Element" : s;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,10 +99,6 @@ public class PsiElementRenameHandler implements RenameHandler {
|
||||
if (element == null) return "";
|
||||
if (!(element instanceof PsiFile) && CollectHighlightsUtil.isOutsideSourceRootJavaFile(element.getContainingFile())) return "";
|
||||
|
||||
if (!element.isWritable()) {
|
||||
return RefactoringBundle.getCannotRefactorMessage("This element cannot be renamed.");
|
||||
}
|
||||
|
||||
boolean hasRenameProcessor = RenamePsiElementProcessor.forElement(element) != RenamePsiElementProcessor.DEFAULT;
|
||||
boolean hasWritableMetaData = element instanceof PsiMetaOwner && ((PsiMetaOwner)element).getMetaData() instanceof PsiWritableMetaData;
|
||||
|
||||
@@ -110,9 +106,15 @@ public class PsiElementRenameHandler implements RenameHandler {
|
||||
return RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("error.wrong.caret.position.symbol.to.rename"));
|
||||
}
|
||||
|
||||
if (!PsiManager.getInstance(project).isInProject(element) && element.isPhysical()) {
|
||||
return RefactoringBundle
|
||||
.getCannotRefactorMessage(RefactoringBundle.message("error.out.of.project.element", UsageViewUtil.getType(element)));
|
||||
if (!PsiManager.getInstance(project).isInProject(element)) {
|
||||
if (element.isPhysical()) {
|
||||
return RefactoringBundle
|
||||
.getCannotRefactorMessage(RefactoringBundle.message("error.out.of.project.element", UsageViewUtil.getType(element)));
|
||||
}
|
||||
|
||||
if (!element.isWritable()) {
|
||||
return RefactoringBundle.getCannotRefactorMessage("This element cannot be renamed.");
|
||||
}
|
||||
}
|
||||
|
||||
if (InjectedLanguageUtil.isInInjectedLanguagePrefixSuffix(element)) {
|
||||
|
||||
@@ -760,11 +760,11 @@ public class PluginManager {
|
||||
ourBuildNumber = BuildNumber.fromString(new String(FileUtil.loadFileText(buildTxtFile)).trim());
|
||||
}
|
||||
else {
|
||||
ourBuildNumber = BuildNumber.fromString("102.SNAPSHOT");
|
||||
ourBuildNumber = BuildNumber.fromString("104.SNAPSHOT");
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
ourBuildNumber = BuildNumber.fromString("102.SNAPSHOT");
|
||||
ourBuildNumber = BuildNumber.fromString("104.SNAPSHOT");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,19 +49,36 @@ public interface Notifications {
|
||||
}
|
||||
|
||||
public static void notify(@NotNull final Notification notification, @NotNull final NotificationDisplayType defaultDisplayType, @Nullable final Project project) {
|
||||
if (project != null && !project.isInitialized()) {
|
||||
StartupManager.getInstance(project).runWhenProjectIsInitialized(new Runnable() {
|
||||
public void run() {
|
||||
project.getMessageBus().syncPublisher(TOPIC).notify(notification, defaultDisplayType);
|
||||
}
|
||||
});
|
||||
if (project != null && !project.isDisposed()) {
|
||||
if (!project.isInitialized()) {
|
||||
StartupManager.getInstance(project).runWhenProjectIsInitialized(new Runnable() {
|
||||
public void run() {
|
||||
project.getMessageBus().syncPublisher(TOPIC).notify(notification, defaultDisplayType);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
if (EventQueue.isDispatchThread()) {
|
||||
project.getMessageBus().syncPublisher(TOPIC).notify(notification, defaultDisplayType);
|
||||
}
|
||||
else {
|
||||
//noinspection SSBasedInspection
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
project.getMessageBus().syncPublisher(TOPIC).notify(notification, defaultDisplayType);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
FrameStateManager.getInstance().getApplicationActive().doWhenDone(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final MessageBus bus = project == null ? ApplicationManager.getApplication().getMessageBus() : (project.isDisposed() ? null : project.getMessageBus());
|
||||
final MessageBus bus =
|
||||
project == null ? ApplicationManager.getApplication().getMessageBus() : (project.isDisposed() ? null : project.getMessageBus());
|
||||
if (bus != null) {
|
||||
if (EventQueue.isDispatchThread()) {
|
||||
bus.syncPublisher(TOPIC).notify(notification, defaultDisplayType);
|
||||
|
||||
@@ -69,4 +69,8 @@ public interface BalloonBuilder {
|
||||
|
||||
@NotNull
|
||||
BalloonBuilder setPositionChangeYShift(int positionChangeYShift);
|
||||
|
||||
boolean isHideOnAction();
|
||||
|
||||
BalloonBuilder setHideOnAction(boolean hideOnAction);
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2011 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;
|
||||
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.ui.EditorCustomization;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Basic super class for {@link EditorCustomization editor customizations} that don't consider un-applying feature.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 1/14/11 12:52 PM
|
||||
*/
|
||||
public abstract class AbstractUnappliableEditorCustomization implements EditorCustomization {
|
||||
|
||||
@Override
|
||||
public void removeCustomization(@NotNull EditorEx editor, @NotNull Feature feature) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
@@ -53,6 +53,7 @@ import java.awt.event.MouseEvent;
|
||||
|
||||
public class IdeTooltipManager implements ApplicationComponent, AWTEventListener {
|
||||
|
||||
public static final Color GRAPHITE_COLOR = new Color(100, 100, 100, 230);
|
||||
private RegistryValue myIsEnabled;
|
||||
|
||||
private Component myCurrentComponent;
|
||||
@@ -304,7 +305,7 @@ public class IdeTooltipManager implements ApplicationComponent, AWTEventListener
|
||||
}
|
||||
|
||||
public Color getTextBackground(boolean awtTooltip) {
|
||||
return useGraphite(awtTooltip) ? new Color(100, 100, 100, 230) : UIUtil.getToolTipBackground();
|
||||
return useGraphite(awtTooltip) ? GRAPHITE_COLOR : UIUtil.getToolTipBackground();
|
||||
}
|
||||
|
||||
public String getUlImg(boolean awtTooltip) {
|
||||
|
||||
+5
@@ -98,6 +98,11 @@ public class PasswordSafePromptDialog extends DialogWrapper {
|
||||
return myRoot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getPreferredFocusedComponent() {
|
||||
return myPasswordPasswordField;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask password possibly asking password database first. The method could be invoked from any thread. If UI needs to be shown,
|
||||
* the method invokes {@link com.intellij.util.ui.UIUtil#invokeAndWaitIfNeeded(Runnable)}
|
||||
|
||||
+6
-2
@@ -165,9 +165,9 @@ public class EditorActionUtil {
|
||||
|
||||
if (isCamel) {
|
||||
if (firstIsIdentifierPart && secondIsIdentifierPart &&
|
||||
(Character.isLowerCase(prev) && Character.isUpperCase(current) ||
|
||||
(isLowerCaseOrDigit(prev) && Character.isUpperCase(current) ||
|
||||
prev == '_' && current != '_' ||
|
||||
Character.isUpperCase(prev) && Character.isUpperCase(current) && Character.isLowerCase(next))) {
|
||||
Character.isUpperCase(prev) && Character.isUpperCase(current) && isLowerCaseOrDigit(next))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -175,6 +175,10 @@ public class EditorActionUtil {
|
||||
return (Character.isWhitespace(prev) || firstIsIdentifierPart) &&
|
||||
!Character.isWhitespace(current) && !secondIsIdentifierPart;
|
||||
}
|
||||
|
||||
private static boolean isLowerCaseOrDigit(char c) {
|
||||
return Character.isLowerCase(c) || Character.isDigit(c);
|
||||
}
|
||||
|
||||
public static boolean isWordEnd(CharSequence text, int offset, boolean isCamel) {
|
||||
char prev = offset > 0 ? text.charAt(offset - 1) : 0;
|
||||
|
||||
@@ -111,6 +111,7 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener,
|
||||
public void moveToVisualPosition(@NotNull VisualPosition pos) {
|
||||
assertIsDispatchThread();
|
||||
validateCallContext();
|
||||
myDesiredX = -1;
|
||||
int column = pos.column;
|
||||
int line = pos.line;
|
||||
|
||||
@@ -213,7 +214,7 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener,
|
||||
int newLineNumber = visualCaret.line + lineShift;
|
||||
int newColumnNumber = visualCaret.column + columnShift;
|
||||
if (desiredX >= 0) {
|
||||
newColumnNumber = myEditor.xyToVisualPosition(new Point(desiredX, newLineNumber * myEditor.getLineHeight())).column;
|
||||
newColumnNumber = myEditor.xyToVisualPosition(new Point(desiredX, Math.max(0, newLineNumber) * myEditor.getLineHeight())).column;
|
||||
}
|
||||
|
||||
Document document = myEditor.getDocument();
|
||||
|
||||
@@ -1015,7 +1015,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
charWidth = EditorUtil.charWidth(c, fontType, this);
|
||||
}
|
||||
|
||||
if (charWidth <= 0) {
|
||||
if (charWidth < 0) {
|
||||
charWidth = spaceSize;
|
||||
}
|
||||
|
||||
|
||||
+21
-1
@@ -311,7 +311,13 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi
|
||||
|
||||
FoldRegion endFold = foldingModel.getCollapsedRegionAtOffset(endOffset);
|
||||
if (endFold != null) {
|
||||
endOffset = endFold.getEndOffset();
|
||||
VisualPosition visualFoldStart = myEditor.offsetToVisualPosition(endFold.getStartOffset());
|
||||
// All visual positions that lay at collapsed fold region placeholder are mapped to the same offset. Hence, there are
|
||||
// at least two distinct situations - selection end is located inside collapsed fold region placeholder and just before it.
|
||||
// We want to expand selection to the fold region end at the former case and keep selection as-is at the latest one.
|
||||
if (visualFoldStart.column < endPosition.column) {
|
||||
endOffset = endFold.getEndOffset();
|
||||
}
|
||||
}
|
||||
|
||||
int oldSelectionStart;
|
||||
@@ -583,6 +589,20 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi
|
||||
if (marker != null) {
|
||||
int startOffset = marker.getStartOffset();
|
||||
int endOffset = marker.getEndOffset();
|
||||
if (caretOffset != startOffset && caretOffset != endOffset) {
|
||||
// Try to check if current selection is tweaked by fold region.
|
||||
FoldingModelEx foldingModel = myEditor.getFoldingModel();
|
||||
FoldRegion foldRegion = foldingModel.getCollapsedRegionAtOffset(caretOffset);
|
||||
if (foldRegion != null) {
|
||||
if (foldRegion.getStartOffset() == startOffset) {
|
||||
return endOffset;
|
||||
}
|
||||
else if (foldRegion.getEndOffset() == endOffset) {
|
||||
return startOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (caretOffset == endOffset) {
|
||||
return startOffset;
|
||||
}
|
||||
|
||||
+6
-1
@@ -51,6 +51,7 @@ import javax.swing.text.Document;
|
||||
import javax.swing.text.JTextComponent;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
@@ -535,6 +536,7 @@ public abstract class FileTextFieldImpl implements FileLookup, Disposable, FileT
|
||||
if (currentDiff == diff) {
|
||||
toPreselect = each;
|
||||
toPreselectFixed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -597,7 +599,10 @@ public abstract class FileTextFieldImpl implements FileLookup, Disposable, FileT
|
||||
if (typed == null) return null;
|
||||
LookupFile lastFound = myFinder.find(typed);
|
||||
if (lastFound == null) return null;
|
||||
if (lastFound.exists()) return lastFound;
|
||||
if (lastFound.exists()) {
|
||||
if (typed.charAt(typed.length() - 1) != File.separatorChar) return lastFound.getParent();
|
||||
return lastFound;
|
||||
}
|
||||
|
||||
final String[] splits = myFinder.normalize(typed).split(myFileSpitRegExp);
|
||||
StringBuffer fullPath = new StringBuffer();
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<text value="Project &name:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="89536" class="javax.swing.JLabel">
|
||||
<component id="89536" class="javax.swing.JLabel" binding="myLocationLabel">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
|
||||
@@ -49,6 +49,7 @@ public class NewDirectoryProjectDialog extends DialogWrapper {
|
||||
private JPanel myRootPane;
|
||||
private JComboBox myProjectTypeComboBox;
|
||||
private JPanel myProjectTypePanel;
|
||||
private JLabel myLocationLabel;
|
||||
private String myBaseDir;
|
||||
private boolean myModifyingLocation = false;
|
||||
private boolean myModifyingProjectName = false;
|
||||
@@ -60,6 +61,8 @@ public class NewDirectoryProjectDialog extends DialogWrapper {
|
||||
setTitle("Create New Project");
|
||||
init();
|
||||
|
||||
myLocationLabel.setLabelFor(myLocationField.getChildComponent());
|
||||
|
||||
myBaseDir = getBaseDir();
|
||||
File projectName = FileUtil.findSequentNonexistentFile(new File(myBaseDir), "untitled", "");
|
||||
myLocationField.setText(projectName.toString());
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2000-2011 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.ui;
|
||||
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Base super class for {@link EditorCustomization editor customizations} that provide the following:
|
||||
* <pre>
|
||||
* <ul>
|
||||
* <li>
|
||||
* Don't process {@link #addCustomization(EditorEx, Feature)} and {@link #removeCustomization(EditorEx, Feature)} if given feature
|
||||
* is not supported by the current customization (supported features are defined at constructor);
|
||||
* </li>
|
||||
* </ul>
|
||||
* </pre>
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 1/24/11 3:56 PM
|
||||
*/
|
||||
public abstract class AbstractEditorCustomization implements EditorCustomization {
|
||||
|
||||
private final Set<Feature> myFeatures = EnumSet.noneOf(Feature.class);
|
||||
|
||||
protected AbstractEditorCustomization(@NotNull Feature... features) {
|
||||
myFeatures.addAll(Arrays.asList(features));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Feature> getSupportedFeatures() {
|
||||
return myFeatures;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCustomization(@NotNull EditorEx editor, @NotNull Feature feature) {
|
||||
if (!myFeatures.contains(feature)) {
|
||||
return;
|
||||
}
|
||||
doProcessCustomization(editor, feature, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCustomization(@NotNull EditorEx editor, @NotNull Feature feature) {
|
||||
if (!myFeatures.contains(feature)) {
|
||||
return;
|
||||
}
|
||||
doProcessCustomization(editor, feature, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Template method for sub-classes to process target feature applying/removal and being sure that given feature
|
||||
* is supported by the current customization.
|
||||
*
|
||||
* @param editor target editor to apply the given feature
|
||||
* @param feature target feature to apply to the given editor
|
||||
* @param apply flag the identifies if given feature should be applied/removed from the given editor
|
||||
*/
|
||||
protected abstract void doProcessCustomization(@NotNull EditorEx editor, @NotNull Feature feature, boolean apply);
|
||||
}
|
||||
+5
-14
@@ -18,29 +18,20 @@ package com.intellij.ui;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* {@link EditorCustomization} for {@link EditorCustomization.Feature#ADDITIONAL_PAGE_AT_BOTTOM}.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 1/21/11 4:06 PM
|
||||
*/
|
||||
public class AdditionalPageAtBottomEditorCustomization implements EditorCustomization {
|
||||
public class AdditionalPageAtBottomEditorCustomization extends AbstractEditorCustomization {
|
||||
|
||||
@Override
|
||||
public Set<Feature> getSupportedFeatures() {
|
||||
return EnumSet.of(Feature.ADDITIONAL_PAGE_AT_BOTTOM);
|
||||
public AdditionalPageAtBottomEditorCustomization() {
|
||||
super(Feature.ADDITIONAL_PAGE_AT_BOTTOM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCustomization(@NotNull EditorEx editor, @NotNull Feature feature) {
|
||||
editor.getSettings().setAdditionalPageAtBottom(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCustomization(@NotNull EditorEx editor, @NotNull Feature feature) {
|
||||
editor.getSettings().setAdditionalPageAtBottom(false);
|
||||
protected void doProcessCustomization(@NotNull EditorEx editor, @NotNull Feature feature, boolean apply) {
|
||||
editor.getSettings().setAdditionalPageAtBottom(apply);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,6 +197,7 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi
|
||||
private final JComponent myContent;
|
||||
private final boolean myHideOnMouse;
|
||||
private final boolean myHideOnKey;
|
||||
private boolean myHideOnAction;
|
||||
private final boolean myEnableCloseButton;
|
||||
private final Icon myCloseButton = IconLoader.getIcon("/general/balloonClose.png");
|
||||
|
||||
@@ -205,6 +206,7 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi
|
||||
Color fillColor,
|
||||
boolean hideOnMouse,
|
||||
boolean hideOnKey,
|
||||
boolean hideOnAction,
|
||||
boolean showPointer,
|
||||
boolean enableCloseButton,
|
||||
long fadeoutTime,
|
||||
@@ -220,6 +222,7 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi
|
||||
myContent = content;
|
||||
myHideOnMouse = hideOnMouse;
|
||||
myHideOnKey = hideOnKey;
|
||||
myHideOnAction = hideOnAction;
|
||||
myShowPointer = showPointer;
|
||||
myEnableCloseButton = enableCloseButton;
|
||||
myHideOnFrameResize = hideOnFrameResize;
|
||||
@@ -380,6 +383,14 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi
|
||||
Toolkit.getDefaultToolkit().addAWTEventListener(myAwtActivityListener, MouseEvent.MOUSE_EVENT_MASK |
|
||||
MouseEvent.MOUSE_MOTION_EVENT_MASK |
|
||||
KeyEvent.KEY_EVENT_MASK);
|
||||
ActionManager.getInstance().addAnActionListener(new AnActionListener.Adapter() {
|
||||
@Override
|
||||
public void beforeActionPerformed(AnAction action, DataContext dataContext, AnActionEvent event) {
|
||||
if (myHideOnAction) {
|
||||
hide();
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
|
||||
private Rectangle getRecForPosition(Position position, boolean adjust) {
|
||||
@@ -462,13 +473,13 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi
|
||||
}
|
||||
myAnimator = new Animator("Balloon", 10, myAnimationCycle, false, 0, 1, forward) {
|
||||
public void paintNow(final float frame, final float totalFrames, final float cycle) {
|
||||
if (myComp.getParent() == null) return;
|
||||
if (myComp == null || myComp.getParent() == null) return;
|
||||
myComp.setAlpha(frame / totalFrames);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintCycleEnd() {
|
||||
if (myComp.getParent() == null) return;
|
||||
if (myComp == null || myComp.getParent() == null) return;
|
||||
|
||||
if (isForward()) {
|
||||
myComp.clear();
|
||||
@@ -1230,7 +1241,7 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi
|
||||
|
||||
//pane.setBorder(new LineBorder(Color.blue));
|
||||
|
||||
balloon.set(new BalloonImpl(new JLabel("FUCK"), Color.black, MessageType.ERROR.getPopupBackground(), true, true, true, true, 0, true, null, false, 500, 5, 0, 0));
|
||||
balloon.set(new BalloonImpl(new JLabel("FUCK"), Color.black, MessageType.ERROR.getPopupBackground(), true, true, true, true, true, 0, true, null, false, 500, 5, 0, 0));
|
||||
balloon.get().setShowPointer(true);
|
||||
|
||||
if (e.isShiftDown()) {
|
||||
|
||||
+5
-15
@@ -18,29 +18,19 @@ package com.intellij.ui;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author irengrig
|
||||
* Date: 12/6/10
|
||||
* Time: 10:18 AM
|
||||
*/
|
||||
public class HorizontalScrollBarEditorCustomization implements EditorCustomization {
|
||||
public Set<Feature> getSupportedFeatures() {
|
||||
return EnumSet.of(Feature.HORIZONTAL_SCROLLBAR);
|
||||
}
|
||||
public class HorizontalScrollBarEditorCustomization extends AbstractEditorCustomization {
|
||||
|
||||
public void addCustomization(@NotNull EditorEx editor, @NotNull Feature feature) {
|
||||
if (Feature.HORIZONTAL_SCROLLBAR.equals(feature)) {
|
||||
editor.setHorizontalScrollbarVisible(true);
|
||||
}
|
||||
public HorizontalScrollBarEditorCustomization() {
|
||||
super(Feature.HORIZONTAL_SCROLLBAR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCustomization(@NotNull EditorEx editor, @NotNull Feature feature) {
|
||||
if (Feature.HORIZONTAL_SCROLLBAR.equals(feature)) {
|
||||
editor.setHorizontalScrollbarVisible(false);
|
||||
}
|
||||
protected void doProcessCustomization(@NotNull EditorEx editor, @NotNull Feature feature, boolean apply) {
|
||||
editor.setHorizontalScrollbarVisible(apply);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,24 +15,20 @@
|
||||
*/
|
||||
package com.intellij.ui;
|
||||
|
||||
import com.intellij.AbstractUnappliableEditorCustomization;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public class OneLineEditorCustomization extends AbstractUnappliableEditorCustomization {
|
||||
public Set<Feature> getSupportedFeatures() {
|
||||
return EnumSet.of(Feature.ONE_LINE);
|
||||
public class OneLineEditorCustomization extends AbstractEditorCustomization {
|
||||
|
||||
public OneLineEditorCustomization() {
|
||||
super(Feature.ONE_LINE);
|
||||
}
|
||||
|
||||
public void addCustomization(@NotNull EditorEx editor, @NotNull Feature feature) {
|
||||
if (Feature.ONE_LINE.equals(feature)) {
|
||||
editor.setOneLineMode(true);
|
||||
}
|
||||
@Override
|
||||
protected void doProcessCustomization(@NotNull EditorEx editor, @NotNull Feature feature, boolean apply) {
|
||||
editor.setOneLineMode(apply);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,13 +15,9 @@
|
||||
*/
|
||||
package com.intellij.ui;
|
||||
|
||||
import com.intellij.AbstractUnappliableEditorCustomization;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Editor customization that can make target editor soft wraps-aware.
|
||||
* <p/>
|
||||
@@ -30,15 +26,14 @@ import java.util.Set;
|
||||
* @author Denis Zhdanov
|
||||
* @since Aug 20, 2010 4:54:48 PM
|
||||
*/
|
||||
public class SoftWrapsEditorCustomization extends AbstractUnappliableEditorCustomization {
|
||||
public class SoftWrapsEditorCustomization extends AbstractEditorCustomization {
|
||||
|
||||
@Override
|
||||
public Set<Feature> getSupportedFeatures() {
|
||||
return EnumSet.of(Feature.SOFT_WRAP);
|
||||
public SoftWrapsEditorCustomization() {
|
||||
super(Feature.SOFT_WRAP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCustomization(@NotNull EditorEx editor, @NotNull Feature feature) {
|
||||
editor.getSettings().setUseSoftWraps(true);
|
||||
protected void doProcessCustomization(@NotNull EditorEx editor, @NotNull Feature feature, boolean apply) {
|
||||
editor.getSettings().setUseSoftWraps(apply);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,11 +46,23 @@ public class BalloonPopupBuilderImpl implements BalloonBuilder {
|
||||
private int myCalloutShift;
|
||||
private int myPositionChangeXShift;
|
||||
private int myPositionChangeYShift;
|
||||
private boolean myHideOnAction = true;
|
||||
|
||||
public BalloonPopupBuilderImpl(@NotNull final JComponent content) {
|
||||
myContent = content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHideOnAction() {
|
||||
return myHideOnAction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BalloonBuilder setHideOnAction(boolean hideOnAction) {
|
||||
myHideOnAction = hideOnAction;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public BalloonBuilder setPreferredPosition(final Balloon.Position position) {
|
||||
myPrefferedPosition = position;
|
||||
@@ -122,7 +134,7 @@ public class BalloonPopupBuilderImpl implements BalloonBuilder {
|
||||
|
||||
@NotNull
|
||||
public Balloon createBalloon() {
|
||||
return new BalloonImpl(myContent, myBorder, myFill, myHideOnMouseOutside, myHideOnKeyOutside, myShowCalllout, myCloseButtonEnabled, myFadeoutTime, myHideOnFrameResize, myClickHandler, myCloseOnClick, myAnimationCycle,
|
||||
return new BalloonImpl(myContent, myBorder, myFill, myHideOnMouseOutside, myHideOnKeyOutside, myHideOnAction, myShowCalllout, myCloseButtonEnabled, myFadeoutTime, myHideOnFrameResize, myClickHandler, myCloseOnClick, myAnimationCycle,
|
||||
myCalloutShift, myPositionChangeXShift, myPositionChangeYShift);
|
||||
}
|
||||
|
||||
@@ -145,4 +157,4 @@ public class BalloonPopupBuilderImpl implements BalloonBuilder {
|
||||
myCalloutShift = length;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,6 +180,7 @@ wrapping.extends.implements.list=Extends/implements list
|
||||
wrapping.extends.implements.keyword=Extends/implements keyword
|
||||
wrapping.throws.list=Throws list
|
||||
wrapping.throws.keyword=Throws keyword
|
||||
wrapping.align.throws.keyword=Align 'throws' to method start
|
||||
wrapping.ternary.operation=Ternary operation
|
||||
wrapping.assignment.variables.groups=Fields/variables groups
|
||||
wrapping.assignment.statement=Assignment statement
|
||||
|
||||
@@ -182,7 +182,10 @@
|
||||
<keyboard-shortcut first-keystroke="control N"/>
|
||||
<keyboard-shortcut first-keystroke="control ENTER"/>
|
||||
</action>
|
||||
<action id="ActivateProjectToolWindow">
|
||||
<action id="NewElementSamePlace">
|
||||
<keyboard-shortcut first-keystroke="control alt N"/>
|
||||
</action>
|
||||
<action id="ActivateProjectToolWindow">
|
||||
<keyboard-shortcut first-keystroke="meta 1"/>
|
||||
</action>
|
||||
<action id="ActivateCommanderToolWindow">
|
||||
|
||||
@@ -209,6 +209,9 @@
|
||||
<keyboard-shortcut first-keystroke="control N"/>
|
||||
<keyboard-shortcut first-keystroke="control ENTER"/>
|
||||
</action>
|
||||
<action id="NewElementSamePlace">
|
||||
<keyboard-shortcut first-keystroke="control alt N"/>
|
||||
</action>
|
||||
<action id="Generate">
|
||||
<keyboard-shortcut first-keystroke="control N"/>
|
||||
<keyboard-shortcut first-keystroke="control ENTER"/>
|
||||
|
||||
+8
@@ -492,6 +492,14 @@ public abstract class LightPlatformCodeInsightTestCase extends LightPlatformTest
|
||||
doAction(IdeActions.ACTION_EDITOR_PASTE);
|
||||
}
|
||||
|
||||
protected static void moveCaretToPreviousWordWithSelection() {
|
||||
doAction("EditorPreviousWordWithSelection");
|
||||
}
|
||||
|
||||
protected static void moveCaretToNextWordWithSelection() {
|
||||
doAction("EditorNextWordWithSelection");
|
||||
}
|
||||
|
||||
protected static void lineComment() {
|
||||
new CommentByLineCommentHandler().invoke(getProject(), getEditor(), getFile());
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ public class BuildNumber implements Comparable<BuildNumber> {
|
||||
private final int myBaselineVersion;
|
||||
private final int myBuildNumber;
|
||||
private static final String BUILD_NUMBER = "__BUILD_NUMBER__";
|
||||
private static final int TOP_BASELINE_VERSION = 102;
|
||||
private static final int TOP_BASELINE_VERSION = 104;
|
||||
|
||||
public BuildNumber(String productCode, int baselineVersion, int buildNumber) {
|
||||
myProductCode = productCode;
|
||||
|
||||
@@ -26,9 +26,18 @@ public class FormBuilder {
|
||||
|
||||
private int line = 0;
|
||||
private final JPanel panel;
|
||||
private boolean vertical;
|
||||
|
||||
/**
|
||||
* @param vertical labels will be placed on their own rows
|
||||
*/
|
||||
public FormBuilder(final boolean vertical) {
|
||||
this.vertical = vertical;
|
||||
panel = new JPanel(new GridBagLayout());
|
||||
}
|
||||
|
||||
public FormBuilder() {
|
||||
panel = new JPanel(new GridBagLayout());
|
||||
this(false);
|
||||
}
|
||||
|
||||
public FormBuilder addLabeledComponent(String labelText, JComponent component) {
|
||||
@@ -38,24 +47,49 @@ public class FormBuilder {
|
||||
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
int verticalInset = line > 0 ? 10 : 0;
|
||||
|
||||
c.gridx = 0;
|
||||
c.gridy = line;
|
||||
c.weightx = 0;
|
||||
c.anchor = GridBagConstraints.EAST;
|
||||
c.insets = new Insets(verticalInset, 0, 0, 5);
|
||||
|
||||
panel.add(label, c);
|
||||
if (vertical) {
|
||||
c.gridwidth = 1;
|
||||
|
||||
c.gridx = 1;
|
||||
c.gridy = line;
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
c.anchor = GridBagConstraints.WEST;
|
||||
c.weightx = 1;
|
||||
c.insets = new Insets(verticalInset, 0, 0, 0);
|
||||
panel.add(component, c);
|
||||
c.gridx = 0;
|
||||
c.gridy = line;
|
||||
c.weightx = 1.0;
|
||||
c.fill = GridBagConstraints.NONE;
|
||||
c.anchor = GridBagConstraints.WEST;
|
||||
c.insets = new Insets(verticalInset, 0, 0, 5);
|
||||
|
||||
line++;
|
||||
panel.add(label, c);
|
||||
|
||||
c.gridx = 0;
|
||||
c.gridy = line + 1;
|
||||
c.weightx = 1.0;
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
c.anchor = GridBagConstraints.WEST;
|
||||
c.insets = new Insets(0, 0, 0, 5);
|
||||
|
||||
panel.add(component, c);
|
||||
|
||||
line += 2;
|
||||
}
|
||||
else {
|
||||
c.gridx = 0;
|
||||
c.gridy = line;
|
||||
c.weightx = 0;
|
||||
c.anchor = GridBagConstraints.EAST;
|
||||
c.insets = new Insets(verticalInset, 0, 0, 5);
|
||||
|
||||
panel.add(label, c);
|
||||
|
||||
c.gridx = 1;
|
||||
c.gridy = line;
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
c.anchor = GridBagConstraints.WEST;
|
||||
c.weightx = 1;
|
||||
c.insets = new Insets(verticalInset, 0, 0, 0);
|
||||
panel.add(component, c);
|
||||
|
||||
line++;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import com.intellij.execution.runners.ExecutionEnvironment;
|
||||
import com.intellij.execution.runners.ProgramRunner;
|
||||
import com.intellij.execution.ui.ExecutionConsole;
|
||||
import com.intellij.execution.ui.RunContentDescriptor;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.xdebugger.breakpoints.XBreakpointManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -71,4 +70,14 @@ public abstract class XDebuggerManager {
|
||||
@NotNull
|
||||
public abstract XDebugSession startSessionAndShowTab(@NotNull String sessionName, @Nullable RunContentDescriptor contentToReuse,
|
||||
@NotNull XDebugProcessStarter starter) throws ExecutionException;
|
||||
|
||||
/**
|
||||
* Start a new debugging session and open 'Debug' tool window
|
||||
* @param sessionName title of 'Debug' tool window
|
||||
* @param showToolWindowOnSuspendOnly if {@code true} 'Debug' tool window won't be shown until debug process is suspended on a breakpoint
|
||||
*/
|
||||
@NotNull
|
||||
public abstract XDebugSession startSessionAndShowTab(@NotNull String sessionName, @Nullable RunContentDescriptor contentToReuse,
|
||||
boolean showToolWindowOnSuspendOnly,
|
||||
@NotNull XDebugProcessStarter starter) throws ExecutionException;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,9 @@
|
||||
*/
|
||||
package com.intellij.xdebugger.impl;
|
||||
|
||||
import com.intellij.execution.ExecutionManager;
|
||||
import com.intellij.execution.configurations.RunProfile;
|
||||
import com.intellij.execution.executors.DefaultDebugExecutor;
|
||||
import com.intellij.execution.filters.HyperlinkInfo;
|
||||
import com.intellij.execution.filters.OpenFileHyperlinkInfo;
|
||||
import com.intellij.execution.process.ProcessHandler;
|
||||
@@ -74,27 +76,30 @@ public class XDebugSessionImpl implements XDebugSession {
|
||||
private MyDependentBreakpointListener myDependentBreakpointListener;
|
||||
private String mySessionName;
|
||||
private XDebugSessionTab mySessionTab;
|
||||
private XDebugSessionData mySessionData;
|
||||
private final EventDispatcher<XDebugSessionListener> myDispatcher = EventDispatcher.create(XDebugSessionListener.class);
|
||||
private Project myProject;
|
||||
private @Nullable ExecutionEnvironment myEnvironment;
|
||||
private ProgramRunner myRunner;
|
||||
private boolean myStopped;
|
||||
private boolean myPauseActionSupported;
|
||||
private boolean myShowTabOnSuspend;
|
||||
|
||||
public XDebugSessionImpl(final @NotNull ExecutionEnvironment env,
|
||||
final @NotNull ProgramRunner runner,
|
||||
XDebuggerManagerImpl debuggerManager) {
|
||||
this(env, runner, debuggerManager, env.getRunProfile().getName());
|
||||
this(env, runner, debuggerManager, env.getRunProfile().getName(), false);
|
||||
}
|
||||
|
||||
public XDebugSessionImpl(final @Nullable ExecutionEnvironment env,
|
||||
final @Nullable ProgramRunner runner,
|
||||
XDebuggerManagerImpl debuggerManager,
|
||||
final @NotNull String sessionName) {
|
||||
final @NotNull String sessionName, final boolean showTabOnSuspend) {
|
||||
myEnvironment = env;
|
||||
myRunner = runner;
|
||||
mySessionName = sessionName;
|
||||
myDebuggerManager = debuggerManager;
|
||||
myShowTabOnSuspend = showTabOnSuspend;
|
||||
myProject = debuggerManager.getProject();
|
||||
ValueLookupManager.getInstance(myProject).startListening();
|
||||
}
|
||||
@@ -106,16 +111,27 @@ public class XDebugSessionImpl implements XDebugSession {
|
||||
|
||||
@NotNull
|
||||
public RunContentDescriptor getRunContentDescriptor() {
|
||||
LOG.assertTrue(mySessionTab != null, "Call init() first!");
|
||||
assertSessionTabInitialized();
|
||||
return mySessionTab.getRunContentDescriptor();
|
||||
}
|
||||
|
||||
private void assertSessionTabInitialized() {
|
||||
if (myShowTabOnSuspend) {
|
||||
LOG.error("Debug tool window isn't shown yet because debug process isn't suspended");
|
||||
}
|
||||
else {
|
||||
LOG.assertTrue(mySessionTab != null, "Debug tool window not initialized yet!");
|
||||
}
|
||||
}
|
||||
|
||||
public void setPauseActionSupported(final boolean isSupported) {
|
||||
myPauseActionSupported = isSupported;
|
||||
}
|
||||
|
||||
public void rebuildViews() {
|
||||
mySessionTab.rebuildViews();
|
||||
if (!myShowTabOnSuspend) {
|
||||
mySessionTab.rebuildViews();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -162,6 +178,7 @@ public class XDebugSessionImpl implements XDebugSession {
|
||||
public XDebugSessionTab init(final XDebugProcess process, @NotNull final XDebugSessionData sessionData) {
|
||||
LOG.assertTrue(myDebugProcess == null);
|
||||
myDebugProcess = process;
|
||||
mySessionData = sessionData;
|
||||
|
||||
XBreakpointManagerImpl breakpointManager = myDebuggerManager.getBreakpointManager();
|
||||
XDependentBreakpointManager dependentBreakpointManager = breakpointManager.getDependentBreakpointManager();
|
||||
@@ -173,8 +190,9 @@ public class XDebugSessionImpl implements XDebugSession {
|
||||
myDependentBreakpointListener = new MyDependentBreakpointListener();
|
||||
dependentBreakpointManager.addListener(myDependentBreakpointListener);
|
||||
|
||||
initSessionTab(sessionData);
|
||||
process.sessionInitialized();
|
||||
if (!myShowTabOnSuspend) {
|
||||
initSessionTab();
|
||||
}
|
||||
|
||||
return mySessionTab;
|
||||
}
|
||||
@@ -183,13 +201,14 @@ public class XDebugSessionImpl implements XDebugSession {
|
||||
return mySessionTab;
|
||||
}
|
||||
|
||||
private void initSessionTab(@NotNull XDebugSessionData sessionData) {
|
||||
private void initSessionTab() {
|
||||
mySessionTab = new XDebugSessionTab(myProject, mySessionName);
|
||||
if (myEnvironment != null) {
|
||||
mySessionTab.setEnvironment(myEnvironment);
|
||||
}
|
||||
Disposer.register(myProject, mySessionTab);
|
||||
mySessionTab.attachToSession(this, myRunner, myEnvironment, sessionData);
|
||||
mySessionTab.attachToSession(this, myRunner, myEnvironment, mySessionData);
|
||||
myDebugProcess.sessionInitialized();
|
||||
}
|
||||
|
||||
private void disableSlaveBreakpoints(final XDependentBreakpointManager dependentBreakpointManager) {
|
||||
@@ -205,6 +224,15 @@ public class XDebugSessionImpl implements XDebugSession {
|
||||
}
|
||||
}
|
||||
|
||||
public void showSessionTab() {
|
||||
RunContentDescriptor descriptor = getRunContentDescriptor();
|
||||
ExecutionManager.getInstance(getProject()).getContentManager().showRunContent(DefaultDebugExecutor.getDebugExecutorInstance(), descriptor);
|
||||
ProcessHandler handler = descriptor.getProcessHandler();
|
||||
if (handler != null) {
|
||||
handler.startNotify();
|
||||
}
|
||||
}
|
||||
|
||||
private static <B extends XBreakpoint<?>> XBreakpointType<?, ?> getBreakpointTypeClass(final XBreakpointHandler<B> handler) {
|
||||
return XDebuggerUtil.getInstance().findBreakpointType(handler.getBreakpointTypeClass());
|
||||
}
|
||||
@@ -483,9 +511,10 @@ public class XDebugSessionImpl implements XDebugSession {
|
||||
}
|
||||
|
||||
private void printMessage(final String message, final String hyperLinkText, @Nullable final HyperlinkInfo info) {
|
||||
assertSessionTabInitialized();
|
||||
DebuggerUIUtil.invokeOnEventDispatch(new Runnable() {
|
||||
public void run() {
|
||||
final ConsoleView consoleView = getConsoleView();
|
||||
final ConsoleView consoleView = (ConsoleView)mySessionTab.getConsole();
|
||||
consoleView.print(message, ConsoleViewContentType.SYSTEM_OUTPUT);
|
||||
if (info != null) {
|
||||
consoleView.printHyperlink(hyperLinkText, info);
|
||||
@@ -498,10 +527,6 @@ public class XDebugSessionImpl implements XDebugSession {
|
||||
});
|
||||
}
|
||||
|
||||
private ConsoleView getConsoleView() {
|
||||
return (ConsoleView)mySessionTab.getConsole();
|
||||
}
|
||||
|
||||
public void positionReached(@NotNull final XSuspendContext suspendContext) {
|
||||
enableBreakpoints();
|
||||
mySuspendContext = suspendContext;
|
||||
@@ -515,6 +540,11 @@ public class XDebugSessionImpl implements XDebugSession {
|
||||
}
|
||||
UIUtil.invokeLaterIfNeeded(new Runnable() {
|
||||
public void run() {
|
||||
if (myShowTabOnSuspend) {
|
||||
myShowTabOnSuspend = false;
|
||||
initSessionTab();
|
||||
showSessionTab();
|
||||
}
|
||||
mySessionTab.toFront();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
package com.intellij.xdebugger.impl;
|
||||
|
||||
import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.execution.ExecutionManager;
|
||||
import com.intellij.execution.Executor;
|
||||
import com.intellij.execution.executors.DefaultDebugExecutor;
|
||||
import com.intellij.execution.process.ProcessHandler;
|
||||
@@ -150,18 +149,24 @@ public class XDebuggerManagerImpl extends XDebuggerManager implements ProjectCom
|
||||
|
||||
@NotNull
|
||||
public XDebugSession startSessionAndShowTab(@NotNull String sessionName, @Nullable RunContentDescriptor contentToReuse,
|
||||
@NotNull XDebugProcessStarter starter) throws ExecutionException {
|
||||
XDebugSession session = startSession(contentToReuse, starter, new XDebugSessionImpl(null, null, this, sessionName));
|
||||
RunContentDescriptor descriptor = session.getRunContentDescriptor();
|
||||
ExecutionManager.getInstance(myProject).getContentManager().showRunContent(DefaultDebugExecutor.getDebugExecutorInstance(), descriptor);
|
||||
ProcessHandler handler = descriptor.getProcessHandler();
|
||||
if (handler != null) {
|
||||
handler.startNotify();
|
||||
@NotNull XDebugProcessStarter starter) throws ExecutionException {
|
||||
return startSessionAndShowTab(sessionName, contentToReuse, false, starter);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public XDebugSession startSessionAndShowTab(@NotNull String sessionName, @Nullable RunContentDescriptor contentToReuse,
|
||||
boolean showToolWindowOnSuspendOnly,
|
||||
@NotNull XDebugProcessStarter starter) throws ExecutionException {
|
||||
XDebugSessionImpl session = startSession(contentToReuse, starter, new XDebugSessionImpl(null, null, this, sessionName,
|
||||
showToolWindowOnSuspendOnly));
|
||||
if (!showToolWindowOnSuspendOnly) {
|
||||
session.showSessionTab();
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
private XDebugSession startSession(final RunContentDescriptor contentToReuse, final XDebugProcessStarter processStarter,
|
||||
private XDebugSessionImpl startSession(final RunContentDescriptor contentToReuse, final XDebugProcessStarter processStarter,
|
||||
final XDebugSessionImpl session) throws ExecutionException {
|
||||
XDebugProcess process = processStarter.start(session);
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Reset to defaults"/>
|
||||
<text value="Reset paths to defaults"/>
|
||||
</properties>
|
||||
</component>
|
||||
<hspacer id="8fb14">
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.maddyhome.idea.copyright;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.components.*;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
@@ -102,7 +103,7 @@ public class CopyrightManager extends AbstractProjectComponent implements JDOMEx
|
||||
new UpdateCopyrightProcessor(myProject, module, file).run();
|
||||
}
|
||||
}
|
||||
});
|
||||
}, ModalityState.NON_MODAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-2
@@ -24,6 +24,7 @@ import com.intellij.lang.documentation.CodeDocumentationProvider;
|
||||
import com.intellij.lang.documentation.ExternalDocumentationProvider;
|
||||
import com.intellij.lang.java.JavaDocumentationProvider;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.javadoc.PsiDocParamRef;
|
||||
import com.intellij.psi.javadoc.PsiDocComment;
|
||||
@@ -162,7 +163,8 @@ public class GroovyDocumentationProvider implements CodeDocumentationProvider, E
|
||||
if (originalElement instanceof GrReferenceExpression) {
|
||||
final PsiType inferredType = ((GrReferenceExpression)originalElement).getType();
|
||||
if (inferredType != null) {
|
||||
buffer.append("[inferred type] ").append(inferredType.getCanonicalText());
|
||||
buffer.append("[inferred type] ");
|
||||
appendTypeString(buffer, inferredType);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -256,7 +258,7 @@ public class GroovyDocumentationProvider implements CodeDocumentationProvider, E
|
||||
|
||||
private static void appendTypeString(StringBuffer buffer, PsiType type) {
|
||||
if (type != null) {
|
||||
buffer.append(type.getCanonicalText());
|
||||
buffer.append(StringUtil.escapeXml(type.getCanonicalText()));
|
||||
}
|
||||
else {
|
||||
buffer.append(GrModifier.DEF);
|
||||
|
||||
-14
@@ -178,20 +178,6 @@ public abstract class ParserUtils {
|
||||
marker.error(msg);
|
||||
}
|
||||
|
||||
public static void waitNextRCurly(PsiBuilder builder) {
|
||||
int i = 0;
|
||||
PsiBuilder.Marker em = builder.mark();
|
||||
while (!builder.eof() && !GroovyElementTypes.mRCURLY.equals(builder.getTokenType())) {
|
||||
builder.advanceLexer();
|
||||
i++;
|
||||
}
|
||||
if (i > 0) {
|
||||
em.error(GroovyBundle.message("rcurly.expected"));
|
||||
} else {
|
||||
em.drop();
|
||||
}
|
||||
}
|
||||
|
||||
public static void advance(PsiBuilder builder, int count) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
builder.getTokenText();
|
||||
|
||||
+2
-1
@@ -17,6 +17,7 @@ package org.jetbrains.plugins.groovy.lang.psi.dataFlow.types;
|
||||
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.dataFlow.Semilattice;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
|
||||
@@ -72,7 +73,7 @@ public class TypesSemilattice implements Semilattice<Map<String, PsiType>> {
|
||||
if (t1 != null || t2 != null) return false;
|
||||
}
|
||||
else {
|
||||
if (!t1.equals(t2)) return false;
|
||||
if (!TypeConversionUtil.erasure(t1).equals(TypeConversionUtil.erasure(t2))) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.intellij.openapi.roots.OrderRootType;
|
||||
import com.intellij.openapi.roots.libraries.Library;
|
||||
import com.intellij.openapi.vfs.JarFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
import com.intellij.testFramework.LightProjectDescriptor;
|
||||
import com.intellij.testFramework.fixtures.DefaultLightProjectDescriptor;
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
|
||||
@@ -288,6 +289,15 @@ public class GroovyHighlightingTest extends LightCodeInsightFixtureTestCase {
|
||||
|
||||
public void testSOEInFieldDeclarations() {doTest();}
|
||||
|
||||
public void testVeryLongDfaWithComplexGenerics() {
|
||||
IdeaTestUtil.assertTiming("", 10000, 1, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
doTest(new GroovyAssignabilityCheckInspection(), new UnusedDefInspection());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void testWrongAnnotation() {doTest();}
|
||||
|
||||
public void testAmbiguousMethods() {
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
class TroubleCase {
|
||||
|
||||
private Foo<Bar> fooBar;
|
||||
private Foo<Baz> fooBaz;
|
||||
|
||||
private void troubleMethod(boolean b) {
|
||||
def <warning descr="Assignment is not used">icDao</warning> = (b?fooBaz:fooBar);
|
||||
|
||||
for(Object x: new ArrayList()) {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public interface Foo<FFIC> {}
|
||||
public class Bar implements Cloneable, Zoo<Goo, Doo, Coo, Woo> {}
|
||||
public interface Zoo<AR, FR, AM extends Hoo<AR>, FM extends Hoo<FR>> {}
|
||||
public interface Hoo<R> {}
|
||||
public class Baz implements Cloneable, Zoo<String,String,Too,Yoo> {}
|
||||
public class Goo {}
|
||||
public class Too implements Hoo<String> {}
|
||||
public class Coo implements Serializable, Cloneable, Hoo<Goo> {}
|
||||
public class Woo implements Serializable, Cloneable, Hoo<Doo> {}
|
||||
public class Yoo implements Serializable, Cloneable, Hoo<String> {}
|
||||
public class Doo {}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 857 B |
@@ -4,7 +4,7 @@
|
||||
<description>Provides integration with Mercurial version control system. Supports Mercurial 1.3+.</description>
|
||||
<category>VCS Integration</category>
|
||||
<version>10.0</version>
|
||||
<vendor email="victor.iacoban@gmail.com, willem.verstraeten@gmail.com" logo="/images/mercurial.png" url="http://www.bitbucket.org/willemv/hg4idea">Victor Iacoban and Willem Verstraeten</vendor>
|
||||
<vendor email="victor.iacoban@gmail.com, willem.verstraeten@gmail.com" url="http://www.bitbucket.org/willemv/hg4idea">Victor Iacoban and Willem Verstraeten</vendor>
|
||||
<depends>com.intellij.modules.vcs</depends>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
@@ -28,7 +28,7 @@
|
||||
<add-to-group group-id="Vcs.Import"/>
|
||||
</action>
|
||||
|
||||
<group id="hg4idea.file.menu" popup="true" icon="/images/mercurial.png" class="org.zmlx.hg4idea.action.HgMercurialMenu">
|
||||
<group id="hg4idea.file.menu" popup="true" class="org.zmlx.hg4idea.action.HgMercurialMenu">
|
||||
<reference ref="CheckinFiles"/>
|
||||
<reference ref="ChangesView.AddUnversioned"/>
|
||||
<reference ref="ChangesView.Rollback"/>
|
||||
|
||||
@@ -34,7 +34,7 @@ public class HgProjectConfigurable implements SearchableConfigurable {
|
||||
}
|
||||
|
||||
public Icon getIcon() {
|
||||
return HgVcs.MERCURIAL_ICON;
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getHelpTopic() {
|
||||
|
||||
@@ -78,8 +78,6 @@ public class HgVcs extends AbstractVcs<CommittedChangeList> {
|
||||
public static final Topic<HgUpdater> OUTGOING_TOPIC =
|
||||
new Topic<HgUpdater>("hg4idea.outgoing", HgUpdater.class);
|
||||
|
||||
public static final Icon MERCURIAL_ICON = IconLoader.getIcon("/images/mercurial.png");
|
||||
|
||||
private static final Icon INCOMING_ICON = IconLoader.getIcon("/actions/moveDown.png");
|
||||
private static final Icon OUTGOING_ICON = IconLoader.getIcon("/actions/moveUp.png");
|
||||
|
||||
|
||||
@@ -22,7 +22,11 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.vcsUtil.VcsUtil;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.zmlx.hg4idea.*;
|
||||
import org.zmlx.hg4idea.HgExecutableValidator;
|
||||
import org.zmlx.hg4idea.HgGlobalSettings;
|
||||
import org.zmlx.hg4idea.HgUtil;
|
||||
import org.zmlx.hg4idea.HgVcs;
|
||||
import org.zmlx.hg4idea.HgVcsMessages;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
@@ -31,7 +35,9 @@ import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@@ -155,15 +161,43 @@ public final class HgCommandService {
|
||||
|
||||
// logging to the Version Control console (without extensions and configs)
|
||||
final String cmdString = String.format("%s %s %s", mySettings.isRunViaBash() ? "bash -c " + HgVcs.HG_EXECUTABLE_FILE_NAME : HgVcs.HG_EXECUTABLE_FILE_NAME, operation,
|
||||
StringUtils.join(arguments, " "));
|
||||
myVcs.showMessageInConsole(cmdString, ConsoleViewContentType.USER_INPUT.getAttributes());
|
||||
StringUtils.join(maskAuthInfoFromUrl(arguments), " "));
|
||||
myVcs.showMessageInConsole(cmdString, ConsoleViewContentType.NORMAL_OUTPUT.getAttributes());
|
||||
LOG.info(cmdString);
|
||||
if (!silent) {
|
||||
myVcs.showMessageInConsole(result.getRawOutput(), ConsoleViewContentType.SYSTEM_OUTPUT.getAttributes());
|
||||
LOG.info(result.getRawOutput());
|
||||
}
|
||||
myVcs.showMessageInConsole(result.getRawError(), ConsoleViewContentType.ERROR_OUTPUT.getAttributes());
|
||||
LOG.info(result.getRawError());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Strips possible authentication information from arguments passed to the command line
|
||||
* to prevent private information appear in the VCS console or logs.
|
||||
* @param arguments command line arguments.
|
||||
* @return command line arguments which don't contain authentication information.
|
||||
*/
|
||||
private static List<String> maskAuthInfoFromUrl(List<String> arguments) {
|
||||
if (arguments == null || arguments.isEmpty()) {
|
||||
return arguments;
|
||||
}
|
||||
final List<String> newArgs = new ArrayList<String>(arguments.size());
|
||||
for (String arg : arguments) {
|
||||
if (!arg.contains("@")) { // simple filter
|
||||
newArgs.add(arg);
|
||||
} else {
|
||||
try {
|
||||
final URI uri = new URI(arg); // parsing via URI methods, exception means it's not an URI
|
||||
newArgs.add(uri.toString().replace(uri.getUserInfo(), "<username>:<password>"));
|
||||
} catch (Throwable e) {
|
||||
newArgs.add(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
return newArgs;
|
||||
}
|
||||
|
||||
private void showError(Exception e) {
|
||||
|
||||
@@ -19,10 +19,12 @@ import com.intellij.notification.Notification;
|
||||
import com.intellij.notification.NotificationType;
|
||||
import com.intellij.notification.Notifications;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vcs.CheckoutProvider;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
@@ -34,13 +36,21 @@ import org.zmlx.hg4idea.command.HgCloneCommand;
|
||||
import org.zmlx.hg4idea.command.HgCommandResult;
|
||||
import org.zmlx.hg4idea.ui.HgCloneDialog;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* Checkout provider for Mercurial
|
||||
*/
|
||||
public class HgCheckoutProvider implements CheckoutProvider {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance(HgCheckoutProvider.class.getName());
|
||||
|
||||
public void doCheckout(@NotNull final Project project, @Nullable final Listener listener) {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
public void run() {
|
||||
@@ -62,30 +72,97 @@ public class HgCheckoutProvider implements CheckoutProvider {
|
||||
final String sourceRepositoryURL = dialog.getSourceRepositoryURL();
|
||||
new Task.Backgroundable(project, HgVcsMessages.message("hg4idea.clone.progress", sourceRepositoryURL), true) {
|
||||
@Override public void run(@NotNull ProgressIndicator indicator) {
|
||||
// clone
|
||||
HgCloneCommand clone = new HgCloneCommand(project);
|
||||
clone.setRepositoryURL(sourceRepositoryURL);
|
||||
clone.setDirectory(targetDir);
|
||||
final HgCommandResult myCloneResult = clone.execute();
|
||||
if (myCloneResult == null) {
|
||||
notifyError("Clone failed", "Clone failed due to unknown error", project);
|
||||
} else if (myCloneResult.getExitValue() != 0) {
|
||||
notifyError("Clone failed", "Clone from " + sourceRepositoryURL + " failed.<br/><br/>" + myCloneResult.getRawError(), project);
|
||||
} else {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (listener != null) {
|
||||
listener.directoryCheckedOut(new File(dialog.getParentDirectory(), dialog.getDirectoryName()));
|
||||
listener.checkoutCompleted();
|
||||
|
||||
// handle result
|
||||
try {
|
||||
final HgCommandResult myCloneResult = clone.execute();
|
||||
if (myCloneResult == null) {
|
||||
notifyError("Clone failed", "Clone failed due to unknown error", project);
|
||||
} else if (myCloneResult.getExitValue() != 0) {
|
||||
notifyError("Clone failed", "Clone from " + sourceRepositoryURL + " failed.<br/><br/>" + myCloneResult.getRawError(), project);
|
||||
} else {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (listener != null) {
|
||||
listener.directoryCheckedOut(new File(dialog.getParentDirectory(), dialog.getDirectoryName()));
|
||||
listener.checkoutCompleted();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
cleanupAuthDataFromHgrc(targetDir);
|
||||
}
|
||||
}
|
||||
}.queue();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes authentication data from the parent URL of a just cloned repository.
|
||||
* @param targetDir directory where the hg project was cloned into.
|
||||
*/
|
||||
private static void cleanupAuthDataFromHgrc(String targetDir) {
|
||||
File hgrc = new File(new File(targetDir, ".hg"), "hgrc");
|
||||
if (!hgrc.exists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++) { // 3 attempts in case of an IOException
|
||||
BufferedReader reader = null;
|
||||
PrintWriter writer = null;
|
||||
try {
|
||||
// writing correct info into a temporary file
|
||||
final File tempFile = FileUtil.createTempFile("hgrc", "temp");
|
||||
tempFile.deleteOnExit();
|
||||
reader = new BufferedReader(new FileReader(hgrc));
|
||||
writer = new PrintWriter(new FileWriter(tempFile));
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
String parseLine = line.trim();
|
||||
if (parseLine.startsWith("default") && parseLine.contains("@")) { // looking for paths.default
|
||||
int eqIdx = parseLine.indexOf('=');
|
||||
parseLine = parseLine.substring(eqIdx+1).trim(); // getting value of paths.default
|
||||
try {
|
||||
final URI uri = new URI(parseLine);
|
||||
final String urlWithoutAuthData = uri.toString().replace(uri.getUserInfo() + "@", "");
|
||||
writer.println("default = " + urlWithoutAuthData);
|
||||
} catch (Throwable t) { // not URI => no sensitive data
|
||||
writer.println(line);
|
||||
}
|
||||
} else {
|
||||
writer.println(line);
|
||||
}
|
||||
}
|
||||
|
||||
// substituting files
|
||||
if (!tempFile.renameTo(hgrc)) { // this may fail in case of different FSs
|
||||
FileUtil.copy(tempFile, hgrc);
|
||||
tempFile.delete();
|
||||
}
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
LOG.info(e);
|
||||
} finally {
|
||||
if (reader != null) {
|
||||
try {
|
||||
reader.close();
|
||||
} catch (IOException e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (writer != null) {
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void notifyError(String title, String description, Project project) {
|
||||
Notifications.Bus.notify(new Notification(HgVcs.NOTIFICATION_GROUP_ID, title, description, NotificationType.ERROR), project);
|
||||
}
|
||||
|
||||
@@ -17,12 +17,15 @@ import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.vcs.FilePath;
|
||||
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.update.*;
|
||||
import com.intellij.openapi.vcs.update.SequentialUpdatesContext;
|
||||
import com.intellij.openapi.vcs.update.UpdateEnvironment;
|
||||
import com.intellij.openapi.vcs.update.UpdateSession;
|
||||
import com.intellij.openapi.vcs.update.UpdateSessionAdapter;
|
||||
import com.intellij.openapi.vcs.update.UpdatedFiles;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -102,7 +105,7 @@ public class HgUpdateEnvironment implements UpdateEnvironment {
|
||||
}
|
||||
|
||||
public Icon getIcon() {
|
||||
return IconLoader.getIcon("/images/mercurial.png");
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getHelpTopic() {
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
// limitations under the License.
|
||||
package org.zmlx.hg4idea.ui;
|
||||
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.openapi.wm.CustomStatusBarWidget;
|
||||
import com.intellij.openapi.wm.StatusBar;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
@@ -25,10 +24,9 @@ import javax.swing.*;
|
||||
import java.util.List;
|
||||
|
||||
public class HgCurrentBranchStatus extends JLabel implements CustomStatusBarWidget {
|
||||
private static final Icon MERCURIAL_ICON = IconLoader.getIcon("/images/mercurial.png");
|
||||
|
||||
public HgCurrentBranchStatus() {
|
||||
super(MERCURIAL_ICON, SwingConstants.TRAILING);
|
||||
super("", SwingConstants.TRAILING);
|
||||
setVisible(false);
|
||||
}
|
||||
|
||||
|
||||
+18
-28
@@ -31,12 +31,14 @@ import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.spellchecker.inspections.SpellCheckerInspectionToolProvider;
|
||||
import com.intellij.ui.EditorCustomization;
|
||||
import com.intellij.ui.AbstractEditorCustomization;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Makes current editor to have spell checking turned on all the time.
|
||||
@@ -46,7 +48,7 @@ import java.util.*;
|
||||
* @author Denis Zhdanov
|
||||
* @since Aug 20, 2010 3:54:42 PM
|
||||
*/
|
||||
public class SpellCheckingEditorCustomization implements EditorCustomization {
|
||||
public class SpellCheckingEditorCustomization extends AbstractEditorCustomization {
|
||||
|
||||
/**
|
||||
* Holds custom inspection profile wrapper.
|
||||
@@ -60,6 +62,10 @@ public class SpellCheckingEditorCustomization implements EditorCustomization {
|
||||
@Nullable
|
||||
private static final InspectionProfileWrapper INSPECTION_PROFILE_WRAPPER = initProvider();
|
||||
|
||||
public SpellCheckingEditorCustomization() {
|
||||
super(Feature.SPELL_CHECK);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
private static InspectionProfileWrapper initProvider() {
|
||||
@@ -116,12 +122,7 @@ public class SpellCheckingEditorCustomization implements EditorCustomization {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Feature> getSupportedFeatures() {
|
||||
return EnumSet.of(Feature.SPELL_CHECK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCustomization(@NotNull EditorEx editor, @NotNull Feature feature) {
|
||||
protected void doProcessCustomization(@NotNull EditorEx editor, @NotNull Feature feature, boolean apply) {
|
||||
if (INSPECTION_PROFILE_WRAPPER == null) {
|
||||
return;
|
||||
}
|
||||
@@ -135,27 +136,16 @@ public class SpellCheckingEditorCustomization implements EditorCustomization {
|
||||
if (file == null) {
|
||||
return;
|
||||
}
|
||||
file.putUserData(InspectionProfileWrapper.KEY, INSPECTION_PROFILE_WRAPPER);
|
||||
editor.putUserData(IntentionManager.SHOW_INTENTION_OPTIONS_KEY, false);
|
||||
updateRepresentation(project, file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCustomization(@NotNull EditorEx editor, @NotNull Feature feature) {
|
||||
Project project = editor.getProject();
|
||||
if (project == null) {
|
||||
return;
|
||||
|
||||
if (apply) {
|
||||
file.putUserData(InspectionProfileWrapper.KEY, INSPECTION_PROFILE_WRAPPER);
|
||||
editor.putUserData(IntentionManager.SHOW_INTENTION_OPTIONS_KEY, false);
|
||||
}
|
||||
else {
|
||||
file.putUserData(InspectionProfileWrapper.KEY, null);
|
||||
}
|
||||
|
||||
PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
|
||||
if (file == null) {
|
||||
return;
|
||||
}
|
||||
file.putUserData(InspectionProfileWrapper.KEY, null);
|
||||
updateRepresentation(project, file);
|
||||
}
|
||||
|
||||
private static void updateRepresentation(@NotNull Project project, @NotNull PsiFile file) {
|
||||
// Update representation.
|
||||
DaemonCodeAnalyzer analyzer = DaemonCodeAnalyzer.getInstance(project);
|
||||
if (analyzer != null) {
|
||||
analyzer.restart(file);
|
||||
|
||||
@@ -628,7 +628,7 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
if (value != VcsShowConfirmationOption.Value.DO_NOTHING_SILENTLY) {
|
||||
final AbstractVcsHelper vcsHelper = AbstractVcsHelper.getInstance(project);
|
||||
final Collection<VirtualFile> filesToProcess = promptAboutAddition(vcs, addedVFiles, value, vcsHelper);
|
||||
if (filesToProcess != null) {
|
||||
if (filesToProcess != null && !filesToProcess.isEmpty()) {
|
||||
final List<VcsException> exceptions = new ArrayList<VcsException>();
|
||||
runInBackground(project, "Adding files to Subversion",
|
||||
createAdditionRunnable(project, vcs, copyFromMap, filesToProcess, exceptions));
|
||||
@@ -758,7 +758,7 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
final AbstractVcsHelper vcsHelper = AbstractVcsHelper.getInstance(project);
|
||||
Collection<FilePath> filesToProcess;
|
||||
filesToProcess = promptAboutDeletion(deletedFiles, vcs, value, vcsHelper);
|
||||
if (filesToProcess != null) {
|
||||
if (filesToProcess != null && !filesToProcess.isEmpty()) {
|
||||
List<VcsException> exceptions = new ArrayList<VcsException>();
|
||||
runInBackground(project, "Deleting files from Subversion", createDeleteRunnable(project, vcs, filesToProcess, exceptions));
|
||||
if (!exceptions.isEmpty()) {
|
||||
@@ -845,6 +845,8 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
}
|
||||
|
||||
private void processMovedFiles(final Project project) {
|
||||
if (myMovedFiles.isEmpty()) return;
|
||||
|
||||
final Runnable runnable = new Runnable() {
|
||||
public void run() {
|
||||
for (Iterator<MovedFileInfo> iterator = myMovedFiles.iterator(); iterator.hasNext();) {
|
||||
|
||||
@@ -33,8 +33,7 @@ import com.intellij.xml.util.XmlTagUtil;
|
||||
/**
|
||||
* @author ven
|
||||
*/
|
||||
public class XMLExternalAnnotator implements ExternalAnnotator, Validator.ValidationHost {
|
||||
private AnnotationHolder myHolder;
|
||||
public class XMLExternalAnnotator implements ExternalAnnotator {
|
||||
|
||||
public void annotate(PsiFile file, AnnotationHolder holder) {
|
||||
if (!(file instanceof XmlFile)) return;
|
||||
@@ -44,64 +43,68 @@ public class XMLExternalAnnotator implements ExternalAnnotator, Validator.Valida
|
||||
XmlNSDescriptor nsDescriptor = rootTag == null ? null : rootTag.getNSDescriptor(rootTag.getNamespace(), false);
|
||||
|
||||
if (nsDescriptor instanceof Validator && !HtmlUtil.isHtml5Document(document)) {
|
||||
myHolder = holder;
|
||||
try {
|
||||
//noinspection unchecked
|
||||
((Validator<XmlDocument>)nsDescriptor).validate(document, this);
|
||||
}
|
||||
finally {
|
||||
myHolder = null;
|
||||
}
|
||||
((Validator<XmlDocument>)nsDescriptor).validate(document, new MyHost(holder));
|
||||
}
|
||||
}
|
||||
|
||||
private static final ErrorType[] types = ErrorType.values();
|
||||
|
||||
public void addMessage(PsiElement context, String message, int type) {
|
||||
addMessage(context, message, types[type]);
|
||||
}
|
||||
|
||||
public void addMessage(final PsiElement context, final String message, final ErrorType type, final IntentionAction... fixes) {
|
||||
if (message != null && message.length() > 0) {
|
||||
if (context instanceof XmlTag) {
|
||||
addMessagesForTag((XmlTag)context, message, type, fixes);
|
||||
}
|
||||
else {
|
||||
if (type == Validator.ValidationHost.ErrorType.ERROR) {
|
||||
appendFixes(myHolder.createErrorAnnotation(context, message), fixes);
|
||||
} else {
|
||||
appendFixes(myHolder.createWarningAnnotation(context, message), fixes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addMessagesForTag(XmlTag tag, String message, ErrorType type, IntentionAction... actions) {
|
||||
XmlToken childByRole = XmlTagUtil.getStartTagNameElement(tag);
|
||||
|
||||
addMessagesForTreeChild(childByRole, type, message, actions);
|
||||
|
||||
childByRole = XmlTagUtil.getEndTagNameElement(tag);
|
||||
addMessagesForTreeChild(childByRole, type, message, actions);
|
||||
}
|
||||
|
||||
private void addMessagesForTreeChild(final XmlToken childByRole, final ErrorType type, final String message, IntentionAction... actions) {
|
||||
if (childByRole != null) {
|
||||
Annotation annotation;
|
||||
if (type == ErrorType.ERROR) {
|
||||
annotation = myHolder.createErrorAnnotation(childByRole, message);
|
||||
}
|
||||
else {
|
||||
annotation = myHolder.createWarningAnnotation(childByRole, message);
|
||||
}
|
||||
|
||||
appendFixes(annotation, actions);
|
||||
}
|
||||
}
|
||||
private static final Validator.ValidationHost.ErrorType[] types = Validator.ValidationHost.ErrorType.values();
|
||||
|
||||
private static void appendFixes(final Annotation annotation, final IntentionAction... actions) {
|
||||
if (actions != null) {
|
||||
for(IntentionAction action:actions) annotation.registerFix(action);
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyHost implements Validator.ValidationHost {
|
||||
|
||||
private final AnnotationHolder myHolder;
|
||||
|
||||
public MyHost(AnnotationHolder holder) {
|
||||
|
||||
myHolder = holder;
|
||||
}
|
||||
|
||||
public void addMessage(PsiElement context, String message, int type) {
|
||||
addMessage(context, message, types[type]);
|
||||
}
|
||||
|
||||
public void addMessage(final PsiElement context, final String message, final ErrorType type, final IntentionAction... fixes) {
|
||||
if (message != null && message.length() > 0) {
|
||||
if (context instanceof XmlTag) {
|
||||
addMessagesForTag((XmlTag)context, message, type, fixes);
|
||||
}
|
||||
else {
|
||||
if (type == Validator.ValidationHost.ErrorType.ERROR) {
|
||||
appendFixes(myHolder.createErrorAnnotation(context, message), fixes);
|
||||
} else {
|
||||
appendFixes(myHolder.createWarningAnnotation(context, message), fixes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addMessagesForTag(XmlTag tag, String message, ErrorType type, IntentionAction... actions) {
|
||||
XmlToken childByRole = XmlTagUtil.getStartTagNameElement(tag);
|
||||
|
||||
addMessagesForTreeChild(childByRole, type, message, actions);
|
||||
|
||||
childByRole = XmlTagUtil.getEndTagNameElement(tag);
|
||||
addMessagesForTreeChild(childByRole, type, message, actions);
|
||||
}
|
||||
|
||||
private void addMessagesForTreeChild(final XmlToken childByRole, final ErrorType type, final String message, IntentionAction... actions) {
|
||||
if (childByRole != null) {
|
||||
Annotation annotation;
|
||||
if (type == ErrorType.ERROR) {
|
||||
annotation = myHolder.createErrorAnnotation(childByRole, message);
|
||||
}
|
||||
else {
|
||||
annotation = myHolder.createWarningAnnotation(childByRole, message);
|
||||
}
|
||||
|
||||
appendFixes(annotation, actions);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ import com.intellij.psi.ResolveState;
|
||||
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceUtil;
|
||||
import com.intellij.psi.scope.PsiScopeProcessor;
|
||||
import com.intellij.psi.search.PsiElementProcessor;
|
||||
import com.intellij.psi.util.CachedValue;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.xml.*;
|
||||
import com.intellij.xml.XmlElementDescriptor;
|
||||
import com.intellij.xml.util.HtmlUtil;
|
||||
@@ -35,7 +37,7 @@ import java.util.List;
|
||||
* @author Maxim.Mossienko
|
||||
*/
|
||||
public class ScriptSupportUtil {
|
||||
private static final Key<XmlTag[]> CachedScriptTagsKey = Key.create("script tags");
|
||||
private static final Key<CachedValue<XmlTag[]>> CachedScriptTagsKey = Key.create("script tags");
|
||||
private static final ThreadLocal<String> ProcessingDeclarationsFlag = new ThreadLocal<String>();
|
||||
private static final @NonNls String SCRIPT_TAG = "script";
|
||||
|
||||
@@ -46,61 +48,71 @@ public class ScriptSupportUtil {
|
||||
element.putUserData(CachedScriptTagsKey,null);
|
||||
}
|
||||
|
||||
public static boolean processDeclarations(XmlFile element, PsiScopeProcessor processor, ResolveState state, PsiElement lastParent, PsiElement place) {
|
||||
XmlTag[] myCachedScriptTags = element.getUserData(CachedScriptTagsKey);
|
||||
|
||||
public static boolean processDeclarations(final XmlFile element,
|
||||
PsiScopeProcessor processor,
|
||||
ResolveState state,
|
||||
PsiElement lastParent,
|
||||
PsiElement place) {
|
||||
CachedValue<XmlTag[]> myCachedScriptTags = element.getUserData(CachedScriptTagsKey);
|
||||
if (myCachedScriptTags == null) {
|
||||
final List<XmlTag> scriptTags = new ArrayList<XmlTag>();
|
||||
final XmlDocument document = HtmlUtil.getRealXmlDocument(element.getDocument());
|
||||
myCachedScriptTags = element.getManager().getCachedValuesManager().createCachedValue(new CachedValueProvider<XmlTag[]>() {
|
||||
@Override
|
||||
public Result<XmlTag[]> compute() {
|
||||
final List<XmlTag> scriptTags = new ArrayList<XmlTag>();
|
||||
final XmlDocument document = HtmlUtil.getRealXmlDocument(element.getDocument());
|
||||
|
||||
if (document != null) {
|
||||
XmlUtil.processXmlElements(document,
|
||||
new PsiElementProcessor() {
|
||||
public boolean execute(final PsiElement element) {
|
||||
if (element instanceof XmlTag) {
|
||||
final XmlTag tag = (XmlTag)element;
|
||||
if (document != null) {
|
||||
PsiElementProcessor psiElementProcessor = new PsiElementProcessor() {
|
||||
public boolean execute(final PsiElement element) {
|
||||
if (element instanceof XmlTag) {
|
||||
final XmlTag tag = (XmlTag)element;
|
||||
|
||||
if (SCRIPT_TAG.equalsIgnoreCase(tag.getName())) {
|
||||
final XmlElementDescriptor descriptor = tag.getDescriptor();
|
||||
if (descriptor != null && SCRIPT_TAG.equals(descriptor.getName())) {
|
||||
scriptTags.add(tag);
|
||||
if (SCRIPT_TAG.equalsIgnoreCase(tag.getName())) {
|
||||
final XmlElementDescriptor descriptor = tag.getDescriptor();
|
||||
if (descriptor != null && SCRIPT_TAG.equals(descriptor.getName())) {
|
||||
scriptTags.add(tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
XmlUtil.processXmlElements(document,psiElementProcessor, true);
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
myCachedScriptTags = scriptTags.toArray(new XmlTag[scriptTags.size()]);
|
||||
return new Result<XmlTag[]>(scriptTags.toArray(new XmlTag[scriptTags.size()]), element);
|
||||
}
|
||||
}, false);
|
||||
element.putUserData(CachedScriptTagsKey, myCachedScriptTags);
|
||||
}
|
||||
|
||||
if (ProcessingDeclarationsFlag.get() != null) return true;
|
||||
|
||||
|
||||
try {
|
||||
ProcessingDeclarationsFlag.set("");
|
||||
|
||||
for (XmlTag tag : myCachedScriptTags) {
|
||||
for (XmlTag tag : myCachedScriptTags.getValue()) {
|
||||
final XmlTagChild[] children = tag.getValue().getChildren();
|
||||
for (XmlTagChild child : children) {
|
||||
if (!child.processDeclarations(processor, state, null, place)) return false;
|
||||
}
|
||||
|
||||
if(tag.getAttributeValue("src") != null) {
|
||||
if (tag.getAttributeValue("src") != null) {
|
||||
final XmlAttribute attribute = tag.getAttribute("src", null);
|
||||
|
||||
if (attribute != null) {
|
||||
final PsiFile psiFile = FileReferenceUtil.findFile(attribute.getValueElement());
|
||||
|
||||
if (psiFile != null && psiFile.isValid()) {
|
||||
if(!psiFile.processDeclarations(processor, state, null, place))
|
||||
if (!psiFile.processDeclarations(processor, state, null, place)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
}
|
||||
finally {
|
||||
ProcessingDeclarationsFlag.set(null);
|
||||
}
|
||||
|
||||
|
||||
@@ -66,16 +66,19 @@ public class XmlEntityRefImpl extends XmlElementImpl implements XmlEntityRef {
|
||||
return cachedValue != null ? cachedValue.getValue():null;
|
||||
}
|
||||
|
||||
public static void cacheParticularEntity(PsiFile file, final XmlEntityDecl decl) {
|
||||
public static void cacheParticularEntity(PsiFile file, XmlEntityDecl decl) {
|
||||
synchronized(PsiLock.LOCK) {
|
||||
final Map<String, CachedValue<XmlEntityDecl>> cachingMap = getCachingMap(file);
|
||||
final String name = decl.getName();
|
||||
if (cachingMap.containsKey(name)) return;
|
||||
final SmartPsiElementPointer declPointer = SmartPointerManager.getInstance(file.getProject()).createSmartPsiElementPointer(decl);
|
||||
|
||||
cachingMap.put(
|
||||
name, CachedValuesManager.getManager(file.getProject()).createCachedValue(new CachedValueProvider<XmlEntityDecl>() {
|
||||
public Result<XmlEntityDecl> compute() {
|
||||
if (decl.isValid() && name.equals(decl.getName()))
|
||||
return new Result<XmlEntityDecl>(decl,decl);
|
||||
PsiElement declElement = declPointer.getElement();
|
||||
if (declElement instanceof XmlEntityDecl && declElement.isValid() && name.equals(((XmlEntityDecl)declElement).getName()))
|
||||
return new Result<XmlEntityDecl>((XmlEntityDecl)declElement, declElement);
|
||||
cachingMap.put(name,null);
|
||||
return new Result<XmlEntityDecl>(null,null);
|
||||
}
|
||||
|
||||
@@ -122,29 +122,7 @@ class AnchorReference implements PsiReference, EmptyResolveMessageProvider {
|
||||
if (file != null) {
|
||||
CachedValue<Map<String, XmlTag>> value = file.getUserData(ourCachedIdsKey);
|
||||
if (value == null) {
|
||||
value = CachedValuesManager.getManager(file.getProject()).createCachedValue(new CachedValueProvider<Map<String, XmlTag>>() {
|
||||
public Result<Map<String, XmlTag>> compute() {
|
||||
final Map<String,XmlTag> resultMap = new HashMap<String, XmlTag>();
|
||||
XmlDocument document = HtmlUtil.getRealXmlDocument(file.getDocument());
|
||||
final XmlTag rootTag = document != null ? document.getRootTag():null;
|
||||
|
||||
if (rootTag != null) {
|
||||
processXmlElements(rootTag,
|
||||
new PsiElementProcessor() {
|
||||
public boolean execute(final PsiElement element) {
|
||||
final String anchorValue = element instanceof XmlTag ? getAnchorValue((XmlTag)element):null;
|
||||
|
||||
if (anchorValue!=null) {
|
||||
resultMap.put(anchorValue, (XmlTag)element);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
return new Result<Map<String, XmlTag>>(resultMap, file);
|
||||
}
|
||||
}, false);
|
||||
value = CachedValuesManager.getManager(file.getProject()).createCachedValue(new MapCachedValueProvider(file), false);
|
||||
file.putUserData(ourCachedIdsKey, value);
|
||||
}
|
||||
|
||||
@@ -239,4 +217,35 @@ class AnchorReference implements PsiReference, EmptyResolveMessageProvider {
|
||||
XmlBundle.message("cannot.resolve.anchor", myAnchor) :
|
||||
XmlBundle.message("cannot.resolve.anchor.in.file", myAnchor, xmlFile.getName());
|
||||
}
|
||||
|
||||
// separate static class to avoid memory leak via this$0
|
||||
private static class MapCachedValueProvider implements CachedValueProvider<Map<String, XmlTag>> {
|
||||
private final XmlFile myFile;
|
||||
|
||||
public MapCachedValueProvider(XmlFile file) {
|
||||
myFile = file;
|
||||
}
|
||||
|
||||
public Result<Map<String, XmlTag>> compute() {
|
||||
final Map<String,XmlTag> resultMap = new HashMap<String, XmlTag>();
|
||||
XmlDocument document = HtmlUtil.getRealXmlDocument(myFile.getDocument());
|
||||
final XmlTag rootTag = document != null ? document.getRootTag():null;
|
||||
|
||||
if (rootTag != null) {
|
||||
processXmlElements(rootTag,
|
||||
new PsiElementProcessor() {
|
||||
public boolean execute(final PsiElement element) {
|
||||
final String anchorValue = element instanceof XmlTag ? getAnchorValue((XmlTag)element):null;
|
||||
|
||||
if (anchorValue!=null) {
|
||||
resultMap.put(anchorValue, (XmlTag)element);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
return new Result<Map<String, XmlTag>>(resultMap, myFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user