Merge remote-tracking branch 'origin/master'

This commit is contained in:
Ekaterina Tuzova
2014-11-07 16:27:03 +03:00
199 changed files with 2734 additions and 1746 deletions
+8 -1
View File
@@ -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");
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 504 B

After

Width:  |  Height:  |  Size: 448 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 249 B

After

Width:  |  Height:  |  Size: 175 B

Binary file not shown.

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.
+14 -2
View File
@@ -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);
}
}

Some files were not shown because too many files have changed in this diff Show More