Merge remote-tracking branch 'origin/master'
@@ -99,4 +99,11 @@ sun.java2d.pmoffscreen=false
|
||||
# Maximum size (kilobytes) IDEA will load for showing past file contents -
|
||||
# in Show Diff or when calculating Digest Diff
|
||||
#---------------------------------------------------------------------
|
||||
#idea.max.vcs.loaded.size.kb=20480
|
||||
#idea.max.vcs.loaded.size.kb=20480
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
# IDEA file chooser peeks inside directories to detect whether they contain a valid project
|
||||
# (to mark such directories with a corresponding icon).
|
||||
# Uncommenting the option prevents this behavior outside of user home directory.
|
||||
#---------------------------------------------------------------------
|
||||
#idea.chooser.lookup.for.project.dirs=false
|
||||
|
||||
@@ -35,6 +35,7 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.refactoring.listeners.RefactoringElementListener;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.xmlb.SmartSerializer;
|
||||
import com.intellij.util.xmlb.annotations.Transient;
|
||||
import org.jdom.Element;
|
||||
@@ -46,7 +47,6 @@ import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@@ -74,7 +74,7 @@ public class AppletConfiguration extends ModuleBasedConfiguration<JavaRunConfigu
|
||||
public AppletConfiguration(@NotNull Project project, ConfigurationFactory factory) {
|
||||
super(new JavaRunConfigurationModule(project, false), factory);
|
||||
|
||||
mySerializer = new SmartSerializer(project.isDefault(), true);
|
||||
mySerializer = new SmartSerializer(!project.isDefault(), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -193,12 +193,18 @@ public class AppletConfiguration extends ModuleBasedConfiguration<JavaRunConfigu
|
||||
@Override
|
||||
public void readExternal(final Element parentNode) throws InvalidDataException {
|
||||
mySerializer.readExternal(this, parentNode);
|
||||
readModule(parentNode);
|
||||
final ArrayList<AppletParameter> parameters = new ArrayList<AppletParameter>();
|
||||
for (final Element element : parentNode.getChildren(PARAMETER_ELEMENT_NAME)) {
|
||||
parameters.add(new AppletParameter(element.getAttributeValue(NAME_ATTR), element.getAttributeValue(VALUE_ATTR)));
|
||||
|
||||
List<Element> paramList = parentNode.getChildren(PARAMETER_ELEMENT_NAME);
|
||||
if (paramList.isEmpty()) {
|
||||
myAppletParameters = null;
|
||||
}
|
||||
else {
|
||||
List<AppletParameter> parameters = new SmartList<AppletParameter>();
|
||||
for (Element element : paramList) {
|
||||
parameters.add(new AppletParameter(element.getAttributeValue(NAME_ATTR), element.getAttributeValue(VALUE_ATTR)));
|
||||
}
|
||||
myAppletParameters = parameters.toArray(new AppletParameter[parameters.size()]);
|
||||
}
|
||||
myAppletParameters = parameters.toArray(new AppletParameter[parameters.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -208,7 +214,6 @@ public class AppletConfiguration extends ModuleBasedConfiguration<JavaRunConfigu
|
||||
|
||||
@Override
|
||||
public void writeExternal(final Element parentNode) throws WriteExternalException {
|
||||
writeModule(parentNode);
|
||||
mySerializer.writeExternal(this, parentNode);
|
||||
if (myAppletParameters != null) {
|
||||
for (AppletParameter myAppletParameter : myAppletParameters) {
|
||||
@@ -227,6 +232,7 @@ public class AppletConfiguration extends ModuleBasedConfiguration<JavaRunConfigu
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transient
|
||||
public PsiClass getMainClass() {
|
||||
return getConfigurationModule().findClass(MAIN_CLASS_NAME);
|
||||
}
|
||||
|
||||
@@ -617,9 +617,10 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
|
||||
myHolder.add(HighlightMethodUtil.checkConstructorName(method));
|
||||
}
|
||||
myHolder.add(HighlightNamesUtil.highlightMethodName(method, identifier, true, colorsScheme));
|
||||
myHolder.add(GenericsHighlightUtil.checkDefaultMethodOverrideEquivalentToObjectNonPrivate(myLanguageLevel,
|
||||
method.getContainingClass(), method,
|
||||
identifier));
|
||||
final PsiClass aClass = method.getContainingClass();
|
||||
if (aClass != null) {
|
||||
myHolder.add(GenericsHighlightUtil.checkDefaultMethodOverrideEquivalentToObjectNonPrivate(myLanguageLevel, aClass, method, identifier));
|
||||
}
|
||||
}
|
||||
|
||||
super.visitIdentifier(identifier);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 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.
|
||||
@@ -18,17 +18,15 @@ package com.intellij.codeInspection.defaultFileTemplateUsage;
|
||||
import com.intellij.codeInspection.*;
|
||||
import com.intellij.ide.fileTemplates.FileTemplate;
|
||||
import com.intellij.ide.fileTemplates.impl.FileTemplateConfigurable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.options.ShowSettingsUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* @author cdr
|
||||
*/
|
||||
@@ -60,26 +58,6 @@ public class DefaultFileTemplateUsageInspection extends BaseJavaLocalInspectionT
|
||||
return "DefaultFileTemplate";
|
||||
}
|
||||
|
||||
static Pair<? extends PsiElement, ? extends PsiElement> getInteriorRange(PsiCodeBlock codeBlock) {
|
||||
PsiElement[] children = codeBlock.getChildren();
|
||||
if (children.length == 0) return Pair.create(codeBlock, codeBlock);
|
||||
int start;
|
||||
for (start=0; start<children.length;start++) {
|
||||
PsiElement child = children[start];
|
||||
if (child instanceof PsiWhiteSpace) continue;
|
||||
if (child instanceof PsiJavaToken && ((PsiJavaToken)child).getTokenType() == JavaTokenType.LBRACE) continue;
|
||||
break;
|
||||
}
|
||||
int end;
|
||||
for (end=children.length-1; end > start;end--) {
|
||||
PsiElement child = children[end];
|
||||
if (child instanceof PsiWhiteSpace) continue;
|
||||
if (child instanceof PsiJavaToken && ((PsiJavaToken)child).getTokenType() == JavaTokenType.RBRACE) continue;
|
||||
break;
|
||||
}
|
||||
return Pair.create(children[start], children[end]);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ProblemDescriptor[] checkFile(@NotNull PsiFile file, @NotNull InspectionManager manager, boolean isOnTheFly) {
|
||||
@@ -92,15 +70,15 @@ public class DefaultFileTemplateUsageInspection extends BaseJavaLocalInspectionT
|
||||
return true;
|
||||
}
|
||||
|
||||
public static LocalQuickFix createEditFileTemplateFix(final FileTemplate templateToEdit, final ReplaceWithFileTemplateFix replaceTemplateFix) {
|
||||
return new MyLocalQuickFix(templateToEdit, replaceTemplateFix);
|
||||
public static LocalQuickFix createEditFileTemplateFix(FileTemplate templateToEdit, ReplaceWithFileTemplateFix replaceTemplateFix) {
|
||||
return new EditFileTemplateFix(templateToEdit, replaceTemplateFix);
|
||||
}
|
||||
|
||||
private static class MyLocalQuickFix implements LocalQuickFix {
|
||||
private static class EditFileTemplateFix implements LocalQuickFix {
|
||||
private final FileTemplate myTemplateToEdit;
|
||||
private final ReplaceWithFileTemplateFix myReplaceTemplateFix;
|
||||
|
||||
public MyLocalQuickFix(FileTemplate templateToEdit, ReplaceWithFileTemplateFix replaceTemplateFix) {
|
||||
public EditFileTemplateFix(FileTemplate templateToEdit, ReplaceWithFileTemplateFix replaceTemplateFix) {
|
||||
myTemplateToEdit = templateToEdit;
|
||||
myReplaceTemplateFix = replaceTemplateFix;
|
||||
}
|
||||
@@ -120,11 +98,10 @@ public class DefaultFileTemplateUsageInspection extends BaseJavaLocalInspectionT
|
||||
@Override
|
||||
public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
|
||||
final FileTemplateConfigurable configurable = new FileTemplateConfigurable();
|
||||
SwingUtilities.invokeLater(new Runnable(){
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
configurable.setTemplate(myTemplateToEdit, null);
|
||||
|
||||
boolean ok = ShowSettingsUtil.getInstance().editConfigurable(project, configurable);
|
||||
if (ok) {
|
||||
WriteCommandAction.runWriteCommandAction(project, new Runnable() {
|
||||
|
||||
@@ -20,97 +20,86 @@ import com.intellij.codeInspection.*;
|
||||
import com.intellij.ide.fileTemplates.FileTemplate;
|
||||
import com.intellij.ide.fileTemplates.FileTemplateManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.JavaRecursiveElementWalkingVisitor;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.JavaPsiFacade;
|
||||
import com.intellij.psi.PsiComment;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.javadoc.PsiDocComment;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import gnu.trove.TIntObjectHashMap;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author Alexey
|
||||
* @author cdr
|
||||
*/
|
||||
public class FileHeaderChecker {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.defaultFileTemplateUsage.FileHeaderChecker");
|
||||
|
||||
static ProblemDescriptor checkFileHeader(@NotNull final PsiFile file, @NotNull InspectionManager manager, boolean onTheFly) {
|
||||
static ProblemDescriptor checkFileHeader(@NotNull PsiFile file, @NotNull InspectionManager manager, boolean onTheFly) {
|
||||
TIntObjectHashMap<String> offsetToProperty = new TIntObjectHashMap<String>();
|
||||
FileTemplate defaultTemplate = FileTemplateManager.getInstance().getDefaultTemplate(FileTemplateManager.FILE_HEADER_TEMPLATE_NAME);
|
||||
Pattern pattern = getTemplatePattern(defaultTemplate, file.getProject(), offsetToProperty);
|
||||
Matcher matcher = pattern.matcher(file.getViewProvider().getContents());
|
||||
if (matcher.matches()) {
|
||||
final int startOffset = matcher.start(1);
|
||||
final int endOffset = matcher.end(1);
|
||||
final Ref<PsiDocComment> docComment = new Ref<PsiDocComment>();
|
||||
file.accept(new JavaRecursiveElementWalkingVisitor(){
|
||||
@Override public void visitElement(PsiElement element) {
|
||||
if (docComment.get() != null) return;
|
||||
TextRange range = element.getTextRange();
|
||||
if (!range.contains(startOffset) && !range.contains(endOffset)) return;
|
||||
super.visitElement(element);
|
||||
}
|
||||
@Override public void visitDocComment(PsiDocComment comment) {
|
||||
docComment.set(comment);
|
||||
}
|
||||
});
|
||||
PsiDocComment element = docComment.get();
|
||||
if (element == null) return null;
|
||||
LocalQuickFix[] quickFix = createQuickFix(matcher, offsetToProperty);
|
||||
final String description = InspectionsBundle.message("default.file.template.description");
|
||||
return manager.createProblemDescriptor(element, description, onTheFly, quickFix, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
|
||||
if (!matcher.matches()) {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
|
||||
PsiComment element = PsiTreeUtil.findElementOfClassAtRange(file, matcher.start(1), matcher.end(1), PsiComment.class);
|
||||
if (element == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
LocalQuickFix[] fixes = createQuickFix(matcher, offsetToProperty);
|
||||
String description = InspectionsBundle.message("default.file.template.description");
|
||||
return manager.createProblemDescriptor(element, description, onTheFly, fixes, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
|
||||
}
|
||||
|
||||
public static Pattern getTemplatePattern(@NotNull FileTemplate template, @NotNull Project project, @NotNull TIntObjectHashMap<String> offsetToProperty) {
|
||||
public static Pattern getTemplatePattern(@NotNull FileTemplate template,
|
||||
@NotNull Project project,
|
||||
@NotNull TIntObjectHashMap<String> offsetToProperty) {
|
||||
String templateText = template.getText().trim();
|
||||
String regex = templateToRegex(templateText, offsetToProperty, project);
|
||||
regex = StringUtil.replace(regex, "with", "(?:with|by)");
|
||||
regex = ".*("+regex+").*";
|
||||
regex = ".*(" + regex + ").*";
|
||||
return Pattern.compile(regex, Pattern.DOTALL);
|
||||
}
|
||||
|
||||
private static Properties computeProperties(final Matcher matcher, final TIntObjectHashMap<String> offsetToProperty) {
|
||||
Properties properties = new Properties(FileTemplateManager.getInstance().getDefaultProperties());
|
||||
|
||||
int[] offsets = offsetToProperty.keys();
|
||||
Arrays.sort(offsets);
|
||||
|
||||
for (int i = 0; i < offsets.length; i++) {
|
||||
final int offset = offsets[i];
|
||||
String propName = offsetToProperty.get(offset);
|
||||
int groupNum = i + 2; // first group is whole doc comment
|
||||
String propValue = matcher.group(groupNum);
|
||||
properties.put(propName, propValue);
|
||||
properties.setProperty(propName, propValue);
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
private static LocalQuickFix[] createQuickFix(final Matcher matcher,
|
||||
final TIntObjectHashMap<String> offsetToProperty) {
|
||||
private static LocalQuickFix[] createQuickFix(final Matcher matcher, final TIntObjectHashMap<String> offsetToProperty) {
|
||||
final FileTemplate template = FileTemplateManager.getInstance().getPattern(FileTemplateManager.FILE_HEADER_TEMPLATE_NAME);
|
||||
|
||||
final ReplaceWithFileTemplateFix replaceTemplateFix = new ReplaceWithFileTemplateFix() {
|
||||
ReplaceWithFileTemplateFix replaceTemplateFix = new ReplaceWithFileTemplateFix() {
|
||||
@Override
|
||||
public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
PsiElement element = descriptor.getPsiElement();
|
||||
if (element == null || !element.isValid()) return;
|
||||
if (!CodeInsightUtil.preparePsiElementsForWrite(element)) return;
|
||||
|
||||
String newText;
|
||||
try {
|
||||
newText = template.getText(computeProperties(matcher, offsetToProperty));
|
||||
@@ -119,49 +108,30 @@ public class FileHeaderChecker {
|
||||
LOG.error(e);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
int offset = element.getTextRange().getStartOffset();
|
||||
PsiFile psiFile = element.getContainingFile();
|
||||
if (psiFile == null) return;
|
||||
PsiDocumentManager documentManager = PsiDocumentManager.getInstance(psiFile.getProject());
|
||||
Document document = documentManager.getDocument(psiFile);
|
||||
if (document == null) return;
|
||||
|
||||
element.delete();
|
||||
documentManager.doPostponedOperationsAndUnblockDocument(document);
|
||||
documentManager.commitDocument(document);
|
||||
|
||||
document.insertString(offset, newText);
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
LOG.error("Cannot create doc comment from text: '" + newText + "'", e);
|
||||
}
|
||||
PsiDocComment newComment = JavaPsiFacade.getElementFactory(project).createDocCommentFromText(newText);
|
||||
element.replace(newComment);
|
||||
}
|
||||
};
|
||||
final LocalQuickFix editFileTemplateFix = DefaultFileTemplateUsageInspection.createEditFileTemplateFix(template, replaceTemplateFix);
|
||||
if (template.isDefault()) {
|
||||
return new LocalQuickFix[]{editFileTemplateFix};
|
||||
}
|
||||
return new LocalQuickFix[]{replaceTemplateFix,editFileTemplateFix};
|
||||
|
||||
LocalQuickFix editFileTemplateFix = DefaultFileTemplateUsageInspection.createEditFileTemplateFix(template, replaceTemplateFix);
|
||||
return template.isDefault() ? new LocalQuickFix[]{editFileTemplateFix} : new LocalQuickFix[]{replaceTemplateFix, editFileTemplateFix};
|
||||
}
|
||||
|
||||
private static String templateToRegex(@NotNull String text, @NotNull TIntObjectHashMap<String> offsetToProperty, @NotNull Project project) {
|
||||
String regex = text;
|
||||
@NonNls Collection<String> properties = new ArrayList<String>((Collection)FileTemplateManager.getInstance().getDefaultProperties(project).keySet());
|
||||
private static String templateToRegex(String text, TIntObjectHashMap<String> offsetToProperty, Project project) {
|
||||
List<Object> properties = ContainerUtil.newArrayList(FileTemplateManager.getInstance().getDefaultProperties(project).keySet());
|
||||
properties.add("PACKAGE_NAME");
|
||||
|
||||
regex = escapeRegexChars(regex);
|
||||
String regex = escapeRegexChars(text);
|
||||
// first group is a whole file header
|
||||
int groupNumber = 1;
|
||||
for (String name : properties) {
|
||||
String escaped = escapeRegexChars("${"+name+"}");
|
||||
for (Object property : properties) {
|
||||
String name = property.toString();
|
||||
String escaped = escapeRegexChars("${" + name + "}");
|
||||
boolean first = true;
|
||||
for (int i = regex.indexOf(escaped); i!=-1 && i<regex.length(); i = regex.indexOf(escaped,i+1)) {
|
||||
for (int i = regex.indexOf(escaped); i != -1 && i < regex.length(); i = regex.indexOf(escaped, i + 1)) {
|
||||
String replacement = first ? "([^\\n]*)" : "\\" + groupNumber;
|
||||
final int delta = escaped.length() - replacement.length();
|
||||
int delta = escaped.length() - replacement.length();
|
||||
int[] offs = offsetToProperty.keys();
|
||||
for (int off : offs) {
|
||||
if (off > i) {
|
||||
@@ -170,7 +140,7 @@ public class FileHeaderChecker {
|
||||
}
|
||||
}
|
||||
offsetToProperty.put(i, name);
|
||||
regex = regex.substring(0,i) + replacement + regex.substring(i+escaped.length());
|
||||
regex = regex.substring(0, i) + replacement + regex.substring(i + escaped.length());
|
||||
if (first) {
|
||||
groupNumber++;
|
||||
first = false;
|
||||
@@ -181,18 +151,18 @@ public class FileHeaderChecker {
|
||||
}
|
||||
|
||||
private static String escapeRegexChars(String regex) {
|
||||
regex = StringUtil.replace(regex,"|", "\\|");
|
||||
regex = StringUtil.replace(regex,".", "\\.");
|
||||
regex = StringUtil.replace(regex,"*", "\\*");
|
||||
regex = StringUtil.replace(regex,"+", "\\+");
|
||||
regex = StringUtil.replace(regex,"?", "\\?");
|
||||
regex = StringUtil.replace(regex,"$", "\\$");
|
||||
regex = StringUtil.replace(regex,"(", "\\(");
|
||||
regex = StringUtil.replace(regex,")", "\\)");
|
||||
regex = StringUtil.replace(regex,"[", "\\[");
|
||||
regex = StringUtil.replace(regex,"]", "\\]");
|
||||
regex = StringUtil.replace(regex,"{", "\\{");
|
||||
regex = StringUtil.replace(regex,"}", "\\}");
|
||||
regex = StringUtil.replace(regex, "|", "\\|");
|
||||
regex = StringUtil.replace(regex, ".", "\\.");
|
||||
regex = StringUtil.replace(regex, "*", "\\*");
|
||||
regex = StringUtil.replace(regex, "+", "\\+");
|
||||
regex = StringUtil.replace(regex, "?", "\\?");
|
||||
regex = StringUtil.replace(regex, "$", "\\$");
|
||||
regex = StringUtil.replace(regex, "(", "\\(");
|
||||
regex = StringUtil.replace(regex, ")", "\\)");
|
||||
regex = StringUtil.replace(regex, "[", "\\[");
|
||||
regex = StringUtil.replace(regex, "]", "\\]");
|
||||
regex = StringUtil.replace(regex, "{", "\\{");
|
||||
regex = StringUtil.replace(regex, "}", "\\}");
|
||||
return regex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 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.
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.codeInspection.miscGenerics;
|
||||
|
||||
import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.codeInsight.ExpectedTypeInfo;
|
||||
import com.intellij.codeInsight.ExpectedTypesProvider;
|
||||
import com.intellij.codeInsight.FileModificationService;
|
||||
@@ -31,6 +32,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -93,7 +95,8 @@ public class RedundantArrayForVarargsCallInspection extends GenericsInspectionTo
|
||||
return;
|
||||
}
|
||||
PsiMethod method = (PsiMethod)element;
|
||||
if (!method.isVarArgs()) {
|
||||
if (!method.isVarArgs() ||
|
||||
AnnotationUtil.isAnnotated(method, Collections.singletonList("java.lang.invoke.MethodHandle.PolymorphicSignature"))) {
|
||||
return;
|
||||
}
|
||||
PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
|
||||
@@ -58,7 +58,9 @@ public class JavaFilterLexer extends BaseFilterLexer {
|
||||
if (tokenType == JavaTokenType.IDENTIFIER
|
||||
|| tokenType == JavaTokenType.LONG_LITERAL
|
||||
|| tokenType == JavaTokenType.INTEGER_LITERAL
|
||||
|| tokenType == JavaTokenType.CHARACTER_LITERAL) {
|
||||
|| tokenType == JavaTokenType.CHARACTER_LITERAL
|
||||
|| tokenType == JavaTokenType.ARROW
|
||||
|| tokenType == JavaTokenType.DOUBLE_COLON) {
|
||||
addOccurrenceInToken(UsageSearchContext.IN_CODE);
|
||||
}
|
||||
else if (tokenType == JavaTokenType.STRING_LITERAL) {
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package com.intellij.psi.impl.java.stubs.index;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.impl.search.JavaSourceFilterScope;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.stubs.StringStubIndexExtension;
|
||||
import com.intellij.psi.stubs.StubIndex;
|
||||
import com.intellij.psi.stubs.StubIndexKey;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class JavaMethodParameterTypesIndex extends StringStubIndexExtension<PsiMethod> {
|
||||
|
||||
private static final JavaMethodParameterTypesIndex ourInstance = new JavaMethodParameterTypesIndex();
|
||||
public static JavaMethodParameterTypesIndex getInstance() {
|
||||
return ourInstance;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public StubIndexKey<String, PsiMethod> getKey() {
|
||||
return JavaStubIndexKeys.METHOD_TYPES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<PsiMethod> get(@NotNull final String s, @NotNull final Project project, @NotNull final GlobalSearchScope scope) {
|
||||
return StubIndex.getElements(getKey(), s, project, new JavaSourceFilterScope(scope), PsiMethod.class);
|
||||
}
|
||||
}
|
||||
@@ -15,37 +15,39 @@
|
||||
*/
|
||||
package com.intellij.psi.impl.search;
|
||||
|
||||
import com.intellij.ide.highlighter.JavaFileType;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.module.impl.scopes.ModulesScope;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.LanguageLevelModuleExtension;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.java.stubs.JavaMethodElementType;
|
||||
import com.intellij.psi.impl.java.stubs.index.JavaMethodParameterTypesIndex;
|
||||
import com.intellij.psi.search.EverythingGlobalScope;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.search.*;
|
||||
import com.intellij.psi.search.searches.FunctionalExpressionSearch;
|
||||
import com.intellij.psi.search.searches.MethodReferencesSearch;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.util.CommonProcessors;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.QueryExecutor;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class JavaFunctionalExpressionSearcher implements QueryExecutor<PsiFunctionalExpression, FunctionalExpressionSearch.SearchParameters> {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance("#" + JavaFunctionalExpressionSearcher.class.getName());
|
||||
|
||||
@Override
|
||||
public boolean execute(@NotNull final FunctionalExpressionSearch.SearchParameters queryParameters,
|
||||
@NotNull final Processor<PsiFunctionalExpression> consumer) {
|
||||
@@ -98,102 +100,74 @@ public class JavaFunctionalExpressionSearcher implements QueryExecutor<PsiFuncti
|
||||
return searchScope.intersectWith(classScope);
|
||||
}
|
||||
});
|
||||
|
||||
final Project project = PsiUtilCore.getProjectInReadAction(aClass);
|
||||
final GlobalSearchScope scope = new ModulesScope(highLevelModules, project)
|
||||
.intersectWith(useScope instanceof GlobalSearchScope ? (GlobalSearchScope)useScope : new EverythingGlobalScope(project));
|
||||
final Collection<PsiMethod> lambdaCandidates = ApplicationManager.getApplication().runReadAction(new Computable<Collection<PsiMethod>>() {
|
||||
|
||||
final ProjectFileIndex index = ProjectRootManager.getInstance(project).getFileIndex();
|
||||
final HashSet<VirtualFile> files = new HashSet<VirtualFile>();
|
||||
CommonProcessors.CollectProcessor<VirtualFile> processor = new CommonProcessors.CollectProcessor<VirtualFile>(files) {
|
||||
@Override
|
||||
public Collection<PsiMethod> compute() {
|
||||
final String functionalInterfaceName = aClass.getName();
|
||||
final GlobalSearchScope useClassScope = classScope instanceof GlobalSearchScope ? (GlobalSearchScope)classScope : scope;
|
||||
JavaMethodParameterTypesIndex parameterTypesIndex = JavaMethodParameterTypesIndex.getInstance();
|
||||
LinkedHashSet<PsiMethod> methods = new LinkedHashSet<PsiMethod>(parameterTypesIndex.get(functionalInterfaceName, project, useClassScope));
|
||||
methods.addAll(parameterTypesIndex.get(JavaMethodElementType.TYPE_PARAMETER_PSEUDO_NAME, project,
|
||||
GlobalSearchScope.allScope(project)));
|
||||
return methods;
|
||||
protected boolean accept(VirtualFile virtualFile) {
|
||||
return scope.contains(virtualFile) && virtualFile.getFileType() == JavaFileType.INSTANCE && index.isInSource(virtualFile);
|
||||
}
|
||||
});
|
||||
for (PsiMethod psiMethod : lambdaCandidates) {
|
||||
for (final PsiReference ref : MethodReferencesSearch.search(psiMethod, scope, false)) {
|
||||
boolean accepted = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
final PsiElement refElement = ref.getElement();
|
||||
if (refElement != null) {
|
||||
final PsiElement candidateElement = refElement.getParent();
|
||||
if (candidateElement instanceof PsiCallExpression) {
|
||||
final PsiExpressionList argumentList = ((PsiCallExpression)candidateElement).getArgumentList();
|
||||
if (argumentList != null) {
|
||||
final PsiExpression[] args = argumentList.getExpressions();
|
||||
for (PsiExpression arg : args) {
|
||||
if (arg instanceof PsiFunctionalExpression) {
|
||||
final PsiFunctionalExpression functionalExpression = (PsiFunctionalExpression)arg;
|
||||
final PsiType functionalType = functionalExpression.getFunctionalInterfaceType();
|
||||
if (PsiUtil.resolveClassInType(functionalType) == aClass) {
|
||||
if (!consumer.process(functionalExpression)) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (!accepted) return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for (final PsiReference reference : ReferencesSearch.search(aClass, scope)) {
|
||||
boolean accepted = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
final PsiSearchHelperImpl helper = (PsiSearchHelperImpl)PsiSearchHelper.SERVICE.getInstance(project);
|
||||
helper.processFilesWithText(scope, UsageSearchContext.IN_CODE, true, "::", processor);
|
||||
helper.processFilesWithText(scope, UsageSearchContext.IN_CODE, true, "->", processor);
|
||||
LOG.info("#files: " + files.size());
|
||||
|
||||
final PsiManager psiManager = PsiManager.getInstance(project);
|
||||
for (final VirtualFile file : files) {
|
||||
if (!ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
final PsiElement element = reference.getElement();
|
||||
if (element != null) {
|
||||
final PsiElement parent = element.getParent();
|
||||
if (parent instanceof PsiTypeElement) {
|
||||
final PsiElement gParent = parent.getParent();
|
||||
if (gParent instanceof PsiVariable) {
|
||||
final PsiExpression initializer = PsiUtil.skipParenthesizedExprDown(((PsiVariable)gParent).getInitializer());
|
||||
if (initializer instanceof PsiFunctionalExpression) {
|
||||
if (!consumer.process((PsiFunctionalExpression)initializer)) return false;
|
||||
}
|
||||
for (PsiReference varRef : ReferencesSearch.search(parent, scope)) {
|
||||
final PsiElement varElement = varRef.getElement();
|
||||
if (varElement != null) {
|
||||
final PsiElement varElementParent = varElement.getParent();
|
||||
if (varElementParent instanceof PsiAssignmentExpression &&
|
||||
((PsiAssignmentExpression)varElementParent).getLExpression() == varElement) {
|
||||
final PsiExpression rExpression = PsiUtil.skipParenthesizedExprDown(((PsiAssignmentExpression)varElementParent).getRExpression());
|
||||
if (rExpression instanceof PsiFunctionalExpression) {
|
||||
if (!consumer.process((PsiFunctionalExpression)rExpression)) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (gParent instanceof PsiMethod) {
|
||||
final PsiReturnStatement[] returnStatements = ApplicationManager.getApplication().runReadAction(
|
||||
new Computable<PsiReturnStatement[]>() {
|
||||
@Override
|
||||
public PsiReturnStatement[] compute() {
|
||||
return PsiUtil.findReturnStatements((PsiMethod)gParent);
|
||||
}
|
||||
});
|
||||
for (PsiReturnStatement returnStatement : returnStatements) {
|
||||
final PsiExpression returnValue = returnStatement.getReturnValue();
|
||||
if (returnValue instanceof PsiFunctionalExpression) {
|
||||
if (!consumer.process((PsiFunctionalExpression)returnValue)) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return processFileWithFunctionalInterfaces(aClass, consumer, psiManager, file);
|
||||
}
|
||||
})) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean processFileWithFunctionalInterfaces(final PsiClass aClass,
|
||||
final Processor<PsiFunctionalExpression> consumer,
|
||||
final PsiManager psiManager, VirtualFile file) {
|
||||
final PsiFile psiFile = psiManager.findFile(file);
|
||||
if (psiFile != null) {
|
||||
final Ref<Boolean> ref = new Ref<Boolean>(true);
|
||||
psiFile.accept(new JavaRecursiveElementWalkingVisitor() {
|
||||
@Override
|
||||
public void visitElement(PsiElement element) {
|
||||
if (!ref.get()) {
|
||||
return;
|
||||
}
|
||||
super.visitElement(element);
|
||||
}
|
||||
|
||||
private void visitFunctionalExpression(PsiFunctionalExpression expression) {
|
||||
PsiType functionalInterfaceType = expression.getFunctionalInterfaceType();
|
||||
if (psiManager.areElementsEquivalent(PsiUtil.resolveClassInType(functionalInterfaceType), aClass)) {
|
||||
if (!consumer.process(expression)) {
|
||||
ref.set(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@Override
|
||||
public void visitLambdaExpression(PsiLambdaExpression expression) {
|
||||
super.visitLambdaExpression(expression);
|
||||
visitFunctionalExpression(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethodReferenceExpression(PsiMethodReferenceExpression expression) {
|
||||
super.visitMethodReferenceExpression(expression);
|
||||
visitFunctionalExpression(expression);
|
||||
}
|
||||
});
|
||||
if (!accepted) return false;
|
||||
|
||||
if (!ref.get()) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -50,7 +50,6 @@ import java.util.Set;
|
||||
* @author max
|
||||
*/
|
||||
public abstract class JavaMethodElementType extends JavaStubElementType<PsiMethodStub, PsiMethod> {
|
||||
public static final String TYPE_PARAMETER_PSEUDO_NAME = "$TYPE_PARAMETER$";
|
||||
public JavaMethodElementType(@NonNls final String name) {
|
||||
super(name);
|
||||
}
|
||||
@@ -150,35 +149,5 @@ public abstract class JavaMethodElementType extends JavaStubElementType<PsiMetho
|
||||
sink.occurrence(JavaStubIndexKeys.JVM_STATIC_MEMBERS_TYPES, stub.getReturnTypeText(false).getShortTypeText());
|
||||
}
|
||||
}
|
||||
|
||||
Set<String> methodTypeParams = null;
|
||||
for (StubElement stubElement : stub.getChildrenStubs()) {
|
||||
if (stubElement instanceof PsiTypeParameterListStub) {
|
||||
for (Object tStub : stubElement.getChildrenStubs()) {
|
||||
if (tStub instanceof PsiTypeParameterStub) {
|
||||
if (methodTypeParams == null) {
|
||||
methodTypeParams = new HashSet<String>();
|
||||
}
|
||||
methodTypeParams.add(((PsiTypeParameterStub)tStub).getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (stubElement instanceof PsiParameterListStub) {
|
||||
for (StubElement paramStub : ((PsiParameterListStub)stubElement).getChildrenStubs()) {
|
||||
if (paramStub instanceof PsiParameterStub) {
|
||||
TypeInfo type = ((PsiParameterStub)paramStub).getType(false);
|
||||
if (type.arrayCount > 0) continue;
|
||||
String typeName = type.getShortTypeText();
|
||||
if (TypeConversionUtil.isPrimitive(typeName) || TypeConversionUtil.isPrimitiveWrapper(typeName)) continue;
|
||||
sink.occurrence(JavaStubIndexKeys.METHOD_TYPES, typeName);
|
||||
if (methodTypeParams != null && methodTypeParams.contains(typeName)) {
|
||||
sink.occurrence(JavaStubIndexKeys.METHOD_TYPES, TYPE_PARAMETER_PSEUDO_NAME);
|
||||
methodTypeParams = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ public class JavaStubIndexKeys {
|
||||
public static final StubIndexKey<String, PsiMember> JVM_STATIC_MEMBERS_NAMES = StubIndexKey.createIndexKey("jvm.static.member.name");
|
||||
public static final StubIndexKey<String, PsiMember> JVM_STATIC_MEMBERS_TYPES = StubIndexKey.createIndexKey("jvm.static.member.type");
|
||||
public static final StubIndexKey<String, PsiAnonymousClass> ANONYMOUS_BASEREF = StubIndexKey.createIndexKey("java.anonymous.baseref");
|
||||
public static final StubIndexKey<String, PsiMethod> METHOD_TYPES = StubIndexKey.createIndexKey("java.method.parameter.types");
|
||||
public static final StubIndexKey<String, PsiClass> CLASS_SHORT_NAMES = StubIndexKey.createIndexKey("java.class.shortname");
|
||||
public static final StubIndexKey<Integer,PsiClass> CLASS_FQN = StubIndexKey.createIndexKey("java.class.fqn");
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ import java.io.IOException;
|
||||
* @author max
|
||||
*/
|
||||
public class JavaFileElementType extends ILightStubFileElementType<PsiJavaFileStub> {
|
||||
public static final int STUB_VERSION = 18;
|
||||
public static final int STUB_VERSION = 19;
|
||||
|
||||
public JavaFileElementType() {
|
||||
super("java.FILE", JavaLanguage.INSTANCE);
|
||||
|
||||
@@ -105,7 +105,7 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm
|
||||
|
||||
if (typeParams != null) {
|
||||
PsiSubstitutor siteSubstitutor =
|
||||
resolveResult instanceof MethodCandidateInfo && method != null && !method.isConstructor() ? ((MethodCandidateInfo)resolveResult).getSiteSubstitutor() : PsiSubstitutor.EMPTY;
|
||||
resolveResult instanceof MethodCandidateInfo && method != null && !method.isConstructor() ? ((MethodCandidateInfo)resolveResult).getSiteSubstitutor() : candidateProperties != null ? candidateProperties.getSubstitutor() : PsiSubstitutor.EMPTY;
|
||||
final InferenceSession callSession = new InferenceSession(typeParams, siteSubstitutor, myExpression.getManager(), myExpression);
|
||||
callSession.propagateVariables(session.getInferenceVariables());
|
||||
if (method != null) {
|
||||
|
||||
@@ -169,13 +169,13 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
|
||||
}
|
||||
LOG.assertTrue(referencedMethodReturnType != null, method);
|
||||
|
||||
session.initBounds(myExpression, method.getTypeParameters());
|
||||
|
||||
if (!PsiTreeUtil.isContextAncestor(containingClass, myExpression, false) ||
|
||||
if (!PsiTreeUtil.isContextAncestor(containingClass, myExpression, false) ||
|
||||
PsiUtil.getEnclosingStaticElement(myExpression, containingClass) != null) {
|
||||
session.initBounds(myExpression, containingClass.getTypeParameters());
|
||||
}
|
||||
|
||||
session.initBounds(myExpression, method.getTypeParameters());
|
||||
|
||||
//if i) the method reference elides NonWildTypeArguments,
|
||||
// ii) the compile-time declaration is a generic method, and
|
||||
// iii) the return type of the compile-time declaration mentions at least one of the method's type parameters;
|
||||
|
||||
@@ -231,7 +231,8 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
|
||||
final PsiMethod method = ((MethodCandidateInfo)conflict).getElement();
|
||||
for (HierarchicalMethodSignature methodSignature : method.getHierarchicalMethodSignature().getSuperSignatures()) {
|
||||
final PsiMethod superMethod = methodSignature.getMethod();
|
||||
if (!CommonClassNames.JAVA_LANG_OBJECT.equals(superMethod.getContainingClass().getQualifiedName())) {
|
||||
final PsiClass aClass = superMethod.getContainingClass();
|
||||
if (aClass != null && !CommonClassNames.JAVA_LANG_OBJECT.equals(aClass.getQualifiedName())) {
|
||||
superMethods.add(superMethod);
|
||||
}
|
||||
}
|
||||
@@ -513,7 +514,7 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
|
||||
if (varargsPosition) {
|
||||
if (type1 instanceof PsiEllipsisType && type2 instanceof PsiEllipsisType &&
|
||||
params1.length == params2.length &&
|
||||
(!JavaVersionService.getInstance().isAtLeast(class1, JavaSdkVersion.JDK_1_7) || ((PsiArrayType)type1).getComponentType().equalsToText(CommonClassNames.JAVA_LANG_OBJECT) || ((PsiArrayType)type2).getComponentType().equalsToText(CommonClassNames.JAVA_LANG_OBJECT))) {
|
||||
class1 != null && (!JavaVersionService.getInstance().isAtLeast(class1, JavaSdkVersion.JDK_1_7) || ((PsiArrayType)type1).getComponentType().equalsToText(CommonClassNames.JAVA_LANG_OBJECT) || ((PsiArrayType)type2).getComponentType().equalsToText(CommonClassNames.JAVA_LANG_OBJECT))) {
|
||||
type1 = ((PsiEllipsisType)type1).toArrayType();
|
||||
type2 = ((PsiEllipsisType)type2).toArrayType();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
class Test {
|
||||
enum FooBar {Foo, Bar}
|
||||
|
||||
void someMethod() {
|
||||
new Infer<>((FooBar) null, FooBar.class);
|
||||
new Infer<FooBar>( (FooBar) null, FooBar.class );
|
||||
}
|
||||
|
||||
|
||||
public class Infer<T extends Enum<T>> {
|
||||
@SafeVarargs
|
||||
public Infer(T inst, Class<T> tClass, T... excludes) {
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public Infer(String inst, Class<T> tClass, T... excludes) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
class Test {
|
||||
public static class Thing {
|
||||
public Integer toPresenter() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
public <U> void map1(Function<Object, U> mapper) {}
|
||||
|
||||
private void getPresentersFailure( final Stream<Thing> stream) {
|
||||
map1((roles) -> {
|
||||
return stream.map(Thing::toPresenter);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Test1 {
|
||||
public interface Convertable {
|
||||
ThingPresenter toPresenter();
|
||||
}
|
||||
|
||||
public static class Thing implements Convertable {
|
||||
@Override
|
||||
public ThingPresenter toPresenter() {
|
||||
return new ThingPresenter("thing");
|
||||
}
|
||||
}
|
||||
|
||||
public static class ThingPresenter {
|
||||
public String value;
|
||||
public ThingPresenter(String value) { this.value = value; }
|
||||
}
|
||||
|
||||
private static Stream<ThingPresenter> getPresentersFailure(Supplier<Optional<List<Thing>>> thingSupplier) {
|
||||
Optional<List<Thing>> personRoles = thingSupplier.get();
|
||||
return personRoles.map(roles -> roles.stream().map(Thing::toPresenter)).get();
|
||||
}
|
||||
|
||||
private static Stream<ThingPresenter> getPresentersWorking(Supplier<Optional<List<Thing>>> thingSupplier) {
|
||||
Optional<List<Thing>> personRoles = thingSupplier.get();
|
||||
return personRoles.map(roles -> roles.stream().map(t -> t.toPresenter())).get();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import java.util.function.Function;
|
||||
|
||||
interface Repository<T> {
|
||||
<S extends T> S save(S s);
|
||||
}
|
||||
|
||||
interface Builder<T> {
|
||||
|
||||
T build();
|
||||
|
||||
default <D> Builder<D> map(Function<T, D> fx) {
|
||||
return () -> fx.apply(this.build());
|
||||
}
|
||||
}
|
||||
|
||||
class Usage {
|
||||
void test(Repository<String> repository, Builder<String> sample) {
|
||||
sample.map(repository::save).build();
|
||||
sample.map((s) -> repository.save(s)).build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package mylibs.aspectjlibs.lib2;
|
||||
|
||||
<warning descr="Default File template">/**
|
||||
* Created by irina on 11/6/2014.
|
||||
*/</warning>
|
||||
class Range {
|
||||
/**
|
||||
* for all public methods with name == foo* and String type
|
||||
*/
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
package x;
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
<warning descr="Default File template">/**
|
||||
* Created by Alexey on 02.12.2005.
|
||||
*/
|
||||
*/</warning>
|
||||
public class X implements Runnable{
|
||||
File f; //kkj lkkl jjkuufdffffjkkjjh kjh kjhj kkjh kjh i k kj kj klj lkj lkj lkjl kj klkl kl
|
||||
{
|
||||
@@ -60,4 +60,3 @@ public class X implements Runnable{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package x;
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
<warning descr="Default File template">/**
|
||||
* Created by Alexey on 02.12.2005.
|
||||
*/
|
||||
*/</warning>
|
||||
public class X2 {
|
||||
}
|
||||
@@ -5,5 +5,5 @@ import java.io.*;
|
||||
* Created by Alexey on 02.12.2005.
|
||||
* This class represents something important.
|
||||
*/
|
||||
public class X2 {
|
||||
public class X3 {
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems>
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>4</line>
|
||||
<problem_class>Default File Template Usage</problem_class>
|
||||
<description>Default File template</description>
|
||||
</problem>
|
||||
|
||||
<problem>
|
||||
<file>X2.java</file>
|
||||
<line>4</line>
|
||||
<problem_class>Default File Template Usage</problem_class>
|
||||
<description>Default File template</description>
|
||||
</problem>
|
||||
</problems>
|
||||
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems>
|
||||
</problems>
|
||||
@@ -0,0 +1,9 @@
|
||||
import java.lang.invoke.MethodHandle;
|
||||
|
||||
public class Test {
|
||||
|
||||
public static void main(String[] args) {
|
||||
MethodHandle meh = null;
|
||||
meh.invokeExact(new Object[] {});
|
||||
}
|
||||
}
|
||||
@@ -107,6 +107,7 @@ public class LightAdvHighlightingJdk7Test extends LightDaemonAnalyzerTestCase {
|
||||
public void testInnerInTypeArguments() { doTest(false, false); }
|
||||
public void testRawSubstitutor() { doTest(false, false); }
|
||||
public void testIncompleteDiamonds() { doTest(false, false); }
|
||||
public void testResolveConflictDiamonds() { doTest(false, false); }
|
||||
|
||||
public void testDynamicallyAddIgnoredAnnotations() {
|
||||
ExtensionPoint<EntryPoint> point = Extensions.getRootArea().getExtensionPoint(ToolExtensionPoints.DEAD_CODE_TOOL);
|
||||
|
||||
@@ -156,6 +156,10 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testPropertiesInsteadOfSiteSubstitutorIfAny() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
@@ -318,6 +318,10 @@ public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testTypeParametersInitOrder() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInspection.defaultFileTemplateUsage.DefaultFileTemplateUsageInspection;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.testFramework.InspectionTestCase;
|
||||
|
||||
public class DefaultFileTemplateInspectionTest extends InspectionTestCase {
|
||||
@Override
|
||||
protected Sdk getTestProjectSdk() {
|
||||
final Sdk sdk = super.getTestProjectSdk();
|
||||
LanguageLevelProjectExtension.getInstance(getProject()).setLanguageLevel(LanguageLevel.JDK_1_7);
|
||||
return sdk;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
return JavaTestUtil.getJavaTestDataPath() + "/inspection";
|
||||
}
|
||||
|
||||
private void doTest() throws Exception {
|
||||
doTest("defaultFileTemplateUsage/" + getTestName(true), new DefaultFileTemplateUsageInspection());
|
||||
}
|
||||
|
||||
public void testDefaultFile() throws Exception{
|
||||
doTest();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.codeInspection;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInspection.defaultFileTemplateUsage.DefaultFileTemplateUsageInspection;
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
|
||||
|
||||
public class DefaultFileTemplateUsageInspectionTest extends LightCodeInsightFixtureTestCase {
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
return JavaTestUtil.getJavaTestDataPath() + "/inspection/defaultFileTemplateUsage";
|
||||
}
|
||||
|
||||
public void testX() { doTest(); }
|
||||
public void testX2() { doTest(); }
|
||||
public void testX3() { doTest(); }
|
||||
public void testRange() { doTest(); }
|
||||
|
||||
public void doTest() {
|
||||
myFixture.enableInspections(new DefaultFileTemplateUsageInspection());
|
||||
myFixture.testHighlighting(true, false, true, getTestName(false) + ".java");
|
||||
}
|
||||
}
|
||||
@@ -24,4 +24,5 @@ public class RedundantArrayForVarargsCallInspectionTest extends InspectionTestCa
|
||||
public void testCheckEnumConstant() throws Exception { doTest(); }
|
||||
public void testGeneric() throws Exception { doTest(); }
|
||||
public void testRawArray() throws Exception { doTest(); }
|
||||
public void testPolymorphicSignature() throws Exception { doTest(); }
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.jetbrains.jps.model.serialization.runConfigurations;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.JDOMUtil;
|
||||
import com.intellij.util.containers.hash.HashMap;
|
||||
import org.jdom.Element;
|
||||
@@ -31,6 +32,8 @@ import java.util.Map;
|
||||
* @author nik
|
||||
*/
|
||||
public class JpsRunConfigurationSerializer {
|
||||
private static final Logger LOG = Logger.getInstance(JpsRunConfigurationSerializer.class);
|
||||
|
||||
public static void loadRunConfigurations(@NotNull JpsProject project, @Nullable Element runManagerTag) {
|
||||
Map<String, JpsRunConfigurationPropertiesSerializer<?>> serializers = new HashMap<String, JpsRunConfigurationPropertiesSerializer<?>>();
|
||||
for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
|
||||
@@ -50,9 +53,12 @@ public class JpsRunConfigurationSerializer {
|
||||
if (serializer != null) {
|
||||
loadRunConfiguration(name, configurationTag, serializer, project);
|
||||
}
|
||||
else {
|
||||
else if (typeId != null) {
|
||||
project.addRunConfiguration(name, new JpsUnknownRunConfigurationType(typeId), JpsElementFactory.getInstance().createDummyElement());
|
||||
}
|
||||
else {
|
||||
LOG.info("Run configuration '" + name + "' wasn't loaded because 'type' attribute is missing");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="invalid">
|
||||
</configuration>
|
||||
</component>
|
||||
@@ -45,6 +45,8 @@
|
||||
<patterns />
|
||||
<method />
|
||||
</configuration>
|
||||
<configuration default="false" name="invalid">
|
||||
</configuration>
|
||||
</component>
|
||||
</project>
|
||||
|
||||
|
||||
@@ -54,7 +54,9 @@ public class JsonStandardComplianceInspection extends LocalInspectionTool {
|
||||
@Override
|
||||
public void visitComment(PsiComment comment) {
|
||||
if (myWarnAboutComments) {
|
||||
holder.registerProblem(comment, JsonBundle.message("msg.compliance.problem.comments"), ProblemHighlightType.WEAK_WARNING);
|
||||
if (JsonStandardComplianceProvider.shouldWarnAboutComment(comment)) {
|
||||
holder.registerProblem(comment, JsonBundle.message("msg.compliance.problem.comments"), ProblemHighlightType.WEAK_WARNING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.json.codeinsight;
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.psi.PsiComment;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Allows to configure a compliance level for JSON.
|
||||
* For example, some tools ignore comments in JSON silently when parsing, so there is no need to warn users about it.
|
||||
*/
|
||||
public abstract class JsonStandardComplianceProvider {
|
||||
public static final ExtensionPointName<JsonStandardComplianceProvider> EP_NAME =
|
||||
ExtensionPointName.create("com.intellij.json.jsonStandardComplianceProvider");
|
||||
|
||||
public abstract boolean isCommentAllowed(@NotNull PsiComment comment);
|
||||
|
||||
public static boolean shouldWarnAboutComment(@NotNull PsiComment comment) {
|
||||
JsonStandardComplianceProvider[] providers = EP_NAME.getExtensions();
|
||||
if (providers.length == 0) {
|
||||
return true;
|
||||
}
|
||||
for (JsonStandardComplianceProvider provider : providers) {
|
||||
if (provider.isCommentAllowed(comment)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.intellij.json.navigation;
|
||||
|
||||
import com.intellij.ide.actions.QualifiedNameProvider;
|
||||
import com.intellij.json.psi.JsonElement;
|
||||
import com.intellij.json.psi.JsonProperty;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.EditorModificationUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
/**
|
||||
* @author Mikhail Golubev
|
||||
*/
|
||||
public class JsonQualifiedNameProvider implements QualifiedNameProvider {
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiElement adjustElementToCopy(PsiElement element) {
|
||||
return element;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getQualifiedName(PsiElement element) {
|
||||
if (!(element instanceof JsonElement)) {
|
||||
return null;
|
||||
}
|
||||
final LinkedList<String> qualifiers = new LinkedList<String>();
|
||||
JsonProperty parentProperty = PsiTreeUtil.getNonStrictParentOfType(element, JsonProperty.class);
|
||||
while (parentProperty != null) {
|
||||
qualifiers.addFirst(parentProperty.getName());
|
||||
parentProperty = PsiTreeUtil.getParentOfType(parentProperty, JsonProperty.class);
|
||||
}
|
||||
return qualifiers.isEmpty() ? null : StringUtil.join(qualifiers, ".");
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement qualifiedNameToElement(String fqn, Project project) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertQualifiedName(String fqn, PsiElement element, Editor editor, Project project) {
|
||||
EditorModificationUtil.insertStringAtCaret(editor, fqn);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.intellij.json;
|
||||
|
||||
import com.intellij.ide.actions.CopyReferenceAction;
|
||||
import com.intellij.json.psi.JsonProperty;
|
||||
import com.intellij.psi.PsiElement;
|
||||
|
||||
/**
|
||||
* @author Mikhail Golubev
|
||||
*/
|
||||
public class JsonNavigationTest extends JsonTestCase {
|
||||
|
||||
// WEB-14048
|
||||
public void testCopyReference() {
|
||||
myFixture.configureByFile("navigation/" + getTestName(false) + ".json");
|
||||
final PsiElement element = myFixture.getElementAtCaret();
|
||||
assertInstanceOf(element, JsonProperty.class);
|
||||
final String qualifiedName = CopyReferenceAction.elementToFqn(element);
|
||||
assertEquals("foo.bar.baz", qualifiedName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"foo": {
|
||||
"bar": [
|
||||
[
|
||||
{
|
||||
"baz<caret>": null
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -23,14 +23,14 @@ import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
|
||||
/**
|
||||
* Created by Max Medvedev on 28/03/14
|
||||
*/
|
||||
@Transient
|
||||
public class SimpleModificationTracker implements ModificationTracker {
|
||||
static {
|
||||
// field made public to workaround bug in JDK7 when AtomicIntegerFieldUpdater can't be created for private field, even from within its own class
|
||||
// fixed in JDK8
|
||||
assert Patches.JDK_BUG_ID_7103570;
|
||||
}
|
||||
|
||||
@Transient
|
||||
|
||||
public volatile int myCounter;
|
||||
|
||||
@Override
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.PlainTextLanguage;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Couple;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.*;
|
||||
@@ -58,7 +59,7 @@ public class BlockSupportImpl extends BlockSupport {
|
||||
project.getMessageBus().connect().subscribe(DocumentBulkUpdateListener.TOPIC, new DocumentBulkUpdateListener.Adapter() {
|
||||
@Override
|
||||
public void updateStarted(@NotNull final Document doc) {
|
||||
doc.putUserData(DO_NOT_REPARSE_INCREMENTALLY, Boolean.TRUE);
|
||||
doc.putUserData(DO_NOT_REPARSE_INCREMENTALLY, Boolean.TRUE);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -80,22 +81,34 @@ public class BlockSupportImpl extends BlockSupport {
|
||||
@NotNull final CharSequence newFileText,
|
||||
@NotNull final ProgressIndicator indicator) {
|
||||
final PsiFileImpl fileImpl = (PsiFileImpl)file;
|
||||
Project project = fileImpl.getProject();
|
||||
final FileElement treeFileElement = fileImpl.getTreeElement();
|
||||
final CharTable charTable = treeFileElement.getCharTable();
|
||||
|
||||
final Couple<ASTNode> reparseableRoots = findReparseableRoots(fileImpl, changedPsiRange, newFileText);
|
||||
return reparseableRoots != null
|
||||
? mergeTrees(fileImpl, reparseableRoots.first, reparseableRoots.second, indicator)
|
||||
: makeFullParse(fileImpl.getTreeElement(), newFileText, newFileText.length(), fileImpl, indicator);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method searches ast node that could be reparsed incrementally and returns pair of target reparseable node and new replacement node.
|
||||
* Returns null if there is no any chance to make incremental parsing.
|
||||
*/
|
||||
@Nullable
|
||||
public Couple<ASTNode> findReparseableRoots(@NotNull PsiFileImpl file,
|
||||
@NotNull TextRange changedPsiRange,
|
||||
@NotNull CharSequence newFileText) {
|
||||
Project project = file.getProject();
|
||||
final FileElement fileElement = file.getTreeElement();
|
||||
final CharTable charTable = fileElement.getCharTable();
|
||||
int lengthShift = newFileText.length() - fileElement.getTextLength();
|
||||
|
||||
final int textLength = newFileText.length();
|
||||
int lengthShift = textLength - treeFileElement.getTextLength();
|
||||
|
||||
if (treeFileElement.getElementType() instanceof ITemplateDataElementType || isTooDeep(file)) {
|
||||
if (fileElement.getElementType() instanceof ITemplateDataElementType || isTooDeep(file)) {
|
||||
// unable to perform incremental reparse for template data in JSP, or in exceptionally deep trees
|
||||
return makeFullParse(treeFileElement, newFileText, textLength, fileImpl, indicator);
|
||||
return null;
|
||||
}
|
||||
|
||||
final ASTNode leafAtStart = treeFileElement.findLeafElementAt(Math.max(0, changedPsiRange.getStartOffset() - 1));
|
||||
final ASTNode leafAtEnd = treeFileElement.findLeafElementAt(changedPsiRange.getEndOffset());
|
||||
ASTNode node = leafAtStart != null && leafAtEnd != null ? TreeUtil.findCommonParent(leafAtStart, leafAtEnd) : treeFileElement;
|
||||
final ASTNode leafAtStart = fileElement.findLeafElementAt(Math.max(0, changedPsiRange.getStartOffset() - 1));
|
||||
final ASTNode leafAtEnd = fileElement.findLeafElementAt(Math.min(changedPsiRange.getEndOffset(), fileElement.getTextLength() - 1));
|
||||
ASTNode node = leafAtStart != null && leafAtEnd != null ? TreeUtil.findCommonParent(leafAtStart, leafAtEnd) : fileElement;
|
||||
Language baseLanguage = file.getViewProvider().getBaseLanguage();
|
||||
|
||||
while (node != null && !(node instanceof FileElement)) {
|
||||
@@ -117,25 +130,24 @@ public class BlockSupportImpl extends BlockSupport {
|
||||
if (reparseable.isParsable(node.getTreeParent(), newTextStr, baseLanguage, project)) {
|
||||
ASTNode chameleon = reparseable.createNode(newTextStr);
|
||||
if (chameleon != null) {
|
||||
DummyHolder holder = DummyHolderFactory.createHolder(fileImpl.getManager(), null, node.getPsi(), charTable);
|
||||
DummyHolder holder = DummyHolderFactory.createHolder(file.getManager(), null, node.getPsi(), charTable);
|
||||
holder.getTreeElement().rawAddChildren((TreeElement)chameleon);
|
||||
|
||||
if (holder.getTextLength() != newTextStr.length()) {
|
||||
String details = ApplicationManager.getApplication().isInternal()
|
||||
? "text=" + newTextStr + "; treeText=" + holder.getText() + ";"
|
||||
: "";
|
||||
? "text=" + newTextStr + "; treeText=" + holder.getText() + ";"
|
||||
: "";
|
||||
LOG.error("Inconsistent reparse: " + details + " type=" + elementType);
|
||||
}
|
||||
|
||||
return mergeTrees(fileImpl, node, chameleon, indicator);
|
||||
return Couple.of(node, chameleon);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
node = node.getTreeParent();
|
||||
}
|
||||
|
||||
return makeFullParse(node, newFileText, textLength, fileImpl, indicator);
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void reportInconsistentLength(PsiFile file, CharSequence newFileText, ASTNode node, int start, int end) {
|
||||
@@ -288,7 +300,7 @@ public class BlockSupportImpl extends BlockSupport {
|
||||
};
|
||||
}
|
||||
|
||||
private static boolean isReplaceWholeNode(@NotNull PsiFileImpl fileImpl, @NotNull ASTNode newRoot) throws ReparsedSuccessfullyException{
|
||||
private static boolean isReplaceWholeNode(@NotNull PsiFileImpl fileImpl, @NotNull ASTNode newRoot) throws ReparsedSuccessfullyException {
|
||||
final Boolean data = fileImpl.getUserData(DO_NOT_REPARSE_INCREMENTALLY);
|
||||
if (data != null) fileImpl.putUserData(DO_NOT_REPARSE_INCREMENTALLY, null);
|
||||
|
||||
@@ -308,7 +320,7 @@ public class BlockSupportImpl extends BlockSupport {
|
||||
}
|
||||
|
||||
public static void sendBeforeChildrenChangeEvent(@NotNull PsiManagerImpl manager, @NotNull PsiElement scope, boolean isGenericChange) {
|
||||
if(!scope.isPhysical()) {
|
||||
if (!scope.isPhysical()) {
|
||||
manager.beforeChange(false);
|
||||
return;
|
||||
}
|
||||
@@ -318,7 +330,7 @@ public class BlockSupportImpl extends BlockSupport {
|
||||
TextRange range = scope.getTextRange();
|
||||
event.setOffset(range == null ? 0 : range.getStartOffset());
|
||||
event.setOldLength(scope.getTextLength());
|
||||
// the "generic" event is being sent on every PSI change. It does not carry any specific info except the fact that "something has changed"
|
||||
// the "generic" event is being sent on every PSI change. It does not carry any specific info except the fact that "something has changed"
|
||||
event.setGenericChange(isGenericChange);
|
||||
manager.beforeChildrenChange(event);
|
||||
}
|
||||
@@ -327,7 +339,7 @@ public class BlockSupportImpl extends BlockSupport {
|
||||
@NotNull PsiFile scope,
|
||||
int oldLength,
|
||||
boolean isGenericChange) {
|
||||
if(!scope.isPhysical()) {
|
||||
if (!scope.isPhysical()) {
|
||||
manager.afterChange(false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -127,7 +127,15 @@ public class PushLog extends JPanel implements TypeSafeDataProvider {
|
||||
public void editingStopped(ChangeEvent e) {
|
||||
DefaultMutableTreeNode node = (DefaultMutableTreeNode)myTree.getLastSelectedPathComponent();
|
||||
if (node != null && node instanceof EditableTreeNode) {
|
||||
((EditableTreeNode)node).fireOnChange();
|
||||
JComponent editedComponent = (JComponent)node.getUserObject();
|
||||
InputVerifier verifier = editedComponent.getInputVerifier();
|
||||
if (verifier != null && !verifier.verify(editedComponent)) {
|
||||
// if invalid and interrupted, then revert
|
||||
((EditableTreeNode)node).fireOnCancel();
|
||||
}
|
||||
else {
|
||||
((EditableTreeNode)node).fireOnChange();
|
||||
}
|
||||
}
|
||||
myTree.firePropertyChange(PushLogTreeUtil.EDIT_MODE_PROP, true, false);
|
||||
}
|
||||
@@ -141,6 +149,8 @@ public class PushLog extends JPanel implements TypeSafeDataProvider {
|
||||
myTree.firePropertyChange(PushLogTreeUtil.EDIT_MODE_PROP, true, false);
|
||||
}
|
||||
});
|
||||
// complete editing when interrupt
|
||||
myTree.setInvokesStopCellEditing(true);
|
||||
myTree.setRootVisible(false);
|
||||
TreeUtil.collapseAll(myTree, 1);
|
||||
final VcsBranchEditorListener linkMouseListener = new VcsBranchEditorListener(myTreeCellRenderer);
|
||||
|
||||
@@ -186,7 +186,7 @@ public class UISettings extends SimpleModificationTracker implements PersistentS
|
||||
|
||||
public static class FontFilter implements SerializationFilter {
|
||||
@Override
|
||||
public boolean accepts(Accessor accessor, Object bean) {
|
||||
public boolean accepts(@NotNull Accessor accessor, Object bean) {
|
||||
UISettings settings = (UISettings)bean;
|
||||
return !hasDefaultFontSetting(settings);
|
||||
}
|
||||
|
||||
@@ -61,5 +61,7 @@ public interface EditorColors {
|
||||
ColorKey MODIFIED_LINES_COLOR = ColorKey.createColorKey("MODIFIED_LINES_COLOR");
|
||||
ColorKey DELETED_LINES_COLOR = ColorKey.createColorKey("DELETED_LINES_COLOR");
|
||||
ColorKey WHITESPACES_MODIFIED_LINES_COLOR = ColorKey.createColorKey("WHITESPACES_MODIFIED_LINES_COLOR");
|
||||
ColorKey BORDER_LINES_COLOR = ColorKey.createColorKey("BORDER_LINES_COLOR");
|
||||
|
||||
TextAttributesKey INJECTED_LANGUAGE_FRAGMENT = TextAttributesKey.createTextAttributesKey("INJECTED_LANGUAGE_FRAGMENT");
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 504 B After Width: | Height: | Size: 448 B |
|
Before Width: | Height: | Size: 249 B After Width: | Height: | Size: 175 B |
|
Before Width: | Height: | Size: 235 B After Width: | Height: | Size: 167 B |
@@ -91,7 +91,7 @@ public class IdIndex extends FileBasedIndexExtension<IdIndexEntry, Integer> {
|
||||
|
||||
@Override
|
||||
public int getVersion() {
|
||||
return 13 + (ourSnapshotMappingsEnabled ? 0xFF:0); // TODO: version should enumerate all word scanner versions and build version upon that set
|
||||
return 14 + (ourSnapshotMappingsEnabled ? 0xFF:0); // TODO: version should enumerate all word scanner versions and build version upon that set
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.intellij.openapi.module.ModuleUtilCore;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.InvalidDataException;
|
||||
import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.intellij.util.xmlb.annotations.Property;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -39,7 +40,10 @@ import java.util.Set;
|
||||
*/
|
||||
public abstract class ModuleBasedConfiguration<ConfigurationModule extends RunConfigurationModule> extends LocatableConfigurationBase implements Cloneable, ModuleRunConfiguration {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.execution.configurations.ModuleBasedConfiguration");
|
||||
|
||||
@Property(surroundWithTag = false)
|
||||
private final ConfigurationModule myModule;
|
||||
|
||||
@NonNls
|
||||
protected static final String TO_CLONE_ELEMENT_NAME = "toClone";
|
||||
|
||||
|
||||
@@ -26,6 +26,9 @@ import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.JDOMExternalizable;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.xmlb.annotations.Attribute;
|
||||
import com.intellij.util.xmlb.annotations.Tag;
|
||||
import com.intellij.util.xmlb.annotations.Transient;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -33,6 +36,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Tag("module")
|
||||
public class RunConfigurationModule implements JDOMExternalizable {
|
||||
private static final Logger LOG = Logger.getInstance(RunConfigurationModule.class);
|
||||
|
||||
@@ -40,7 +44,10 @@ public class RunConfigurationModule implements JDOMExternalizable {
|
||||
@NonNls private static final String ATTRIBUTE = "name";
|
||||
|
||||
private Module myModule = null;
|
||||
|
||||
@Attribute("name")
|
||||
private String myModuleName;
|
||||
|
||||
private final Project myProject;
|
||||
|
||||
public RunConfigurationModule(@NotNull Project project) {
|
||||
@@ -81,6 +88,7 @@ public class RunConfigurationModule implements JDOMExternalizable {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Transient
|
||||
public Module getModule() {
|
||||
if (myModuleName != null) { //caching
|
||||
myModule = findModule(myModuleName);
|
||||
|
||||
@@ -26,10 +26,7 @@ import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiWhiteSpace;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
|
||||
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
|
||||
@@ -62,7 +59,7 @@ public class CustomFoldingSurroundDescriptor implements SurroundDescriptor {
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement[] getElementsToSurround(PsiFile file, int startOffset, int endOffset) {
|
||||
if (startOffset >= endOffset - 1) return PsiElement.EMPTY_ARRAY;
|
||||
if (startOffset >= endOffset) return PsiElement.EMPTY_ARRAY;
|
||||
Commenter commenter = LanguageCommenters.INSTANCE.forLanguage(file.getLanguage());
|
||||
if (commenter == null || commenter.getLineCommentPrefix() == null) return PsiElement.EMPTY_ARRAY;
|
||||
PsiElement startElement = file.findElementAt(startOffset);
|
||||
@@ -70,18 +67,11 @@ public class CustomFoldingSurroundDescriptor implements SurroundDescriptor {
|
||||
PsiElement endElement = file.findElementAt(endOffset - 1);
|
||||
if (endElement instanceof PsiWhiteSpace) endElement = endElement.getPrevSibling();
|
||||
if (startElement != null && endElement != null) {
|
||||
if (startElement.getTextRange().getStartOffset() > endElement.getTextRange().getStartOffset()) return PsiElement.EMPTY_ARRAY;
|
||||
startElement = findClosestParentAfterLineBreak(startElement);
|
||||
if (startElement != null) {
|
||||
endElement = findClosestParentBeforeLineBreak(endElement);
|
||||
if (endElement != null) {
|
||||
startElement = adjustStartElementIfEndAbsorbed(startElement, endElement);
|
||||
endElement = adjustEndElementIfStartAbsorbed(startElement, endElement);
|
||||
final PsiElement commonParent = startElement.getParent();
|
||||
if (endElement.getParent() == commonParent) {
|
||||
if (startElement == endElement) return new PsiElement[]{startElement};
|
||||
return new PsiElement[]{startElement, endElement};
|
||||
}
|
||||
return adjustRange(startElement, endElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -89,46 +79,116 @@ public class CustomFoldingSurroundDescriptor implements SurroundDescriptor {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PsiElement adjustEndElementIfStartAbsorbed(@NotNull PsiElement start, @NotNull PsiElement end) {
|
||||
if (PsiTreeUtil.isAncestor(end, start, false) && start.getTextRange().getEndOffset() == end.getTextRange().getEndOffset()) {
|
||||
return start;
|
||||
private static PsiElement[] adjustRange(@NotNull PsiElement start, @NotNull PsiElement end) {
|
||||
PsiElement newStart = lowerStartElementIfNeeded(start, end);
|
||||
PsiElement newEnd = lowerEndElementIfNeeded(start, end);
|
||||
if (newStart == null || newEnd == null) {
|
||||
return PsiElement.EMPTY_ARRAY;
|
||||
}
|
||||
final PsiElement commonParent = findCommonAncestorForWholeRange(newStart, newEnd);
|
||||
if (commonParent != null) {
|
||||
return new PsiElement[] {commonParent};
|
||||
}
|
||||
// If either start or end element is the first/last leaf element in its parent, use the parent itself instead
|
||||
// to prevent selection of clearly illegal ranges like the following:
|
||||
// [
|
||||
// <selection>1
|
||||
// ]</selection>
|
||||
// E.g. in case shown, because of that adjustment, closing bracket and number literal won't have the same parent
|
||||
// and next test will fail.
|
||||
if (newStart.getParent().getFirstChild() == newStart && newStart.getFirstChild() == null) {
|
||||
newStart = newStart.getParent();
|
||||
}
|
||||
if (newEnd.getParent().getLastChild() == newEnd && newEnd.getFirstChild() == null) {
|
||||
newEnd = newEnd.getParent();
|
||||
}
|
||||
if (newStart.getParent() == newEnd.getParent()) {
|
||||
return new PsiElement[] {newStart, newEnd};
|
||||
}
|
||||
return PsiElement.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiElement lowerEndElementIfNeeded(@NotNull PsiElement start, @NotNull PsiElement end) {
|
||||
if (PsiTreeUtil.isAncestor(end, start, true)) {
|
||||
PsiElement lastChild = end.getLastChild();
|
||||
while (lastChild != null && lastChild.getParent() != start.getParent()) {
|
||||
lastChild = lastChild.getLastChild();
|
||||
}
|
||||
return lastChild;
|
||||
}
|
||||
return end;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PsiElement adjustStartElementIfEndAbsorbed(@NotNull PsiElement start, @NotNull PsiElement end) {
|
||||
if (PsiTreeUtil.isAncestor(start, end, false) && start.getTextRange().getStartOffset() == end.getTextRange().getStartOffset()) {
|
||||
return end;
|
||||
@Nullable
|
||||
private static PsiElement lowerStartElementIfNeeded(@NotNull PsiElement start, @NotNull PsiElement end) {
|
||||
if (PsiTreeUtil.isAncestor(start, end, true)) {
|
||||
PsiElement firstChild = start.getFirstChild();
|
||||
while (firstChild != null && firstChild.getParent() != end.getParent()) {
|
||||
firstChild = firstChild.getFirstChild();
|
||||
}
|
||||
return firstChild;
|
||||
}
|
||||
return start;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiElement findClosestParentAfterLineBreak(PsiElement element) {
|
||||
PsiElement parent = element;
|
||||
while (parent != null) {
|
||||
PsiElement prev = parent.getPrevSibling();
|
||||
while (prev != null && prev.getTextLength() <= 0) {
|
||||
prev = prev.getPrevSibling();
|
||||
}
|
||||
if (isWhiteSpaceWithLineFeed(prev)) return parent;
|
||||
parent = parent.getParent();
|
||||
private static PsiElement findCommonAncestorForWholeRange(@NotNull PsiElement start, @NotNull PsiElement end) {
|
||||
final PsiElement parent = PsiTreeUtil.findCommonParent(start, end);
|
||||
if (parent == null) {
|
||||
return null;
|
||||
}
|
||||
final TextRange parentRange = parent.getTextRange();
|
||||
if (parentRange.getStartOffset() == start.getTextRange().getStartOffset() &&
|
||||
parentRange.getEndOffset() == end.getTextRange().getEndOffset()) {
|
||||
return parent;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiElement findClosestParentBeforeLineBreak(PsiElement element) {
|
||||
private static PsiElement findClosestParentAfterLineBreak(PsiElement element) {
|
||||
PsiElement parent = element;
|
||||
while (parent != null) {
|
||||
PsiElement next = parent.getNextSibling();
|
||||
if (isWhiteSpaceWithLineFeed(next)) return parent;
|
||||
while (parent != null && !(parent instanceof PsiFileSystemItem)) {
|
||||
PsiElement prev = parent.getPrevSibling();
|
||||
while (prev != null && prev.getTextLength() <= 0) {
|
||||
prev = prev.getPrevSibling();
|
||||
}
|
||||
if (firstElementInFile(parent)) {
|
||||
return parent.getContainingFile();
|
||||
}
|
||||
else if (isWhiteSpaceWithLineFeed(prev)) {
|
||||
return parent;
|
||||
}
|
||||
parent = parent.getParent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean firstElementInFile(@NotNull PsiElement element) {
|
||||
return element.getTextOffset() == 0;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiElement findClosestParentBeforeLineBreak(PsiElement element) {
|
||||
PsiElement parent = element;
|
||||
while (parent != null && !(parent instanceof PsiFileSystemItem)) {
|
||||
final PsiElement next = parent.getNextSibling();
|
||||
if (lastElementInFile(parent)) {
|
||||
return parent.getContainingFile();
|
||||
}
|
||||
else if (isWhiteSpaceWithLineFeed(next)) {
|
||||
return parent;
|
||||
}
|
||||
parent = parent.getParent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean lastElementInFile(@NotNull PsiElement element) {
|
||||
return element.getTextRange().getEndOffset() == element.getContainingFile().getTextRange().getEndOffset();
|
||||
}
|
||||
|
||||
private static boolean isWhiteSpaceWithLineFeed(@Nullable PsiElement element) {
|
||||
if (element == null) {
|
||||
return false;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 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.
|
||||
@@ -66,8 +66,9 @@ public class FontEditorPreview implements PreviewPanel{
|
||||
|
||||
static void installTrafficLights(@NotNull EditorEx editor) {
|
||||
TrafficLightRenderer renderer = new TrafficLightRenderer(null, null,null){
|
||||
@NotNull
|
||||
@Override
|
||||
protected DaemonCodeAnalyzerStatus getDaemonCodeAnalyzerStatus(boolean fillErrorsCount, SeverityRegistrar severityRegistrar) {
|
||||
protected DaemonCodeAnalyzerStatus getDaemonCodeAnalyzerStatus(@NotNull SeverityRegistrar severityRegistrar) {
|
||||
DaemonCodeAnalyzerStatus status = new DaemonCodeAnalyzerStatus();
|
||||
status.errorAnalyzingFinished = true;
|
||||
status.errorCount = new int[]{1, 2};
|
||||
|
||||
@@ -18,9 +18,12 @@ package com.intellij.codeInsight.daemon.impl;
|
||||
|
||||
import com.intellij.codeHighlighting.HighlightDisplayLevel;
|
||||
import com.intellij.codeHighlighting.TextEditorHighlightingPass;
|
||||
import com.intellij.codeInsight.daemon.DaemonBundle;
|
||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.HighlightingLevelManager;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.FileHighlightingSetting;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.HighlightingSettingsPerFile;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.PowerSaveMode;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.lang.annotation.HighlightSeverity;
|
||||
import com.intellij.openapi.Disposable;
|
||||
@@ -35,14 +38,22 @@ import com.intellij.openapi.editor.impl.EditorMarkupModelImpl;
|
||||
import com.intellij.openapi.editor.impl.event.MarkupModelListener;
|
||||
import com.intellij.openapi.editor.markup.ErrorStripeRenderer;
|
||||
import com.intellij.openapi.editor.markup.RangeHighlighter;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.FileViewProvider;
|
||||
import com.intellij.psi.PsiCompiledElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.ui.LayeredIcon;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.io.storage.HeavyProcessLatch;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.xml.util.XmlStringUtil;
|
||||
import gnu.trove.TIntArrayList;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -50,20 +61,27 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class TrafficLightRenderer implements ErrorStripeRenderer, Disposable {
|
||||
private static final Icon NO_ANALYSIS_ICON = AllIcons.General.NoAnalysis;
|
||||
private static final Icon STARING_EYE_ICON = AllIcons.General.InspectionInProgress;
|
||||
|
||||
private final Project myProject;
|
||||
private final Document myDocument;
|
||||
private final PsiFile myFile;
|
||||
private final DaemonCodeAnalyzerImpl myDaemonCodeAnalyzer;
|
||||
private final SeverityRegistrar mySeverityRegistrar;
|
||||
Icon icon;
|
||||
String statistics;
|
||||
String statusLabel;
|
||||
String statusExtraLine;
|
||||
boolean passStatusesVisible;
|
||||
final Map<ProgressableTextEditorHighlightingPass, Pair<JProgressBar, JLabel>> passes = ContainerUtil.newLinkedHashMap();
|
||||
final Map<JProgressBar, JLabel> myProgressToText = new HashMap<JProgressBar, JLabel>();
|
||||
static final int MAX = 100;
|
||||
boolean progressBarsEnabled;
|
||||
Boolean progressBarsCompleted;
|
||||
|
||||
/**
|
||||
* array filled with number of highlighters with a given severity.
|
||||
@@ -131,8 +149,12 @@ public class TrafficLightRenderer implements ErrorStripeRenderer, Disposable {
|
||||
Disposer.dispose(tlr);
|
||||
}
|
||||
renderer = new TrafficLightRenderer(project, document, file);
|
||||
Disposer.register(((EditorImpl)editorMarkupModel.getEditor()).getDisposable(), (Disposable)renderer);
|
||||
editorMarkupModel.setErrorStripeRenderer(renderer);
|
||||
EditorImpl editor = (EditorImpl)editorMarkupModel.getEditor();
|
||||
|
||||
if (!editor.isDisposed()) {
|
||||
Disposer.register(editor.getDisposable(), (Disposable)renderer);
|
||||
editorMarkupModel.setErrorStripeRenderer(renderer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -153,10 +175,9 @@ public class TrafficLightRenderer implements ErrorStripeRenderer, Disposable {
|
||||
public static class DaemonCodeAnalyzerStatus {
|
||||
public boolean errorAnalyzingFinished; // all passes done
|
||||
public List<ProgressableTextEditorHighlightingPass> passStati = Collections.emptyList();
|
||||
public String[/*rootsNumber*/] noHighlightingRoots;
|
||||
public String[/*rootsNumber*/] noInspectionRoots;
|
||||
public int[] errorCount = ArrayUtil.EMPTY_INT_ARRAY;
|
||||
public boolean enabled = true;
|
||||
public String reasonWhyDisabled;
|
||||
public String reasonWhySuspended;
|
||||
|
||||
public int rootsNumber;
|
||||
@Override
|
||||
@@ -171,30 +192,65 @@ public class TrafficLightRenderer implements ErrorStripeRenderer, Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected DaemonCodeAnalyzerStatus getDaemonCodeAnalyzerStatus(boolean fillErrorsCount, SeverityRegistrar severityRegistrar) {
|
||||
if (myFile == null || myProject != null && myProject.isDisposed() || !myDaemonCodeAnalyzer.isHighlightingAvailable(myFile)) return null;
|
||||
@NotNull
|
||||
protected DaemonCodeAnalyzerStatus getDaemonCodeAnalyzerStatus(@NotNull SeverityRegistrar severityRegistrar) {
|
||||
DaemonCodeAnalyzerStatus status = new DaemonCodeAnalyzerStatus();
|
||||
if (myFile == null) {
|
||||
status.reasonWhyDisabled = "No file";
|
||||
status.errorAnalyzingFinished = true;
|
||||
return status;
|
||||
}
|
||||
if (myProject != null && myProject.isDisposed()) {
|
||||
status.reasonWhyDisabled = "Project is disposed";
|
||||
status.errorAnalyzingFinished = true;
|
||||
return status;
|
||||
}
|
||||
if (!myDaemonCodeAnalyzer.isHighlightingAvailable(myFile)) {
|
||||
if (!myFile.isPhysical()) {
|
||||
status.reasonWhyDisabled = "File is generated";
|
||||
status.errorAnalyzingFinished = true;
|
||||
return status;
|
||||
}
|
||||
else if (myFile instanceof PsiCompiledElement) {
|
||||
status.reasonWhyDisabled = "File is decompiled";
|
||||
status.errorAnalyzingFinished = true;
|
||||
return status;
|
||||
}
|
||||
final FileType fileType = myFile.getFileType();
|
||||
if (fileType.isBinary()) {
|
||||
status.reasonWhyDisabled = "File is binary";
|
||||
status.errorAnalyzingFinished = true;
|
||||
return status;
|
||||
}
|
||||
status.reasonWhyDisabled = "Highlighting is disabled for this file";
|
||||
status.errorAnalyzingFinished = true;
|
||||
return status;
|
||||
}
|
||||
|
||||
List<String> noInspectionRoots = new ArrayList<String>();
|
||||
List<String> noHighlightingRoots = new ArrayList<String>();
|
||||
FileViewProvider provider = myFile.getViewProvider();
|
||||
Set<Language> languages = provider.getLanguages();
|
||||
HighlightingSettingsPerFile levelSettings = HighlightingSettingsPerFile.getInstance(myProject);
|
||||
boolean shouldHighlight = languages.isEmpty();
|
||||
for (Language language : languages) {
|
||||
PsiFile root = provider.getPsi(language);
|
||||
if (!HighlightingLevelManager.getInstance(myProject).shouldHighlight(root)) {
|
||||
noHighlightingRoots.add(language.getID());
|
||||
}
|
||||
else if (!HighlightingLevelManager.getInstance(myProject).shouldInspect(root)) {
|
||||
noInspectionRoots.add(language.getID());
|
||||
}
|
||||
FileHighlightingSetting level = levelSettings.getHighlightingSettingForRoot(root);
|
||||
shouldHighlight |= level != FileHighlightingSetting.SKIP_HIGHLIGHTING;
|
||||
}
|
||||
if (!shouldHighlight) {
|
||||
status.reasonWhyDisabled = "Highlighting level is None";
|
||||
status.errorAnalyzingFinished = true;
|
||||
return status;
|
||||
}
|
||||
|
||||
if (HeavyProcessLatch.INSTANCE.isRunning()) {
|
||||
status.reasonWhySuspended = StringUtil.defaultIfEmpty(HeavyProcessLatch.INSTANCE.getRunningOperationName(), "Heavy operation is running");
|
||||
status.errorAnalyzingFinished = true;
|
||||
return status;
|
||||
}
|
||||
DaemonCodeAnalyzerStatus status = new DaemonCodeAnalyzerStatus();
|
||||
status.noInspectionRoots = noInspectionRoots.isEmpty() ? null : ArrayUtil.toStringArray(noInspectionRoots);
|
||||
status.noHighlightingRoots = noHighlightingRoots.isEmpty() ? null : ArrayUtil.toStringArray(noHighlightingRoots);
|
||||
|
||||
status.errorCount = errorCount.clone();
|
||||
status.rootsNumber = languages.size();
|
||||
fillDaemonCodeAnalyzerErrorsStatus(status, fillErrorsCount, severityRegistrar);
|
||||
fillDaemonCodeAnalyzerErrorsStatus(status, severityRegistrar);
|
||||
List<TextEditorHighlightingPass> passes = myDaemonCodeAnalyzer.getPassesToShowProgressFor(myDocument);
|
||||
status.passStati = passes.isEmpty() ? Collections.<ProgressableTextEditorHighlightingPass>emptyList() :
|
||||
new ArrayList<ProgressableTextEditorHighlightingPass>(passes.size());
|
||||
@@ -208,14 +264,13 @@ public class TrafficLightRenderer implements ErrorStripeRenderer, Disposable {
|
||||
status.passStati.add(pass);
|
||||
}
|
||||
status.errorAnalyzingFinished = myDaemonCodeAnalyzer.isAllAnalysisFinished(myFile);
|
||||
status.enabled = myDaemonCodeAnalyzer.isUpdateByTimerEnabled();
|
||||
status.reasonWhySuspended = myDaemonCodeAnalyzer.isUpdateByTimerEnabled() ? null : "Highlighting is paused temporarily";
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
protected void fillDaemonCodeAnalyzerErrorsStatus(final DaemonCodeAnalyzerStatus status,
|
||||
final boolean fillErrorsCount,
|
||||
final SeverityRegistrar severityRegistrar) {
|
||||
protected void fillDaemonCodeAnalyzerErrorsStatus(@NotNull DaemonCodeAnalyzerStatus status,
|
||||
@NotNull SeverityRegistrar severityRegistrar) {
|
||||
}
|
||||
|
||||
public final Project getProject() {
|
||||
@@ -230,7 +285,7 @@ public class TrafficLightRenderer implements ErrorStripeRenderer, Disposable {
|
||||
|
||||
@Override
|
||||
public void paint(Component c, Graphics g, Rectangle r) {
|
||||
DaemonCodeAnalyzerStatus status = getDaemonCodeAnalyzerStatus(false, mySeverityRegistrar);
|
||||
DaemonCodeAnalyzerStatus status = getDaemonCodeAnalyzerStatus(mySeverityRegistrar);
|
||||
Icon icon = getIcon(status);
|
||||
|
||||
int height = icon.getIconHeight();
|
||||
@@ -240,32 +295,17 @@ public class TrafficLightRenderer implements ErrorStripeRenderer, Disposable {
|
||||
icon.paintIcon(c, g, x, y);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Icon getIcon(DaemonCodeAnalyzerStatus status) {
|
||||
if (status == null || status.noHighlightingRoots != null && status.noHighlightingRoots.length == status.rootsNumber) {
|
||||
return NO_ANALYSIS_ICON;
|
||||
}
|
||||
|
||||
Icon icon = HighlightDisplayLevel.DO_NOT_SHOW.getIcon();
|
||||
for (int i = status.errorCount.length - 1; i >= 0; i--) {
|
||||
if (status.errorCount[i] != 0) {
|
||||
icon = mySeverityRegistrar.getRendererIconByIndex(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (status.errorAnalyzingFinished) {
|
||||
if (myProject != null && DumbService.isDumb(myProject)) {
|
||||
return new LayeredIcon(NO_ANALYSIS_ICON, icon, STARING_EYE_ICON);
|
||||
}
|
||||
|
||||
updatePanel(status, getProject());
|
||||
Icon icon = this.icon;
|
||||
if (PowerSaveMode.isEnabled() || status.reasonWhySuspended != null || status.reasonWhyDisabled != null) {
|
||||
return icon;
|
||||
}
|
||||
if (!status.enabled) return NO_ANALYSIS_ICON;
|
||||
|
||||
double progress = getOverallProgress(status);
|
||||
TruncatingIcon trunc = new TruncatingIcon(icon, icon.getIconWidth(), (int)(icon.getIconHeight() * progress));
|
||||
|
||||
return new LayeredIcon(NO_ANALYSIS_ICON, trunc, STARING_EYE_ICON);
|
||||
return new LayeredIcon(NO_ANALYSIS_ICON, trunc);
|
||||
}
|
||||
|
||||
private static double getOverallProgress(DaemonCodeAnalyzerStatus status) {
|
||||
@@ -277,4 +317,108 @@ public class TrafficLightRenderer implements ErrorStripeRenderer, Disposable {
|
||||
}
|
||||
return limit == 0 ? status.errorAnalyzingFinished ? 1 : 0 : advancement * 1.0 / limit;
|
||||
}
|
||||
|
||||
// return true if panel needs to be rebuilt
|
||||
boolean updatePanel(@NotNull DaemonCodeAnalyzerStatus status, Project project) {
|
||||
progressBarsEnabled = false;
|
||||
progressBarsCompleted = null;
|
||||
statistics = "";
|
||||
passStatusesVisible = (false);
|
||||
statusLabel = null;
|
||||
statusExtraLine = null;
|
||||
|
||||
boolean result = false;
|
||||
if (!status.passStati.equals(new ArrayList<ProgressableTextEditorHighlightingPass>(passes.keySet()))) {
|
||||
// passes set has changed
|
||||
rebuildPassesMap(status);
|
||||
result = true;
|
||||
}
|
||||
|
||||
if (PowerSaveMode.isEnabled()) {
|
||||
statusLabel = "Code analysis is disabled in power save mode";
|
||||
status.errorAnalyzingFinished = true;
|
||||
icon = AllIcons.Nodes.Plugin;
|
||||
return result;
|
||||
}
|
||||
if (status.reasonWhyDisabled != null) {
|
||||
statusLabel = "No analysis has been performed";
|
||||
statusExtraLine = "(" + status.reasonWhyDisabled + ")";
|
||||
passStatusesVisible = (true);
|
||||
progressBarsCompleted = Boolean.FALSE;
|
||||
icon = AllIcons.General.NoAnalysis;
|
||||
return result;
|
||||
}
|
||||
if (status.reasonWhySuspended != null) {
|
||||
statusLabel = "Code analysis has been suspended";
|
||||
statusExtraLine = "(" + status.reasonWhySuspended + ")";
|
||||
passStatusesVisible = (true);
|
||||
progressBarsCompleted = Boolean.FALSE;
|
||||
icon = AllIcons.Actions.Pause;
|
||||
return result;
|
||||
}
|
||||
|
||||
Icon icon = HighlightDisplayLevel.DO_NOT_SHOW.getIcon();
|
||||
for (int i = status.errorCount.length - 1; i >= 0; i--) {
|
||||
if (status.errorCount[i] != 0) {
|
||||
icon = SeverityRegistrar.getSeverityRegistrar(project).getRendererIconByIndex(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (status.errorAnalyzingFinished) {
|
||||
boolean isDumb = DumbService.isDumb(project);
|
||||
if (isDumb) {
|
||||
statusLabel = "Shallow analysis completed";
|
||||
statusExtraLine = "Complete results will be available after indexing";
|
||||
}
|
||||
else {
|
||||
statusLabel = DaemonBundle.message("analysis.completed");
|
||||
}
|
||||
progressBarsCompleted = Boolean.TRUE;
|
||||
}
|
||||
else {
|
||||
statusLabel = DaemonBundle.message("performing.code.analysis");
|
||||
passStatusesVisible = true;
|
||||
progressBarsEnabled = true;
|
||||
progressBarsCompleted = null;
|
||||
}
|
||||
|
||||
int currentSeverityErrors = 0;
|
||||
@org.intellij.lang.annotations.Language("HTML")
|
||||
String text = "";
|
||||
for (int i = status.errorCount.length - 1; i >= 0; i--) {
|
||||
if (status.errorCount[i] > 0) {
|
||||
final HighlightSeverity severity = SeverityRegistrar.getSeverityRegistrar(project).getSeverityByIndex(i);
|
||||
String name =
|
||||
status.errorCount[i] > 1 ? StringUtil.pluralize(severity.getName().toLowerCase()) : severity.getName().toLowerCase();
|
||||
text += status.errorAnalyzingFinished
|
||||
? DaemonBundle.message("errors.found", status.errorCount[i], name)
|
||||
: DaemonBundle.message("errors.found.so.far", status.errorCount[i], name);
|
||||
text += "<br>";
|
||||
currentSeverityErrors += status.errorCount[i];
|
||||
}
|
||||
}
|
||||
if (currentSeverityErrors == 0) {
|
||||
text += status.errorAnalyzingFinished
|
||||
? DaemonBundle.message("no.errors.or.warnings.found")
|
||||
: DaemonBundle.message("no.errors.or.warnings.found.so.far") + "<br>";
|
||||
}
|
||||
statistics = XmlStringUtil.wrapInHtml(text);
|
||||
|
||||
this.icon = icon;
|
||||
return result;
|
||||
}
|
||||
|
||||
private void rebuildPassesMap(@NotNull DaemonCodeAnalyzerStatus status) {
|
||||
passes.clear();
|
||||
for (ProgressableTextEditorHighlightingPass pass : status.passStati) {
|
||||
JProgressBar progressBar = new JProgressBar(0, MAX);
|
||||
progressBar.setMaximum(TrafficLightRenderer.MAX);
|
||||
progressBar.putClientProperty("JComponent.sizeVariant", "mini");
|
||||
JLabel percLabel = new JLabel();
|
||||
percLabel.setText(TrafficProgressPanel.MAX_TEXT);
|
||||
passes.put(pass, Pair.create(progressBar, percLabel));
|
||||
myProgressToText.put(progressBar, percLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,11 +16,8 @@
|
||||
package com.intellij.codeInsight.daemon.impl;
|
||||
|
||||
import com.intellij.codeInsight.daemon.DaemonBundle;
|
||||
import com.intellij.ide.PowerSaveMode;
|
||||
import com.intellij.lang.annotation.HighlightSeverity;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
@@ -32,10 +29,7 @@ import com.intellij.ui.components.panels.NonOpaquePanel;
|
||||
import com.intellij.ui.components.panels.VerticalBox;
|
||||
import com.intellij.ui.components.panels.Wrapper;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.containers.hash.LinkedHashMap;
|
||||
import com.intellij.util.ui.AwtVisitor;
|
||||
import com.intellij.xml.util.XmlStringUtil;
|
||||
import org.intellij.lang.annotations.Language;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -48,16 +42,14 @@ import java.util.Map;
|
||||
* User: cdr
|
||||
*/
|
||||
public class TrafficProgressPanel extends JPanel {
|
||||
private static final int MAX = 100;
|
||||
private static final String MAX_TEXT = "100%";
|
||||
static final String MAX_TEXT = "100%";
|
||||
private static final String MIN_TEXT = "0%";
|
||||
|
||||
private final JLabel statistics = new JLabel();
|
||||
private final Map<ProgressableTextEditorHighlightingPass, Pair<JProgressBar, JLabel>> passes = new LinkedHashMap<ProgressableTextEditorHighlightingPass, Pair<JProgressBar, JLabel>>();
|
||||
private final Map<JProgressBar, JLabel> myProgressToText = new HashMap<JProgressBar, JLabel>();
|
||||
|
||||
private final JLabel statusLabel = new JLabel();
|
||||
private final JLabel dumbLabel = new JLabel("Complete results will be available after indexing");
|
||||
private final JLabel statusExtraLineLabel = new JLabel();
|
||||
@NotNull private final TrafficLightRenderer myTrafficLightRenderer;
|
||||
|
||||
private final JPanel myPassStatuses = new JPanel();
|
||||
@@ -73,10 +65,10 @@ public class TrafficProgressPanel extends JPanel {
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
VerticalBox center = new VerticalBox();
|
||||
add(center, BorderLayout.NORTH);
|
||||
|
||||
add(center, BorderLayout.NORTH);
|
||||
center.add(statusLabel);
|
||||
center.add(dumbLabel);
|
||||
center.add(statusExtraLineLabel);
|
||||
center.add(new Separator());
|
||||
center.add(Box.createVerticalStrut(6));
|
||||
|
||||
@@ -98,19 +90,46 @@ public class TrafficProgressPanel extends JPanel {
|
||||
}
|
||||
});
|
||||
}
|
||||
rebuildPassesPanel(fakeStatusLargeEnough);
|
||||
for (Pair<JProgressBar, JLabel> pair : passes.values()) {
|
||||
JProgressBar bar = pair.first;
|
||||
bar.setMaximum(MAX);
|
||||
JLabel label = pair.second;
|
||||
label.setText(MAX_TEXT);
|
||||
}
|
||||
center.add(myPassStatusesContainer);
|
||||
|
||||
add(statistics, BorderLayout.SOUTH);
|
||||
updatePanel(fakeStatusLargeEnough, true);
|
||||
|
||||
hintHint.initStyle(this, true);
|
||||
statusLabel.setFont(statusLabel.getFont().deriveFont(Font.BOLD));
|
||||
}
|
||||
|
||||
public int getMinWidth() {
|
||||
return Math.max(Math.max(Math.max(getLabelMinWidth(statistics), getLabelMinWidth(statusExtraLineLabel)), getLabelMinWidth(statusLabel)), getLabelMinWidth(new JLabel("<html><b>Slow inspections progress report long line</b></html>")));
|
||||
}
|
||||
|
||||
private int getLabelMinWidth(@NotNull JLabel label) {
|
||||
String text = label.getText();
|
||||
Icon icon = label.isEnabled() ? label.getIcon() : label.getDisabledIcon();
|
||||
|
||||
if ((icon == null) && (StringUtil.isEmpty(text))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Rectangle paintIconR = new Rectangle();
|
||||
Rectangle paintTextR = new Rectangle();
|
||||
Rectangle paintViewR = new Rectangle(10000, 10000);
|
||||
|
||||
SwingUtilities.layoutCompoundLabel(
|
||||
label,
|
||||
getFontMetrics(getFont()),
|
||||
text,
|
||||
icon,
|
||||
label.getVerticalAlignment(),
|
||||
label.getHorizontalAlignment(),
|
||||
label.getVerticalTextPosition(),
|
||||
label.getHorizontalTextPosition(),
|
||||
paintViewR,
|
||||
paintIconR,
|
||||
paintTextR,
|
||||
label.getIconTextGap());
|
||||
|
||||
return paintTextR.width;
|
||||
}
|
||||
|
||||
private class Separator extends NonOpaquePanel {
|
||||
@@ -137,115 +156,34 @@ public class TrafficProgressPanel extends JPanel {
|
||||
}
|
||||
}
|
||||
|
||||
private void rebuildPassesPanel(@Nullable TrafficLightRenderer.DaemonCodeAnalyzerStatus status) {
|
||||
myPassStatuses.removeAll();
|
||||
myPassStatuses.setLayout(new GridBagLayout());
|
||||
passes.clear();
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
c.gridy = 0;
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
if (status != null) {
|
||||
for (ProgressableTextEditorHighlightingPass pass : status.passStati) {
|
||||
JLabel label = new JLabel(pass.getPresentableName() + ": ");
|
||||
label.setHorizontalTextPosition(SwingConstants.RIGHT);
|
||||
|
||||
JProgressBar progressBar = new JProgressBar(0, MAX);
|
||||
progressBar.putClientProperty("JComponent.sizeVariant", "mini");
|
||||
JLabel percLabel = new JLabel();
|
||||
passes.put(pass, Pair.create(progressBar, percLabel));
|
||||
myProgressToText.put(progressBar, percLabel);
|
||||
c.gridx = 0;
|
||||
myPassStatuses.add(label, c);
|
||||
c.gridx = 1;
|
||||
myPassStatuses.add(progressBar, c);
|
||||
c.gridx = 2;
|
||||
c.weightx = 1;
|
||||
myPassStatuses.add(percLabel, c);
|
||||
|
||||
c.gridy++;
|
||||
}
|
||||
}
|
||||
|
||||
myHintHint.initStyle(myPassStatuses, true);
|
||||
statusLabel.setFont(statusLabel.getFont().deriveFont(Font.BOLD));
|
||||
}
|
||||
|
||||
public void updatePanel(@Nullable TrafficLightRenderer.DaemonCodeAnalyzerStatus status, boolean isFake) {
|
||||
boolean isDumb = DumbService.isDumb(myTrafficLightRenderer.getProject());
|
||||
dumbLabel.setVisible(isDumb);
|
||||
public void updatePanel(@NotNull TrafficLightRenderer.DaemonCodeAnalyzerStatus status, boolean isFake) {
|
||||
try {
|
||||
if (PowerSaveMode.isEnabled()) {
|
||||
statusLabel.setText("Code analysis is disabled in power save mode");
|
||||
myPassStatuses.setVisible(false);
|
||||
statistics.setText("");
|
||||
}
|
||||
else if (status == null || status.noHighlightingRoots != null && status.noHighlightingRoots.length == status.rootsNumber) {
|
||||
statusLabel.setText(DaemonBundle.message("analysis.hasnot.been.run"));
|
||||
myPassStatuses.setVisible(true);
|
||||
setPassesEnabled(false, Boolean.FALSE);
|
||||
statistics.setText("");
|
||||
}
|
||||
else if (status.errorAnalyzingFinished) {
|
||||
if (isDumb) {
|
||||
statusLabel.setText("Shallow analysis completed");
|
||||
}
|
||||
else {
|
||||
statusLabel.setText(DaemonBundle.message("analysis.completed"));
|
||||
}
|
||||
myPassStatuses.setVisible(true);
|
||||
setPassesEnabled(false, Boolean.TRUE);
|
||||
}
|
||||
else if (!status.enabled) {
|
||||
statusLabel.setText("Code analysis has been suspended");
|
||||
myPassStatuses.setVisible(true);
|
||||
setPassesEnabled(false, Boolean.FALSE);
|
||||
statistics.setText("");
|
||||
boolean needRebuild = myTrafficLightRenderer.updatePanel(status, myTrafficLightRenderer.getProject());
|
||||
statusLabel.setText(myTrafficLightRenderer.statusLabel);
|
||||
if (myTrafficLightRenderer.statusExtraLine == null) {
|
||||
statusExtraLineLabel.setVisible(false);
|
||||
}
|
||||
else {
|
||||
statusLabel.setText(DaemonBundle.message("performing.code.analysis"));
|
||||
myPassStatuses.setVisible(true);
|
||||
setPassesEnabled(true, null);
|
||||
statusExtraLineLabel.setText(myTrafficLightRenderer.statusExtraLine);
|
||||
statusExtraLineLabel.setVisible(true);
|
||||
}
|
||||
myPassStatuses.setVisible(myTrafficLightRenderer.passStatusesVisible);
|
||||
statistics.setText(myTrafficLightRenderer.statistics);
|
||||
resetProgressBars(myTrafficLightRenderer.progressBarsEnabled, myTrafficLightRenderer.progressBarsCompleted);
|
||||
|
||||
|
||||
if (status == null ||
|
||||
!status.passStati.equals(new ArrayList<ProgressableTextEditorHighlightingPass>(passes.keySet()))) {
|
||||
if (needRebuild) {
|
||||
// passes set has changed
|
||||
rebuildPassesPanel(status);
|
||||
rebuildPassesProgress(status);
|
||||
}
|
||||
|
||||
if (status != null) {
|
||||
for (ProgressableTextEditorHighlightingPass pass : status.passStati) {
|
||||
double progress = pass.getProgress();
|
||||
Pair<JProgressBar, JLabel> pair = passes.get(pass);
|
||||
JProgressBar progressBar = pair.first;
|
||||
int percent = (int)Math.round(progress * MAX);
|
||||
progressBar.setValue(percent);
|
||||
JLabel percentage = pair.second;
|
||||
percentage.setText(percent + "%");
|
||||
}
|
||||
|
||||
int currentSeverityErrors = 0;
|
||||
@Language("HTML")
|
||||
String text = "";
|
||||
for (int i = status.errorCount.length - 1; i >= 0; i--) {
|
||||
if (status.errorCount[i] > 0) {
|
||||
final HighlightSeverity severity = SeverityRegistrar.getSeverityRegistrar(myTrafficLightRenderer.getProject()).getSeverityByIndex(i);
|
||||
String name =
|
||||
status.errorCount[i] > 1 ? StringUtil.pluralize(severity.getName().toLowerCase()) : severity.getName().toLowerCase();
|
||||
text += status.errorAnalyzingFinished
|
||||
? DaemonBundle.message("errors.found", status.errorCount[i], name)
|
||||
: DaemonBundle.message("errors.found.so.far", status.errorCount[i], name);
|
||||
text += "<br>";
|
||||
currentSeverityErrors += status.errorCount[i];
|
||||
}
|
||||
}
|
||||
if (currentSeverityErrors == 0) {
|
||||
text += status.errorAnalyzingFinished
|
||||
? DaemonBundle.message("no.errors.or.warnings.found")
|
||||
: DaemonBundle.message("no.errors.or.warnings.found.so.far") + "<br>";
|
||||
}
|
||||
statistics.setText(XmlStringUtil.wrapInHtml(text));
|
||||
for (ProgressableTextEditorHighlightingPass pass : status.passStati) {
|
||||
double progress = pass.getProgress();
|
||||
Pair<JProgressBar, JLabel> pair = myTrafficLightRenderer.passes.get(pass);
|
||||
JProgressBar progressBar = pair.first;
|
||||
int percent = (int)Math.round(progress * TrafficLightRenderer.MAX);
|
||||
progressBar.setValue(percent);
|
||||
JLabel percentage = pair.second;
|
||||
percentage.setText(percent + "%");
|
||||
}
|
||||
}
|
||||
finally {
|
||||
@@ -259,7 +197,7 @@ public class TrafficProgressPanel extends JPanel {
|
||||
}
|
||||
}
|
||||
|
||||
private void setPassesEnabled(final boolean enabled, @Nullable final Boolean completed) {
|
||||
private void resetProgressBars(final boolean enabled, @Nullable final Boolean completed) {
|
||||
new AwtVisitor(myPassStatuses) {
|
||||
@Override
|
||||
public boolean visit(Component component) {
|
||||
@@ -268,7 +206,7 @@ public class TrafficProgressPanel extends JPanel {
|
||||
progress.setEnabled(enabled);
|
||||
if (completed != null) {
|
||||
if (completed) {
|
||||
progress.setValue(MAX);
|
||||
progress.setValue(TrafficLightRenderer.MAX);
|
||||
myProgressToText.get(progress).setText(MAX_TEXT);
|
||||
}
|
||||
else {
|
||||
@@ -281,4 +219,33 @@ public class TrafficProgressPanel extends JPanel {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void rebuildPassesProgress(@NotNull TrafficLightRenderer.DaemonCodeAnalyzerStatus status) {
|
||||
myPassStatuses.removeAll();
|
||||
myPassStatuses.setLayout(new GridBagLayout());
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
c.gridy = 0;
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
for (ProgressableTextEditorHighlightingPass pass : status.passStati) {
|
||||
JLabel label = new JLabel(pass.getPresentableName() + ": ");
|
||||
label.setHorizontalTextPosition(SwingConstants.RIGHT);
|
||||
|
||||
Pair<JProgressBar, JLabel> pair = myTrafficLightRenderer.passes.get(pass);
|
||||
JProgressBar progressBar = pair.getFirst();
|
||||
progressBar.putClientProperty("JComponent.sizeVariant", "mini");
|
||||
JLabel percLabel = pair.getSecond();
|
||||
myProgressToText.put(progressBar, percLabel);
|
||||
c.gridx = 0;
|
||||
myPassStatuses.add(label, c);
|
||||
c.gridx = 1;
|
||||
myPassStatuses.add(progressBar, c);
|
||||
c.gridx = 2;
|
||||
c.weightx = 1;
|
||||
myPassStatuses.add(percLabel, c);
|
||||
|
||||
c.gridy++;
|
||||
}
|
||||
|
||||
myHintHint.initStyle(myPassStatuses, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2010 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 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.
|
||||
@@ -48,7 +48,7 @@ public class TrafficTooltipRendererImpl extends ComparableObject.Impl implements
|
||||
public void repaintTooltipWindow() {
|
||||
if (myPanel != null) {
|
||||
SeverityRegistrar severityRegistrar = SeverityRegistrar.getSeverityRegistrar(myTrafficLightRenderer.getProject());
|
||||
TrafficLightRenderer.DaemonCodeAnalyzerStatus status = myTrafficLightRenderer.getDaemonCodeAnalyzerStatus(true, severityRegistrar);
|
||||
TrafficLightRenderer.DaemonCodeAnalyzerStatus status = myTrafficLightRenderer.getDaemonCodeAnalyzerStatus(severityRegistrar);
|
||||
myPanel.updatePanel(status, false);
|
||||
}
|
||||
}
|
||||
@@ -57,7 +57,8 @@ public class TrafficTooltipRendererImpl extends ComparableObject.Impl implements
|
||||
public LightweightHint show(@NotNull Editor editor, @NotNull Point p, boolean alignToRight, @NotNull TooltipGroup group, @NotNull HintHint hintHint) {
|
||||
myTrafficLightRenderer = (TrafficLightRenderer)((EditorMarkupModelImpl)editor.getMarkupModel()).getErrorStripeRenderer();
|
||||
myPanel = new TrafficProgressPanel(myTrafficLightRenderer, editor, hintHint);
|
||||
LineTooltipRenderer.correctLocation(editor, myPanel, p, alignToRight, false, -1);
|
||||
repaintTooltipWindow();
|
||||
LineTooltipRenderer.correctLocation(editor, myPanel, p, alignToRight, true, myPanel.getMinWidth());
|
||||
LightweightHint hint = new LightweightHint(myPanel);
|
||||
|
||||
HintManagerImpl hintManager = (HintManagerImpl)HintManager.getInstance();
|
||||
@@ -72,7 +73,6 @@ public class TrafficTooltipRendererImpl extends ComparableObject.Impl implements
|
||||
onHide.run();
|
||||
}
|
||||
});
|
||||
repaintTooltipWindow();
|
||||
return hint;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.vcs.FileStatusManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.ui.IdeBorderFactory;
|
||||
import com.intellij.ui.ListCellRendererWrapper;
|
||||
@@ -329,12 +330,26 @@ public class ImplementationViewComponent extends JPanel {
|
||||
if (element instanceof PsiNamedElement) {
|
||||
names.add(((PsiNamedElement)element).getName());
|
||||
}
|
||||
if (names.size() > 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (PsiElement element : elements) {
|
||||
PsiFile file = getContainingFile(element);
|
||||
if (file == null) continue;
|
||||
final PsiElement parent = element.getParent();
|
||||
files.add(new FileDescriptor(file, names.size() > 1 || parent == file ? element : parent));
|
||||
if (names.size() > 1) {
|
||||
files.add(new FileDescriptor(file, element));
|
||||
}
|
||||
else {
|
||||
final PsiElement parent = PsiTreeUtil.getStubOrPsiParent(element);
|
||||
if (parent == file) {
|
||||
files.add(new FileDescriptor(file, element));
|
||||
}
|
||||
else {
|
||||
files.add(new FileDescriptor(file, parent));
|
||||
}
|
||||
}
|
||||
candidates.add(element);
|
||||
}
|
||||
|
||||
|
||||
@@ -59,18 +59,19 @@ public class LookupTypedHandler extends TypedActionHandlerBase {
|
||||
@Override
|
||||
public void execute(@NotNull Editor originalEditor, char charTyped, @NotNull DataContext dataContext) {
|
||||
final Project project = CommonDataKeys.PROJECT.getData(dataContext);
|
||||
PsiFile file;
|
||||
PsiFile file = project == null ? null : PsiUtilBase.getPsiFileInEditor(originalEditor, project);
|
||||
|
||||
if (project == null
|
||||
|| (file = PsiUtilBase.getPsiFileInEditor(originalEditor, project)) == null
|
||||
|| !CodeInsightUtilBase.prepareEditorForWrite(originalEditor)
|
||||
|| !FileDocumentManager.getInstance().requestWriting(originalEditor.getDocument(), project)) {
|
||||
if (file == null) {
|
||||
if (myOriginalHandler != null){
|
||||
myOriginalHandler.execute(originalEditor, charTyped, dataContext);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CodeInsightUtilBase.prepareEditorForWrite(originalEditor) || !FileDocumentManager.getInstance().requestWriting(originalEditor.getDocument(), project)) {
|
||||
return;
|
||||
}
|
||||
|
||||
CompletionPhase oldPhase = CompletionServiceImpl.getCompletionPhase();
|
||||
if (oldPhase instanceof CompletionPhase.CommittingDocuments && ((CompletionPhase.CommittingDocuments)oldPhase).isRestartingCompletion()) {
|
||||
assert oldPhase.indicator != null;
|
||||
|
||||
@@ -16,8 +16,9 @@
|
||||
package com.intellij.formatting;
|
||||
|
||||
import com.intellij.diagnostic.LogMessageEx;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -50,10 +51,16 @@ public abstract class AbstractBlockAlignmentProcessor implements BlockAlignmentP
|
||||
}
|
||||
|
||||
if (diff > 0) {
|
||||
whiteSpace.setSpaces(whiteSpace.getSpaces() + diff, whiteSpace.getIndentSpaces());
|
||||
int alignmentSpaces = whiteSpace.getSpaces() + diff;
|
||||
if (alignmentSpaces > context.maxAlignmentSpaces) {
|
||||
whiteSpace.setSpaces(1, whiteSpace.getIndentSpaces());
|
||||
reportAlignmentProcessingError(context);
|
||||
return Result.RECURSION_DETECTED;
|
||||
}
|
||||
whiteSpace.setSpaces(alignmentSpaces, whiteSpace.getIndentSpaces());
|
||||
|
||||
// Avoid tabulations usage for aligning blocks that are not the first blocks on a line.
|
||||
if (!whiteSpace.containsLineFeeds()) {
|
||||
// Avoid tabulations usage for aligning blocks that are not the first blocks on a line.
|
||||
whiteSpace.setForceSkipTabulationsUsage(true);
|
||||
}
|
||||
return Result.TARGET_BLOCK_ALIGNED;
|
||||
@@ -127,4 +134,12 @@ public abstract class AbstractBlockAlignmentProcessor implements BlockAlignmentP
|
||||
* @return alignment anchor indent minus current target block indent
|
||||
*/
|
||||
protected abstract int getAlignmentIndentDiff(@NotNull IndentData alignmentAnchorIndent, @NotNull Context context);
|
||||
|
||||
private static void reportAlignmentProcessingError(Context context) {
|
||||
ASTNode node = context.targetBlock.getNode();
|
||||
Language language = node != null ? node.getPsi().getLanguage() : null;
|
||||
LogMessageEx.error(LOG,
|
||||
(language != null ? language.getDisplayName() + ": " : "") +
|
||||
"Can't align block " + context.targetBlock, context.document.getText());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,13 +71,15 @@ public interface BlockAlignmentProcessor {
|
||||
@NotNull public final Map<AbstractBlockWrapper, Set<AbstractBlockWrapper>> alignmentMappings;
|
||||
@NotNull public final Map<LeafBlockWrapper, Set<LeafBlockWrapper>> backwardShiftedAlignedBlocks;
|
||||
@NotNull public final CommonCodeStyleSettings.IndentOptions indentOptions;
|
||||
public int maxAlignmentSpaces;
|
||||
|
||||
public Context(@NotNull Document document,
|
||||
@NotNull AlignmentImpl alignment,
|
||||
@NotNull LeafBlockWrapper targetBlock,
|
||||
@NotNull Map<AbstractBlockWrapper, Set<AbstractBlockWrapper>> alignmentMappings,
|
||||
@NotNull Map<LeafBlockWrapper, Set<LeafBlockWrapper>> backwardShiftedAlignedBlocks,
|
||||
@NotNull CommonCodeStyleSettings.IndentOptions indentOptions)
|
||||
@NotNull CommonCodeStyleSettings.IndentOptions indentOptions,
|
||||
int maxAlignmentSpaces)
|
||||
{
|
||||
this.document = document;
|
||||
this.alignment = alignment;
|
||||
@@ -85,6 +87,7 @@ public interface BlockAlignmentProcessor {
|
||||
this.alignmentMappings = alignmentMappings;
|
||||
this.backwardShiftedAlignedBlocks = backwardShiftedAlignedBlocks;
|
||||
this.indentOptions = indentOptions;
|
||||
this.maxAlignmentSpaces = maxAlignmentSpaces;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -683,7 +683,7 @@ class FormatProcessor {
|
||||
|
||||
BlockAlignmentProcessor.Context context = new BlockAlignmentProcessor.Context(
|
||||
myDocument, alignment, myCurrentBlock, myAlignmentMappings, myBackwardShiftedAlignedBlocks,
|
||||
getIndentOptionsToUse(myCurrentBlock, myDefaultIndentOption)
|
||||
getIndentOptionsToUse(myCurrentBlock, myDefaultIndentOption), myRightMargin
|
||||
);
|
||||
BlockAlignmentProcessor.Result result = alignmentProcessor.applyAlignment(context);
|
||||
final LeafBlockWrapper offsetResponsibleBlock = alignment.getOffsetRespBlockBefore(myCurrentBlock);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 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.
|
||||
@@ -24,17 +24,18 @@ import com.intellij.openapi.vfs.VFileProperty;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiFileSystemItem;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class GoToLinkTargetAction extends DumbAwareAction {
|
||||
@Override
|
||||
public void update(AnActionEvent e) {
|
||||
public void update(@NotNull AnActionEvent e) {
|
||||
Project project = getEventProject(e);
|
||||
VirtualFile file = CommonDataKeys.VIRTUAL_FILE.getData(e.getDataContext());
|
||||
e.getPresentation().setEnabledAndVisible(project != null && file != null && file.is(VFileProperty.SYMLINK));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
Project project = getEventProject(e);
|
||||
VirtualFile file = CommonDataKeys.VIRTUAL_FILE.getData(e.getDataContext());
|
||||
if (project != null && file != null && file.is(VFileProperty.SYMLINK)) {
|
||||
|
||||
@@ -443,7 +443,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
private ActionCallback onFocusLost() {
|
||||
final ActionCallback result = new ActionCallback();
|
||||
//noinspection SSBasedInspection
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
UIUtil.invokeLaterIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
package com.intellij.ide.hierarchy;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.actions.ToggleToolbarAction;
|
||||
import com.intellij.ide.impl.ContentManagerWatcher;
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup;
|
||||
import com.intellij.openapi.components.*;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.SimpleToolWindowPanel;
|
||||
import com.intellij.openapi.wm.ToolWindow;
|
||||
import com.intellij.openapi.wm.ToolWindowAnchor;
|
||||
import com.intellij.openapi.wm.ToolWindowId;
|
||||
@@ -52,7 +52,7 @@ public final class HierarchyBrowserManager implements PersistentStateComponent<H
|
||||
ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(project);
|
||||
ToolWindow toolWindow = toolWindowManager.registerToolWindow(ToolWindowId.HIERARCHY, true, ToolWindowAnchor.RIGHT, project);
|
||||
DefaultActionGroup gearActions = new DefaultActionGroup();
|
||||
gearActions.addAction(SimpleToolWindowPanel.createToggleToolbarAction(project, toolWindow)).setAsSecondary(true);
|
||||
gearActions.addAction(ToggleToolbarAction.createToggleToolbarGroup(project, toolWindow)).setAsSecondary(true);
|
||||
((ToolWindowEx)toolWindow).setAdditionalGearActions(gearActions);
|
||||
|
||||
myContentManager = toolWindow.getContentManager();
|
||||
|
||||
@@ -16,8 +16,10 @@
|
||||
|
||||
package com.intellij.ide.impl;
|
||||
|
||||
import com.intellij.ide.CommonActionsManager;
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.ide.IdeBundle;
|
||||
import com.intellij.ide.actions.ToggleToolbarAction;
|
||||
import com.intellij.ide.projectView.impl.ProjectRootsUtil;
|
||||
import com.intellij.ide.structureView.*;
|
||||
import com.intellij.ide.structureView.impl.StructureViewComposite;
|
||||
@@ -36,7 +38,6 @@ import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleUtil;
|
||||
import com.intellij.openapi.module.ModuleUtilCore;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.SimpleToolWindowPanel;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
@@ -92,7 +93,7 @@ public class StructureViewWrapperImpl implements StructureViewWrapper, Disposabl
|
||||
public StructureViewWrapperImpl(Project project, ToolWindowEx toolWindow) {
|
||||
myProject = project;
|
||||
myToolWindow = toolWindow;
|
||||
myShowToolbarAction = SimpleToolWindowPanel.createToggleToolbarAction(project, myToolWindow);
|
||||
myShowToolbarAction = ToggleToolbarAction.createToggleToolbarGroup(project, myToolWindow);
|
||||
|
||||
myUpdateQueue = new MergingUpdateQueue("StructureView", Registry.intValue("structureView.coalesceTime"), false, myToolWindow.getComponent(), this, myToolWindow.getComponent(), true);
|
||||
myUpdateQueue.setRestartTimerOnAdd(true);
|
||||
@@ -368,12 +369,14 @@ public class StructureViewWrapperImpl implements StructureViewWrapper, Disposabl
|
||||
}
|
||||
|
||||
private void updateHeaderActions(StructureView structureView) {
|
||||
DefaultActionGroup gearActions = new DefaultActionGroup();
|
||||
AnAction[] titleActions = AnAction.EMPTY_ARRAY;
|
||||
if (structureView instanceof StructureViewComponent) {
|
||||
gearActions.addAll(((StructureViewComponent)structureView).getGearActions());
|
||||
titleActions = ((StructureViewComponent)structureView).getTitleActions();
|
||||
JTree tree = ((StructureViewComponent)structureView).getTree();
|
||||
titleActions = new AnAction[]{
|
||||
CommonActionsManager.getInstance().createExpandAllHeaderAction(tree),
|
||||
CommonActionsManager.getInstance().createCollapseAllHeaderAction(tree)};
|
||||
}
|
||||
DefaultActionGroup gearActions = new DefaultActionGroup();
|
||||
gearActions.addAction(myShowToolbarAction).setAsSecondary(true);
|
||||
myToolWindow.setAdditionalGearActions(gearActions);
|
||||
myToolWindow.setTitleActions(titleActions);
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.intellij.ide.structureView.newStructureView;
|
||||
|
||||
import com.intellij.ide.CommonActionsManager;
|
||||
import com.intellij.ide.CopyPasteDelegator;
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.ide.PsiCopyPasteManager;
|
||||
@@ -387,26 +386,11 @@ public class StructureViewComponent extends SimpleToolWindowPanel implements Tre
|
||||
}
|
||||
}
|
||||
|
||||
public ActionGroup getGearActions() {
|
||||
return createActionGroup(true);
|
||||
}
|
||||
|
||||
private StructureViewFactoryImpl.State getSettings() {
|
||||
return ((StructureViewFactoryImpl)StructureViewFactory.getInstance(myProject)).getState();
|
||||
}
|
||||
|
||||
public AnAction[] getTitleActions() {
|
||||
return new AnAction[]{
|
||||
CommonActionsManager.getInstance().createExpandAllHeaderAction(getTree()),
|
||||
CommonActionsManager.getInstance().createCollapseAllHeaderAction(getTree()),
|
||||
};
|
||||
}
|
||||
|
||||
protected ActionGroup createActionGroup() {
|
||||
return createActionGroup(false);
|
||||
}
|
||||
|
||||
protected DefaultActionGroup createActionGroup(boolean togglesOnly) {
|
||||
DefaultActionGroup result = new DefaultActionGroup();
|
||||
Sorter[] sorters = myTreeModel.getSorters();
|
||||
for (final Sorter sorter : sorters) {
|
||||
@@ -431,10 +415,8 @@ public class StructureViewComponent extends SimpleToolWindowPanel implements Tre
|
||||
}
|
||||
}
|
||||
|
||||
if (!togglesOnly) {
|
||||
result.add(new ExpandAllAction(getTree()));
|
||||
result.add(new CollapseAllAction(getTree()));
|
||||
}
|
||||
result.add(new ExpandAllAction(getTree()));
|
||||
result.add(new CollapseAllAction(getTree()));
|
||||
|
||||
if (showScrollToFromSourceActions()) {
|
||||
result.addSeparator();
|
||||
|
||||
@@ -1192,6 +1192,10 @@ public abstract class ChooseByNameBase {
|
||||
myPostponedOkAction = null;
|
||||
}
|
||||
|
||||
public boolean hasPostponedAction() {
|
||||
return myPostponedOkAction != null;
|
||||
}
|
||||
|
||||
protected abstract void showList();
|
||||
|
||||
protected abstract void hideList();
|
||||
|
||||
@@ -122,6 +122,7 @@ public class GeneralColorsPage implements ColorSettingsPage, InspectionColorSett
|
||||
new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.modified.lines"), EditorColors.MODIFIED_LINES_COLOR, ColorDescriptor.Kind.BACKGROUND),
|
||||
new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.deleted.lines"), EditorColors.DELETED_LINES_COLOR, ColorDescriptor.Kind.BACKGROUND),
|
||||
new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.whitespaces.modified.lines"), EditorColors.WHITESPACES_MODIFIED_LINES_COLOR, ColorDescriptor.Kind.BACKGROUND),
|
||||
new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.border.lines"), EditorColors.BORDER_LINES_COLOR, ColorDescriptor.Kind.BACKGROUND),
|
||||
new ColorDescriptor(OptionsBundle.message("options.java.color.descriptor.method.separator.color"), CodeInsightColors.METHOD_SEPARATORS_COLOR, ColorDescriptor.Kind.FOREGROUND),
|
||||
new ColorDescriptor(OptionsBundle.message("options.general.color.soft.wrap.sign"), EditorColors.SOFT_WRAP_SIGN_COLOR, ColorDescriptor.Kind.FOREGROUND),
|
||||
};
|
||||
|
||||
@@ -52,7 +52,7 @@ public class PersistableCodeStyleSchemes extends CodeStyleSchemesImpl implements
|
||||
public Element getState() {
|
||||
return XmlSerializer.serialize(this, new SerializationFilter() {
|
||||
@Override
|
||||
public boolean accepts(Accessor accessor, Object bean) {
|
||||
public boolean accepts(@NotNull Accessor accessor, Object bean) {
|
||||
return accessor.getValueClass().equals(String.class);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
package com.intellij.usageView.impl;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.actions.ToggleToolbarAction;
|
||||
import com.intellij.ide.impl.ContentManagerWatcher;
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.SimpleToolWindowPanel;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.wm.ToolWindow;
|
||||
import com.intellij.openapi.wm.ToolWindowAnchor;
|
||||
@@ -45,7 +45,7 @@ public class UsageViewManagerImpl extends UsageViewManager {
|
||||
toolWindow.setToHideOnEmptyContent(true);
|
||||
toolWindow.setIcon(AllIcons.Toolwindows.ToolWindowFind);
|
||||
DefaultActionGroup gearActions = new DefaultActionGroup();
|
||||
gearActions.addAction(SimpleToolWindowPanel.createToggleToolbarAction(project, toolWindow)).setAsSecondary(true);
|
||||
gearActions.addAction(ToggleToolbarAction.createToggleToolbarGroup(project, toolWindow)).setAsSecondary(true);
|
||||
((ToolWindowEx)toolWindow).setAdditionalGearActions(gearActions);
|
||||
|
||||
myFindContentManager = toolWindow.getContentManager();
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.intellij.history.core.changes;
|
||||
import com.intellij.history.core.Content;
|
||||
import com.intellij.history.core.StreamUtil;
|
||||
import com.intellij.history.utils.LocalHistoryLog;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.util.Producer;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
@@ -60,15 +61,27 @@ public class ChangeSet {
|
||||
isLocked = true;
|
||||
}
|
||||
|
||||
public void write(DataOutput out) throws IOException {
|
||||
public void write(final DataOutput out) throws IOException {
|
||||
out.writeLong(myId);
|
||||
StreamUtil.writeStringOrNull(out, myName);
|
||||
out.writeLong(myTimestamp);
|
||||
|
||||
out.writeInt(myChanges.size());
|
||||
for (Change c : myChanges) {
|
||||
StreamUtil.writeChange(out, c);
|
||||
}
|
||||
final Ref<IOException> ref = new Ref<IOException>();
|
||||
accessChanges(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
out.writeInt(myChanges.size());
|
||||
for (Change c : myChanges) {
|
||||
StreamUtil.writeChange(out, c);
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
ref.set(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (ref.get() != null) throw ref.get();
|
||||
}
|
||||
|
||||
public void setName(@Nullable String name) {
|
||||
|
||||
@@ -38,6 +38,7 @@ public abstract class ActionPlaces {
|
||||
public static final String COMMANDER_POPUP = "CommanderPopup";
|
||||
public static final String COMMANDER_TOOLBAR = "CommanderToolbar";
|
||||
public static final String CONTEXT_TOOLBAR = "ContextToolbar";
|
||||
public static final String TOOLWINDOW_TITLE = "ToolwindowTitle";
|
||||
|
||||
public static final String PROJECT_VIEW_POPUP = "ProjectViewPopup";
|
||||
public static final String PROJECT_VIEW_TOOLBAR = "ProjectViewToolbar";
|
||||
|
||||
@@ -15,23 +15,14 @@
|
||||
*/
|
||||
package com.intellij.openapi.ui;
|
||||
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Conditions;
|
||||
import com.intellij.openapi.actionSystem.ActionToolbar;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.DataProvider;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.wm.ToolWindow;
|
||||
import com.intellij.ui.content.Content;
|
||||
import com.intellij.ui.content.ContentManager;
|
||||
import com.intellij.ui.content.ContentManagerAdapter;
|
||||
import com.intellij.ui.content.ContentManagerEvent;
|
||||
import com.intellij.ui.switcher.QuickActionProvider;
|
||||
import com.intellij.util.ui.AwtVisitor;
|
||||
import com.intellij.util.ui.JBSwingUtilities;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -172,61 +163,4 @@ public class SimpleToolWindowPanel extends JPanel implements QuickActionProvider
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static AnAction createToggleToolbarAction(Project project, @NotNull ToolWindow toolWindow) {
|
||||
return new ToggleToolbarAction(toolWindow, PropertiesComponent.getInstance(project));
|
||||
}
|
||||
|
||||
private static class ToggleToolbarAction extends ToggleAction implements DumbAware {
|
||||
|
||||
private final PropertiesComponent myPropertiesComponent;
|
||||
private final ToolWindow myToolWindow;
|
||||
|
||||
private ToggleToolbarAction(@NotNull ToolWindow toolWindow, @NotNull PropertiesComponent propertiesComponent) {
|
||||
super("Show Toolbar");
|
||||
myPropertiesComponent = propertiesComponent;
|
||||
myToolWindow = toolWindow;
|
||||
myToolWindow.getContentManager().addContentManagerListener(new ContentManagerAdapter() {
|
||||
@Override
|
||||
public void contentAdded(ContentManagerEvent event) {
|
||||
JComponent component = event.getContent().getComponent();
|
||||
setContentToolbarVisible(component, getVisibilityValue());
|
||||
|
||||
// support nested content managers, e.g. RunnerLayoutUi as content component
|
||||
ContentManager contentManager =
|
||||
component instanceof DataProvider ? PlatformDataKeys.CONTENT_MANAGER.getData((DataProvider)component) : null;
|
||||
if (contentManager != null) contentManager.addContentManagerListener(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSelected(AnActionEvent e) {
|
||||
return getVisibilityValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(AnActionEvent e, boolean state) {
|
||||
myPropertiesComponent.setValue(getProperty(), String.valueOf(state), String.valueOf(true));
|
||||
for (Content content : myToolWindow.getContentManager().getContents()) {
|
||||
setContentToolbarVisible(content.getComponent(), state);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String getProperty() {
|
||||
return myToolWindow.getStripeTitle() + ".ShowToolbar";
|
||||
}
|
||||
|
||||
private boolean getVisibilityValue() {
|
||||
return myPropertiesComponent.getBoolean(getProperty(), true);
|
||||
}
|
||||
|
||||
private static void setContentToolbarVisible(@NotNull JComponent root, boolean state) {
|
||||
for (Component c : JBSwingUtilities.uiTraverser().preOrderTraversal(root).filter(Conditions.instanceOf(ActionToolbar.class))) {
|
||||
c.setVisible(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package com.intellij.ui.popup;
|
||||
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.ui.popup.JBPopup;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.psi.PsiElement;
|
||||
@@ -55,12 +57,40 @@ public abstract class HintUpdateSupply {
|
||||
if (supply != null) supply.hideHint();
|
||||
}
|
||||
|
||||
public static void installSimpleHintUpdateSupply(@NotNull final JComponent component) {
|
||||
HintUpdateSupply supply = new HintUpdateSupply(component) {
|
||||
@Nullable
|
||||
@Override
|
||||
protected PsiElement getPsiElementForHint(@Nullable Object selectedValue) {
|
||||
return selectedValue instanceof PsiElement ? (PsiElement)selectedValue :
|
||||
CommonDataKeys.PSI_ELEMENT.getData(DataManager.getInstance().getDataContext(component));
|
||||
}
|
||||
};
|
||||
if (component instanceof JList) supply.installListListener((JList)component);
|
||||
if (component instanceof JTree) supply.installTreeListener((JTree)component);
|
||||
if (component instanceof JTable) supply.installTableListener((JTable)component);
|
||||
}
|
||||
|
||||
protected HintUpdateSupply(@NotNull JComponent component) {
|
||||
installSupply(component);
|
||||
}
|
||||
|
||||
public HintUpdateSupply(@NotNull final JBTable table) {
|
||||
public HintUpdateSupply(@NotNull JBTable table) {
|
||||
installSupply(table);
|
||||
installTableListener(table);
|
||||
}
|
||||
|
||||
public HintUpdateSupply(@NotNull Tree tree) {
|
||||
installSupply(tree);
|
||||
installTreeListener(tree);
|
||||
}
|
||||
|
||||
public HintUpdateSupply(@NotNull JBList list) {
|
||||
installSupply(list);
|
||||
installListListener(list);
|
||||
}
|
||||
|
||||
protected void installTableListener(@NotNull final JTable table) {
|
||||
ListSelectionListener listener = new ListSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(final ListSelectionEvent e) {
|
||||
@@ -80,8 +110,7 @@ public abstract class HintUpdateSupply {
|
||||
table.getColumnModel().getSelectionModel().addListSelectionListener(listener);
|
||||
}
|
||||
|
||||
public HintUpdateSupply(@NotNull final Tree tree) {
|
||||
installSupply(tree);
|
||||
protected void installTreeListener(@NotNull final JTree tree) {
|
||||
tree.addTreeSelectionListener(new TreeSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(final TreeSelectionEvent e) {
|
||||
@@ -98,8 +127,7 @@ public abstract class HintUpdateSupply {
|
||||
});
|
||||
}
|
||||
|
||||
public HintUpdateSupply(@NotNull final JBList list) {
|
||||
installSupply(list);
|
||||
protected void installListListener(@NotNull final JList list) {
|
||||
list.addListSelectionListener(new ListSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(final ListSelectionEvent e) {
|
||||
|
||||
@@ -275,14 +275,8 @@ public class ButtonlessScrollBarUI extends BasicScrollBarUI {
|
||||
super.setThumbBounds(x, y, width, height);
|
||||
}
|
||||
else {
|
||||
/* If the thumbs bounds haven't changed, we're done.
|
||||
*/
|
||||
if ((thumbRect.x == x) &&
|
||||
(thumbRect.y == y) &&
|
||||
(thumbRect.width == width) &&
|
||||
(thumbRect.height == height)) {
|
||||
return;
|
||||
}
|
||||
// We want to repaint whole scrollbar even if thumb wasn't moved (on small scroll of a big panel)
|
||||
// Even if scrollbar wasn't changed itself, myRepaintCallback could need repaint
|
||||
|
||||
/* Update thumbRect, and repaint the union of x,y,w,h and
|
||||
* the old thumbRect.
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.projectImport.ProjectOpenProcessor;
|
||||
import com.intellij.util.SystemProperties;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -34,6 +35,7 @@ import javax.swing.*;
|
||||
*/
|
||||
public class OpenProjectFileChooserDescriptor extends FileChooserDescriptor {
|
||||
private static final Icon ourProjectIcon = IconLoader.getIcon(ApplicationInfoEx.getInstanceEx().getSmallIconUrl());
|
||||
private static final boolean ourCanInspectDirs = SystemProperties.getBooleanProperty("idea.chooser.lookup.for.project.dirs", true);
|
||||
|
||||
public OpenProjectFileChooserDescriptor(boolean chooseFiles) {
|
||||
super(chooseFiles, true, chooseFiles, chooseFiles, false, false);
|
||||
@@ -64,15 +66,14 @@ public class OpenProjectFileChooserDescriptor extends FileChooserDescriptor {
|
||||
}
|
||||
|
||||
private static boolean canInspectDirectory(VirtualFile file) {
|
||||
if (file.getParent() == null) return false;
|
||||
|
||||
VirtualFile home = VfsUtil.getUserHomeDir();
|
||||
if (home == null) return false; // unnatural situation
|
||||
VirtualFile homes = home.getParent();
|
||||
if (homes == null) return false; // another one
|
||||
if (homes.equals(file.getParent()) || VfsUtilCore.isAncestor(file, homes, false)) return false;
|
||||
|
||||
return true;
|
||||
if (home == null || VfsUtilCore.isAncestor(file, home, false)) {
|
||||
return false;
|
||||
}
|
||||
if (ourCanInspectDirs || VfsUtilCore.isAncestor(home, file, true)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static Icon getImporterIcon(VirtualFile file) {
|
||||
|
||||
@@ -53,11 +53,11 @@ class SwitcherToolWindowsListRenderer extends ColoredListCellRenderer {
|
||||
final String name;
|
||||
|
||||
String stripeTitle = tw.getStripeTitle();
|
||||
if (myPinned) {
|
||||
String shortcut = shortcuts.get(tw);
|
||||
if (myPinned || shortcut == null) {
|
||||
name = stripeTitle;
|
||||
}
|
||||
else {
|
||||
append(shortcuts.get(tw), new SimpleTextAttributes(SimpleTextAttributes.STYLE_UNDERLINE, null));
|
||||
} else {
|
||||
append(shortcut, new SimpleTextAttributes(SimpleTextAttributes.STYLE_UNDERLINE, null));
|
||||
name = ": " + stripeTitle;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.ide.actions;
|
||||
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.wm.ToolWindow;
|
||||
import com.intellij.ui.content.Content;
|
||||
import com.intellij.ui.content.ContentManager;
|
||||
import com.intellij.ui.content.ContentManagerAdapter;
|
||||
import com.intellij.ui.content.ContentManagerEvent;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.ui.JBSwingUtilities;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author gregsh
|
||||
*/
|
||||
public class ToggleToolbarAction extends ToggleAction implements DumbAware {
|
||||
|
||||
@NotNull
|
||||
public static ActionGroup createToggleToolbarGroup(@NotNull Project project, @NotNull ToolWindow toolWindow) {
|
||||
return new DefaultActionGroup(new OptionsGroup(toolWindow),
|
||||
new ToggleToolbarAction(toolWindow, PropertiesComponent.getInstance(project)));
|
||||
}
|
||||
|
||||
private final PropertiesComponent myPropertiesComponent;
|
||||
private final ToolWindow myToolWindow;
|
||||
|
||||
ToggleToolbarAction(@NotNull ToolWindow toolWindow, @NotNull PropertiesComponent propertiesComponent) {
|
||||
super("Show Toolbar");
|
||||
myPropertiesComponent = propertiesComponent;
|
||||
myToolWindow = toolWindow;
|
||||
myToolWindow.getContentManager().addContentManagerListener(new ContentManagerAdapter() {
|
||||
@Override
|
||||
public void contentAdded(ContentManagerEvent event) {
|
||||
JComponent component = event.getContent().getComponent();
|
||||
setContentToolbarVisible(component, getVisibilityValue());
|
||||
|
||||
// support nested content managers, e.g. RunnerLayoutUi as content component
|
||||
ContentManager contentManager =
|
||||
component instanceof DataProvider ? PlatformDataKeys.CONTENT_MANAGER.getData((DataProvider)component) : null;
|
||||
if (contentManager != null) contentManager.addContentManagerListener(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSelected(AnActionEvent e) {
|
||||
return getVisibilityValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(AnActionEvent e, boolean state) {
|
||||
myPropertiesComponent.setValue(getProperty(), String.valueOf(state), String.valueOf(true));
|
||||
for (Content content : myToolWindow.getContentManager().getContents()) {
|
||||
setContentToolbarVisible(content.getComponent(), state);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String getProperty() {
|
||||
return getShowToolbarProperty(myToolWindow);
|
||||
}
|
||||
|
||||
private boolean getVisibilityValue() {
|
||||
return myPropertiesComponent.getBoolean(getProperty(), true);
|
||||
}
|
||||
|
||||
private static void setContentToolbarVisible(@NotNull JComponent root, boolean state) {
|
||||
for (ActionToolbar toolbar : iterateToolbars(root)) {
|
||||
toolbar.getComponent().setVisible(state);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getShowToolbarProperty(@NotNull ToolWindow window) {
|
||||
return window.getStripeTitle() + ".ShowToolbar";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Iterable<ActionToolbar> iterateToolbars(JComponent root) {
|
||||
return JBSwingUtilities.uiTraverser().preOrderTraversal(root).filter(ActionToolbar.class);
|
||||
}
|
||||
|
||||
private static class OptionsGroup extends ActionGroup {
|
||||
|
||||
private final ToolWindow myToolWindow;
|
||||
|
||||
public OptionsGroup(ToolWindow toolWindow) {
|
||||
super("View Options", true);
|
||||
myToolWindow = toolWindow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPopup() {
|
||||
// configured in getChildren()
|
||||
return super.isPopup();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent e) {
|
||||
e.getPresentation().setVisible(!ActionGroupUtil.isGroupEmpty(this, e));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public AnAction[] getChildren(@Nullable AnActionEvent e) {
|
||||
ContentManager contentManager = myToolWindow.getContentManager();
|
||||
Content selectedContent = contentManager.getSelectedContent();
|
||||
JComponent contentComponent = selectedContent != null ? selectedContent.getComponent() : null;
|
||||
if (contentComponent == null) return EMPTY_ARRAY;
|
||||
List<AnAction> result = ContainerUtil.newSmartList();
|
||||
boolean addSeparator = false;
|
||||
for (final ActionToolbar toolbar : iterateToolbars(contentComponent)) {
|
||||
JComponent c = toolbar.getComponent();
|
||||
if (c.isVisible() || !c.isValid()) continue;
|
||||
List<AnAction> actions = toolbar.getActions(false);
|
||||
for (AnAction action : actions) {
|
||||
if (action instanceof Separator && (addSeparator = true) || !(action instanceof ToggleAction)) continue;
|
||||
if (addSeparator && !result.isEmpty()) result.add(Separator.getInstance());
|
||||
result.add(action);
|
||||
addSeparator = false;
|
||||
}
|
||||
}
|
||||
boolean popup = result.size() > 3;
|
||||
setPopup(popup);
|
||||
if (!popup && !result.isEmpty()) result.add(Separator.getInstance());
|
||||
return result.toArray(new AnAction[result.size()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -97,7 +97,7 @@ public class DarculaTextFieldUI extends BasicTextFieldUI {
|
||||
}
|
||||
|
||||
protected void showSearchPopup() {
|
||||
final Object value = getComponent().getClientProperty("JTextField.Search.FindPopup");
|
||||
final Object value = myTextField.getClientProperty("JTextField.Search.FindPopup");
|
||||
if (value instanceof JPopupMenu) {
|
||||
final JPopupMenu popup = (JPopupMenu)value;
|
||||
popup.show(getComponent(), getSearchIconCoord().x, getComponent().getHeight());
|
||||
@@ -168,7 +168,7 @@ public class DarculaTextFieldUI extends BasicTextFieldUI {
|
||||
}
|
||||
}
|
||||
Point p = getSearchIconCoord();
|
||||
Icon searchIcon = getComponent().getClientProperty("JTextField.Search.FindPopup") instanceof JPopupMenu ? UIManager.getIcon("TextField.darcula.searchWithHistory.icon") : UIManager.getIcon("TextField.darcula.search.icon");
|
||||
Icon searchIcon = myTextField.getClientProperty("JTextField.Search.FindPopup") instanceof JPopupMenu ? UIManager.getIcon("TextField.darcula.searchWithHistory.icon") : UIManager.getIcon("TextField.darcula.search.icon");
|
||||
if (searchIcon == null) {
|
||||
searchIcon = IconLoader.findIcon("/com/intellij/ide/ui/laf/icons/search.png", DarculaTextFieldUI.class, true);
|
||||
}
|
||||
|
||||
@@ -24,31 +24,26 @@ import com.intellij.openapi.actionSystem.ex.ActionButtonLook;
|
||||
import com.intellij.openapi.actionSystem.ex.ActionManagerEx;
|
||||
import com.intellij.openapi.actionSystem.ex.AnActionListener;
|
||||
import com.intellij.openapi.actionSystem.ex.CustomComponentAction;
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.keymap.Keymap;
|
||||
import com.intellij.openapi.keymap.KeymapManagerListener;
|
||||
import com.intellij.openapi.keymap.ex.KeymapManagerEx;
|
||||
import com.intellij.openapi.project.DumbAwareRunnable;
|
||||
import com.intellij.openapi.ui.popup.*;
|
||||
import com.intellij.openapi.util.ActionCallback;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.IdRunnable;
|
||||
import com.intellij.openapi.wm.IdeFocusManager;
|
||||
import com.intellij.openapi.wm.WindowManager;
|
||||
import com.intellij.openapi.wm.ex.WindowManagerEx;
|
||||
import com.intellij.ui.ColorUtil;
|
||||
import com.intellij.ui.Gray;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.ui.ScreenUtil;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.ui.awt.RelativeRectangle;
|
||||
import com.intellij.ui.switcher.SwitchTarget;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.util.ui.update.UiNotifyConnector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -96,11 +91,12 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
private int myOrientation;
|
||||
private final ActionGroup myActionGroup;
|
||||
private final String myPlace;
|
||||
private final MyKeymapManagerListener myKeymapManagerListener;
|
||||
private List<AnAction> myNewVisibleActions;
|
||||
protected List<AnAction> myVisibleActions;
|
||||
private final PresentationFactory myPresentationFactory;
|
||||
private final PresentationFactory myPresentationFactory = new PresentationFactory();
|
||||
private final boolean myDecorateButtons;
|
||||
|
||||
private final ToolbarUpdater myUpdater;
|
||||
|
||||
/**
|
||||
* @see ActionToolbar#adjustTheSameSize(boolean)
|
||||
*/
|
||||
@@ -109,7 +105,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
private final ActionButtonLook myButtonLook = null;
|
||||
private final ActionButtonLook myMinimalButtonLook = new InplaceActionButtonLook();
|
||||
private final DataManager myDataManager;
|
||||
@NotNull protected final ActionManagerEx myActionManager;
|
||||
protected final ActionManagerEx myActionManager;
|
||||
|
||||
private Rectangle myAutoPopupRec;
|
||||
|
||||
@@ -122,7 +118,6 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
}
|
||||
|
||||
private ActionButton mySecondaryActionsButton;
|
||||
private final KeymapManagerEx myKeymapManager;
|
||||
|
||||
private int myFirstOutsideIndex = -1;
|
||||
private JBPopup myPopup;
|
||||
@@ -131,45 +126,46 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
private boolean myReservePlaceAutoPopupIcon = true;
|
||||
private boolean myAddSeparatorFirst;
|
||||
|
||||
private final WeakTimerListener myWeakTimerListener;
|
||||
@SuppressWarnings({"FieldCanBeLocal"}) private final ActionToolbarImpl.MyTimerListener myTimerListener;
|
||||
public ActionToolbarImpl(final String place,
|
||||
public ActionToolbarImpl(String place,
|
||||
@NotNull final ActionGroup actionGroup,
|
||||
final boolean horizontal,
|
||||
DataManager dataManager,
|
||||
boolean horizontal,
|
||||
@NotNull DataManager dataManager,
|
||||
@NotNull ActionManagerEx actionManager,
|
||||
KeymapManagerEx keymapManager) {
|
||||
@NotNull KeymapManagerEx keymapManager) {
|
||||
this(place, actionGroup, horizontal, false, dataManager, actionManager, keymapManager, false);
|
||||
}
|
||||
public ActionToolbarImpl(final String place,
|
||||
@NotNull final ActionGroup actionGroup,
|
||||
final boolean horizontal,
|
||||
final boolean decorateButtons,
|
||||
DataManager dataManager,
|
||||
|
||||
public ActionToolbarImpl(String place,
|
||||
@NotNull ActionGroup actionGroup,
|
||||
boolean horizontal,
|
||||
boolean decorateButtons,
|
||||
@NotNull DataManager dataManager,
|
||||
@NotNull ActionManagerEx actionManager,
|
||||
KeymapManagerEx keymapManager) {
|
||||
@NotNull KeymapManagerEx keymapManager) {
|
||||
this(place, actionGroup, horizontal, decorateButtons, dataManager, actionManager, keymapManager, false);
|
||||
}
|
||||
|
||||
public ActionToolbarImpl(final String place,
|
||||
@NotNull final ActionGroup actionGroup,
|
||||
public ActionToolbarImpl(String place,
|
||||
@NotNull ActionGroup actionGroup,
|
||||
final boolean horizontal,
|
||||
final boolean decorateButtons,
|
||||
DataManager dataManager,
|
||||
@NotNull DataManager dataManager,
|
||||
@NotNull ActionManagerEx actionManager,
|
||||
KeymapManagerEx keymapManager,
|
||||
@NotNull KeymapManagerEx keymapManager,
|
||||
boolean updateActionsNow) {
|
||||
super(null);
|
||||
myActionManager = actionManager;
|
||||
myKeymapManager = keymapManager;
|
||||
myPlace = place;
|
||||
myActionGroup = actionGroup;
|
||||
myPresentationFactory = new PresentationFactory();
|
||||
myKeymapManagerListener = new MyKeymapManagerListener();
|
||||
myVisibleActions = new ArrayList<AnAction>();
|
||||
myNewVisibleActions = new ArrayList<AnAction>();
|
||||
myDataManager = dataManager;
|
||||
myDecorateButtons = decorateButtons;
|
||||
myUpdater = new ToolbarUpdater(actionManager, keymapManager, this) {
|
||||
@Override
|
||||
protected void updateActionsImpl(boolean transparentOnly, boolean forced) {
|
||||
ActionToolbarImpl.this.updateActionsImpl(transparentOnly, forced);
|
||||
}
|
||||
};
|
||||
|
||||
setLayout(new BorderLayout());
|
||||
setOrientation(horizontal ? SwingConstants.HORIZONTAL : SwingConstants.VERTICAL);
|
||||
@@ -177,12 +173,8 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
mySecondaryActions.getTemplatePresentation().setIcon(AllIcons.General.SecondaryGroup);
|
||||
mySecondaryActions.setPopup(true);
|
||||
|
||||
updateActions(updateActionsNow, false, false);
|
||||
myUpdater.updateActions(updateActionsNow, false);
|
||||
|
||||
//
|
||||
keymapManager.addWeakListener(myKeymapManagerListener);
|
||||
myTimerListener = new MyTimerListener();
|
||||
myWeakTimerListener = new WeakTimerListener(actionManager, myTimerListener);
|
||||
// If the panel doesn't handle mouse event then it will be passed to its parent.
|
||||
// It means that if the panel is in sliding mode then the focus goes to the editor
|
||||
// and panel will be automatically hidden.
|
||||
@@ -202,9 +194,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
public void addNotify() {
|
||||
super.addNotify();
|
||||
ourToolbars.add(this);
|
||||
myActionManager.addTimerListener(500, myWeakTimerListener);
|
||||
myActionManager.addTransparentTimerListener(500, myWeakTimerListener);
|
||||
|
||||
|
||||
// should update action right on the showing, otherwise toolbar may not be displayed at all,
|
||||
// since by default all updates are postponed until frame gets focused.
|
||||
updateActionsImmediately();
|
||||
@@ -226,10 +216,6 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
public void removeNotify() {
|
||||
super.removeNotify();
|
||||
ourToolbars.remove(this);
|
||||
myActionManager.removeTimerListener(myWeakTimerListener);
|
||||
myActionManager.removeTransparentTimerListener(myWeakTimerListener);
|
||||
if (ScreenUtil.isStandardAddRemoveNotify(this))
|
||||
myKeymapManager.removeWeakListener(myKeymapManagerListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -373,7 +359,11 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
}
|
||||
|
||||
private ActionButton createToolbarButton(final AnAction action) {
|
||||
return createToolbarButton(action, myMinimalMode ? myMinimalButtonLook : myDecorateButtons ? new MacToolbarDecoratorButtonLook() : myButtonLook, myPlace, myPresentationFactory.getPresentation(action), myMinimumButtonSize);
|
||||
return createToolbarButton(
|
||||
action,
|
||||
myMinimalMode ? myMinimalButtonLook : myDecorateButtons ? new MacToolbarDecoratorButtonLook() : myButtonLook,
|
||||
myPlace, myPresentationFactory.getPresentation(action),
|
||||
myMinimumButtonSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -847,53 +837,6 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
}
|
||||
}
|
||||
|
||||
private final class MyKeymapManagerListener implements KeymapManagerListener {
|
||||
@Override
|
||||
public void activeKeymapChanged(final Keymap keymap) {
|
||||
final int componentCount = getComponentCount();
|
||||
for (int i = 0; i < componentCount; i++) {
|
||||
final Component component = getComponent(i);
|
||||
if (component instanceof ActionButton) {
|
||||
((ActionButton)component).updateToolTipText();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class MyTimerListener implements TimerListener {
|
||||
|
||||
@Override
|
||||
public ModalityState getModalityState() {
|
||||
return ModalityState.stateForComponent(ActionToolbarImpl.this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (!isShowing()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// do not update when a popup menu is shown (if popup menu contains action which is also in the toolbar, it should not be enabled/disabled)
|
||||
final MenuSelectionManager menuSelectionManager = MenuSelectionManager.defaultManager();
|
||||
final MenuElement[] selectedPath = menuSelectionManager.getSelectedPath();
|
||||
if (selectedPath.length > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// don't update toolbar if there is currently active modal dialog
|
||||
|
||||
final Window window = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusedWindow();
|
||||
if (window instanceof Dialog) {
|
||||
final Dialog dialog = (Dialog)window;
|
||||
if (dialog.isModal() && !SwingUtilities.isDescendingFrom(ActionToolbarImpl.this, dialog)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
updateActions(false, myActionManager.isTransparentOnlyActionsUpdateNow(), false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void adjustTheSameSize(final boolean value) {
|
||||
if (myAdjustTheSameSize == value) {
|
||||
@@ -927,79 +870,47 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
@Override
|
||||
public void updateActionsImmediately() {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
updateActions(true, false, false);
|
||||
myUpdater.updateActions(true, false);
|
||||
}
|
||||
|
||||
private void updateActions(boolean now, final boolean transparentOnly, final boolean forced) {
|
||||
final IdRunnable updateRunnable = new IdRunnable(this) {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!isVisible()) {
|
||||
return;
|
||||
}
|
||||
private void updateActionsImpl(boolean transparentOnly, boolean forced) {
|
||||
List<AnAction> newVisibleActions = ContainerUtil.newArrayListWithCapacity(myVisibleActions.size());
|
||||
DataContext dataContext = getDataContext();
|
||||
|
||||
myNewVisibleActions.clear();
|
||||
final DataContext dataContext = getDataContext();
|
||||
Utils.expandActionGroup(myActionGroup, newVisibleActions, myPresentationFactory, dataContext,
|
||||
myPlace, myActionManager, transparentOnly);
|
||||
|
||||
Utils.expandActionGroup(myActionGroup, myNewVisibleActions, myPresentationFactory, dataContext, myPlace, myActionManager, transparentOnly);
|
||||
if (forced || !newVisibleActions.equals(myVisibleActions)) {
|
||||
boolean shouldRebuildUI = newVisibleActions.isEmpty() || myVisibleActions.isEmpty();
|
||||
myVisibleActions = newVisibleActions;
|
||||
|
||||
if (forced || !myNewVisibleActions.equals(myVisibleActions)) {
|
||||
// should rebuild UI
|
||||
Dimension oldSize = getPreferredSize();
|
||||
|
||||
final boolean changeBarVisibility = myNewVisibleActions.isEmpty() || myVisibleActions.isEmpty();
|
||||
removeAll();
|
||||
mySecondaryActions.removeAll();
|
||||
mySecondaryActionsButton = null;
|
||||
fillToolBar(myVisibleActions, getLayoutPolicy() == AUTO_LAYOUT_POLICY && myOrientation == SwingConstants.HORIZONTAL);
|
||||
|
||||
final List<AnAction> temp = myVisibleActions;
|
||||
myVisibleActions = myNewVisibleActions;
|
||||
myNewVisibleActions = temp;
|
||||
Dimension newSize = getPreferredSize();
|
||||
|
||||
Dimension oldSize = getPreferredSize();
|
||||
((WindowManagerEx)WindowManager.getInstance()).adjustContainerWindow(this, oldSize, newSize);
|
||||
|
||||
removeAll();
|
||||
mySecondaryActions.removeAll();
|
||||
mySecondaryActionsButton = null;
|
||||
fillToolBar(myVisibleActions, getLayoutPolicy() == AUTO_LAYOUT_POLICY && myOrientation == SwingConstants.HORIZONTAL);
|
||||
|
||||
Dimension newSize = getPreferredSize();
|
||||
|
||||
if (changeBarVisibility) {
|
||||
revalidate();
|
||||
}
|
||||
else {
|
||||
final Container parent = getParent();
|
||||
if (parent != null) {
|
||||
parent.invalidate();
|
||||
parent.validate();
|
||||
}
|
||||
}
|
||||
|
||||
((WindowManagerEx)WindowManager.getInstance()).adjustContainerWindow(ActionToolbarImpl.this, oldSize, newSize);
|
||||
|
||||
repaint();
|
||||
if (shouldRebuildUI) {
|
||||
revalidate();
|
||||
}
|
||||
else {
|
||||
Container parent = getParent();
|
||||
if (parent != null) {
|
||||
parent.invalidate();
|
||||
parent.validate();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (now) {
|
||||
updateRunnable.run();
|
||||
} else {
|
||||
final Application app = ApplicationManager.getApplication();
|
||||
final IdeFocusManager fm = IdeFocusManager.getInstance(null);
|
||||
|
||||
if (!app.isUnitTestMode() && !app.isHeadlessEnvironment()) {
|
||||
if (app.isDispatchThread()) {
|
||||
fm.doWhenFocusSettlesDown(updateRunnable);
|
||||
} else {
|
||||
UiNotifyConnector.doWhenFirstShown(this, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
fm.doWhenFocusSettlesDown(updateRunnable);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasVisibleActions() {
|
||||
return !myVisibleActions.isEmpty();
|
||||
@@ -1013,7 +924,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
ApplicationManager.getApplication().invokeLater(new DumbAwareRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateActions(false, false, false);
|
||||
myUpdater.updateActions(false, false);
|
||||
}
|
||||
}, ModalityState.stateForComponent(myTargetComponent));
|
||||
}
|
||||
@@ -1060,7 +971,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
group = outside;
|
||||
}
|
||||
|
||||
PopupToolbar popupToolbar = new PopupToolbar(myPlace, group, true, myDataManager, myActionManager, myKeymapManager, this) {
|
||||
PopupToolbar popupToolbar = new PopupToolbar(myPlace, group, true, myDataManager, myActionManager, myUpdater.getKeymapManager(), this) {
|
||||
@Override
|
||||
protected void onOtherActionPerformed() {
|
||||
hidePopup();
|
||||
@@ -1094,7 +1005,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
public Boolean compute() {
|
||||
final boolean toClose = myActionManager.isActionPopupStackEmpty();
|
||||
if (toClose) {
|
||||
updateActions(false, false, true);
|
||||
myUpdater.updateActions(false, true);
|
||||
}
|
||||
return toClose;
|
||||
}
|
||||
@@ -1191,7 +1102,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
Disposer.dispose(myPopup);
|
||||
myPopup = null;
|
||||
|
||||
updateActions(false, false, false);
|
||||
myUpdater.updateActions(false, false);
|
||||
}
|
||||
|
||||
abstract static class PopupToolbar extends ActionToolbarImpl implements AnActionListener, Disposable {
|
||||
@@ -1264,7 +1175,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
return result;
|
||||
}
|
||||
|
||||
private class ActionTarget implements SwitchTarget {
|
||||
private static class ActionTarget implements SwitchTarget {
|
||||
private final ActionButton myButton;
|
||||
|
||||
private ActionTarget(ActionButton button) {
|
||||
@@ -1350,11 +1261,11 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
setLayoutPolicy(AUTO_LAYOUT_POLICY);
|
||||
}
|
||||
|
||||
updateActions(false, false, true);
|
||||
myUpdater.updateActions(false, true);
|
||||
}
|
||||
|
||||
public void setAddSeparatorFirst(boolean addSeparatorFirst) {
|
||||
myAddSeparatorFirst = addSeparatorFirst;
|
||||
updateActions(false, false, true);
|
||||
myUpdater.updateActions(false, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.actionSystem.impl;
|
||||
|
||||
import com.intellij.openapi.actionSystem.TimerListener;
|
||||
import com.intellij.openapi.actionSystem.ex.ActionManagerEx;
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.keymap.Keymap;
|
||||
import com.intellij.openapi.keymap.KeymapManagerListener;
|
||||
import com.intellij.openapi.keymap.ex.KeymapManagerEx;
|
||||
import com.intellij.openapi.util.IdRunnable;
|
||||
import com.intellij.openapi.wm.IdeFocusManager;
|
||||
import com.intellij.ui.ScreenUtil;
|
||||
import com.intellij.util.ui.JBSwingUtilities;
|
||||
import com.intellij.util.ui.update.Activatable;
|
||||
import com.intellij.util.ui.update.UiNotifyConnector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* @author Konstantin Bulenkov
|
||||
*/
|
||||
public abstract class ToolbarUpdater implements Activatable {
|
||||
private final KeymapManagerListener myKeymapManagerListener;
|
||||
private final WeakTimerListener myWeakTimerListener;
|
||||
/** @noinspection FieldCanBeLocal*/
|
||||
private final TimerListener myTimerListener;
|
||||
private final ActionManagerEx myActionManager;
|
||||
private final KeymapManagerEx myKeymapManager;
|
||||
private final JComponent myComponent;
|
||||
|
||||
public ToolbarUpdater(@NotNull JComponent component) {
|
||||
this(ActionManagerEx.getInstanceEx(), KeymapManagerEx.getInstanceEx(), component);
|
||||
}
|
||||
|
||||
public ToolbarUpdater(@NotNull ActionManagerEx actionManager, @NotNull KeymapManagerEx keymapManager, @NotNull JComponent component) {
|
||||
new UiNotifyConnector(component, this);
|
||||
myActionManager = actionManager;
|
||||
myKeymapManager = keymapManager;
|
||||
myComponent = component;
|
||||
myKeymapManagerListener = new MyKeymapManagerListener();
|
||||
keymapManager.addWeakListener(myKeymapManagerListener);
|
||||
myTimerListener = new MyTimerListener();
|
||||
myWeakTimerListener = new WeakTimerListener(actionManager, myTimerListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showNotify() {
|
||||
myActionManager.addTimerListener(500, myWeakTimerListener);
|
||||
myActionManager.addTransparentTimerListener(500, myWeakTimerListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideNotify() {
|
||||
//noinspection ConstantConditions
|
||||
if (myActionManager == null) return; // not yet initialized
|
||||
myActionManager.removeTimerListener(myWeakTimerListener);
|
||||
myActionManager.removeTransparentTimerListener(myWeakTimerListener);
|
||||
if (ScreenUtil.isStandardAddRemoveNotify(myComponent)) {
|
||||
myKeymapManager.removeWeakListener(myKeymapManagerListener);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public KeymapManagerEx getKeymapManager() {
|
||||
return myKeymapManager;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ActionManagerEx getActionManager() {
|
||||
return myActionManager;
|
||||
}
|
||||
|
||||
public void updateActions(boolean now, boolean forced) {
|
||||
updateActions(now, false, forced);
|
||||
}
|
||||
|
||||
private void updateActions(boolean now, final boolean transparentOnly, final boolean forced) {
|
||||
final IdRunnable updateRunnable = new IdRunnable(this) {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!myComponent.isVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
updateActionsImpl(transparentOnly, forced);
|
||||
}
|
||||
};
|
||||
|
||||
if (now) {
|
||||
updateRunnable.run();
|
||||
}
|
||||
else {
|
||||
final Application app = ApplicationManager.getApplication();
|
||||
final IdeFocusManager fm = IdeFocusManager.getInstance(null);
|
||||
|
||||
if (!app.isUnitTestMode() && !app.isHeadlessEnvironment()) {
|
||||
if (app.isDispatchThread()) {
|
||||
fm.doWhenFocusSettlesDown(updateRunnable);
|
||||
}
|
||||
else {
|
||||
UiNotifyConnector.doWhenFirstShown(myComponent, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
fm.doWhenFocusSettlesDown(updateRunnable);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void updateActionsImpl(boolean transparentOnly, boolean forced);
|
||||
|
||||
protected void updateActionTooltips() {
|
||||
for (ActionButton actionButton : JBSwingUtilities.uiTraverser().preOrderTraversal(myComponent).filter(ActionButton.class)) {
|
||||
actionButton.updateToolTipText();
|
||||
}
|
||||
}
|
||||
|
||||
private final class MyKeymapManagerListener implements KeymapManagerListener {
|
||||
@Override
|
||||
public void activeKeymapChanged(Keymap keymap) {
|
||||
updateActionTooltips();
|
||||
}
|
||||
}
|
||||
|
||||
private final class MyTimerListener implements TimerListener {
|
||||
|
||||
@Override
|
||||
public ModalityState getModalityState() {
|
||||
return ModalityState.stateForComponent(myComponent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (!myComponent.isShowing()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// do not update when a popup menu is shown (if popup menu contains action which is also in the toolbar, it should not be enabled/disabled)
|
||||
MenuSelectionManager menuSelectionManager = MenuSelectionManager.defaultManager();
|
||||
MenuElement[] selectedPath = menuSelectionManager.getSelectedPath();
|
||||
if (selectedPath.length > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// don't update toolbar if there is currently active modal dialog
|
||||
Window window = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusedWindow();
|
||||
if (window instanceof Dialog && ((Dialog)window).isModal() && !SwingUtilities.isDescendingFrom(myComponent, window)) {
|
||||
return;
|
||||
}
|
||||
|
||||
updateActions(false, myActionManager.isTransparentOnlyActionsUpdateNow(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.command.impl;
|
||||
|
||||
import com.intellij.openapi.command.undo.DocumentReference;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
class DocumentReferenceByNonlocalVirtualFile implements DocumentReference {
|
||||
private final VirtualFile myFile;
|
||||
|
||||
DocumentReferenceByNonlocalVirtualFile(@NotNull VirtualFile file) {
|
||||
myFile = file;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Document getDocument() {
|
||||
return FileDocumentManager.getInstance().getDocument(myFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public VirtualFile getFile() {
|
||||
return myFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return myFile.toString();
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,6 @@ import com.intellij.openapi.command.undo.DocumentReference;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.testFramework.LightVirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -33,7 +32,7 @@ public class DocumentReferenceByVirtualFile implements DocumentReference {
|
||||
@Override
|
||||
@Nullable
|
||||
public Document getDocument() {
|
||||
assert myFile.isValid() || myFile instanceof LightVirtualFile : "should not be called on references to deleted file: " + myFile;
|
||||
assert myFile.isValid() : "should not be called on references to deleted file: " + myFile;
|
||||
return FileDocumentManager.getInstance().getDocument(myFile);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ import com.intellij.openapi.vfs.VirtualFileEvent;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
|
||||
import com.intellij.reference.SoftReference;
|
||||
import com.intellij.testFramework.LightVirtualFile;
|
||||
import com.intellij.util.containers.WeakKeyWeakValueHashMap;
|
||||
import com.intellij.util.containers.WeakValueHashMap;
|
||||
import com.intellij.util.io.fs.FilePath;
|
||||
@@ -46,6 +45,7 @@ public class DocumentReferenceManagerImpl extends DocumentReferenceManager imple
|
||||
private final Map<Document, DocumentReference> myDocToRef = new WeakKeyWeakValueHashMap<Document, DocumentReference>();
|
||||
|
||||
private static final Key<Reference<DocumentReference>> FILE_TO_REF_KEY = Key.create("FILE_TO_REF_KEY");
|
||||
private static final Key<DocumentReference> FILE_TO_STRONG_REF_KEY = Key.create("FILE_TO_STRONG_REF_KEY");
|
||||
private final Map<FilePath, DocumentReference> myDeletedFilePathToRef = new WeakValueHashMap<FilePath, DocumentReference>();
|
||||
|
||||
@Override
|
||||
@@ -132,7 +132,16 @@ public class DocumentReferenceManagerImpl extends DocumentReferenceManager imple
|
||||
@Override
|
||||
public DocumentReference create(@NotNull VirtualFile file) {
|
||||
assertInDispatchThread();
|
||||
assert file.isValid() || file instanceof LightVirtualFile : "file is invalid: " + file;
|
||||
|
||||
if (!file.isInLocalFileSystem()) { // we treat local files differently from non local because we can undo their deletion
|
||||
DocumentReference reference = file.getUserData(FILE_TO_STRONG_REF_KEY);
|
||||
if (reference == null) {
|
||||
file.putUserData(FILE_TO_STRONG_REF_KEY, reference = new DocumentReferenceByNonlocalVirtualFile(file));
|
||||
}
|
||||
return reference;
|
||||
}
|
||||
|
||||
assert file.isValid() : "file is invalid: " + file;
|
||||
|
||||
DocumentReference result = SoftReference.dereference(file.getUserData(FILE_TO_REF_KEY));
|
||||
if (result == null) {
|
||||
|
||||
@@ -19,8 +19,8 @@ import com.intellij.openapi.command.undo.DocumentReference;
|
||||
import com.intellij.openapi.command.undo.DocumentReferenceManager;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.UserDataHolder;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.testFramework.LightVirtualFile;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.containers.WeakList;
|
||||
import gnu.trove.THashSet;
|
||||
@@ -34,8 +34,11 @@ class UndoRedoStacksHolder {
|
||||
private final boolean myUndo;
|
||||
|
||||
private final LinkedList<UndoableGroup> myGlobalStack = new LinkedList<UndoableGroup>();
|
||||
// strongly reference local files for which we can undo file removal
|
||||
// document without files and nonlocal files are stored without strong reference
|
||||
private final Map<DocumentReference, LinkedList<UndoableGroup>> myDocumentStacks = new HashMap<DocumentReference, LinkedList<UndoableGroup>>();
|
||||
private final List<Document> myDocumentsWithStacks = new WeakList<Document>();
|
||||
private final WeakList<Document> myDocumentsWithStacks = new WeakList<Document>();
|
||||
private final WeakList<VirtualFile> myNonlocalVirtualFilesWithStacks = new WeakList<VirtualFile>();
|
||||
|
||||
public UndoRedoStacksHolder(boolean isUndo) {
|
||||
myUndo = isUndo;
|
||||
@@ -43,17 +46,25 @@ class UndoRedoStacksHolder {
|
||||
|
||||
@NotNull
|
||||
LinkedList<UndoableGroup> getStack(@NotNull DocumentReference r) {
|
||||
VirtualFile file = r.getFile();
|
||||
return file != null && !(file instanceof LightVirtualFile) ? doGetStackForFile(r) : doGetStackForDocument(r);
|
||||
return r.getFile() != null ? doGetStackForFile(r) : doGetStackForDocument(r);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private LinkedList<UndoableGroup> doGetStackForFile(@NotNull DocumentReference r) {
|
||||
LinkedList<UndoableGroup> result = myDocumentStacks.get(r);
|
||||
if (result == null) {
|
||||
result = new LinkedList<UndoableGroup>();
|
||||
myDocumentStacks.put(r, result);
|
||||
LinkedList<UndoableGroup> result;
|
||||
VirtualFile file = r.getFile();
|
||||
|
||||
if (!file.isInLocalFileSystem()) {
|
||||
result = addWeaklyTrackedEmptyStack(file, myNonlocalVirtualFilesWithStacks);
|
||||
}
|
||||
else {
|
||||
result = myDocumentStacks.get(r);
|
||||
if (result == null) {
|
||||
result = new LinkedList<UndoableGroup>();
|
||||
myDocumentStacks.put(r, result);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -63,12 +74,15 @@ class UndoRedoStacksHolder {
|
||||
// itself to avoid memory leaks caused by holding stacks of all documents, ever created, here.
|
||||
// And to know, what documents do exist now, we have to maintain weak reference list of them.
|
||||
|
||||
Document d = r.getDocument();
|
||||
LinkedList<UndoableGroup> result = d.getUserData(STACK_IN_DOCUMENT_KEY);
|
||||
return addWeaklyTrackedEmptyStack(r.getDocument(), myDocumentsWithStacks);
|
||||
}
|
||||
|
||||
private <T extends UserDataHolder> LinkedList<UndoableGroup> addWeaklyTrackedEmptyStack(T holder, WeakList<T> allHolders) {
|
||||
LinkedList<UndoableGroup> result;
|
||||
result = holder.getUserData(STACK_IN_DOCUMENT_KEY);
|
||||
if (result == null) {
|
||||
result = new LinkedList<UndoableGroup>();
|
||||
d.putUserData(STACK_IN_DOCUMENT_KEY, result);
|
||||
myDocumentsWithStacks.add(d);
|
||||
holder.putUserData(STACK_IN_DOCUMENT_KEY, result = new LinkedList<UndoableGroup>());
|
||||
allHolders.add(holder);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -164,15 +178,20 @@ class UndoRedoStacksHolder {
|
||||
}
|
||||
|
||||
|
||||
Set<Document> docsToDrop = new THashSet<Document>();
|
||||
for (Document each : myDocumentsWithStacks) {
|
||||
LinkedList<UndoableGroup> stack = each.getUserData(STACK_IN_DOCUMENT_KEY);
|
||||
cleanWeaklyTrackedEmptyStacks(myDocumentsWithStacks);
|
||||
cleanWeaklyTrackedEmptyStacks(myNonlocalVirtualFilesWithStacks);
|
||||
}
|
||||
|
||||
private <T extends UserDataHolder> void cleanWeaklyTrackedEmptyStacks(WeakList<T> stackHolders) {
|
||||
Set<T> holdersToDrop = new THashSet<T>();
|
||||
for (T holder : stackHolders) {
|
||||
LinkedList<UndoableGroup> stack = holder.getUserData(STACK_IN_DOCUMENT_KEY);
|
||||
if (stack != null && stack.isEmpty()) {
|
||||
each.putUserData(STACK_IN_DOCUMENT_KEY, null);
|
||||
docsToDrop.add(each);
|
||||
holder.putUserData(STACK_IN_DOCUMENT_KEY, null);
|
||||
holdersToDrop.add(holder);
|
||||
}
|
||||
}
|
||||
myDocumentsWithStacks.removeAll(docsToDrop);
|
||||
stackHolders.removeAll(holdersToDrop);
|
||||
}
|
||||
|
||||
private void clearStacksFrom(@NotNull UndoableGroup from) {
|
||||
@@ -217,8 +236,13 @@ class UndoRedoStacksHolder {
|
||||
|
||||
private void collectLocalAffectedDocuments(@NotNull Collection<DocumentReference> result) {
|
||||
result.addAll(myDocumentStacks.keySet());
|
||||
DocumentReferenceManager documentReferenceManager = DocumentReferenceManager.getInstance();
|
||||
|
||||
for (Document each : myDocumentsWithStacks) {
|
||||
result.add(DocumentReferenceManager.getInstance().create(each));
|
||||
result.add(documentReferenceManager.create(each));
|
||||
}
|
||||
for (VirtualFile each : myNonlocalVirtualFilesWithStacks) {
|
||||
result.add(documentReferenceManager.create(each));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ public abstract class AbstractUpdateDialog extends DialogWrapper {
|
||||
|
||||
|
||||
protected void configureMessageArea(@NotNull JEditorPane area) {
|
||||
configureMessageArea(area, IdeBundle.message("updates.configure.label", ShowSettingsUtil.getSettingsMenuName()), null, null);
|
||||
configureMessageArea(area, myEnableLink ? IdeBundle.message("updates.configure.label", ShowSettingsUtil.getSettingsMenuName()) : "", null, null);
|
||||
}
|
||||
|
||||
protected void configureMessageArea(final @NotNull JEditorPane area,
|
||||
@@ -113,7 +113,7 @@ public abstract class AbstractUpdateDialog extends DialogWrapper {
|
||||
UIUtil.getCssFontDeclaration(UIUtil.getLabelFont(), fontColor, null, null) +
|
||||
"<style>body {background: #" + ColorUtil.toHex(UIUtil.getPanelBackground()) + ";}</style>" +
|
||||
"</head><body>" +
|
||||
(myEnableLink ? messageBody : "") +
|
||||
messageBody +
|
||||
"</body></html>";
|
||||
|
||||
area.setBackground(UIUtil.getPanelBackground());
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.intellij.openapi.vcs.readOnlyHandler;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.VcsBundle;
|
||||
import com.intellij.openapi.vfs.ReadonlyStatusHandler;
|
||||
import com.intellij.ui.CollectionComboBoxModel;
|
||||
@@ -107,11 +108,12 @@ public class ReadOnlyStatusDialog extends OptionsDialog {
|
||||
@Override
|
||||
protected void doCustomize(JList list, String value, int index, boolean selected, boolean hasFocus) {
|
||||
if (value == null) return;
|
||||
String trimmed = StringUtil.first(value, 50, true);
|
||||
if (value.equals(defaultChangelist)) {
|
||||
append(value, selected ? SELECTED_BOLD_ATTRIBUTES : BOLD_ATTRIBUTES);
|
||||
append(trimmed, selected ? SELECTED_BOLD_ATTRIBUTES : BOLD_ATTRIBUTES);
|
||||
}
|
||||
else {
|
||||
append(value, selected ? SimpleTextAttributes.SELECTED_SIMPLE_CELL_ATTRIBUTES : SimpleTextAttributes.SIMPLE_CELL_ATTRIBUTES);
|
||||
append(trimmed, selected ? SimpleTextAttributes.SELECTED_SIMPLE_CELL_ATTRIBUTES : SimpleTextAttributes.SIMPLE_CELL_ATTRIBUTES);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -19,9 +19,6 @@ import com.intellij.ide.actions.ResizeToolWindowAction;
|
||||
import com.intellij.idea.ActionsBundle;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.keymap.Keymap;
|
||||
import com.intellij.openapi.keymap.KeymapManagerListener;
|
||||
import com.intellij.openapi.keymap.ex.KeymapManagerEx;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Queryable;
|
||||
@@ -54,7 +51,7 @@ import java.util.Map;
|
||||
* @author Eugene Belyaev
|
||||
* @author Vladimir Kondratyev
|
||||
*/
|
||||
public final class InternalDecorator extends JPanel implements Queryable, TypeSafeDataProvider {
|
||||
public final class InternalDecorator extends JPanel implements Queryable, DataProvider {
|
||||
|
||||
private Project myProject;
|
||||
private WindowInfoImpl myInfo;
|
||||
@@ -74,7 +71,6 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa
|
||||
/**
|
||||
* Catches all event from tool window and modifies decorator's appearance.
|
||||
*/
|
||||
private final MyKeymapManagerListener myWeakKeymapManagerListener;
|
||||
@NonNls private static final String HIDE_ACTIVE_WINDOW_ACTION_ID = "HideActiveWindow";
|
||||
@NonNls public static final String TOGGLE_PINNED_MODE_ACTION_ID = "TogglePinnedMode";
|
||||
@NonNls public static final String TOGGLE_DOCK_MODE_ACTION_ID = "ToggleDockMode";
|
||||
@@ -124,11 +120,6 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa
|
||||
}
|
||||
};
|
||||
|
||||
MyKeymapManagerListener keymapManagerListener = new MyKeymapManagerListener();
|
||||
final KeymapManagerEx keymapManager = KeymapManagerEx.getInstanceEx();
|
||||
myWeakKeymapManagerListener = keymapManagerListener;
|
||||
keymapManager.addWeakListener(keymapManagerListener);
|
||||
|
||||
init();
|
||||
|
||||
apply(info);
|
||||
@@ -192,11 +183,13 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa
|
||||
setBorder(new InnerPanelBorder(myToolWindow));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public void calcData(DataKey key, DataSink sink) {
|
||||
if (PlatformDataKeys.TOOL_WINDOW.equals(key)) {
|
||||
sink.put(PlatformDataKeys.TOOL_WINDOW, myToolWindow);
|
||||
public Object getData(@NonNls String dataId) {
|
||||
if (PlatformDataKeys.TOOL_WINDOW.is(dataId)) {
|
||||
return myToolWindow;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
final void addInternalDecoratorListener(InternalDecoratorListener l) {
|
||||
@@ -209,7 +202,6 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa
|
||||
|
||||
final void dispose() {
|
||||
removeAll();
|
||||
KeymapManagerEx.getInstanceEx().removeWeakListener(myWeakKeymapManagerListener);
|
||||
|
||||
Disposer.dispose(myHeader);
|
||||
myHeader = null;
|
||||
@@ -502,7 +494,7 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void actionPerformed(final AnActionEvent e) {
|
||||
public final void actionPerformed(@NotNull final AnActionEvent e) {
|
||||
fireAnchorChanged(myAnchor);
|
||||
}
|
||||
}
|
||||
@@ -581,7 +573,7 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(final AnActionEvent e) {
|
||||
public void update(@NotNull final AnActionEvent e) {
|
||||
super.update(e);
|
||||
}
|
||||
}
|
||||
@@ -595,12 +587,12 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void actionPerformed(final AnActionEvent e) {
|
||||
public final void actionPerformed(@NotNull final AnActionEvent e) {
|
||||
fireHidden();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void update(final AnActionEvent event) {
|
||||
public final void update(@NotNull final AnActionEvent event) {
|
||||
final Presentation presentation = event.getPresentation();
|
||||
presentation.setEnabled(myInfo.isVisible());
|
||||
}
|
||||
@@ -714,6 +706,7 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Cursor getCursor() {
|
||||
final boolean isVerticalCursor = myInfo.isDocked() ? myInfo.getAnchor().isSplitVertically() : myInfo.getAnchor().isHorizontal();
|
||||
@@ -721,18 +714,6 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates tooltips.
|
||||
*/
|
||||
private final class MyKeymapManagerListener implements KeymapManagerListener {
|
||||
@Override
|
||||
public final void activeKeymapChanged(final Keymap keymap) {
|
||||
if (myHeader != null) {
|
||||
myHeader.updateTooltips();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putInfo(@NotNull Map<String, String> info) {
|
||||
info.put("toolWindowTitle", myToolWindow.getTitle());
|
||||
|
||||
@@ -22,8 +22,7 @@ import com.intellij.ide.ui.UISettingsListener;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.actionSystem.ex.ActionManagerEx;
|
||||
import com.intellij.openapi.actionSystem.impl.ActionManagerImpl;
|
||||
import com.intellij.openapi.actionSystem.impl.MenuItemPresentationFactory;
|
||||
import com.intellij.openapi.actionSystem.impl.*;
|
||||
import com.intellij.openapi.keymap.KeymapUtil;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
@@ -37,7 +36,9 @@ import com.intellij.ui.UIBundle;
|
||||
import com.intellij.ui.components.panels.Wrapper;
|
||||
import com.intellij.ui.tabs.TabsUtil;
|
||||
import com.intellij.util.Producer;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.ui.EmptyIcon;
|
||||
import com.intellij.util.ui.JBSwingUtilities;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -49,6 +50,7 @@ import java.awt.event.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author pegov
|
||||
@@ -66,6 +68,11 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS
|
||||
private final JPanel myButtonPanel;
|
||||
private final ToolWindowHeader.ActionButton myGearButton;
|
||||
|
||||
private final PresentationFactory myPresentationFactory = new PresentationFactory();
|
||||
private final ToolbarUpdater myUpdater;
|
||||
private final DefaultActionGroup myActionGroup = new DefaultActionGroup();
|
||||
private List<AnAction> myVisibleActions = ContainerUtil.newArrayListWithCapacity(2);
|
||||
|
||||
public ToolWindowHeader(final ToolWindowImpl toolWindow, @NotNull WindowInfoImpl info, @NotNull final Producer<ActionGroup> gearProducer) {
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
@@ -103,7 +110,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS
|
||||
|
||||
myGearButton = new ActionButton(new AnAction() {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
final InputEvent inputEvent = e.getInputEvent();
|
||||
final ActionPopupMenu popupMenu =
|
||||
((ActionManagerImpl)ActionManager.getInstance())
|
||||
@@ -127,17 +134,15 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS
|
||||
|
||||
myHideButton = new ActionButton(new HideAction() {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
hideToolWindow();
|
||||
}
|
||||
}, new HideSideAction() {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
sideHidden();
|
||||
}
|
||||
},
|
||||
AllIcons.General.HideLeft, null, null
|
||||
) {
|
||||
}, AllIcons.General.HideLeft, null, null) {
|
||||
@Override
|
||||
protected Icon getActiveIcon() {
|
||||
return getHideToolWindowIcon(myToolWindow);
|
||||
@@ -190,6 +195,19 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS
|
||||
setBorder(BorderFactory.createEmptyBorder(TabsUtil.TABS_BORDER, 1, TabsUtil.TABS_BORDER, 1));
|
||||
|
||||
UISettings.getInstance().addUISettingsListener(this, toolWindow.getContentUI());
|
||||
myUpdater = new ToolbarUpdater(this) {
|
||||
@Override
|
||||
protected void updateActionsImpl(boolean transparentOnly, boolean forced) {
|
||||
ToolWindowHeader.this.updateActionsImpl(transparentOnly, forced);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateActionTooltips() {
|
||||
for (ActionButton actionButton : JBSwingUtilities.uiTraverser().preOrderTraversal(myButtonPanel).filter(ActionButton.class)) {
|
||||
actionButton.updateTooltip();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -211,32 +229,46 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS
|
||||
myInfo = null;
|
||||
}
|
||||
|
||||
public void updateTooltips() {
|
||||
if (myHideButton != null) {
|
||||
myHideButton.updateTooltip();
|
||||
}
|
||||
public void setAdditionalTitleActions(AnAction[] actions) {
|
||||
myActionGroup.removeAll();
|
||||
myActionGroup.addAll(actions);
|
||||
myUpdater.updateActions(false, true);
|
||||
}
|
||||
|
||||
public void setAdditionalTitleActions(AnAction[] actions) {
|
||||
myButtonPanel.removeAll();
|
||||
boolean actionAdded = false;
|
||||
for (final AnAction action : actions) {
|
||||
if (action == null) continue;
|
||||
myButtonPanel.add(new ActionButton(action, action.getTemplatePresentation().getIcon()) {
|
||||
@Override
|
||||
protected Icon getActiveHoveredIcon() {
|
||||
final Icon icon = action.getTemplatePresentation().getHoveredIcon();
|
||||
return icon != null ? icon : super.getActiveHoveredIcon();
|
||||
}
|
||||
});
|
||||
myButtonPanel.add(Box.createHorizontalStrut(9));
|
||||
actionAdded = true;
|
||||
private void updateActionsImpl(boolean transparentOnly, boolean forced) {
|
||||
List<AnAction> newVisibleActions = ContainerUtil.newArrayListWithCapacity(myVisibleActions.size());
|
||||
DataContext dataContext = DataManager.getInstance().getDataContext(this);
|
||||
|
||||
Utils.expandActionGroup(myActionGroup, newVisibleActions, myPresentationFactory, dataContext,
|
||||
ActionPlaces.TOOLWINDOW_TITLE, myUpdater.getActionManager(), transparentOnly);
|
||||
|
||||
if (forced || !newVisibleActions.equals(myVisibleActions)) {
|
||||
myVisibleActions = newVisibleActions;
|
||||
|
||||
myButtonPanel.removeAll();
|
||||
boolean actionAdded = false;
|
||||
for (final AnAction action : newVisibleActions) {
|
||||
if (action == null) continue;
|
||||
final Presentation presentation = myPresentationFactory.getPresentation(action);
|
||||
myButtonPanel.add(new ActionButton(action, presentation.getIcon()) {
|
||||
@Override
|
||||
protected Icon getActiveHoveredIcon() {
|
||||
Icon icon = presentation.getHoveredIcon();
|
||||
return icon != null ? icon : super.getActiveHoveredIcon();
|
||||
}
|
||||
});
|
||||
myButtonPanel.add(Box.createHorizontalStrut(9));
|
||||
actionAdded = true;
|
||||
}
|
||||
if (actionAdded) {
|
||||
myButtonPanel.add(new JLabel(AllIcons.General.Divider));
|
||||
myButtonPanel.add(Box.createHorizontalStrut(6));
|
||||
}
|
||||
addDefaultActions(myButtonPanel);
|
||||
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
if (actionAdded) {
|
||||
myButtonPanel.add(new JLabel(AllIcons.General.Divider));
|
||||
myButtonPanel.add(Box.createHorizontalStrut(6));
|
||||
}
|
||||
addDefaultActions(myButtonPanel);
|
||||
}
|
||||
|
||||
private static Icon getHideToolWindowIcon(ToolWindow toolWindow) {
|
||||
@@ -484,7 +516,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS
|
||||
final ActionManagerEx actionManager = ActionManagerEx.getInstanceEx();
|
||||
InputEvent inputEvent = e.getSource() instanceof InputEvent ? (InputEvent) e.getSource() : null;
|
||||
final AnActionEvent event =
|
||||
new AnActionEvent(inputEvent, dataContext, ActionPlaces.UNKNOWN, action.getTemplatePresentation(),
|
||||
new AnActionEvent(inputEvent, dataContext, ActionPlaces.TOOLWINDOW_TITLE, action.getTemplatePresentation(),
|
||||
ActionManager.getInstance(),
|
||||
0);
|
||||
actionManager.fireBeforeActionPerformed(action, dataContext, event);
|
||||
@@ -542,9 +574,9 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS
|
||||
getTemplatePresentation().setText(UIBundle.message("tool.window.hideSide.action.name"));
|
||||
}
|
||||
|
||||
public abstract void actionPerformed(final AnActionEvent e);
|
||||
public abstract void actionPerformed(@NotNull final AnActionEvent e);
|
||||
|
||||
public final void update(final AnActionEvent event) {
|
||||
public final void update(@NotNull final AnActionEvent event) {
|
||||
final Presentation presentation = event.getPresentation();
|
||||
presentation.setEnabled(myInfo.isVisible());
|
||||
}
|
||||
@@ -558,7 +590,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS
|
||||
getTemplatePresentation().setText(UIBundle.message("tool.window.hide.action.name"));
|
||||
}
|
||||
|
||||
public final void update(final AnActionEvent event) {
|
||||
public final void update(@NotNull final AnActionEvent event) {
|
||||
final Presentation presentation = event.getPresentation();
|
||||
presentation.setEnabled(myInfo.isVisible());
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ import com.intellij.openapi.wm.StatusBar;
|
||||
import com.intellij.openapi.wm.StatusBarWidget;
|
||||
import com.intellij.openapi.wm.ex.ProgressIndicatorEx;
|
||||
import com.intellij.ui.Gray;
|
||||
import com.intellij.ui.TabbedPaneWrapper;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.ui.components.labels.LinkLabel;
|
||||
import com.intellij.ui.components.labels.LinkListener;
|
||||
@@ -414,6 +415,8 @@ public class InfoAndProgressPanel extends JPanel implements CustomStatusBarWidge
|
||||
|
||||
@NotNull
|
||||
private static Component getAnchor(@NotNull JRootPane pane) {
|
||||
Component tabWrapper = UIUtil.findComponentOfType(pane, TabbedPaneWrapper.TabWrapper.class);
|
||||
if (tabWrapper != null) return tabWrapper;
|
||||
Component splitters = UIUtil.findComponentOfType(pane, EditorsSplitters.class);
|
||||
if (splitters != null) return splitters;
|
||||
FileEditorManagerEx ex = FileEditorManagerEx.getInstanceEx(ProjectUtil.guessCurrentProject(pane));
|
||||
|
||||
@@ -23,6 +23,8 @@ import com.intellij.ui.InplaceButton;
|
||||
import com.intellij.ui.TransparentPanel;
|
||||
import com.intellij.util.ui.EmptyIcon;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.util.ui.update.MergingUpdateQueue;
|
||||
import com.intellij.util.ui.update.Update;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -40,6 +42,8 @@ public class PresentationModeProgressPanel {
|
||||
private InplaceButton myCancelButton;
|
||||
private JLabel myText2;
|
||||
private JPanel myRootPanel;
|
||||
private MergingUpdateQueue myUpdateQueue;
|
||||
private Update myUpdate;
|
||||
|
||||
public PresentationModeProgressPanel(InlineProgressIndicator progress) {
|
||||
myProgress = progress;
|
||||
@@ -48,15 +52,17 @@ public class PresentationModeProgressPanel {
|
||||
myText2.setFont(font);
|
||||
myText.setIcon(EmptyIcon.create(1, 16));
|
||||
myText2.setIcon(EmptyIcon.create(1, 16));
|
||||
}
|
||||
|
||||
public void update() {
|
||||
UIUtil.invokeLaterIfNeeded(new Runnable() {
|
||||
myUpdateQueue = new MergingUpdateQueue("Presentation Mode Progress", 100, true, null);
|
||||
myUpdate = new Update("Update UI") {
|
||||
@Override
|
||||
public void run() {
|
||||
updateImpl();
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
public void update() {
|
||||
myUpdateQueue.queue(myUpdate);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -140,23 +140,10 @@ public interface PopupComponent {
|
||||
myDialog.setFocusableWindowState(false);
|
||||
}
|
||||
|
||||
try {
|
||||
if (UIUtil.isUnderDarcula()) {
|
||||
AWTUtilities.setWindowOpaque(myDialog, false);
|
||||
}
|
||||
}
|
||||
catch (Exception ignore) {
|
||||
}
|
||||
|
||||
AwtPopupWrapper.fixFlickering(myDialog, false);
|
||||
myDialog.setVisible(true);
|
||||
AwtPopupWrapper.fixFlickering(myDialog, true);
|
||||
|
||||
try {
|
||||
if (UIUtil.isUnderDarcula()) {
|
||||
AWTUtilities.setWindowOpaque(myDialog, true);
|
||||
}
|
||||
}
|
||||
catch (Exception ignore) {
|
||||
}
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
myDialog.setFocusableWindowState(true);
|
||||
|
||||
@@ -1401,7 +1401,7 @@ action.Console.History.Browse.text=Browse History
|
||||
action.Console.History.Browse.description=Browse console history
|
||||
action.RevealIn.description=Highlights the file in platform's file manager
|
||||
action.GoToLinkTarget.text=Go to Link Target
|
||||
action.GoToLinkTarget.description=Opens a target ot this symlink in the Project View
|
||||
action.GoToLinkTarget.description=Opens a target of this symlink in the Project View
|
||||
|
||||
action.Images.EditExternally.text=Jump to External Editor
|
||||
action.Images.EditExternally.description=Open image in external editor
|
||||
|
||||
@@ -126,10 +126,11 @@ options.general.color.descriptor.vcs.annotations=VCS annotations
|
||||
options.general.color.descriptor.vcs.annotations.merged=VCS annotations (merged from)
|
||||
options.general.color.descriptor.tearline=Tear line
|
||||
options.general.color.descriptor.tearline.selected=Selected tear line
|
||||
options.general.color.descriptor.added.lines=Added lines
|
||||
options.general.color.descriptor.modified.lines=Modified lines
|
||||
options.general.color.descriptor.deleted.lines=Deleted lines
|
||||
options.general.color.descriptor.whitespaces.modified.lines=Minor modified lines
|
||||
options.general.color.descriptor.added.lines=Added lines in gutter
|
||||
options.general.color.descriptor.modified.lines=Modified lines in gutter
|
||||
options.general.color.descriptor.deleted.lines=Deleted lines in gutter
|
||||
options.general.color.descriptor.whitespaces.modified.lines=Minor modified lines in gutter
|
||||
options.general.color.descriptor.border.lines=Border for changed lines in gutter
|
||||
options.general.color.descriptor.console.background=Console background
|
||||
options.general.color.descriptor.console.stdout=Console standard output
|
||||
options.general.color.descriptor.console.stderr=Console error output
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
<!-- Codeinsight -->
|
||||
<breadcrumbsInfoProvider implementation="com.intellij.json.breadcrumbs.JsonBreadcrumbsProvider"/>
|
||||
<qualifiedNameProvider implementation="com.intellij.json.navigation.JsonQualifiedNameProvider"/>
|
||||
<completion.contributor language="JSON" implementationClass="com.intellij.json.codeinsight.JsonCompletionContributor"/>
|
||||
<lang.psiStructureViewFactory language="JSON" implementationClass="com.intellij.json.structureView.JsonStructureViewBuilderFactory"/>
|
||||
<lang.foldingBuilder language="JSON" implementationClass="com.intellij.json.editor.folding.JsonFoldingBuilder"/>
|
||||
@@ -58,4 +59,10 @@
|
||||
implementationClass="com.intellij.json.psi.JsonStringLiteralManipulator"/>
|
||||
</extensions>
|
||||
|
||||
|
||||
<extensionPoints>
|
||||
<extensionPoint qualifiedName="com.intellij.json.jsonStandardComplianceProvider"
|
||||
interface="com.intellij.json.codeinsight.JsonStandardComplianceProvider"/>
|
||||
</extensionPoints>
|
||||
|
||||
</idea-plugin>
|
||||
@@ -57,6 +57,7 @@ public interface FileIndex {
|
||||
|
||||
/**
|
||||
* Returns true if <code>file</code> is a source file which belongs to sources of the content.
|
||||
* (Returns true for both source and test source).<p/>
|
||||
* Note that sometimes a file can belong to the content and be a source file but not belong to sources of the content.
|
||||
* This happens if sources of some library are located under the content (so they belong to the project content but not as sources).
|
||||
*
|
||||
|
||||
@@ -125,7 +125,7 @@ public interface ProjectFileIndex extends FileIndex {
|
||||
boolean isLibraryClassFile(@NotNull VirtualFile file);
|
||||
|
||||
/**
|
||||
* Returns true if <code>fileOrDir</code> is a file or directory from the content source or library sources.
|
||||
* Returns true if <code>fileOrDir</code> is a file or directory from the content production/test source or library source.
|
||||
*
|
||||
* @param fileOrDir the file or directory to check.
|
||||
* @return true if the file or directory belongs to project or library sources, false otherwise.
|
||||
|
||||
@@ -250,11 +250,23 @@ public class JBColor extends Color {
|
||||
public static final Color CYAN = cyan;
|
||||
|
||||
public static Color foreground() {
|
||||
return UIUtil.getLabelForeground();
|
||||
return new JBColor(new NotNullProducer<Color>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public Color produce() {
|
||||
return UIUtil.getLabelForeground();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static Color background() {
|
||||
return UIUtil.getListBackground();
|
||||
return new JBColor(new NotNullProducer<Color>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public Color produce() {
|
||||
return UIUtil.getListBackground();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static Color border() {
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.intellij.util.containers;
|
||||
|
||||
import com.intellij.util.containers.hash.LinkedHashMap;
|
||||
@@ -26,15 +25,15 @@ import java.util.Map;
|
||||
* @author Evgeny Gerashchenko
|
||||
*/
|
||||
public class LinkedMultiMap<K, V> extends MultiMap<K, V> {
|
||||
@NotNull
|
||||
@Override
|
||||
protected Map<K, Collection<V>> createMap() {
|
||||
return new LinkedHashMap<K, Collection<V>>();
|
||||
}
|
||||
@NotNull
|
||||
@Override
|
||||
protected Map<K, Collection<V>> createMap() {
|
||||
return new LinkedHashMap<K, Collection<V>>();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Map<K, Collection<V>> createMap(int initialCapacity, float loadFactor) {
|
||||
return new LinkedHashMap<K, Collection<V>>(initialCapacity, loadFactor);
|
||||
}
|
||||
@NotNull
|
||||
@Override
|
||||
protected Map<K, Collection<V>> createMap(int initialCapacity, float loadFactor) {
|
||||
return new LinkedHashMap<K, Collection<V>>(initialCapacity, loadFactor);
|
||||
}
|
||||
}
|
||||
|
||||