Merge remote-tracking branch 'origin/master'

This commit is contained in:
Vladimir.Orlov
2014-07-02 11:14:55 +04:00
131 changed files with 2751 additions and 1387 deletions
+1 -1
View File
@@ -770,7 +770,7 @@ def layoutJps(String home, String targetDir, String buildNumber, Closure additio
include(name: "jdom.jar")
include(name: "jna.jar")
include(name: "trove4j.jar")
include(name: "asm4-all.jar")
include(name: "asm-all.jar")
include(name: "nanoxml-*.jar")
include(name: "protobuf-*.jar")
include(name: "cli-parser-*.jar")
+1
View File
@@ -226,6 +226,7 @@ binding.setVariable("wireBuildDate", { String buildNumber, String appInfoFile ->
binding.setVariable("commonJvmArgs", {
return [
"-ea",
"-server",
"-Didea.home.path=$home",
"-Xbootclasspath/p:${projectBuilder.moduleOutput(findModule("boot"))}",
"-XX:+HeapDumpOnOutOfMemoryError",
@@ -80,7 +80,8 @@ public class JavaSmartStepIntoHandler extends JvmSmartStepIntoHandler {
//noinspection unchecked
final List<SmartStepTarget> targets = new OrderedSet<SmartStepTarget>();
final Range<Integer> lines = new Range<Integer>(doc.getLineNumber(element.getTextOffset()), doc.getLineNumber(element.getTextOffset() + element.getTextLength()));
TextRange textRange = element.getTextRange();
final Range<Integer> lines = new Range<Integer>(doc.getLineNumber(textRange.getStartOffset()), doc.getLineNumber(textRange.getEndOffset()));
final PsiElementVisitor methodCollector = new JavaRecursiveElementVisitor() {
final Stack<PsiMethod> myContextStack = new Stack<PsiMethod>();
@@ -20,7 +20,6 @@ import com.intellij.debugger.engine.evaluation.TextWithImportsImpl;
import com.intellij.debugger.engine.events.DebuggerContextCommandImpl;
import com.intellij.debugger.impl.EditorTextProvider;
import com.intellij.debugger.ui.impl.watch.WatchItemDescriptor;
import com.intellij.debugger.ui.tree.render.DescriptorLabelListener;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
@@ -60,6 +59,11 @@ public class JavaDebuggerEvaluator extends XDebuggerEvaluator {
@NotNull final XEvaluationCallback callback,
@Nullable XSourcePosition expressionPosition) {
myDebugProcess.getManagerThread().schedule(new DebuggerContextCommandImpl(myDebugProcess.getDebuggerContext()) {
@Override
public Priority getPriority() {
return Priority.NORMAL;
}
@Override
public void threadAction() {
WatchItemDescriptor descriptor = new WatchItemDescriptor(myDebugProcess.getProject(), TextWithImportsImpl.fromXExpression(
@@ -33,6 +33,7 @@ import com.intellij.openapi.components.*;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.CommonClassNames;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiElementFactory;
@@ -546,7 +547,12 @@ public class NodeRendererSettings implements PersistentStateComponent<Element> {
}
static String constructLabelText(final String keylabel, final String valueLabel) {
return keylabel + " -> " + valueLabel;
StringBuilder sb = new StringBuilder();
sb.append('\"').append(keylabel).append("\" -> ");
if (!StringUtil.isEmpty(valueLabel)) {
sb.append('\"').append(valueLabel).append('\"');
}
return sb.toString();
}
private static String getDescriptorLabel(final ValueDescriptorImpl keyDescriptor) {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 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,13 +18,19 @@ package com.intellij.ide.actions;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.options.ex.SingleConfigurableEditor;
import com.intellij.openapi.options.newEditor.OptionsEditorDialog;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurable;
import com.intellij.openapi.util.registry.Registry;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
public class ShowStructureSettingsAction extends AnAction implements DumbAware {
public void actionPerformed(AnActionEvent e) {
@@ -33,6 +39,23 @@ public class ShowStructureSettingsAction extends AnAction implements DumbAware {
project = ProjectManager.getInstance().getDefaultProject();
}
ShowSettingsUtil.getInstance().editConfigurable(project, OptionsEditorDialog.DIMENSION_KEY, ProjectStructureConfigurable.getInstance(project));
if (Registry.is("ide.new.project.settings")) {
new SingleConfigurableEditor(project, ProjectStructureConfigurable.getInstance(project), OptionsEditorDialog.DIMENSION_KEY) {
@Nullable
@Override
protected Border createContentPaneBorder() {
return new EmptyBorder(0,0,0,0);
}
@Nullable
@Override
protected JComponent createSouthPanel() {
return null;
}
}.show();
} else {
ShowSettingsUtil
.getInstance().editConfigurable(project, OptionsEditorDialog.DIMENSION_KEY, ProjectStructureConfigurable.getInstance(project));
}
}
}
@@ -21,6 +21,7 @@ import com.intellij.ide.util.newProjectWizard.StepSequence;
import com.intellij.ide.util.projectWizard.ModuleWizardStep;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
import com.intellij.openapi.util.Disposer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -46,6 +47,7 @@ public class NewProjectWizard extends AbstractProjectWizard {
protected void init(@NotNull ModulesProvider modulesProvider) {
myWizardContext.setNewWizard(true);
ProjectTypeStep projectTypeStep = new ProjectTypeStep(myWizardContext, this, modulesProvider);
Disposer.register(getDisposable(), projectTypeStep);
mySequence.addCommonStep(projectTypeStep);
ChooseTemplateStep chooseTemplateStep = new ChooseTemplateStep(myWizardContext, projectTypeStep);
mySequence.addCommonStep(chooseTemplateStep);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 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.
@@ -37,6 +37,7 @@ import com.intellij.openapi.roots.impl.libraries.LibraryEx;
import com.intellij.openapi.roots.impl.libraries.LibraryTableBase;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.ui.navigation.History;
import com.intellij.ui.navigation.Place;
import com.intellij.util.EventDispatcher;
@@ -238,9 +239,10 @@ public abstract class ModuleEditor implements Place.Navigator, Disposable {
createEditors(getModule());
JPanel northPanel = new JPanel(new GridBagLayout());
myGenericSettingsPanel.add(northPanel, BorderLayout.NORTH);
if (!Registry.is("ide.new.project.settings")) {
JPanel northPanel = new JPanel(new GridBagLayout());
myGenericSettingsPanel.add(northPanel, BorderLayout.NORTH);
}
final JComponent component = createCenterPanel();
myGenericSettingsPanel.add(component, BorderLayout.CENTER);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 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.
@@ -38,11 +38,13 @@ import com.intellij.openapi.roots.ui.configuration.artifacts.ArtifactsStructureC
import com.intellij.openapi.roots.ui.configuration.projectRoot.*;
import com.intellij.openapi.ui.DetailsComponent;
import com.intellij.openapi.ui.MasterDetailsComponent;
import com.intellij.openapi.ui.Splitter;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.wm.ex.IdeFocusTraversalPolicy;
import com.intellij.packaging.artifacts.Artifact;
import com.intellij.ui.Gray;
import com.intellij.ui.JBSplitter;
import com.intellij.ui.components.panels.Wrapper;
import com.intellij.ui.navigation.BackAction;
import com.intellij.ui.navigation.ForwardAction;
@@ -67,7 +69,7 @@ public class ProjectStructureConfigurable extends BaseConfigurable implements Se
public static final DataKey<ProjectStructureConfigurable> KEY = DataKey.create("ProjectStructureConfiguration");
protected final UIState myUiState = new UIState();
private Splitter mySplitter;
private JBSplitter mySplitter;
private JComponent myToolbarComponent;
@NonNls public static final String CATEGORY = "category";
private JComponent myToFocus;
@@ -173,8 +175,16 @@ public class ProjectStructureConfigurable extends BaseConfigurable implements Se
public JComponent createComponent() {
myComponent = new MyPanel();
mySplitter = new Splitter(false, .15f);
mySplitter = new JBSplitter(false, .15f);
mySplitter.setSplitterProportionKey("ProjectStructure.TopLevelElements");
mySplitter.setHonorComponentsMinimumSize(true);
if (Registry.is("ide.new.project.settings")) {
mySplitter.setDividerWidth(1);
mySplitter.setShowDividerIcon(false);
mySplitter.getDivider().setBackground(Gray._153.withAlpha(128));
mySplitter.setShowDividerControls(false);
mySplitter.setOrientation(mySplitter.getOrientation());
}
initSidePanel();
@@ -192,7 +202,11 @@ public class ProjectStructureConfigurable extends BaseConfigurable implements Se
final ActionToolbar toolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, toolbarGroup, true);
toolbar.setTargetComponent(myComponent);
myToolbarComponent = toolbar.getComponent();
left.add(myToolbarComponent, BorderLayout.NORTH);
if (Registry.is("ide.new.project.settings")) {
left.setBackground(new Color(0xD2D6DD));
} else {
left.add(myToolbarComponent, BorderLayout.NORTH);
}
left.add(mySidePanel, BorderLayout.CENTER);
mySplitter.setFirstComponent(left);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 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.
@@ -17,14 +17,17 @@ package com.intellij.openapi.roots.ui.configuration;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.ui.popup.ListItemDescriptor;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.components.JBList;
import com.intellij.ui.navigation.History;
import com.intellij.ui.navigation.Place;
import com.intellij.ui.popup.list.GroupedItemsListRenderer;
import com.intellij.util.ui.EmptyIcon;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
@@ -52,7 +55,10 @@ public class SidePanel extends JPanel {
myModel = new DefaultListModel();
myList = new JBList(myModel);
if (Registry.is("ide.new.project.settings")) {
myList.setBackground(new Color(0xD2D6DD));
myList.setBorder(new EmptyBorder(5, 0, 0, 0));
}
final ListItemDescriptor descriptor = new ListItemDescriptor() {
@Override
public String getTextFor(final Object value) {
@@ -66,7 +72,7 @@ public class SidePanel extends JPanel {
@Override
public Icon getIconFor(final Object value) {
return null;
return Registry.is("ide.new.project.settings") ? EmptyIcon.create(16, 20) : null;
//return myPlace2Presentation.get(value).getIcon();
}
@@ -78,14 +84,22 @@ public class SidePanel extends JPanel {
@Override
public String getCaptionAboveOf(final Object value) {
return myIndex2Separator.get(myPlaces.indexOf(value));
String text = myIndex2Separator.get(myPlaces.indexOf(value));
return text != null && Registry.is("ide.new.project.settings") ? text.toUpperCase() : text;
}
};
myList.setCellRenderer(new GroupedItemsListRenderer(descriptor));
myList.setCellRenderer(new GroupedItemsListRenderer(descriptor) {
{
mySeparatorComponent.setCaptionCentered(false);
}
@Override
protected Color getBackground() {
return Registry.is("ide.new.project.settings") ? new Color(0xD2D6DD) : super.getBackground();
}
});
add(ScrollPaneFactory.createScrollPane(myList), BorderLayout.CENTER);
add(ScrollPaneFactory.createScrollPane(myList, Registry.is("ide.new.project.settings")), BorderLayout.CENTER);
myList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
myList.addListSelectionListener(new ListSelectionListener() {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 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.
@@ -38,6 +38,8 @@ import com.intellij.openapi.ui.NamedConfigurable;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.packaging.artifacts.Artifact;
import com.intellij.ui.TreeSpeedSearch;
import com.intellij.ui.awt.RelativePoint;
@@ -300,7 +302,9 @@ public abstract class BaseStructureConfigurable extends MasterDetailsComponent i
result.addAll(copyActions);
result.add(Separator.getInstance());
result.add(new MyFindUsagesAction(myTree));
if (fromPopup || !(SystemInfo.isMac && Registry.is("ide.new.project.settings"))) {
result.add(new MyFindUsagesAction(myTree));
}
return result;
@@ -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.
@@ -53,7 +53,9 @@ import com.intellij.openapi.ui.*;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.NullableComputable;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
@@ -149,7 +151,9 @@ public class ModuleStructureConfigurable extends BaseStructureConfigurable imple
final ArrayList<AnAction> result = super.createActions(fromPopup);
result.add(Separator.getInstance());
result.add(new MyGroupAction());
addCollapseExpandActions(result);
if (fromPopup || !(SystemInfo.isMac && Registry.is("ide.new.project.settings"))) {
addCollapseExpandActions(result);
}
return result;
}
@@ -53,6 +53,7 @@ import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.Consumer;
import com.intellij.util.ObjectUtils;
import com.intellij.util.PairConsumer;
import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NotNull;
@@ -340,6 +341,7 @@ public class JavaCompletionContributor extends CompletionContributor {
}
final Object[] variants = reference.getVariants();
//noinspection ConstantConditions
if (variants == null) {
LOG.error("Reference=" + reference);
}
@@ -365,6 +367,7 @@ public class JavaCompletionContributor extends CompletionContributor {
}
else {
//noinspection deprecation
LookupElement element = LookupItemUtil.objectToLookupItem(completion);
usedWords.add(element.getLookupString());
result.addElement(element);
@@ -434,7 +437,7 @@ public class JavaCompletionContributor extends CompletionContributor {
private static void completeAnnotationAttributeName(CompletionResultSet result, PsiElement insertedElement,
CompletionParameters parameters) {
PsiNameValuePair pair = PsiTreeUtil.getParentOfType(insertedElement, PsiNameValuePair.class);
PsiAnnotationParameterList parameterList = (PsiAnnotationParameterList)pair.getParent();
PsiAnnotationParameterList parameterList = (PsiAnnotationParameterList)ObjectUtils.assertNotNull(pair).getParent();
PsiAnnotation anno = (PsiAnnotation)parameterList.getParent();
boolean showClasses = psiElement().afterLeaf("(").accepts(insertedElement);
PsiClass annoClass = null;
@@ -507,7 +510,7 @@ public class JavaCompletionContributor extends CompletionContributor {
if (psiElement().withParent(psiReferenceExpression().withFirstChild(psiReferenceExpression().referencing(psiClass()))).accepts(position)) {
if (CompletionUtil.shouldShowFeature(parameters, JavaCompletionFeatures.GLOBAL_MEMBER_NAME)) {
final String shortcut = getActionShortcut(IdeActions.ACTION_CODE_COMPLETION);
if (shortcut != null) {
if (StringUtil.isNotEmpty(shortcut)) {
return "Pressing " + shortcut + " twice without a class qualifier would show all accessible static methods";
}
}
@@ -517,7 +520,7 @@ public class JavaCompletionContributor extends CompletionContributor {
if (parameters.getCompletionType() != CompletionType.SMART && shouldSuggestSmartCompletion(parameters.getPosition())) {
if (CompletionUtil.shouldShowFeature(parameters, CodeCompletionFeatures.EDITING_COMPLETION_SMARTTYPE_GENERAL)) {
final String shortcut = getActionShortcut(IdeActions.ACTION_SMART_TYPE_COMPLETION);
if (shortcut != null) {
if (StringUtil.isNotEmpty(shortcut)) {
return CompletionBundle.message("completion.smart.hint", shortcut);
}
}
@@ -528,7 +531,7 @@ public class JavaCompletionContributor extends CompletionContributor {
if (psiTypes.length > 0) {
if (CompletionUtil.shouldShowFeature(parameters, JavaCompletionFeatures.SECOND_SMART_COMPLETION_TOAR)) {
final String shortcut = getActionShortcut(IdeActions.ACTION_SMART_TYPE_COMPLETION);
if (shortcut != null) {
if (StringUtil.isNotEmpty(shortcut)) {
for (final PsiType psiType : psiTypes) {
final PsiType type = PsiUtil.extractIterableTypeParameter(psiType, false);
if (type != null) {
@@ -539,7 +542,7 @@ public class JavaCompletionContributor extends CompletionContributor {
}
if (CompletionUtil.shouldShowFeature(parameters, JavaCompletionFeatures.SECOND_SMART_COMPLETION_ASLIST)) {
final String shortcut = getActionShortcut(IdeActions.ACTION_SMART_TYPE_COMPLETION);
if (shortcut != null) {
if (StringUtil.isNotEmpty(shortcut)) {
for (final PsiType psiType : psiTypes) {
if (psiType instanceof PsiArrayType) {
final PsiType componentType = ((PsiArrayType)psiType).getComponentType();
@@ -553,7 +556,7 @@ public class JavaCompletionContributor extends CompletionContributor {
if (CompletionUtil.shouldShowFeature(parameters, JavaCompletionFeatures.SECOND_SMART_COMPLETION_CHAIN)) {
final String shortcut = getActionShortcut(IdeActions.ACTION_SMART_TYPE_COMPLETION);
if (shortcut != null) {
if (StringUtil.isNotEmpty(shortcut)) {
return CompletionBundle.message("completion.smart.chain.hint", shortcut);
}
}
@@ -639,9 +642,12 @@ public class JavaCompletionContributor extends CompletionContributor {
final PsiFile file = context.getFile();
if (file instanceof PsiJavaFile) {
JavaCompletionUtil.initOffsets(file, context.getOffsetMap());
if (context.getInvocationCount() > 0) {
autoImport(file, context.getStartOffset() - 1, context.getEditor());
PsiDocumentManager.getInstance(context.getProject()).commitDocument(context.getEditor().getDocument());
}
autoImport(file, context.getStartOffset() - 1, context.getEditor());
JavaCompletionUtil.initOffsets(file, context.getOffsetMap());
if (context.getCompletionType() == CompletionType.BASIC) {
if (semicolonNeeded(context.getEditor(), file, context.getStartOffset())) {
@@ -103,10 +103,11 @@ public class PsiTypeLookupItem extends LookupItem {
myImportFixer.handleInsert(context, this);
PsiElement position = context.getFile().findElementAt(context.getStartOffset());
assert position != null;
int genericsStart = context.getTailOffset();
context.getDocument().insertString(genericsStart, JavaCompletionUtil.escapeXmlIfNeeded(context, calcGenerics(position, context)));
JavaCompletionUtil.shortenReference(context.getFile(), genericsStart - 1);
if (position != null) {
int genericsStart = context.getTailOffset();
context.getDocument().insertString(genericsStart, JavaCompletionUtil.escapeXmlIfNeeded(context, calcGenerics(position, context)));
JavaCompletionUtil.shortenReference(context.getFile(), genericsStart - 1);
}
int tail = context.getTailOffset();
String braces = StringUtil.repeat("[]", getBracketsCount());
@@ -229,4 +229,9 @@ public class JavaArrangementParseInfo {
public List<ArrangementEntryDependencyInfo> getFieldDependencyRoots() {
return new FieldDependenciesManager(myFieldDependencies, myFields).getRoots();
}
@NotNull
public Collection<JavaElementArrangementEntry> getFields() {
return myFields.values();
}
}
@@ -27,6 +27,7 @@ import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.codeStyle.arrangement.engine.ArrangementEngine;
import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingRule;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryMatcher;
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementEntryMatcher;
@@ -34,8 +35,6 @@ import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementCompositeMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementColorsAware;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementStandardSettingsAware;
import com.intellij.psi.codeStyle.arrangement.std.*;
import com.intellij.util.containers.ContainerUtilRt;
import org.jetbrains.annotations.NotNull;
@@ -46,10 +45,10 @@ import java.util.*;
import java.util.List;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.EntryType.*;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.General.*;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Grouping.*;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Modifier.*;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Order.*;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.General.*;
/**
* @author Denis Zhdanov
@@ -250,19 +249,34 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>,
setupOverriddenMethods(parseInfo);
}
}
setupFieldInitializationDependencies(parseInfo.getFieldDependencyRoots());
List<ArrangementEntryDependencyInfo> fieldDependencyRoots = parseInfo.getFieldDependencyRoots();
if (!fieldDependencyRoots.isEmpty()) {
setupFieldInitializationDependencies(fieldDependencyRoots, settings, parseInfo);
}
return parseInfo.getEntries();
}
public void setupFieldInitializationDependencies(@NotNull List<ArrangementEntryDependencyInfo> fieldDependencyRoots) {
public void setupFieldInitializationDependencies(@NotNull List<ArrangementEntryDependencyInfo> fieldDependencyRoots,
@NotNull ArrangementSettings settings,
@NotNull JavaArrangementParseInfo parseInfo)
{
Collection<JavaElementArrangementEntry> fields = parseInfo.getFields();
List<JavaElementArrangementEntry> arrangedFields = ArrangementEngine.arrange(fields, settings.getSections(), settings.getRulesSortedByPriority(), null);
for (ArrangementEntryDependencyInfo root : fieldDependencyRoots) {
JavaElementArrangementEntry anchorField = root.getAnchorEntry();
final int anchorEntryIndex = arrangedFields.indexOf(anchorField);
for (ArrangementEntryDependencyInfo fieldInInitializerInfo : root.getDependentEntriesInfos()) {
anchorField.addDependency(fieldInInitializerInfo.getAnchorEntry());
JavaElementArrangementEntry fieldInInitializer = fieldInInitializerInfo.getAnchorEntry();
if (arrangedFields.indexOf(fieldInInitializer) > anchorEntryIndex) {
anchorField.addDependency(fieldInInitializer);
}
}
}
}
@Override
public int getBlankLines(@NotNull CodeStyleSettings settings,
@Nullable JavaElementArrangementEntry parent,
@@ -17,8 +17,10 @@ package com.intellij.spellchecker;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.psi.JavaTokenType;
import com.intellij.psi.PsiLanguageInjectionHost;
import com.intellij.psi.PsiLiteralExpression;
import com.intellij.psi.PsiModifierListOwner;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.psi.impl.source.tree.java.PsiLiteralExpressionImpl;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.spellchecker.inspections.PlainTextSplitter;
@@ -30,8 +32,6 @@ import org.jetbrains.annotations.NotNull;
import java.util.Collections;
/**
* Created by IntelliJ IDEA.
*
* @author shkate@jetbrains.com
*/
public class LiteralExpressionTokenizer extends Tokenizer<PsiLiteralExpression> {
@@ -42,6 +42,8 @@ public class LiteralExpressionTokenizer extends Tokenizer<PsiLiteralExpression>
return; // not a string literal
}
if (InjectedLanguageUtil.hasInjections((PsiLanguageInjectionHost)element)) return;
final PsiModifierListOwner listOwner = PsiTreeUtil.getParentOfType(element, PsiModifierListOwner.class);
if (listOwner != null && AnnotationUtil.isAnnotated(listOwner, Collections.singleton(AnnotationUtil.NON_NLS), false, false)) {
return;
@@ -48,6 +48,7 @@ import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.Function;
import com.intellij.util.ObjectUtils;
import com.intellij.util.text.CharArrayUtil;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -703,7 +704,7 @@ public abstract class JavaFoldingBuilderBase extends CustomFoldingBuilder implem
else if (element instanceof PsiComment) {
return settings.isCollapseEndOfLineComments();
}
else if (element instanceof PsiLiteralExpression
else if (isLiteralExpression(element)
&& element.getParent() instanceof PsiExpressionList
&& (element.getParent().getParent() instanceof PsiCallExpression
|| element.getParent().getParent() instanceof PsiAnonymousClass)) {
@@ -775,7 +776,7 @@ public abstract class JavaFoldingBuilderBase extends CustomFoldingBuilder implem
for (int i = 0; i < callArguments.length; i++) {
PsiExpression callArgument = callArguments[i];
if (callArgument instanceof PsiLiteralExpression) {
if (isLiteralExpression(callArgument)) {
if (!isResolved) {
PsiMethod method = expression.resolveMethod();
isResolved = true;
@@ -799,6 +800,20 @@ public abstract class JavaFoldingBuilderBase extends CustomFoldingBuilder implem
}
}
@Contract("null -> false")
private static boolean isLiteralExpression(@Nullable PsiElement callArgument) {
if (callArgument instanceof PsiLiteralExpression)
return true;
if (callArgument instanceof PsiPrefixExpression) {
PsiPrefixExpression expr = (PsiPrefixExpression)callArgument;
IElementType tokenType = expr.getOperationTokenType();
return JavaTokenType.MINUS.equals(tokenType) && expr.getOperand() instanceof PsiLiteralExpression;
}
return false;
}
private boolean addClosureFolding(final PsiClass aClass, final Document document, final List<FoldingDescriptor> foldElements,
@NotNull Set<PsiElement> processedComments, final boolean quick) {
if (!JavaCodeFoldingSettings.getInstance().isCollapseLambdas()) {
@@ -0,0 +1,26 @@
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
class Test {
void foo(final Stream<Person> stream) {
final Map<String,List<Person>> mapByFirstLetter = stream.collect(Collectors.groupingBy(p -> "" + p.name.charAt(0)));
final String vV = mapByFirstLetter.values().stream().map(lp -> lp.stream().map(p -> p.name)
.collect(Collectors.joining("/","<",">"))) .collect(Collectors.joining(" : "));
final String vV2 = mapByFirstLetter.values().stream()
.map(lp -> lp.stream().map(Person::getName).collect(Collectors.joining("/","<",">")))
.collect(Collectors.joining(" : "));
System.out.println("mapByFirstLetter2 : "+ vV2);
}
public static class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {return name;}
}
}
@@ -234,6 +234,10 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
doTest();
}
public void testIDEA126109() throws Exception {
doTest();
}
private void doTest() {
doTest(false);
}
@@ -698,6 +698,29 @@ public class CharSymbol {
assert regions[2].placeholderText == "fast: false"
}
public void "test inline negative numbers (IDEA-126753)"() {
def text = """
public class CharSymbol {
public void main() {
Object obj = new Object();
count(-1, obj);
}
public void count(int test, Object obj) {
Object tmp = obj;
boolean isFast = false;
}
}
"""
configure text
def regions = myFixture.editor.foldingModel.allFoldRegions.sort { it.startOffset }
assert regions.size() == 3
checkRangeOffsetByPositionInText(regions[1], text, "-1")
assert regions[1].placeholderText == "test: -1"
}
public void "test inline constructor literal arguments names"() {
def text = """
public class Test {
@@ -328,9 +328,61 @@ class Second extends First {
)
}
void "test IDEA-123875"() {
doTest(
initial: '''\
public class RearrangeFail {
public static final byte[] ENTITIES_END = "</entities>".getBytes();
private final Element entitiesEndElement = new Element(ENTITIES_END);
public static final byte[] ENTITIES_START = "<entities>".getBytes();
private final Element entitiesStartElement = new Element(ENTITIES_START);
}
''',
expected: '''\
public class RearrangeFail {
public static final byte[] ENTITIES_END = "</entities>".getBytes();
public static final byte[] ENTITIES_START = "<entities>".getBytes();
private final Element entitiesEndElement = new Element(ENTITIES_END);
private final Element entitiesStartElement = new Element(ENTITIES_START);
}
''',
rules: [
rule(PUBLIC, STATIC, FINAL),
rule(PRIVATE),
]
)
}
void "test IDEA-125099"() {
doTest(
initial: '''\
public class test {
private int a = 2;
public static final String TEST = "1";
public static final String SHOULD_BE_IN_BETWEEN = "2";
public static final String USERS_ROLE_ID_COLUMN = TEST;
}
''',
expected: '''\
public class test {
public static final String TEST = "1";
public static final String SHOULD_BE_IN_BETWEEN = "2";
public static final String USERS_ROLE_ID_COLUMN = TEST;
private int a = 2;
}
''',
rules: [
rule(PUBLIC, STATIC, FINAL),
rule(PRIVATE)
]
)
}
}
@@ -25,7 +25,8 @@ import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
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
assert Patches.HACK_USED_WHICH_IS_FIXED_IN_JDK8;
// fixed in JDK8
assert Patches.JDK_BUG_ID_7103570;
}
public volatile int myCounter;
@@ -60,6 +60,7 @@ public class VFileContentChangeEvent extends VFileEvent {
return "VfsEvent[update: " + myFile.getUrl() + "]";
}
@NotNull
@Override
public String getPath() {
return myFile.getPath();
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 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.
@@ -29,7 +29,7 @@ public class VFileCopyEvent extends VFileEvent {
private final VirtualFile myNewParent;
private final String myNewChildName;
public VFileCopyEvent(final Object requestor, final VirtualFile file, final VirtualFile newParent, final String newChildName) {
public VFileCopyEvent(final Object requestor, @NotNull VirtualFile file, @NotNull VirtualFile newParent, @NotNull String newChildName) {
super(requestor, false);
myFile = file;
myNewParent = newParent;
@@ -37,23 +37,28 @@ public class VFileCopyEvent extends VFileEvent {
}
@Override
@NotNull
public VirtualFile getFile() {
return myFile;
}
@NotNull
public VirtualFile getNewParent() {
return myNewParent;
}
@NotNull
public String getNewChildName() {
return myNewChildName;
}
@Override
@NonNls
public String toString() {
return "VfsEvent[copy " + myFile +" to " + myNewParent + " as " + myNewChildName +"]";
}
@NotNull
@Override
public String getPath() {
return myNewParent.getPath() + "/" + myNewChildName;
@@ -70,6 +75,7 @@ public class VFileCopyEvent extends VFileEvent {
return myFile.isValid() && myNewParent.findChild(myNewChildName) == null;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
@@ -83,9 +89,9 @@ public class VFileCopyEvent extends VFileEvent {
return true;
}
@Override
public int hashCode() {
int result;
result = myFile.hashCode();
int result = myFile.hashCode();
result = 31 * result + myNewParent.hashCode();
result = 31 * result + myNewChildName.hashCode();
return result;
@@ -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,9 +24,9 @@ import org.jetbrains.annotations.NotNull;
* @author max
*/
public class VFileCreateEvent extends VFileEvent {
private final VirtualFile myParent;
@NotNull private final VirtualFile myParent;
private final boolean myDirectory;
private final String myChildName;
@NotNull private final String myChildName;
private final boolean myReCreation;
private VirtualFile myCreatedFile;
@@ -51,6 +51,7 @@ public class VFileCreateEvent extends VFileEvent {
myReCreation = isReCreation;
}
@NotNull
public String getChildName() {
return myChildName;
}
@@ -59,6 +60,7 @@ public class VFileCreateEvent extends VFileEvent {
return myDirectory;
}
@NotNull
public VirtualFile getParent() {
return myParent;
}
@@ -74,6 +76,7 @@ public class VFileCreateEvent extends VFileEvent {
myChildName + " in " + myParent.getUrl() + "]";
}
@NotNull
@Override
public String getPath() {
return myParent.getPath() + "/" + myChildName;
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 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.
@@ -40,11 +40,13 @@ public class VFileDeleteEvent extends VFileEvent {
return myFile;
}
@Override
@NonNls
public String toString() {
return "VfsEvent[deleted: " + myFile.getUrl() + "]";
}
@NotNull
@Override
public String getPath() {
return myFile.getPath();
@@ -61,6 +63,7 @@ public class VFileDeleteEvent extends VFileEvent {
return myFile.isValid();
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
@@ -70,6 +73,7 @@ public class VFileDeleteEvent extends VFileEvent {
return myFile.equals(event.myFile);
}
@Override
public int hashCode() {
return myFile.hashCode();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 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.
@@ -41,6 +41,7 @@ public abstract class VFileEvent {
return myRequestor;
}
@NotNull
public abstract String getPath();
/**
@@ -58,6 +59,8 @@ public abstract class VFileEvent {
public abstract boolean isValid();
@Override
public abstract int hashCode();
@Override
public abstract boolean equals(Object o);
}
@@ -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.
@@ -30,7 +30,7 @@ public class VFileMoveEvent extends VFileEvent {
private final VirtualFile myOldParent;
private final VirtualFile myNewParent;
public VFileMoveEvent(final Object requestor, @NotNull final VirtualFile file, final VirtualFile newParent) {
public VFileMoveEvent(final Object requestor, @NotNull VirtualFile file, @NotNull VirtualFile newParent) {
super(requestor, false);
myFile = file;
myNewParent = newParent;
@@ -43,6 +43,7 @@ public class VFileMoveEvent extends VFileEvent {
return myFile;
}
@NotNull
public VirtualFile getNewParent() {
return myNewParent;
}
@@ -51,11 +52,13 @@ public class VFileMoveEvent extends VFileEvent {
return myOldParent;
}
@Override
@NonNls
public String toString() {
return "VfsEvent[move " + myFile.getName() +" from " + myOldParent + " to " + myNewParent + "]";
}
@NotNull
@Override
public String getPath() {
return myFile.getPath();
@@ -72,6 +75,7 @@ public class VFileMoveEvent extends VFileEvent {
return myFile.isValid() && Comparing.equal(myFile.getParent(), myOldParent) && myOldParent.isValid();
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
@@ -85,9 +89,9 @@ public class VFileMoveEvent extends VFileEvent {
return true;
}
@Override
public int hashCode() {
int result;
result = myFile.hashCode();
int result = myFile.hashCode();
result = 31 * result + myOldParent.hashCode();
result = 31 * result + myNewParent.hashCode();
return result;
@@ -91,6 +91,7 @@ public class VFilePropertyChangeEvent extends VFileEvent {
return myPropertyName;
}
@NotNull
@Override
public String getPath() {
return myFile.getPath();
@@ -131,6 +132,7 @@ public class VFilePropertyChangeEvent extends VFileEvent {
return result;
}
@Override
@NotNull
@NonNls
public String toString() {
@@ -114,6 +114,9 @@ public class PsiFileFactoryImpl extends PsiFileFactory {
final PsiFile psiFile = viewProvider.getPsi(language);
if (psiFile != null) {
if (markAsCopy) {
if (psiFile.getNode() == null) {
throw new AssertionError("No node for file " + psiFile + "; language=" + language);
}
markGenerated(psiFile);
}
return psiFile;
@@ -21,6 +21,7 @@ import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiUtilBase;
import com.intellij.util.ObjectUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -40,13 +41,15 @@ public class CompletionInitializationContext {
private final Editor myEditor;
private final PsiFile myFile;
private final CompletionType myCompletionType;
private final int myInvocationCount;
private final OffsetMap myOffsetMap;
private String myDummyIdentifier = DUMMY_IDENTIFIER;
public CompletionInitializationContext(final Editor editor, final PsiFile file, final CompletionType completionType) {
public CompletionInitializationContext(final Editor editor, final PsiFile file, final CompletionType completionType, int invocationCount) {
myEditor = editor;
myFile = file;
myCompletionType = completionType;
myInvocationCount = invocationCount;
myOffsetMap = new OffsetMap(editor.getDocument());
myOffsetMap.addOffset(START_OFFSET, calcStartOffset(editor));
@@ -79,7 +82,7 @@ public class CompletionInitializationContext {
@NotNull
public Language getPositionLanguage() {
return PsiUtilBase.getLanguageInEditor(getEditor(), getProject());
return ObjectUtils.assertNotNull(PsiUtilBase.getLanguageInEditor(getEditor(), getProject()));
}
public String getDummyIdentifier() {
@@ -127,9 +130,12 @@ public class CompletionInitializationContext {
return getIdentifierEndOffset();
}
public int getInvocationCount() {
return myInvocationCount;
}
/**
* Mark the offset up to which the text will be deleted if a completion variant is selected using Replace character (Tab)
* @param idEnd
*/
public void setReplacementOffset(int idEnd) {
myOffsetMap.addOffset(IDENTIFIER_END_OFFSET, idEnd);
@@ -43,30 +43,30 @@ public class EnvironmentVariablesComponent extends LabeledComponent<TextFieldWit
@NonNls private static final String OPTION = "option";
@NonNls private static final String ENV_VARIABLES = "ENV_VARIABLES";
private final EnvironmentVariablesTextField myEnvsTextField;
private final EnvironmentVariablesTextFieldWithBrowseButton myEnvVars;
public EnvironmentVariablesComponent() {
super();
myEnvsTextField = new EnvironmentVariablesTextField();
setComponent(myEnvsTextField.getComponent());
myEnvVars = new EnvironmentVariablesTextFieldWithBrowseButton();
setComponent(myEnvVars);
setText(ExecutionBundle.message("environment.variables.component.title"));
}
public void setEnvs(@NotNull Map<String, String> envs) {
myEnvsTextField.setEnvs(envs);
myEnvVars.setEnvs(envs);
}
@NotNull
public Map<String, String> getEnvs() {
return myEnvsTextField.getEnvs();
return myEnvVars.getEnvs();
}
public boolean isPassParentEnvs() {
return myEnvsTextField.isPassParentEnvs();
return myEnvVars.isPassParentEnvs();
}
public void setPassParentEnvs(final boolean passParentEnvs) {
myEnvsTextField.setPassParentEnvs(passParentEnvs);
myEnvVars.setPassParentEnvs(passParentEnvs);
}
public static void readExternal(Element element, Map<String, String> envs) {
@@ -93,12 +93,10 @@ public class EnvironmentVariablesComponent extends LabeledComponent<TextFieldWit
private static void splitVars(final Map<String, String> envs, final String val) {
if (val != null) {
final String[] envVars = val.split(";");
if (envVars != null) {
for (String envVar : envVars) {
final int idx = envVar.indexOf('=');
if (idx > -1) {
envs.put(envVar.substring(0, idx), idx < envVar.length() - 1 ? envVar.substring(idx + 1) : "");
}
for (String envVar : envVars) {
final int idx = envVar.indexOf('=');
if (idx > -1) {
envs.put(envVar.substring(0, idx), idx < envVar.length() - 1 ? envVar.substring(idx + 1) : "");
}
}
}
@@ -134,11 +132,11 @@ public class EnvironmentVariablesComponent extends LabeledComponent<TextFieldWit
@Override
public void addChangeListener(final ChangeListener changeListener) {
myEnvsTextField.addChangeListener(changeListener);
myEnvVars.addChangeListener(changeListener);
}
@Override
public void removeChangeListener(final ChangeListener changeListener) {
myEnvsTextField.removeChangeListener(changeListener);
myEnvVars.removeChangeListener(changeListener);
}
}
@@ -34,17 +34,16 @@ import java.awt.event.ActionListener;
import java.util.*;
import java.util.List;
public class EnvironmentVariablesTextField {
public class EnvironmentVariablesTextFieldWithBrowseButton extends TextFieldWithBrowseButton {
private final TextFieldWithBrowseButton myEnvsTextField;
private final Map<String, String> myEnvs = new THashMap<String, String>();
private boolean myPassParentEnvs;
private final List<ChangeListener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
public EnvironmentVariablesTextField() {
myEnvsTextField = new TextFieldWithBrowseButton();
myEnvsTextField.setEditable(false);
myEnvsTextField.addActionListener(new ActionListener() {
public EnvironmentVariablesTextFieldWithBrowseButton() {
super();
setEditable(false);
addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
new MyEnvironmentVariablesDialog().show();
@@ -52,11 +51,6 @@ public class EnvironmentVariablesTextField {
});
}
@NotNull
public TextFieldWithBrowseButton getComponent() {
return myEnvsTextField;
}
@NotNull
public Map<String, String> getEnvs() {
return myEnvs;
@@ -66,7 +60,7 @@ public class EnvironmentVariablesTextField {
myEnvs.clear();
myEnvs.putAll(envs);
String envsStr = stringifyEnvs(myEnvs);
myEnvsTextField.setText(envsStr);
setText(envsStr);
}
@NotNull
@@ -115,7 +109,7 @@ public class EnvironmentVariablesTextField {
private final JPanel myWholePanel = new JPanel(new BorderLayout());
protected MyEnvironmentVariablesDialog() {
super(myEnvsTextField, true);
super(EnvironmentVariablesTextFieldWithBrowseButton.this, true);
myEnvVariablesTable = new EnvVariablesTable();
List<EnvironmentVariable> envVariables = ContainerUtil.newArrayList();
for (Map.Entry<String, String> entry : myEnvs.entrySet()) {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 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.
@@ -22,6 +22,7 @@ import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.search.SearchScope;
import com.intellij.util.messages.Topic;
import org.intellij.lang.annotations.MagicConstant;
import org.jetbrains.annotations.NotNull;
@@ -217,6 +218,7 @@ public abstract class FindManager {
* @param element the element to find the usages for.
*/
public abstract void findUsages(@NotNull PsiElement element);
public abstract void findUsagesInScope(@NotNull PsiElement element, @NotNull SearchScope searchScope);
/**
* Shows the Find Usages dialog (if {@code showDialog} is true} and performs the Find Usages operation for the
@@ -135,19 +135,18 @@ public class CodeCompletionHandlerBase {
}
*/
int newTime = phase.newCompletionStarted(time, repeated);
final int newTime = phase.newCompletionStarted(time, repeated);
if (invokedExplicitly) {
time = newTime;
}
final int invocationCount = time;
if (CompletionServiceImpl.isPhase(CompletionPhase.InsertedSingleItem.class)) {
CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion);
}
CompletionServiceImpl.assertPhase(CompletionPhase.NoCompletion.getClass(), CompletionPhase.CommittingDocuments.class);
if (time > 1) {
if (myCompletionType == CompletionType.BASIC) {
FeatureUsageTracker.getInstance().triggerFeatureUsed(CodeCompletionFeatures.SECOND_BASIC_COMPLETION);
}
if (invocationCount > 1 && myCompletionType == CompletionType.BASIC) {
FeatureUsageTracker.getInstance().triggerFeatureUsed(CodeCompletionFeatures.SECOND_BASIC_COMPLETION);
}
final CompletionInitializationContext[] initializationContext = {null};
@@ -168,7 +167,7 @@ public class CodeCompletionHandlerBase {
psiFile.putUserData(PsiFileEx.BATCH_REFERENCE_PROCESSING, Boolean.TRUE);
CompletionAssertions.assertCommitSuccessful(editor, psiFile);
initializationContext[0] = runContributorsBeforeCompletion(editor, psiFile);
initializationContext[0] = runContributorsBeforeCompletion(editor, psiFile, invocationCount);
}
};
ApplicationManager.getApplication().runWriteAction(runnable);
@@ -184,12 +183,12 @@ public class CodeCompletionHandlerBase {
CommandProcessor.getInstance().executeCommand(project, initCmd, null, null);
}
insertDummyIdentifier(initializationContext[0], hasModifiers, time);
insertDummyIdentifier(initializationContext[0], hasModifiers, invocationCount);
}
private CompletionInitializationContext runContributorsBeforeCompletion(Editor editor, PsiFile psiFile) {
private CompletionInitializationContext runContributorsBeforeCompletion(Editor editor, PsiFile psiFile, int invocationCount) {
final Ref<CompletionContributor> current = Ref.create(null);
CompletionInitializationContext context = new CompletionInitializationContext(editor, psiFile, myCompletionType) {
CompletionInitializationContext context = new CompletionInitializationContext(editor, psiFile, myCompletionType, invocationCount) {
CompletionContributor dummyIdentifierChanger;
@Override
@@ -759,10 +758,12 @@ public class CodeCompletionHandlerBase {
}
if (context.getCompletionChar() == Lookup.COMPLETE_STATEMENT_SELECT_CHAR) {
final Language language = PsiUtilBase.getLanguageInEditor(editor, project);
final List<SmartEnterProcessor> processors = SmartEnterProcessors.INSTANCE.forKey(language);
if (processors.size() > 0) {
for (SmartEnterProcessor processor : processors) {
processor.process(project, editor, indicator.getParameters().getOriginalFile());
if (language != null) {
final List<SmartEnterProcessor> processors = SmartEnterProcessors.INSTANCE.forKey(language);
if (processors.size() > 0) {
for (SmartEnterProcessor processor : processors) {
processor.process(project, editor, indicator.getParameters().getOriginalFile());
}
}
}
}
@@ -21,6 +21,7 @@ import com.intellij.codeHighlighting.Pass;
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzerSettings;
import com.intellij.codeInsight.hint.TooltipController;
import com.intellij.ide.IdeTooltipManager;
import com.intellij.ide.PowerSaveMode;
import com.intellij.ide.todo.TodoConfiguration;
import com.intellij.openapi.Disposable;
@@ -599,6 +600,7 @@ public class DaemonListeners implements Disposable {
if (editor.offsetToLogicalPosition(offset).column != logical.column) return; // we are in virtual space
HighlightInfo info = myDaemonCodeAnalyzer.findHighlightByOffset(editor.getDocument(), offset, false);
if (info == null || info.getDescription() == null) return;
if (IdeTooltipManager.getInstance().hasCurrent()) return;
DaemonTooltipUtil.showInfoTooltip(info, editor, offset);
shown = true;
}
@@ -51,10 +51,7 @@ public class LookupOffsets {
private void updateLookupStart(int minPrefixLength) {
int offset = getPivotOffset();
int start = offset - minPrefixLength - myAdditionalPrefix.length() + myRemovedPrefix;
if (start < 0) {
LOG.error("Invalid start offset: o=" + offset + ", mpl=" + minPrefixLength + ", ap=" + myAdditionalPrefix + ", rp=" + myRemovedPrefix);
return;
}
start = Math.max(Math.min(start, myEditor.getDocument().getTextLength()), 0);
if (myLookupStartMarker != null) {
if (myLookupStartMarker.isValid() && myLookupStartMarker.getStartOffset() == start && myLookupStartMarker.getEndOffset() == start) {
return;
@@ -162,16 +162,9 @@ public class ConsoleExecuteAction extends DumbAwareAction {
protected void beforeExecution(@NotNull LanguageConsoleImpl console) {
}
protected boolean shouldExecute(@NotNull LanguageConsoleImpl console) {
protected void runExecuteAction(@NotNull LanguageConsoleImpl console, @Nullable LanguageConsoleView consoleView) {
//noinspection deprecation
beforeExecution(console);
return true;
}
final void runExecuteAction(@NotNull LanguageConsoleImpl console, @Nullable LanguageConsoleView consoleView) {
if (!shouldExecute(console)) {
return;
}
String text = console.prepareExecuteAction(myAddToHistory, myPreserveMarkup, true);
((UndoManagerImpl)UndoManager.getInstance(console.getProject())).invalidateActionsFor(DocumentReferenceManager.getInstance().create(console.getCurrentEditor().getDocument()));
@@ -22,6 +22,7 @@ import com.intellij.facet.FacetManagerAdapter;
import com.intellij.facet.FacetModificationTrackingService;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.util.ModificationTracker;
import com.intellij.openapi.util.ModificationTrackerListener;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.SimpleModificationTracker;
@@ -35,8 +36,8 @@ import java.util.Map;
* @author nik
*/
public class FacetModificationTrackingServiceImpl extends FacetModificationTrackingService {
private final Map<Facet, Pair<FacetModificationTracker, EventDispatcher<ModificationTrackerListener>>> myModificationsTrackers =
new THashMap<Facet, Pair<FacetModificationTracker, EventDispatcher<ModificationTrackerListener>>>();
private final Map<Facet, Pair<SimpleModificationTracker, EventDispatcher<ModificationTrackerListener>>> myModificationsTrackers =
new THashMap<Facet, Pair<SimpleModificationTracker, EventDispatcher<ModificationTrackerListener>>>();
public FacetModificationTrackingServiceImpl(final Module module) {
module.getMessageBus().connect().subscribe(FacetManager.FACETS_TOPIC, new FacetModificationTrackingListener());
@@ -44,14 +45,14 @@ public class FacetModificationTrackingServiceImpl extends FacetModificationTrack
@Override
@NotNull
public FacetModificationTracker getFacetModificationTracker(@NotNull final Facet facet) {
public ModificationTracker getFacetModificationTracker(@NotNull final Facet facet) {
return getFacetInfo(facet).first;
}
private Pair<FacetModificationTracker, EventDispatcher<ModificationTrackerListener>> getFacetInfo(final Facet facet) {
Pair<FacetModificationTracker, EventDispatcher<ModificationTrackerListener>> pair = myModificationsTrackers.get(facet);
private Pair<SimpleModificationTracker, EventDispatcher<ModificationTrackerListener>> getFacetInfo(final Facet facet) {
Pair<SimpleModificationTracker, EventDispatcher<ModificationTrackerListener>> pair = myModificationsTrackers.get(facet);
if (pair == null) {
pair = Pair.create(new FacetModificationTracker(), EventDispatcher.create(ModificationTrackerListener.class));
pair = Pair.create(new SimpleModificationTracker(), EventDispatcher.create(ModificationTrackerListener.class));
myModificationsTrackers.put(facet, pair);
}
return pair;
@@ -59,7 +60,7 @@ public class FacetModificationTrackingServiceImpl extends FacetModificationTrack
@Override
public void incFacetModificationTracker(@NotNull final Facet facet) {
final Pair<FacetModificationTracker, EventDispatcher<ModificationTrackerListener>> pair = getFacetInfo(facet);
final Pair<SimpleModificationTracker, EventDispatcher<ModificationTrackerListener>> pair = getFacetInfo(facet);
pair.first.incModificationCount();
pair.second.getMulticaster().modificationCountChanged(facet);
}
@@ -74,13 +75,10 @@ public class FacetModificationTrackingServiceImpl extends FacetModificationTrack
getFacetInfo(facet).second.removeListener(listener);
}
private static class FacetModificationTracker extends SimpleModificationTracker {
}
private class FacetModificationTrackingListener extends FacetManagerAdapter {
@Override
public void facetConfigurationChanged(@NotNull final Facet facet) {
final Pair<FacetModificationTracker, EventDispatcher<ModificationTrackerListener>> pair = myModificationsTrackers.get(facet);
final Pair<SimpleModificationTracker, EventDispatcher<ModificationTrackerListener>> pair = myModificationsTrackers.get(facet);
if (pair != null) {
pair.first.incModificationCount();
pair.second.getMulticaster().modificationCountChanged(facet);
@@ -37,6 +37,7 @@ import com.intellij.openapi.keymap.KeymapUtil;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.PopupChooserBuilder;
@@ -50,7 +51,6 @@ import com.intellij.pom.Navigatable;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.ProjectScope;
import com.intellij.psi.search.PsiElementProcessor;
import com.intellij.psi.search.SearchScope;
import com.intellij.ui.*;
@@ -84,14 +84,17 @@ import java.awt.event.ActionListener;
import java.util.*;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
public class ShowUsagesAction extends AnAction implements PopupAction {
private final boolean showSettingsDialogBefore;
private static final int USAGES_PAGE_SIZE = 100;
static final NullUsage MORE_USAGES_SEPARATOR = NullUsage.INSTANCE;
static final Usage MORE_USAGES_SEPARATOR = NullUsage.INSTANCE;
private static final UsageNode MORE_USAGES_SEPARATOR_NODE = UsageViewImpl.NULL_NODE;
static final Usage USAGES_OUTSIDE_SCOPE_SEPARATOR = new UsageAdapter();
private static final UsageNode USAGES_OUTSIDE_SCOPE_NODE = new UsageNode(USAGES_OUTSIDE_SCOPE_SEPARATOR, new UsageViewTreeModelBuilder(new UsageViewPresentation(), UsageTarget.EMPTY_ARRAY));
private static final Comparator<UsageNode> USAGE_NODE_COMPARATOR = new Comparator<UsageNode>() {
@Override
@@ -100,8 +103,9 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
if (c2 instanceof StringNode) return -1;
Usage o1 = c1.getUsage();
Usage o2 = c2.getUsage();
if (o1 == MORE_USAGES_SEPARATOR) return 1;
if (o2 == MORE_USAGES_SEPARATOR) return -1;
int weight1 = o1 == USAGES_OUTSIDE_SCOPE_SEPARATOR ? 2 : o1 == MORE_USAGES_SEPARATOR ? 1 : 0;
int weight2 = o2 == USAGES_OUTSIDE_SCOPE_SEPARATOR ? 2 : o2 == MORE_USAGES_SEPARATOR ? 1 : 0;
if (weight1 != weight2) return weight1 - weight2;
VirtualFile v1 = UsageListCellRenderer.getVirtualFile(o1);
VirtualFile v2 = UsageListCellRenderer.getVirtualFile(o2);
@@ -193,26 +197,18 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
private void startFindUsages(@NotNull PsiElement element, @NotNull RelativePoint popupPosition, Editor editor, int maxUsages) {
Project project = element.getProject();
FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(project)).getFindUsagesManager();
FindUsagesHandler handler = findUsagesManager.getNewFindUsagesHandler(element, false);
FindUsagesHandler handler = findUsagesManager.getFindUsagesHandler(element, false);
if (handler == null) return;
if (showSettingsDialogBefore) {
showDialogAndFindUsages(handler, popupPosition, editor, maxUsages);
return;
}
showElementUsages(handler, editor, popupPosition, maxUsages, getDefaultOptions(handler));
showElementUsages(editor, popupPosition, handler, maxUsages, handler.getFindUsagesOptions(DataManager.getInstance().getDataContext()));
}
@NotNull
private static FindUsagesOptions getDefaultOptions(@NotNull FindUsagesHandler handler) {
FindUsagesOptions options = handler.getFindUsagesOptions(DataManager.getInstance().getDataContext());
// by default, scope in FindUsagesOptions is copied from the FindSettings, but we need a default one
options.searchScope = GlobalSearchScope.projectScope(handler.getProject());
return options;
}
private void showElementUsages(@NotNull final FindUsagesHandler handler,
final Editor editor,
private void showElementUsages(final Editor editor,
@NotNull final RelativePoint popupPosition,
@NotNull final FindUsagesHandler handler,
final int maxUsages,
@NotNull final FindUsagesOptions options) {
ApplicationManager.getApplication().assertIsDispatchThread();
@@ -236,30 +232,26 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
usageViewSettings.loadState(savedGlobalSettings);
}
});
final AtomicInteger outOfScopeUsages = new AtomicInteger();
final List<Usage> usages = new ArrayList<Usage>();
final Set<UsageNode> visibleNodes = new LinkedHashSet<UsageNode>();
final MyTable table = new MyTable();
final AsyncProcessIcon processIcon = new AsyncProcessIcon("xxx");
boolean hadMoreSeparator = visibleNodes.remove(MORE_USAGES_SEPARATOR_NODE);
if (hadMoreSeparator) {
usages.add(MORE_USAGES_SEPARATOR);
visibleNodes.add(MORE_USAGES_SEPARATOR_NODE);
}
addUsageNodes(usageView.getRoot(), usageView, new ArrayList<UsageNode>());
TableScrollingUtil.installActions(table);
final List<UsageNode> data = collectData(usages, visibleNodes, usageView, presentation);
setTableModel(table, usageView, data);
setTableModel(table, usageView, data, outOfScopeUsages, options.searchScope);
SpeedSearchBase<JTable> speedSearch = new MySpeedSearch(table);
speedSearch.setComparator(new SpeedSearchComparator(false));
final JBPopup popup = createUsagePopup(usages, visibleNodes, handler, editor, popupPosition,
maxUsages, usageView, options, table, presentation, processIcon, hadMoreSeparator);
maxUsages, usageView, options, table, presentation, processIcon);
Disposer.register(popup, usageView);
@@ -293,7 +285,8 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
copy = new ArrayList<Usage>(usages);
}
rebuildPopup(usageView, copy, nodes, table, popup, presentation, popupPosition, !processIcon.isDisposed());
rebuildPopup(usageView, copy, nodes, table, popup, presentation, popupPosition, !processIcon.isDisposed(), outOfScopeUsages,
options.searchScope);
}
});
@@ -305,11 +298,17 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
}
});
final UsageTarget[] myUsageTarget = {new PsiElement2UsageTargetAdapter(handler.getPsiElement())};
Processor<Usage> collect = new Processor<Usage>() {
private final UsageTarget[] myUsageTarget = {new PsiElement2UsageTargetAdapter(handler.getPsiElement())};
@Override
public boolean process(@NotNull final Usage usage) {
if (!UsageViewManagerImpl.isInScope(usage, options.searchScope)) {
if (outOfScopeUsages.getAndIncrement() == 0) {
visibleNodes.add(USAGES_OUTSIDE_SCOPE_NODE);
usages.add(USAGES_OUTSIDE_SCOPE_SEPARATOR);
}
return true;
}
synchronized (usages) {
if (visibleNodes.size() >= maxUsages) return false;
if(UsageViewManager.isSelfUsage(usage, myUsageTarget)) return true;
@@ -352,8 +351,8 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
synchronized (usages) {
if (visibleNodes.isEmpty()) {
if (usages.isEmpty()) {
String text = UsageViewBundle.message("no.usages.found.in", searchScopePresentableName(options, project));
showHint(text, editor, popupPosition, handler, maxUsages, options);
String text = UsageViewBundle.message("no.usages.found.in", searchScopePresentableName(options));
hint(editor, text, handler, popupPosition, maxUsages, options, false);
popup.cancel();
}
else {
@@ -364,8 +363,13 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
if (usages.size() == 1) {
//the only usage
Usage usage = visibleNodes.iterator().next().getUsage();
String message = UsageViewBundle.message("show.usages.only.usage", searchScopePresentableName(options, project));
navigateAndHint(usage, message, handler, popupPosition, maxUsages, options);
if (usage == USAGES_OUTSIDE_SCOPE_SEPARATOR) {
hint(editor, UsageViewManagerImpl.outOfScopeMessage(outOfScopeUsages.get(), options.searchScope), handler, popupPosition, maxUsages, options, true);
}
else {
String message = UsageViewBundle.message("show.usages.only.usage", searchScopePresentableName(options));
navigateAndHint(usage, message, handler, popupPosition, maxUsages, options);
}
popup.cancel();
}
else {
@@ -373,7 +377,7 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
// usage view can filter usages down to one
Usage visibleUsage = visibleNodes.iterator().next().getUsage();
if (areAllUsagesInOneLine(visibleUsage, usages)) {
String hint = UsageViewBundle.message("all.usages.are.in.this.line", usages.size(), searchScopePresentableName(options, project));
String hint = UsageViewBundle.message("all.usages.are.in.this.line", usages.size(), searchScopePresentableName(options));
navigateAndHint(visibleUsage, hint, handler, popupPosition, maxUsages, options);
popup.cancel();
}
@@ -451,21 +455,6 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
}
}
private void showHint(@NotNull String text,
@Nullable final Editor editor,
@NotNull final RelativePoint popupPosition,
@NotNull FindUsagesHandler handler,
int maxUsages,
@NotNull FindUsagesOptions options) {
JComponent label = createHintComponent(text, handler, popupPosition, editor, HIDE_HINTS_ACTION, maxUsages, options);
if (editor == null || editor.isDisposed() || !editor.getComponent().isShowing()) {
HintManager.getInstance().showHint(label, popupPosition, HintManager.HIDE_BY_ANY_KEY |
HintManager.HIDE_BY_TEXT_CHANGE | HintManager.HIDE_BY_SCROLLING, 0);
}
else {
HintManager.getInstance().showInformationHint(editor, label);
}
}
@NotNull
private JComponent createHintComponent(@NotNull String text,
@@ -474,8 +463,12 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
final Editor editor,
@NotNull final Runnable cancelAction,
final int maxUsages,
@NotNull final FindUsagesOptions options) {
@NotNull final FindUsagesOptions options,
boolean isWarning) {
JComponent label = HintUtil.createInformationLabel(suggestSecondInvocation(options, handler, text + "&nbsp;"));
if (isWarning) {
label.setBackground(MessageType.WARNING.getPopupBackground());
}
InplaceButton button = createSettingsButton(handler, popupPosition, editor, maxUsages, cancelAction);
JPanel panel = new JPanel(new BorderLayout()) {
@@ -540,19 +533,13 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
if (dialog.isOK()) {
dialog.calcFindUsagesOptions();
FindUsagesOptions options = handler.getFindUsagesOptions(DataManager.getInstance().getDataContext());
showElementUsages(handler, editor, popupPosition, maxUsages, options);
showElementUsages(editor, popupPosition, handler, maxUsages, options);
}
}
private static String searchScopePresentableName(@NotNull FindUsagesOptions options, @NotNull Project project) {
return notNullizeScope(options, project).getDisplayName();
}
@NotNull
private static SearchScope notNullizeScope(@NotNull FindUsagesOptions options, @NotNull Project project) {
SearchScope scope = options.searchScope;
if (scope == null) return ProjectScope.getAllScope(project);
return scope;
private static String searchScopePresentableName(@NotNull FindUsagesOptions options) {
return options.searchScope.getDisplayName();
}
@NotNull
@@ -566,8 +553,7 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
@NotNull final FindUsagesOptions options,
@NotNull final JTable table,
@NotNull final UsageViewPresentation presentation,
@NotNull final AsyncProcessIcon processIcon,
boolean hadMoreSeparator) {
@NotNull final AsyncProcessIcon processIcon) {
table.setRowHeight(PlatformIcons.CLASS_ICON.getIconHeight()+2);
table.setShowGrid(false);
table.setShowVerticalLines(false);
@@ -579,14 +565,15 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
PopupChooserBuilder builder = new PopupChooserBuilder(table);
final String title = presentation.getTabText();
if (title != null) {
String result = getFullTitle(usages, title, hadMoreSeparator, visibleNodes.size() - 1, true);
String result = getFullTitle(usages, title, false, visibleNodes.size() - 1, true);
builder.setTitle(result);
builder.setAdText(getSecondInvocationTitle(options, handler));
}
builder.setMovable(true).setResizable(true);
final AtomicReference<Object> selectedUsage = new AtomicReference<Object>();
final AtomicBoolean moreUsages = new AtomicBoolean();
final AtomicBoolean moreUsagesSelected = new AtomicBoolean();
final AtomicBoolean outsideScopeUsagesSelected = new AtomicBoolean();
table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
@@ -596,12 +583,17 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
Object value = table.getValueAt(i, 0);
if (value instanceof UsageNode) {
Usage usage = ((UsageNode)value).getUsage();
if (usage == MORE_USAGES_SEPARATOR) {
moreUsages.set(true);
outsideScopeUsagesSelected.set(false);
moreUsagesSelected.set(false);
if (usage == USAGES_OUTSIDE_SCOPE_SEPARATOR) {
outsideScopeUsagesSelected.set(true);
selectedUsage.set(null);
}
else if (usage == MORE_USAGES_SEPARATOR) {
moreUsagesSelected.set(true);
selectedUsage.set(null);
}
else {
moreUsages.set(false);
selectedUsage.set(usage instanceof UsageInfo2UsageAdapter ? ((UsageInfo2UsageAdapter)usage).getUsageInfo().copy() : usage);
}
break;
@@ -613,10 +605,15 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
builder.setItemChoosenCallback(new Runnable() {
@Override
public void run() {
if (moreUsages.get()) {
if (moreUsagesSelected.get()) {
appendMoreUsages(editor, popupPosition, handler, maxUsages, options);
return;
}
if (outsideScopeUsagesSelected.get()) {
options.searchScope = GlobalSearchScope.projectScope(handler.getProject());
showElementUsages(editor, popupPosition, handler, maxUsages, options);
return;
}
Object usage = selectedUsage.get();
if (usage instanceof UsageInfo) {
UsageViewUtil.navigateTo((UsageInfo)usage, true);
@@ -684,7 +681,7 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
JComponent content = popup[0].getContent();
myWidth = (int)(toolBar.getPreferredSize().getWidth()
+ new JLabel(getFullTitle(usages, title, hadMoreSeparator, visibleNodes.size() - 1, true)).getPreferredSize().getWidth()
+ new JLabel(getFullTitle(usages, title, false, visibleNodes.size() - 1, true)).getPreferredSize().getWidth()
+ settingsButton.getPreferredSize().getWidth());
myWidth = -1;
for (AnAction action : toolbar.getChildren(null)) {
@@ -770,7 +767,7 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
private static String getSecondInvocationTitle(@NotNull FindUsagesOptions options, @NotNull FindUsagesHandler handler) {
if (getShowUsagesShortcut() != null) {
GlobalSearchScope maximalScope = FindUsagesManager.getMaximalScope(handler);
if (!notNullizeScope(options, handler.getProject()).equals(maximalScope)) {
if (!options.searchScope.equals(maximalScope)) {
return "Press " + KeymapUtil.getShortcutText(getShowUsagesShortcut()) + " again to search in " + maximalScope.getDisplayName();
}
}
@@ -784,7 +781,7 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
int maxUsages) {
FindUsagesOptions cloned = options.clone();
cloned.searchScope = FindUsagesManager.getMaximalScope(handler);
showElementUsages(handler, editor, popupPosition, maxUsages, cloned);
showElementUsages(editor, popupPosition, handler, maxUsages, cloned);
}
@Nullable
@@ -827,7 +824,9 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
@NotNull
private static MyModel setTableModel(@NotNull JTable table,
@NotNull UsageViewImpl usageView,
@NotNull final List<UsageNode> data) {
@NotNull final List<UsageNode> data,
@NotNull AtomicInteger outOfScopeUsages,
@NotNull SearchScope searchScope) {
ApplicationManager.getApplication().assertIsDispatchThread();
final int columnCount = calcColumnCount(data);
MyModel model = table.getModel() instanceof MyModel ? (MyModel)table.getModel() : null;
@@ -835,7 +834,7 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
model = new MyModel(data, columnCount);
table.setModel(model);
ShowUsagesTableCellRenderer renderer = new ShowUsagesTableCellRenderer(usageView);
ShowUsagesTableCellRenderer renderer = new ShowUsagesTableCellRenderer(usageView, outOfScopeUsages, searchScope);
for (int i=0;i<table.getColumnModel().getColumnCount();i++) {
TableColumn column = table.getColumnModel().getColumn(i);
column.setCellRenderer(renderer);
@@ -908,21 +907,27 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
@NotNull final JBPopup popup,
@NotNull final UsageViewPresentation presentation,
@NotNull final RelativePoint popupPosition,
boolean findUsagesInProgress) {
boolean findUsagesInProgress,
@NotNull AtomicInteger outOfScopeUsages,
@NotNull SearchScope searchScope) {
ApplicationManager.getApplication().assertIsDispatchThread();
boolean shouldShowMoreSeparator = usages.contains(MORE_USAGES_SEPARATOR);
if (shouldShowMoreSeparator) {
nodes.add(MORE_USAGES_SEPARATOR_NODE);
}
boolean hasOutsideScopeUsages = usages.contains(USAGES_OUTSIDE_SCOPE_SEPARATOR);
if (hasOutsideScopeUsages && !shouldShowMoreSeparator) {
nodes.add(USAGES_OUTSIDE_SCOPE_NODE);
}
String title = presentation.getTabText();
String fullTitle = getFullTitle(usages, title, shouldShowMoreSeparator, nodes.size() - (shouldShowMoreSeparator ? 1 : 0), findUsagesInProgress);
String fullTitle = getFullTitle(usages, title, shouldShowMoreSeparator || hasOutsideScopeUsages, nodes.size() - (shouldShowMoreSeparator || hasOutsideScopeUsages ? 1 : 0), findUsagesInProgress);
((AbstractPopup)popup).setCaption(fullTitle);
List<UsageNode> data = collectData(usages, nodes, usageView, presentation);
MyModel tableModel = setTableModel(table, usageView, data);
MyModel tableModel = setTableModel(table, usageView, data, outOfScopeUsages, searchScope);
List<UsageNode> existingData = tableModel.getItems();
int row = table.getSelectedRow();
@@ -1021,8 +1026,9 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
private void appendMoreUsages(Editor editor,
@NotNull RelativePoint popupPosition,
@NotNull FindUsagesHandler handler,
int maxUsages, final FindUsagesOptions options) {
showElementUsages(handler, editor, popupPosition, maxUsages+USAGES_PAGE_SIZE, options);
int maxUsages,
@NotNull FindUsagesOptions options) {
showElementUsages(editor, popupPosition, handler, maxUsages+USAGES_PAGE_SIZE, options);
}
private static void addUsageNodes(@NotNull GroupNode root, @NotNull final UsageViewImpl usageView, @NotNull List<UsageNode> outNodes) {
@@ -1054,25 +1060,51 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
if (hint == null) return;
final Editor newEditor = getEditorFor(usage);
if (newEditor == null) return;
hint(newEditor, hint, handler, popupPosition, maxUsages, options, false);
}
private void showHint(@Nullable final Editor editor,
@NotNull String hint,
@NotNull FindUsagesHandler handler,
@NotNull final RelativePoint popupPosition,
int maxUsages,
@NotNull FindUsagesOptions options,
boolean isWarning) {
JComponent label = createHintComponent(hint, handler, popupPosition, editor, HIDE_HINTS_ACTION, maxUsages, options, isWarning);
if (editor == null || editor.isDisposed() || !editor.getComponent().isShowing()) {
HintManager.getInstance().showHint(label, popupPosition, HintManager.HIDE_BY_ANY_KEY |
HintManager.HIDE_BY_TEXT_CHANGE | HintManager.HIDE_BY_SCROLLING, 0);
}
else {
HintManager.getInstance().showInformationHint(editor, label);
}
}
private void hint(@Nullable final Editor editor,
@NotNull final String hint,
@NotNull final FindUsagesHandler handler,
@NotNull final RelativePoint popupPosition,
final int maxUsages,
@NotNull final FindUsagesOptions options,
final boolean isWarning) {
final Project project = handler.getProject();
//opening editor is performing in invokeLater
IdeFocusManager.getInstance(project).doWhenFocusSettlesDown(new Runnable() {
@Override
public void run() {
newEditor.getScrollingModel().runActionOnScrollingFinished(new Runnable() {
Runnable runnable = new Runnable() {
@Override
public void run() {
// after new editor created, some editor resizing events are still bubbling. To prevent hiding hint, invokeLater this
IdeFocusManager.getInstance(project).doWhenFocusSettlesDown(new Runnable() {
@Override
public void run() {
if (newEditor.getComponent().isShowing()) {
showHint(hint, newEditor, popupPosition, handler, maxUsages, options);
}
showHint(editor, hint, handler, popupPosition, maxUsages, options, isWarning);
}
});
}
});
};
if (editor == null) runnable.run(); else editor.getScrollingModel().runActionOnScrollingFinished(runnable);
}
});
}
@@ -1119,9 +1151,9 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
}
static class StringNode extends UsageNode {
private final Object myString;
@NotNull private final Object myString;
public StringNode(Object string) {
public StringNode(@NotNull Object string) {
super(NullUsage.INSTANCE, new UsageViewTreeModelBuilder(new UsageViewPresentation(), UsageTarget.EMPTY_ARRAY));
myString = string;
}
@@ -1159,7 +1191,7 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
UsageNode node = (UsageNode)element;
if (node instanceof StringNode) return "";
Usage usage = node.getUsage();
if (usage == MORE_USAGES_SEPARATOR) return "";
if (usage == MORE_USAGES_SEPARATOR || usage == USAGES_OUTSIDE_SCOPE_SEPARATOR) return "";
GroupNode group = (GroupNode)node.getParent();
return usage.getPresentation().getPlainText() + group;
}
@@ -20,6 +20,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.search.SearchScope;
import com.intellij.ui.FileColorManager;
import com.intellij.ui.SimpleColoredComponent;
import com.intellij.ui.SimpleTextAttributes;
@@ -30,24 +31,30 @@ import com.intellij.usages.UsagePresentation;
import com.intellij.usages.impl.GroupNode;
import com.intellij.usages.impl.UsageNode;
import com.intellij.usages.impl.UsageViewImpl;
import com.intellij.usages.impl.UsageViewManagerImpl;
import com.intellij.usages.rules.UsageInFile;
import com.intellij.util.ui.EmptyIcon;
import com.intellij.util.ui.UIUtil;
import com.intellij.xml.util.XmlStringUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumnModel;
import java.awt.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author cdr
*/
class ShowUsagesTableCellRenderer implements TableCellRenderer {
private final UsageViewImpl myUsageView;
@NotNull private final AtomicInteger myOutOfScopeUsages;
@NotNull private final SearchScope mySearchScope;
ShowUsagesTableCellRenderer(@NotNull UsageViewImpl usageView) {
ShowUsagesTableCellRenderer(@NotNull UsageViewImpl usageView, @NotNull AtomicInteger outOfScopeUsages, @NotNull SearchScope searchScope) {
myUsageView = usageView;
myOutOfScopeUsages = outOfScopeUsages;
mySearchScope = searchScope;
}
@Override
@@ -60,32 +67,37 @@ class ShowUsagesTableCellRenderer implements TableCellRenderer {
Color fileBgColor = getBackgroundColor(isSelected, usage);
final Color bg = UIUtil.getListSelectionBackground();
final Color fg = UIUtil.getListSelectionForeground();
panel.setBackground(isSelected ? bg : fileBgColor == null ? list.getBackground() : fileBgColor);
panel.setForeground(isSelected ? fg : list.getForeground());
if (usage == null || usageNode instanceof ShowUsagesAction.StringNode) {
panel.setLayout(new BorderLayout());
if (column == 0) {
panel.add(new JLabel(XmlStringUtil.wrapInHtml("<b>" + value + "</b>"), SwingConstants.CENTER));
}
return panel;
}
Color panelBackground = isSelected ? bg : fileBgColor == null ? list.getBackground() : fileBgColor;
Color panelForeground = isSelected ? fg : list.getForeground();
panel.setBackground(panelBackground);
panel.setForeground(panelForeground);
SimpleColoredComponent textChunks = new SimpleColoredComponent();
textChunks.setIpad(new Insets(0,0,0,0));
textChunks.setIpad(new Insets(0, 0, 0, 0));
textChunks.setBorder(null);
if (usage == null || usageNode instanceof ShowUsagesAction.StringNode) {
textChunks.append(value.toString(), SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
return textComponentSpanningWholeRow(textChunks, panelBackground, panelForeground, column, list, row);
}
if (usage == ShowUsagesAction.MORE_USAGES_SEPARATOR) {
textChunks.append("...<");
textChunks.append("more usages", SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
textChunks.append(">...");
return textComponentSpanningWholeRow(textChunks, panelBackground, panelForeground, column, list, row);
}
else if (usage == ShowUsagesAction.USAGES_OUTSIDE_SCOPE_SEPARATOR) {
textChunks.append("...<");
textChunks.append(UsageViewManagerImpl.outOfScopeMessage(myOutOfScopeUsages.get(), mySearchScope), SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
textChunks.append(">...");
return textComponentSpanningWholeRow(textChunks, panelBackground, panelForeground, column, list, row);
}
if (column == 0) {
GroupNode parent = (GroupNode)usageNode.getParent();
appendGroupText(parent, panel, fileBgColor);
if (usage == ShowUsagesAction.MORE_USAGES_SEPARATOR) {
textChunks.append("...<");
textChunks.append("more usages", SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
textChunks.append(">...");
}
}
else if (usage != ShowUsagesAction.MORE_USAGES_SEPARATOR) {
else if (usage != ShowUsagesAction.MORE_USAGES_SEPARATOR && usage != ShowUsagesAction.USAGES_OUTSIDE_SCOPE_SEPARATOR) {
UsagePresentation presentation = usage.getPresentation();
TextChunk[] text = presentation.getText();
@@ -116,6 +128,59 @@ class ShowUsagesTableCellRenderer implements TableCellRenderer {
return panel;
}
@NotNull
private static Component textComponentSpanningWholeRow(@NotNull SimpleColoredComponent chunks,
Color panelBackground,
Color panelForeground,
final int column,
@NotNull final JTable table, int row) {
final SimpleColoredComponent component = new SimpleColoredComponent() {
@Override
protected void doPaint(Graphics2D g) {
int offset = 0;
int i = 0;
final TableColumnModel columnModel = table.getColumnModel();
while (i < column) {
offset += columnModel.getColumn(i).getWidth();
i++;
}
g.translate(-offset, 0);
//if (column == columnModel.getColumnCount()-1) {
//}
setSize(getWidth()+offset, getHeight()); // should increase the column width so that selection background will be visible even after offset translation
super.doPaint(g);
g.translate(+offset, 0);
}
@NotNull
@Override
public Dimension getPreferredSize() {
//return super.getPreferredSize();
return column == table.getColumnModel().getColumnCount()-1 ? super.getPreferredSize() : new Dimension(0,0);
// it should span the whole row, so we can't return any specific value here,
// because otherwise it would be used in the "max width" calculation in com.intellij.find.actions.ShowUsagesAction.calcMaxWidth
}
};
component.setIpad(new Insets(0,0,0,0));
component.setBorder(null);
component.setBackground(panelBackground);
component.setForeground(panelForeground);
for (SimpleColoredComponent.ColoredIterator iterator = chunks.iterator(); iterator.hasNext(); ) {
iterator.next();
String fragment = iterator.getFragment();
SimpleTextAttributes attributes = iterator.getTextAttributes();
attributes = attributes.derive(attributes.getStyle(), panelForeground, panelBackground, attributes.getWaveColor());
component.append(fragment, attributes);
}
return component;
}
private static SimpleTextAttributes deriveAttributesWithColor(SimpleTextAttributes attributes, Color fileBgColor) {
if (fileBgColor != null) {
attributes = attributes.derive(-1,null, fileBgColor,null);
@@ -205,8 +205,8 @@ public class FindUsagesManager implements JDOMExternalizable {
return null;
}
public void findUsages(@NotNull PsiElement psiElement, final PsiFile scopeFile, final FileEditor editor, boolean showDialog) {
FindUsagesHandler handler = getNewFindUsagesHandler(psiElement, false);
public void findUsages(@NotNull PsiElement psiElement, final PsiFile scopeFile, final FileEditor editor, boolean showDialog, @Nullable("null means default (stored in options)") SearchScope searchScope) {
FindUsagesHandler handler = getFindUsagesHandler(psiElement, false);
if (handler == null) return;
boolean singleFile = scopeFile != null;
@@ -222,8 +222,8 @@ public class FindUsagesManager implements JDOMExternalizable {
setOpenInNewTab(dialog.isShowInSeparateWindow());
FindUsagesOptions findUsagesOptions = dialog.calcFindUsagesOptions();
if (!showDialog) {
findUsagesOptions.searchScope = GlobalSearchScope.projectScope(myProject);
if (searchScope != null) {
findUsagesOptions.searchScope = searchScope;
}
clearFindingNextUsageInFile();
@@ -235,7 +235,7 @@ public class FindUsagesManager implements JDOMExternalizable {
@NotNull FindUsagesOptions findUsagesOptions,
PsiFile scopeFile,
FileEditor editor) {
FindUsagesHandler handler = getNewFindUsagesHandler(psiElement, false);
FindUsagesHandler handler = getFindUsagesHandler(psiElement, false);
if (handler == null) return;
startFindUsages(findUsagesOptions, handler, scopeFile, editor);
}
@@ -262,7 +262,7 @@ public class FindUsagesManager implements JDOMExternalizable {
}
}
public void showSettingsAndFindUsages(@NotNull NavigationItem[] targets) {
public static void showSettingsAndFindUsages(@NotNull NavigationItem[] targets) {
if (targets.length == 0) return;
NavigationItem target = targets[0];
if (!(target instanceof ConfigurableUsageTarget)) return;
@@ -368,9 +368,10 @@ public class FindUsagesManager implements JDOMExternalizable {
final Iterable<PsiElement> elements = ContainerUtil.concat(primaryElements, secondaryElements);
optionsClone.fastTrack = new SearchRequestCollector(new SearchSession());
//if (optionsClone.searchScope instanceof GlobalSearchScope) {
// optionsClone.searchScope = optionsClone.searchScope.union(GlobalSearchScope.projectScope(project));
//}
if (optionsClone.searchScope instanceof GlobalSearchScope) {
// we will search in project scope always but warn if some usage is out of scope
optionsClone.searchScope = optionsClone.searchScope.union(GlobalSearchScope.projectScope(project));
}
try {
for (final PsiElement element : elements) {
ApplicationManager.getApplication().runReadAction(new Runnable() {
@@ -437,14 +438,14 @@ public class FindUsagesManager implements JDOMExternalizable {
throw new AssertionError(handler + " " + findUsagesOptions);
}
Iterable<PsiElement> allElements = ContainerUtil.concat(primaryElements, secondaryElements);
final UsageTarget[] targets = convertToUsageTargets(allElements, findUsagesOptions);
final PsiElement2UsageTargetAdapter[] targets = convertToUsageTargets(allElements, findUsagesOptions);
myAnotherManager.searchAndShowUsages(targets, new Factory<UsageSearcher>() {
@Override
public UsageSearcher create() {
return createUsageSearcher(primaryElements, secondaryElements, handler, findUsagesOptions, null);
}
}, !toSkipUsagePanelWhenOneUsage, true, createPresentation(primaryElements[0], findUsagesOptions, shouldOpenInNewTab()), null);
myHistory.add((ConfigurableUsageTarget)targets[0]);
myHistory.add(targets[0]);
}
private static void dropResolveCacheRegularly(ProgressIndicator indicator, @NotNull final Project project) {
@@ -40,7 +40,6 @@ import com.intellij.psi.meta.PsiMetaData;
import com.intellij.psi.meta.PsiMetaOwner;
import com.intellij.psi.meta.PsiPresentableMetaData;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.ProjectScope;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.ui.ComputableIcon;
@@ -219,18 +218,16 @@ public class PsiElement2UsageTargetAdapter
return psiElement == null ? UsageViewBundle.message("node.invalid") :
FindBundle.message("recent.find.usages.action.popup", StringUtil.capitalize(UsageViewUtil.getType(psiElement)),
DescriptiveNameUtil.getDescriptiveName(psiElement),
scopeString == null
? ProjectScope.getAllScope(psiElement.getProject()).getDisplayName()
: scopeString
scopeString
);
}
@Override
public void showSettings() {
FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(myPointer.getProject())).getFindUsagesManager();
PsiElement element = getElement();
if (element != null) {
findUsagesManager.findUsages(element, null, null, true);
FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(myPointer.getProject())).getFindUsagesManager();
findUsagesManager.findUsages(element, null, null, true, null);
}
}
@@ -43,7 +43,7 @@ public class PsiElement2UsageTargetComposite extends PsiElement2UsageTargetAdapt
PsiElement element = getElement();
if (element == null) return;
FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(element.getProject())).getFindUsagesManager();
FindUsagesHandler handler = findUsagesManager.getNewFindUsagesHandler(element, false);
FindUsagesHandler handler = findUsagesManager.getFindUsagesHandler(element, false);
boolean skipResultsWithOneUsage = FindSettings.getInstance().isSkipResultsWithOneUsage();
findUsagesManager.findUsages(myDescriptor.getPrimaryElements(), myDescriptor.getAdditionalElements(), handler, myOptions, skipResultsWithOneUsage);
}
@@ -59,6 +59,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.impl.search.LexerEditorHighlighterLexer;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.ui.LightweightHint;
@@ -859,14 +860,19 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
findUsages(element, false);
}
@Override
public void findUsagesInScope(@NotNull PsiElement element, @NotNull SearchScope searchScope) {
myFindUsagesManager.findUsages(element, null, null, false, searchScope);
}
@Override
public void findUsages(@NotNull PsiElement element, boolean showDialog) {
myFindUsagesManager.findUsages(element, null, null, showDialog);
myFindUsagesManager.findUsages(element, null, null, showDialog, null);
}
@Override
public void showSettingsAndFindUsages(@NotNull NavigationItem[] targets) {
myFindUsagesManager.showSettingsAndFindUsages(targets);
FindUsagesManager.showSettingsAndFindUsages(targets);
}
@Override
@@ -882,7 +888,7 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
Document document = editor.getDocument();
PsiFile psiFile = PsiDocumentManager.getInstance(myProject).getPsiFile(document);
myFindUsagesManager.findUsages(element, psiFile, fileEditor, false);
myFindUsagesManager.findUsages(element, psiFile, fileEditor, false, null);
}
}
@@ -60,9 +60,7 @@ public abstract class TemplateLanguageStructureViewBuilder implements StructureV
myVirtualFile = psiElement.getContainingFile().getVirtualFile();
myProject = psiElement.getProject();
final TemplateLanguageFileViewProvider provider = getViewProvider();
assert provider != null;
myTemplateDataLanguage = provider.getTemplateDataLanguage();
myTemplateDataLanguage = getNotNullViewProvider().getTemplateDataLanguage();
}
private void updateAfterPsiChange() {
@@ -115,6 +113,15 @@ public abstract class TemplateLanguageStructureViewBuilder implements StructureV
return provider instanceof TemplateLanguageFileViewProvider ? (TemplateLanguageFileViewProvider)provider : null;
}
@NotNull
private TemplateLanguageFileViewProvider getNotNullViewProvider() {
final FileViewProvider provider = PsiManager.getInstance(myProject).findViewProvider(myVirtualFile);
if (provider == null || !(provider instanceof TemplateLanguageFileViewProvider)) {
throw new AssertionError("Not a template view provider for " + myVirtualFile + ": " + provider);
}
return (TemplateLanguageFileViewProvider)provider;
}
private void updateBaseLanguageView() {
if (myBaseStructureViewDescriptor == null || !myProject.isOpen()) return;
final StructureViewComponent view = (StructureViewComponent)myBaseStructureViewDescriptor.structureView;
@@ -158,8 +165,7 @@ public abstract class TemplateLanguageStructureViewBuilder implements StructureV
public StructureView createStructureView(FileEditor fileEditor, @NotNull Project project) {
myFileEditor = fileEditor;
List<StructureViewComposite.StructureViewDescriptor> viewDescriptors = new ArrayList<StructureViewComposite.StructureViewDescriptor>();
final TemplateLanguageFileViewProvider provider = getViewProvider();
assert provider != null;
final TemplateLanguageFileViewProvider provider = getNotNullViewProvider();
final StructureViewComposite.StructureViewDescriptor structureViewDescriptor = createMainView(fileEditor, provider.getPsi(provider.getBaseLanguage()));
if (structureViewDescriptor != null) viewDescriptors.add(structureViewDescriptor);
@@ -580,7 +580,7 @@ public class EditorWindowImpl extends UserDataHolderBase implements EditorWindow
if (offsetInLine > end- lineStartOffset) offsetInLine = end - lineStartOffset;
CharSequence text = myDocumentWindow.getCharsSequence();
return EditorUtil.calcColumnNumber(this, text, lineStartOffset, lineStartOffset +offsetInLine, EditorUtil.getTabSize(myDelegate));
return EditorUtil.calcColumnNumber(this, text, lineStartOffset, lineStartOffset +offsetInLine);
}
private int calcOffset(int col, int lineNumber, int lineStartOffset) {
if (myDocumentWindow.getTextLength() == 0) return 0;
@@ -82,7 +82,7 @@ public class PsiElementRenameHandler implements RenameHandler {
}
}
public static void invoke(PsiElement element, Project project, PsiElement nameSuggestionContext, Editor editor) {
public static void invoke(PsiElement element, Project project, PsiElement nameSuggestionContext, @Nullable Editor editor) {
if (element != null && !canRename(project, editor, element)) {
return;
}
@@ -26,7 +26,6 @@ import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.help.HelpManager;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.Comparing;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
@@ -137,12 +136,12 @@ public class RenameDialog extends RefactoringDialog {
return RenamePsiElementProcessor.forElement(myPsiElement).isToSearchInComments(myPsiElement);
}
private String getFullName() {
protected String getFullName() {
final String name = DescriptiveNameUtil.getDescriptiveName(myPsiElement);
return (UsageViewUtil.getType(myPsiElement) + " " + name).trim();
}
private void createNewNameComponent() {
protected void createNewNameComponent() {
String[] suggestedNames = getSuggestedNames();
myOldName = suggestedNames.length > 0 ? suggestedNames[0] : null;
myNameSuggestionsField = new NameSuggestionsField(suggestedNames, myProject, FileTypes.PLAIN_TEXT, myEditor) {
@@ -341,4 +340,12 @@ public class RenameDialog extends RefactoringDialog {
final String newName = getNewName();
return RenameUtil.isValidName(myProject, myPsiElement, newName);
}
protected NameSuggestionsField getNameSuggestionsField() {
return myNameSuggestionsField;
}
public JCheckBox getCbSearchInComments() {
return myCbSearchInComments;
}
}
@@ -74,9 +74,6 @@ public class ComponentWithBrowseButton<Comp extends JComponent> extends JPanel i
if (ApplicationManager.getApplication() != null) { // avoid crash at design time
new MyDoClickAction(myBrowseButton).registerShortcut(myComponent);
}
if (UIUtil.isUnderIntelliJLaF() || UIUtil.isUnderDarcula()) {
setBorder(new EmptyBorder(0, 1, 0, 1));
}
}
public final Comp getChildComponent() {
@@ -16,6 +16,7 @@
package com.intellij.openapi.ui;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.ui.components.panels.NonOpaquePanel;
import com.intellij.ui.components.panels.Wrapper;
import com.intellij.util.ArrayUtil;
@@ -44,13 +45,13 @@ public class DetailsComponent {
private final NonOpaquePanel myBanner;
private String[] myBannerText;
private boolean myDetailsEnabled = true;
private boolean myDetailsEnabled = !Registry.is("ide.new.project.settings");
private String[] myPrefix;
private String[] myText;
private final Wrapper myContentGutter = new Wrapper();
private boolean myPaintBorder = true;
private boolean myPaintBorder = !Registry.is("ide.new.project.settings");
public DetailsComponent() {
myComponent = new JPanel(new BorderLayout()) {
@@ -109,7 +110,9 @@ public class DetailsComponent {
myBanner = new NonOpaquePanel(new BorderLayout());
myBannerLabel = new Banner();
myBanner.add(myBannerLabel, BorderLayout.CENTER);
if (!Registry.is("ide.new.project.settings")) {
myBanner.add(myBannerLabel, BorderLayout.CENTER);
}
myEmptyContentLabel = new JLabel("", SwingConstants.CENTER);
@@ -167,7 +170,11 @@ public class DetailsComponent {
myContent.setBorder(new EmptyBorder(UIUtil.PANEL_REGULAR_INSETS));
}
else {
myContent.setBorder(null);
if (Registry.is("ide.new.project.settings")) {
myContent.setBorder(new EmptyBorder(16, 10, 16, 10));
} else {
myContent.setBorder(null);
}
}
}
@@ -76,7 +76,7 @@ import java.util.Set;
public abstract class DialogWrapper {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.ui.DialogWrapper");
public static enum IdeModalityType {
public enum IdeModalityType {
IDE,
PROJECT,
MODELESS;
@@ -839,7 +839,7 @@ public abstract class DialogWrapper {
/**
* Dispose the wrapped and releases all resources allocated be the wrapper to help
* more effecient garbage collection. You should never invoke this method twice or
* more efficient garbage collection. You should never invoke this method twice or
* invoke any method of the wrapper after invocation of <code>dispose</code>.
*
* @throws IllegalStateException if the dialog is disposed not on the event dispatch thread
@@ -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.
@@ -29,6 +29,7 @@ import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Conditions;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.*;
import com.intellij.ui.navigation.History;
@@ -46,6 +47,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.tree.*;
import java.awt.*;
import java.util.*;
@@ -61,7 +63,7 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom
protected static final Icon COPY_ICON = PlatformIcons.COPY_ICON;
protected NamedConfigurable myCurrentConfigurable;
private final Splitter mySplitter = new Splitter(false, .2f);
private final JBSplitter mySplitter;
@NonNls public static final String TREE_OBJECT = "treeObject";
@NonNls public static final String TREE_NAME = "treeName";
@@ -79,7 +81,7 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom
public void queryPlace(@NotNull final Place place) {
}
});
private JScrollPane myMaster;
private JComponent myMaster;
public void setHistory(final History history) {
myHistory = history;
@@ -128,6 +130,18 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom
protected MasterDetailsComponent(MasterDetailsState state) {
myState = state;
mySplitter = new JBSplitter(false, .2f);
mySplitter.setSplitterProportionKey("ProjectStructure.SecondLevelElements");
mySplitter.setHonorComponentsMinimumSize(true);
if (Registry.is("ide.new.project.settings")) {
mySplitter.setDividerWidth(1);
mySplitter.setShowDividerIcon(false);
mySplitter.getDivider().setBackground(Gray._153.withAlpha(128));
mySplitter.setShowDividerControls(false);
mySplitter.setOrientation(mySplitter.getOrientation());
}
installAutoScroll();
reInitWholePanelIfNeeded();
}
@@ -163,8 +177,18 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom
}
};
left.add(myNorthPanel, BorderLayout.NORTH);
myMaster = ScrollPaneFactory.createScrollPane(myTree);
if (Registry.is("ide.new.project.settings")) {
ToolbarDecorator decorator = ToolbarDecorator.createDecorator(myTree);
DefaultActionGroup group = createToolbarActionGroup();
if (group != null) {
decorator.setActionGroup(group);
}
//left.add(myNorthPanel, BorderLayout.NORTH);
myMaster = decorator.setPanelBorder(new EmptyBorder(0, 0, 0, 0)).createPanel();
} else {
left.add(myNorthPanel, BorderLayout.NORTH);
myMaster = ScrollPaneFactory.createScrollPane(myTree);
}
left.add(myMaster, BorderLayout.CENTER);
mySplitter.setFirstComponent(left);
@@ -245,7 +269,7 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom
return myHistory == null || !myHistory.isNavigatingNow();
}
private void initToolbar() {
protected DefaultActionGroup createToolbarActionGroup() {
final ArrayList<AnAction> actions = createActions(false);
if (actions != null) {
final DefaultActionGroup group = new DefaultActionGroup();
@@ -257,6 +281,14 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom
group.add(action);
}
}
return group;
}
return null;
}
private void initToolbar() {
DefaultActionGroup group = createToolbarActionGroup();
if (group != null) {
final JComponent component = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, true).getComponent();
myNorthPanel.add(component, BorderLayout.NORTH);
}
@@ -270,6 +302,7 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom
return new Dimension(800, 600);
}
@NotNull
public JComponent createComponent() {
reInitWholePanelIfNeeded();
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 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,7 +15,9 @@
*/
package com.intellij.ui;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.ui.components.panels.OpaquePanel;
import com.intellij.util.ui.GraphicsUtil;
import com.intellij.util.ui.UIUtil;
import javax.swing.*;
@@ -24,16 +26,43 @@ import javax.swing.border.EmptyBorder;
import javax.swing.tree.TreeCellRenderer;
import java.awt.*;
import static javax.swing.SwingConstants.CENTER;
import static javax.swing.SwingConstants.LEFT;
public abstract class GroupedElementsRenderer {
public static final Color POPUP_SEPARATOR_FOREGROUND = new JBColor(Color.gray.brighter(), Gray._43);
public static final Color POPUP_SEPARATOR_TEXT_FOREGROUND = Color.gray;
public static final Color SELECTED_FRAME_FOREGROUND = Color.black;
protected SeparatorWithText mySeparatorComponent = new SeparatorWithText();
protected SeparatorWithText mySeparatorComponent = new SeparatorWithText() {
@Override
protected void paintComponent(Graphics g) {
if (Registry.is("ide.new.project.settings")) {
g.setColor(POPUP_SEPARATOR_FOREGROUND);
Rectangle viewR = new Rectangle(0, getVgap(), getWidth() - 1, getHeight() - getVgap() - 1);
Rectangle iconR = new Rectangle();
Rectangle textR = new Rectangle();
String s = SwingUtilities
.layoutCompoundLabel(g.getFontMetrics(), getCaption(), null, CENTER,
LEFT,
CENTER,
LEFT,
viewR, iconR, textR, 0);
GraphicsUtil.setupAAPainting(g);
g.setColor(Gray._255.withAlpha(80));
g.drawString(s, textR.x + 10, textR.y + 1 + g.getFontMetrics().getAscent());
g.setColor(new Color(0x5F6D7B));
g.drawString(s, textR.x + 10, textR.y + g.getFontMetrics().getAscent());
} else {
super.paintComponent(g);
}
}
};
protected JComponent myComponent;
protected MyComponent myRendererComponent;
protected ErrorLabel myTextLabel;
protected JLabel myTextLabel;
public GroupedElementsRenderer() {
@@ -58,14 +87,16 @@ public abstract class GroupedElementsRenderer {
myTextLabel.setIcon(icon);
myTextLabel.setDisabledIcon(disabledIcon);
if (myTextLabel instanceof EngravedLabel) {
((EngravedLabel)myTextLabel).setShadowColor(isSelected ? UIUtil.getTreeSelectionBackground() : null);
}
if (isSelected) {
myComponent.setBorder(getSelectedBorder());
//myComponent.setBorder(getSelectedBorder());
setSelected(myComponent);
setSelected(myTextLabel);
}
else {
myComponent.setBorder(getBorder());
} else {
//myComponent.setBorder(getBorder());
setDeselected(myComponent);
setDeselected(myTextLabel);
}
@@ -98,7 +129,7 @@ public abstract class GroupedElementsRenderer {
protected final void setDeselected(JComponent aComponent) {
aComponent.setBackground(getBackground());
aComponent.setForeground(getForeground());
aComponent.setForeground(Registry.is("ide.new.project.settings") ? Gray._60 : getForeground());
}
protected abstract Color getSelectionBackground();
@@ -139,12 +170,12 @@ public abstract class GroupedElementsRenderer {
}
@Override
protected final Color getBackground() {
protected Color getBackground() {
return UIUtil.getListBackground();
}
@Override
protected final Color getForeground() {
protected Color getForeground() {
return UIUtil.getListForeground();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 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.
@@ -20,7 +20,8 @@ import com.intellij.util.ui.UIUtil;
import javax.swing.*;
import java.awt.*;
import static javax.swing.SwingConstants.*;
import static javax.swing.SwingConstants.CENTER;
import static javax.swing.SwingConstants.LEFT;
public class SeparatorWithText extends JComponent {
@@ -34,11 +35,11 @@ public class SeparatorWithText extends JComponent {
setFont(getFont().deriveFont(Font.BOLD));
}
private static int getVgap() {
protected static int getVgap() {
return UIUtil.isUnderNativeMacLookAndFeel() ? 1 : 3;
}
private static int getHgap() {
protected static int getHgap() {
return 3;
}
@@ -109,6 +110,10 @@ public class SeparatorWithText extends JComponent {
}
}
protected String getCaption() {
return myCaption;
}
public void setCaption(String captionAboveOf) {
myCaption = captionAboveOf;
}
@@ -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,10 +15,7 @@
*/
package com.intellij.ui;
import com.intellij.openapi.actionSystem.ActionGroup;
import com.intellij.openapi.actionSystem.ActionToolbar;
import com.intellij.openapi.actionSystem.ActionToolbarPosition;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.SystemInfo;
@@ -296,7 +293,9 @@ public abstract class ToolbarDecorator implements CommonActionsPanel.ListenerFac
public ToolbarDecorator setActionGroup(@NotNull ActionGroup actionGroup) {
AnAction[] actions = actionGroup.getChildren(null);
for (AnAction action : actions) {
addExtraAction(AnActionButton.fromAction(action));
if (!(action instanceof Separator)) {
addExtraAction(AnActionButton.fromAction(action));
}
}
return this;
}
@@ -753,6 +753,7 @@ public class Tree extends JTree implements ComponentWithEmptyText, ComponentWith
UIUtil.setLineStyleAngled(this);
}
@NotNull
public <T> T[] getSelectedNodes(Class<T> nodeType, @Nullable NodeFilter<T> filter) {
TreePath[] paths = getSelectionPaths();
if (paths == null) return (T[])Array.newInstance(nodeType, 0);
@@ -488,8 +488,6 @@ public final class EditorUtil {
}
if (editor == null || useOptimization) {
int shift = 0;
Document document = editor == null ? null : editor.getDocument();
if (document != null && start < offset-1 && document.getLineNumber(start) != document.getLineNumber(offset-1)) {
String editorInfo = editor instanceof EditorImpl ? ". Editor info: " + ((EditorImpl)editor).dumpState() : "";
@@ -504,6 +502,7 @@ public final class EditorUtil {
LOG, "detected incorrect offset -> column number calculation",
"start: " + start + ", given offset: " + offset+", given tab size: " + tabSize + ". "+documentInfo+ editorInfo);
}
int shift = 0;
if (hasTabs) {
for (int i = start; i < offset; i++) {
char c = text.charAt(i);
@@ -561,7 +561,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
myEditor.updateCaretCursor();
requestRepaint(oldInfo);
if (locateBeforeSoftWrap && SoftWrapHelper.isCaretAfterSoftWrap(myEditor)) {
if (locateBeforeSoftWrap && SoftWrapHelper.isCaretAfterSoftWrap(this)) {
int lineToUse = myVisibleCaret.line - 1;
if (lineToUse >= 0) {
final VisualPosition visualPosition = new VisualPosition(lineToUse, EditorUtil.getLastVisualLineColumnNumber(myEditor, lineToUse));
@@ -1451,6 +1451,10 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
return marker != null && marker.isValid() && isVirtualSelectionEnabled() && myEndVirtualOffset > myStartVirtualOffset;
}
public EditorImpl getEditor() {
return myEditor;
}
/**
* Encapsulates information about target vertical range info - its <code>'y'</code> coordinate and height in pixels.
*/
@@ -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.
@@ -15,9 +15,9 @@
*/
package com.intellij.openapi.editor.impl.softwrap;
import com.intellij.openapi.editor.CaretModel;
import com.intellij.openapi.editor.SoftWrap;
import com.intellij.openapi.editor.SoftWrapModel;
import com.intellij.openapi.editor.impl.CaretImpl;
import com.intellij.openapi.editor.impl.EditorImpl;
/**
@@ -48,18 +48,18 @@ public class SoftWrapHelper {
* @return <code>true</code> if caret offset of the given editor points to visual position that belongs to
* visual line where soft wrap end is located
*/
public static boolean isCaretAfterSoftWrap(EditorImpl editor) {
CaretModel caretModel = editor.getCaretModel();
if (!caretModel.isUpToDate()) {
public static boolean isCaretAfterSoftWrap(CaretImpl caret) {
if (!caret.isUpToDate()) {
return false;
}
EditorImpl editor = caret.getEditor();
SoftWrapModel softWrapModel = editor.getSoftWrapModel();
int offset = caretModel.getOffset();
int offset = caret.getOffset();
SoftWrap softWrap = softWrapModel.getSoftWrap(offset);
if (softWrap == null) {
return false;
}
return editor.offsetToVisualLine(offset) == caretModel.getVisualPosition().line;
return editor.offsetToVisualLine(offset) == caret.getVisualPosition().line;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 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.
@@ -16,8 +16,11 @@
package com.intellij.ui.popup.list;
import com.intellij.openapi.ui.popup.ListItemDescriptor;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.EngravedLabel;
import com.intellij.ui.ErrorLabel;
import com.intellij.ui.Gray;
import com.intellij.ui.GroupedElementsRenderer;
import com.intellij.ui.components.panels.OpaquePanel;
@@ -55,15 +58,21 @@ public class GroupedItemsListRenderer extends GroupedElementsRenderer.List imple
@Override
protected JComponent createItemComponent() {
myTextLabel = new ErrorLabel();
myTextLabel.setOpaque(true);
myTextLabel.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
if (Registry.is("ide.new.project.settings")) {
myTextLabel = new EngravedLabel();
myTextLabel.setFont(myTextLabel.getFont().deriveFont(Font.BOLD));
myTextLabel.setForeground(Gray._240);
} else {
myTextLabel = new ErrorLabel();
myTextLabel.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
}
myTextLabel.setOpaque(true);
return layoutComponent(myTextLabel);
}
protected final JComponent layoutComponent(JComponent middleItemComponent) {
JPanel result = new OpaquePanel(new BorderLayout(4, 4), Color.white);
JPanel result = new OpaquePanel(Registry.is("ide.new.project.settings") ? new BorderLayout(0, 0) : new BorderLayout(4, 4), Color.white);
myNextStepLabel = new JLabel();
myNextStepLabel.setOpaque(true);
@@ -138,6 +138,8 @@ button.configure=&Configure VCS...
action.name.rollback=Rollback
command.name.rollback.change=Rollback Change
action.name.show.difference=Show Difference
tooltip.text.line.before.deleted=Line before {0} deleted
tooltip.text.lines.before.deleted={1} lines before {0} deleted
tooltip.text.line.changed=Line {0} changed
tooltip.text.lines.changed=Lines {0}-{1} changed
dialog.title.diff.for.range=Diff for Range
@@ -402,3 +402,5 @@ console.too.much.text.buffer.ratio=10
console.too.much.text.buffer.ratio.description=Used for disabling of console processing(console filters for highlights, foldings...),\n\
when there is too much of text to process.\n\
The ratio is used against the console cycle buffer size (idea.cycle.buffer.size/theRatio=maxTextLength).
ide.new.project.settings=false
ide.new.project.settings.description=Temporary key for new project settings dialog UI
@@ -21,6 +21,7 @@ import com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
import com.intellij.openapi.editor.impl.AbstractEditorTest;
import com.intellij.openapi.keymap.Keymap;
import com.intellij.openapi.keymap.KeymapManager;
import com.intellij.testFramework.EditorTestUtil;
import com.intellij.testFramework.TestFileType;
import java.awt.event.InputEvent;
@@ -305,4 +306,18 @@ public class EditorMultiCaretTest extends AbstractEditorTest {
"brown\n" +
"fox");
}
public void testCaretPositionsRecalculationOnDocumentChange() throws Exception {
init("\n" +
"<selection><caret>word</selection>\n" +
"some long prefix <selection><caret>word</selection>-suffix", TestFileType.TEXT);
EditorTestUtil.configureSoftWraps(myEditor, 17); // wrapping right before 'word-suffix'
delete();
checkResultByText("\n" +
"<caret>\n" +
"some long prefix <caret>-suffix");
verifySoftWrapPositions(19);
}
}
@@ -282,7 +282,7 @@ public abstract class ModuleManagerImpl extends ModuleManager implements Project
}
}
fireErrors(errors);
onModuleLoadErrors(errors);
showUnknownModuleTypeNotification(modulesWithUnknownTypes);
@@ -321,7 +321,7 @@ public abstract class ModuleManagerImpl extends ModuleManager implements Project
}
}
private void fireErrors(final List<ModuleLoadingErrorDescription> errors) {
protected void onModuleLoadErrors(final List<ModuleLoadingErrorDescription> errors) {
if (errors.isEmpty()) return;
myModuleModel.myModulesCache = null;
@@ -337,6 +337,10 @@ public abstract class ModuleManagerImpl extends ModuleManager implements Project
}
}
fireModuleLoadErrors(errors);
}
protected void fireModuleLoadErrors(List<ModuleLoadingErrorDescription> errors) {
if (ApplicationManager.getApplication().isHeadlessEnvironment()) {
throw new RuntimeException(errors.get(0).getDescription());
}
@@ -21,6 +21,9 @@ public abstract class ServerRuntimeInstance<D extends DeploymentConfiguration> {
return getDeploymentName(source);
}
/**
* @deprecated use {@link #getDeploymentName(com.intellij.remoteServer.configuration.deployment.DeploymentSource, D configuration)} instead
*/
@NotNull
public String getDeploymentName(@NotNull DeploymentSource source) {
return source.getPresentableName();
@@ -0,0 +1,25 @@
/*
* 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 org.jetbrains.debugger;
import com.intellij.util.Url;
import org.jetbrains.annotations.NotNull;
public interface HasUrl {
@NotNull
Url getUrl();
}
@@ -6,7 +6,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.debugger.sourcemap.SourceMap;
public interface Script extends UserDataHolderEx {
public interface Script extends UserDataHolderEx, HasUrl {
void setSourceMap(SourceMap sourceMap);
enum Type {
@@ -60,9 +60,23 @@ class FieldProcessor<T> {
private MethodHandler processFieldGetterMethod(Method m, String fieldName) {
Type genericReturnType = m.getGenericReturnType();
boolean nullable = m.getAnnotation(JsonNullable.class) != null ||
(genericReturnType == String.class && ((m.getAnnotation(JsonField.class) != null && m.getAnnotation(JsonField.class).optional())
|| m.getAnnotation(JsonOptionalField.class) != null));
boolean nullable;
if (m.getAnnotation(JsonNullable.class) != null) {
nullable = true;
}
else if (genericReturnType == String.class || genericReturnType == Enum.class) {
JsonField jsonField = m.getAnnotation(JsonField.class);
if (jsonField != null) {
nullable = jsonField.optional() && !jsonField.allowAnyPrimitiveValue() && !jsonField.allowAnyPrimitiveValueAndMap();
}
else {
nullable = m.getAnnotation(JsonOptionalField.class) != null;
}
}
else {
nullable = false;
}
ValueReader fieldTypeParser = reader.getFieldTypeParser(genericReturnType, nullable, false, m);
if (fieldTypeParser != InterfaceReader.VOID_PARSER) {
fieldLoaders.add(new FieldLoader(fieldName, fieldTypeParser));
@@ -0,0 +1,478 @@
/*
* 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.usages.impl;
import com.intellij.find.FindManager;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.KeyboardShortcut;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.colors.CodeInsightColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.keymap.KeymapUtil;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.util.ProgressWrapper;
import com.intellij.openapi.progress.util.TooManyUsagesStatus;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.popup.Balloon;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Factory;
import com.intellij.openapi.util.Segment;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.ToolWindowId;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.SearchScope;
import com.intellij.ui.HyperlinkAdapter;
import com.intellij.usageView.UsageViewBundle;
import com.intellij.usages.*;
import com.intellij.util.Alarm;
import com.intellij.util.ArrayUtil;
import com.intellij.util.CommonProcessors;
import com.intellij.util.Processor;
import com.intellij.util.ui.RangeBlinker;
import com.intellij.xml.util.XmlStringUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import java.awt.event.ActionEvent;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
class SearchForUsagesRunnable implements Runnable {
@NonNls private static final String FIND_OPTIONS_HREF_TARGET = "FindOptions";
@NonNls private static final String SEARCH_IN_PROJECT_HREF_TARGET = "SearchInProject";
@NonNls private static final String LARGE_FILES_HREF_TARGET = "LargeFiles";
private final AtomicInteger myUsageCountWithoutDefinition = new AtomicInteger(0);
private final AtomicReference<Usage> myFirstUsage = new AtomicReference<Usage>();
@NotNull
private final Project myProject;
private final AtomicReference<UsageViewImpl> myUsageViewRef;
private final UsageViewPresentation myPresentation;
private final UsageTarget[] mySearchFor;
private final Factory<UsageSearcher> mySearcherFactory;
private final FindUsagesProcessPresentation myProcessPresentation;
@NotNull private final SearchScope mySearchScope;
private final UsageViewManager.UsageViewStateListener myListener;
private final UsageViewManagerImpl myUsageViewManager;
private final AtomicInteger myOutOfScopeUsages = new AtomicInteger();
SearchForUsagesRunnable(@NotNull UsageViewManagerImpl usageViewManager,
@NotNull Project project,
@NotNull AtomicReference<UsageViewImpl> usageViewRef,
@NotNull UsageViewPresentation presentation,
@NotNull UsageTarget[] searchFor,
@NotNull Factory<UsageSearcher> searcherFactory,
@NotNull FindUsagesProcessPresentation processPresentation,
@NotNull SearchScope scope,
@Nullable UsageViewManager.UsageViewStateListener listener) {
myProject = project;
myUsageViewRef = usageViewRef;
myPresentation = presentation;
mySearchFor = searchFor;
mySearcherFactory = searcherFactory;
myProcessPresentation = processPresentation;
mySearchScope = scope;
myListener = listener;
myUsageViewManager = usageViewManager;
}
@NotNull
private static String createOptionsHtml(@NonNls UsageTarget[] searchFor) {
KeyboardShortcut shortcut = UsageViewImpl.getShowUsagesWithSettingsShortcut(searchFor);
String shortcutText = "";
if (shortcut != null) {
shortcutText = "&nbsp;(" + KeymapUtil.getShortcutText(shortcut) + ")";
}
return "<a href='" + FIND_OPTIONS_HREF_TARGET + "'>Find Options...</a>" + shortcutText;
}
@NotNull
private static String createSearchInProjectHtml() {
return "<a href='" + SEARCH_IN_PROJECT_HREF_TARGET + "'>Search in Project</a>";
}
private static void notifyByFindBalloon(final HyperlinkListener listener,
@NotNull final MessageType info,
@NotNull FindUsagesProcessPresentation processPresentation,
@NotNull final Project project,
@NotNull final List<String> lines) {
com.intellij.usageView.UsageViewManager.getInstance(project); // in case tool window not registered
final Collection<PsiFile> largeFiles = processPresentation.getLargeFiles();
List<String> resultLines = new ArrayList<String>(lines);
HyperlinkListener resultListener = listener;
if (!largeFiles.isEmpty()) {
String shortMessage = "(<a href='" + LARGE_FILES_HREF_TARGET + "'>"
+ UsageViewBundle.message("large.files.were.ignored", largeFiles.size()) + "</a>)";
resultLines.add(shortMessage);
resultListener = new HyperlinkAdapter(){
@Override
protected void hyperlinkActivated(HyperlinkEvent e) {
if (e.getDescription().equals(LARGE_FILES_HREF_TARGET)) {
String detailedMessage = detailedLargeFilesMessage(largeFiles);
List<String> strings = new ArrayList<String>(lines);
strings.add(detailedMessage);
ToolWindowManager.getInstance(project).notifyByBalloon(ToolWindowId.FIND, info, wrapInHtml(strings), AllIcons.Actions.Find, listener);
}
else if (listener != null) {
listener.hyperlinkUpdate(e);
}
}
};
}
ToolWindowManager.getInstance(project).notifyByBalloon(ToolWindowId.FIND, info, wrapInHtml(resultLines), AllIcons.Actions.Find, resultListener);
}
@NotNull
private static String wrapInHtml(@NotNull List<String> strings) {
return XmlStringUtil.wrapInHtml(StringUtil.join(strings, "<br>"));
}
@NotNull
private static String detailedLargeFilesMessage(@NotNull Collection<PsiFile> largeFiles) {
String message = "";
if (largeFiles.size() == 1) {
final VirtualFile vFile = largeFiles.iterator().next().getVirtualFile();
message += "File " + presentableFileInfo(vFile) + " is ";
}
else {
message += "Files<br> ";
int counter = 0;
for (PsiFile file : largeFiles) {
final VirtualFile vFile = file.getVirtualFile();
message += presentableFileInfo(vFile) + "<br> ";
if (counter++ > 10) break;
}
message += "are ";
}
message += "too large and cannot be scanned";
return message;
}
@NotNull
private static String presentableFileInfo(@NotNull VirtualFile vFile) {
return getPresentablePath(vFile)
+ "&nbsp;("
+ UsageViewManagerImpl.presentableSize(UsageViewManagerImpl.getFileLength(vFile))
+ ")";
}
@NotNull
private static String getPresentablePath(@NotNull final VirtualFile virtualFile) {
return "'" + ApplicationManager.getApplication().runReadAction(new Computable<String>() {
@Override
public String compute() {
return virtualFile.getPresentableUrl();
}
}) + "'";
}
@NotNull
private HyperlinkListener createGotToOptionsListener(@NotNull final UsageTarget[] targets) {
return new HyperlinkAdapter() {
@Override
protected void hyperlinkActivated(HyperlinkEvent e) {
if (e.getDescription().equals(FIND_OPTIONS_HREF_TARGET)) {
FindManager.getInstance(myProject).showSettingsAndFindUsages(targets);
}
}
};
}
@NotNull
private HyperlinkListener createSearchInProjectListener() {
return new HyperlinkAdapter() {
@Override
protected void hyperlinkActivated(HyperlinkEvent e) {
if (e.getDescription().equals(SEARCH_IN_PROJECT_HREF_TARGET)) {
PsiElement psiElement = getPsiElement(mySearchFor);
if (psiElement != null) {
FindManager.getInstance(myProject).findUsagesInScope(psiElement, GlobalSearchScope.projectScope(myProject));
}
}
}
};
}
private static PsiElement getPsiElement(UsageTarget[] searchFor) {
if (!(searchFor[0] instanceof PsiElementUsageTarget)) return null;
return ((PsiElementUsageTarget)searchFor[0]).getElement();
}
private static void flashUsageScriptaculously(@NotNull final Usage usage) {
if (!(usage instanceof UsageInfo2UsageAdapter)) {
return;
}
UsageInfo2UsageAdapter usageInfo = (UsageInfo2UsageAdapter)usage;
Editor editor = usageInfo.openTextEditor(true);
if (editor == null) return;
TextAttributes attributes = EditorColorsManager.getInstance().getGlobalScheme().getAttributes(CodeInsightColors.BLINKING_HIGHLIGHTS_ATTRIBUTES);
RangeBlinker rangeBlinker = new RangeBlinker(editor, attributes, 6);
List<Segment> segments = new ArrayList<Segment>();
CommonProcessors.CollectProcessor<Segment> processor = new CommonProcessors.CollectProcessor<Segment>(segments);
usageInfo.processRangeMarkers(processor);
rangeBlinker.resetMarkers(segments);
rangeBlinker.startBlinking();
}
private UsageViewImpl getUsageView(ProgressIndicator indicator) {
UsageViewImpl usageView = myUsageViewRef.get();
if (usageView != null) return usageView;
int usageCount = myUsageCountWithoutDefinition.get();
if (usageCount >= 2 || usageCount == 1 && myProcessPresentation.isShowPanelIfOnlyOneUsage()) {
usageView = new UsageViewImpl(myProject, myPresentation, mySearchFor, mySearcherFactory);
usageView.associateProgress(indicator);
if (myUsageViewRef.compareAndSet(null, usageView)) {
openView(usageView);
final Usage firstUsage = myFirstUsage.get();
if (firstUsage != null) {
final UsageViewImpl finalUsageView = usageView;
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
public void run() {
finalUsageView.appendUsage(firstUsage);
}
});
}
}
else {
Disposer.dispose(usageView);
}
return myUsageViewRef.get();
}
return null;
}
private void openView(@NotNull final UsageViewImpl usageView) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
if (myProject.isDisposed()) return;
myUsageViewManager.addContent(usageView, myPresentation);
if (myListener != null) {
myListener.usageViewCreated(usageView);
}
myUsageViewManager.showToolWindow(false);
}
});
}
@Override
public void run() {
AtomicBoolean findUsagesStartedShown = new AtomicBoolean();
searchUsages(findUsagesStartedShown);
endSearchForUsages(findUsagesStartedShown);
}
private void searchUsages(@NotNull final AtomicBoolean findStartedBalloonShown) {
ProgressIndicator indicator = ProgressWrapper.unwrap(ProgressManager.getInstance().getProgressIndicator());
TooManyUsagesStatus.createFor(indicator);
Alarm findUsagesStartedBalloon = new Alarm();
findUsagesStartedBalloon.addRequest(new Runnable() {
@Override
public void run() {
notifyByFindBalloon(null, MessageType.WARNING, myProcessPresentation, myProject,
Collections.singletonList(UsageViewManagerImpl.getProgressTitle(myPresentation)));
findStartedBalloonShown.set(true);
}
}, 300, ModalityState.NON_MODAL);
UsageSearcher usageSearcher = mySearcherFactory.create();
usageSearcher.generate(new Processor<Usage>() {
@Override
public boolean process(final Usage usage) {
ProgressIndicator indicator = ProgressWrapper.unwrap(ProgressManager.getInstance().getProgressIndicator());
if (indicator != null && indicator.isCanceled()) return false;
if (!UsageViewManagerImpl.isInScope(usage, mySearchScope)) {
myOutOfScopeUsages.incrementAndGet();
return true;
}
boolean incrementCounter = !UsageViewManager.isSelfUsage(usage, mySearchFor);
if (incrementCounter) {
final int usageCount = myUsageCountWithoutDefinition.incrementAndGet();
if (usageCount == 1 && !myProcessPresentation.isShowPanelIfOnlyOneUsage()) {
myFirstUsage.compareAndSet(null, usage);
}
final UsageViewImpl usageView = getUsageView(indicator);
TooManyUsagesStatus tooManyUsagesStatus;
if (usageCount > UsageLimitUtil.USAGES_LIMIT && (tooManyUsagesStatus = TooManyUsagesStatus.getFrom(indicator)).switchTooManyUsagesStatus()) {
UsageViewManagerImpl.showTooManyUsagesWarning(myProject, tooManyUsagesStatus, indicator, myPresentation, usageCount, usageView);
}
if (usageView != null) {
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
public void run() {
usageView.appendUsage(usage);
}
});
}
}
return indicator == null || !indicator.isCanceled();
}
});
if (getUsageView(indicator) != null) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
myUsageViewManager.showToolWindow(true);
}
}, myProject.getDisposed());
}
Disposer.dispose(findUsagesStartedBalloon);
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
if (findStartedBalloonShown.get()) {
Balloon balloon = ToolWindowManager.getInstance(myProject).getToolWindowBalloon(ToolWindowId.FIND);
if (balloon != null) {
balloon.hide();
}
}
}
}, myProject.getDisposed());
}
private void endSearchForUsages(@NotNull final AtomicBoolean findStartedBalloonShown) {
assert !ApplicationManager.getApplication().isDispatchThread() : Thread.currentThread();
int usageCount = myUsageCountWithoutDefinition.get();
if (usageCount == 0 && myProcessPresentation.isShowNotFoundMessage()) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
final List<Action> notFoundActions = myProcessPresentation.getNotFoundActions();
final String message = UsageViewBundle.message("dialog.no.usages.found.in",
StringUtil.decapitalize(myPresentation.getUsagesString()),
myPresentation.getScopeText());
if (notFoundActions.isEmpty()) {
List<String> lines = new ArrayList<String>();
lines.add(StringUtil.escapeXml(message));
if (myOutOfScopeUsages.get() != 0) {
lines.add(UsageViewManagerImpl.outOfScopeMessage(myOutOfScopeUsages.get(), mySearchScope));
}
if (myProcessPresentation.isShowFindOptionsPrompt()) {
lines.add(createOptionsHtml(mySearchFor));
}
MessageType type = myOutOfScopeUsages.get() == 0 ? MessageType.INFO : MessageType.WARNING;
notifyByFindBalloon(createGotToOptionsListener(mySearchFor),
type, myProcessPresentation, myProject, lines);
findStartedBalloonShown.set(false);
}
else {
List<String> titles = new ArrayList<String>(notFoundActions.size() + 1);
titles.add(UsageViewBundle.message("dialog.button.ok"));
for (Action action : notFoundActions) {
Object value = action.getValue(FindUsagesProcessPresentation.NAME_WITH_MNEMONIC_KEY);
if (value == null) value = action.getValue(Action.NAME);
titles.add((String)value);
}
int option = Messages.showDialog(myProject, message, UsageViewBundle.message("dialog.title.information"),
ArrayUtil.toStringArray(titles), 0, Messages.getInformationIcon());
if (option > 0) {
notFoundActions.get(option - 1).actionPerformed(new ActionEvent(this, 0, titles.get(option)));
}
}
}
}, ModalityState.NON_MODAL, myProject.getDisposed());
}
else if (usageCount == 1 && !myProcessPresentation.isShowPanelIfOnlyOneUsage()) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
Usage usage = myFirstUsage.get();
if (usage.canNavigate()) {
usage.navigate(true);
flashUsageScriptaculously(usage);
}
List<String> lines = new ArrayList<String>();
lines.add("Only one usage found.");
if (myOutOfScopeUsages.get() != 0) {
lines.add(UsageViewManagerImpl.outOfScopeMessage(myOutOfScopeUsages.get(), mySearchScope));
}
lines.add(createOptionsHtml(mySearchFor));
MessageType type = myOutOfScopeUsages.get() == 0 ? MessageType.INFO : MessageType.WARNING;
notifyByFindBalloon(createGotToOptionsListener(mySearchFor),
type, myProcessPresentation, myProject,
lines);
}
}, ModalityState.NON_MODAL, myProject.getDisposed());
}
else {
final UsageViewImpl usageView = myUsageViewRef.get();
if (usageView != null) {
usageView.drainQueuedUsageNodes();
usageView.setSearchInProgress(false);
}
final List<String> lines;
final HyperlinkListener hyperlinkListener;
if (myOutOfScopeUsages.get() == 0 || getPsiElement(mySearchFor)==null) {
lines = Collections.emptyList();
hyperlinkListener = null;
}
else {
lines = Arrays.asList(UsageViewManagerImpl.outOfScopeMessage(myOutOfScopeUsages.get(), mySearchScope), createSearchInProjectHtml());
hyperlinkListener = createSearchInProjectListener();
}
if (!myProcessPresentation.getLargeFiles().isEmpty() || myOutOfScopeUsages.get() != 0) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
MessageType type = myOutOfScopeUsages.get() == 0 ? MessageType.INFO : MessageType.WARNING;
notifyByFindBalloon(hyperlinkListener, type, myProcessPresentation, myProject, lines);
}
}, ModalityState.NON_MODAL, myProject.getDisposed());
}
}
if (myListener != null) {
myListener.findingUsagesFinished(myUsageViewRef.get());
}
}
}
@@ -15,59 +15,37 @@
*/
package com.intellij.usages.impl;
import com.intellij.find.FindManager;
import com.intellij.find.SearchInBackgroundOption;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.KeyboardShortcut;
import com.intellij.openapi.actionSystem.DataKey;
import com.intellij.openapi.actionSystem.DataSink;
import com.intellij.openapi.actionSystem.TypeSafeDataProvider;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.colors.CodeInsightColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.keymap.KeymapUtil;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.progress.util.ProgressWrapper;
import com.intellij.openapi.progress.util.TooManyUsagesStatus;
import com.intellij.openapi.project.DumbModeAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.popup.Balloon;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.Factory;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowId;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.psi.PsiFile;
import com.intellij.ui.HyperlinkAdapter;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.ui.content.Content;
import com.intellij.usageView.UsageViewBundle;
import com.intellij.usages.*;
import com.intellij.util.Alarm;
import com.intellij.util.ArrayUtil;
import com.intellij.util.CommonProcessors;
import com.intellij.util.Processor;
import com.intellij.util.ui.RangeBlinker;
import com.intellij.usages.rules.PsiElementUsage;
import com.intellij.usages.rules.UsageInFile;
import com.intellij.util.ui.UIUtil;
import com.intellij.xml.util.XmlStringUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
/**
@@ -76,8 +54,6 @@ import java.util.concurrent.atomic.AtomicReference;
public class UsageViewManagerImpl extends UsageViewManager {
private final Project myProject;
private static final Key<UsageView> USAGE_VIEW_KEY = Key.create("USAGE_VIEW");
@NonNls private static final String LARGE_FILES_HREF_TARGET = "LargeFiles";
@NonNls private static final String FIND_OPTIONS_HREF_TARGET = "FindOptions";
public UsageViewManagerImpl(@NotNull Project project) {
myProject = project;
@@ -113,7 +89,7 @@ public class UsageViewManagerImpl extends UsageViewManager {
return showUsages(searchedFor, foundUsages, presentation, null);
}
private void addContent(@NotNull UsageViewImpl usageView, @NotNull UsageViewPresentation presentation) {
void addContent(@NotNull UsageViewImpl usageView, @NotNull UsageViewPresentation presentation) {
Content content = com.intellij.usageView.UsageViewManager.getInstance(myProject).addContent(
presentation.getTabText(),
presentation.getTabName(),
@@ -146,14 +122,26 @@ public class UsageViewManagerImpl extends UsageViewManager {
@NotNull final UsageViewPresentation presentation,
@NotNull final FindUsagesProcessPresentation processPresentation,
@Nullable final UsageViewStateListener listener) {
final SearchScope searchScope = getSearchScope(searchFor);
return doSearchAndShow(searchFor, searcherFactory, presentation, processPresentation, listener, searchScope);
}
UsageView doSearchAndShow(@NotNull final UsageTarget[] searchFor,
@NotNull final Factory<UsageSearcher> searcherFactory,
@NotNull final UsageViewPresentation presentation,
@NotNull final FindUsagesProcessPresentation processPresentation,
@Nullable final UsageViewStateListener listener,
@NotNull final SearchScope searchScope) {
final AtomicReference<UsageViewImpl> usageViewRef = new AtomicReference<UsageViewImpl>();
Task.Backgroundable task = new Task.Backgroundable(myProject, getProgressTitle(presentation), true, new SearchInBackgroundOption()) {
@Override
public void run(@NotNull final ProgressIndicator indicator) {
new SearchForUsagesRunnable(UsageViewManagerImpl.this.myProject, usageViewRef, presentation, searchFor, searcherFactory,
processPresentation, listener).run();
new SearchForUsagesRunnable(UsageViewManagerImpl.this, UsageViewManagerImpl.this.myProject, usageViewRef, presentation, searchFor, searcherFactory,
processPresentation, searchScope, listener).run();
}
@NotNull
@Override
public DumbModeAction getDumbModeAction() {
return DumbModeAction.CANCEL;
@@ -170,6 +158,22 @@ public class UsageViewManagerImpl extends UsageViewManager {
return usageViewRef.get();
}
@NotNull
private SearchScope getSearchScope(@NotNull UsageTarget[] searchFor) {
UsageTarget target = searchFor[0];
if (target instanceof TypeSafeDataProvider) {
final SearchScope[] scope = new SearchScope[1];
((TypeSafeDataProvider)target).calcData(UsageView.USAGE_SCOPE, new DataSink() {
@Override
public <T> void put(DataKey<T> key, T data) {
scope[0] = (SearchScope)data;
}
});
return scope[0];
}
return GlobalSearchScope.projectScope(myProject);
}
@Override
public void searchAndShowUsages(@NotNull UsageTarget[] searchFor,
@NotNull Factory<UsageSearcher> searcherFactory,
@@ -197,7 +201,7 @@ public class UsageViewManagerImpl extends UsageViewManager {
return StringUtil.escapeXml(result);
}
private void showToolWindow(boolean activateWindow) {
void showToolWindow(boolean activateWindow) {
ToolWindow toolWindow = ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.FIND);
toolWindow.show(null);
if (activateWindow && !toolWindow.isActive()) {
@@ -238,304 +242,6 @@ public class UsageViewManagerImpl extends UsageViewManager {
});
}
private class SearchForUsagesRunnable implements Runnable {
private final AtomicInteger myUsageCountWithoutDefinition = new AtomicInteger(0);
private final AtomicReference<Usage> myFirstUsage = new AtomicReference<Usage>();
@NotNull
private final Project myProject;
private final AtomicReference<UsageViewImpl> myUsageViewRef;
private final UsageViewPresentation myPresentation;
private final UsageTarget[] mySearchFor;
private final Factory<UsageSearcher> mySearcherFactory;
private final FindUsagesProcessPresentation myProcessPresentation;
private final UsageViewStateListener myListener;
private SearchForUsagesRunnable(@NotNull Project project,
@NotNull AtomicReference<UsageViewImpl> usageViewRef,
@NotNull UsageViewPresentation presentation,
@NotNull UsageTarget[] searchFor,
@NotNull Factory<UsageSearcher> searcherFactory,
@NotNull FindUsagesProcessPresentation processPresentation,
@Nullable UsageViewStateListener listener) {
myProject = project;
myUsageViewRef = usageViewRef;
myPresentation = presentation;
mySearchFor = searchFor;
mySearcherFactory = searcherFactory;
myProcessPresentation = processPresentation;
myListener = listener;
}
private UsageViewImpl getUsageView(ProgressIndicator indicator) {
UsageViewImpl usageView = myUsageViewRef.get();
if (usageView != null) return usageView;
int usageCount = myUsageCountWithoutDefinition.get();
if (usageCount >= 2 || usageCount == 1 && myProcessPresentation.isShowPanelIfOnlyOneUsage()) {
usageView = new UsageViewImpl(myProject, myPresentation, mySearchFor, mySearcherFactory);
usageView.associateProgress(indicator);
if (myUsageViewRef.compareAndSet(null, usageView)) {
openView(usageView);
final Usage firstUsage = myFirstUsage.get();
if (firstUsage != null) {
final UsageViewImpl finalUsageView = usageView;
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
public void run() {
finalUsageView.appendUsage(firstUsage);
}
});
}
}
else {
Disposer.dispose(usageView);
}
return myUsageViewRef.get();
}
return null;
}
private void openView(@NotNull final UsageViewImpl usageView) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
if (myProject.isDisposed()) return;
addContent(usageView, myPresentation);
if (myListener != null) {
myListener.usageViewCreated(usageView);
}
showToolWindow(false);
}
});
}
@Override
public void run() {
AtomicBoolean findUsagesStartedShown = new AtomicBoolean();
searchUsages(findUsagesStartedShown);
endSearchForUsages(findUsagesStartedShown);
}
private void searchUsages(@NotNull final AtomicBoolean findStartedBalloonShown) {
ProgressIndicator indicator = ProgressWrapper.unwrap(ProgressManager.getInstance().getProgressIndicator());
TooManyUsagesStatus.createFor(indicator);
Alarm findUsagesStartedBalloon = new Alarm();
findUsagesStartedBalloon.addRequest(new Runnable() {
@Override
public void run() {
notifyByFindBalloon(null, MessageType.WARNING, myProcessPresentation, UsageViewManagerImpl.this.myProject,
getProgressTitle(myPresentation));
findStartedBalloonShown.set(true);
}
}, 300, ModalityState.NON_MODAL);
UsageSearcher usageSearcher = mySearcherFactory.create();
usageSearcher.generate(new Processor<Usage>() {
@Override
public boolean process(final Usage usage) {
ProgressIndicator indicator = ProgressWrapper.unwrap(ProgressManager.getInstance().getProgressIndicator());
if (indicator != null && indicator.isCanceled()) return false;
TooManyUsagesStatus tooManyUsagesStatus = TooManyUsagesStatus.getFrom(indicator);
boolean incrementCounter = !isSelfUsage(usage, mySearchFor);
if (incrementCounter) {
final int usageCount = myUsageCountWithoutDefinition.incrementAndGet();
if (usageCount == 1 && !myProcessPresentation.isShowPanelIfOnlyOneUsage()) {
myFirstUsage.compareAndSet(null, usage);
}
final UsageViewImpl usageView = getUsageView(indicator);
if (usageCount > UsageLimitUtil.USAGES_LIMIT && tooManyUsagesStatus.switchTooManyUsagesStatus()) {
showTooManyUsagesWarning(myProject, tooManyUsagesStatus, indicator, myPresentation, usageCount, usageView);
}
if (usageView != null) {
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
public void run() {
usageView.appendUsage(usage);
}
});
}
}
return indicator == null || !indicator.isCanceled();
}
});
if (getUsageView(indicator) != null) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
showToolWindow(true);
}
}, myProject.getDisposed());
}
Disposer.dispose(findUsagesStartedBalloon);
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
if (findStartedBalloonShown.get()) {
Balloon balloon = ToolWindowManager.getInstance(myProject).getToolWindowBalloon(ToolWindowId.FIND);
if (balloon != null) {
balloon.hide();
}
}
}
}, myProject.getDisposed());
}
private void endSearchForUsages(@NotNull final AtomicBoolean findStartedBalloonShown) {
assert !ApplicationManager.getApplication().isDispatchThread() : Thread.currentThread();
int usageCount = myUsageCountWithoutDefinition.get();
if (usageCount == 0 && myProcessPresentation.isShowNotFoundMessage()) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
final List<Action> notFoundActions = myProcessPresentation.getNotFoundActions();
final String message = UsageViewBundle.message("dialog.no.usages.found.in",
StringUtil.decapitalize(myPresentation.getUsagesString()),
myPresentation.getScopeText());
if (notFoundActions.isEmpty()) {
String[] lines = myProcessPresentation.isShowFindOptionsPrompt() ? new String[] {StringUtil.escapeXml(message), createOptionsHtml(mySearchFor)} : new String[]{StringUtil.escapeXml(message)};
notifyByFindBalloon(createGotToOptionsListener(mySearchFor),
MessageType.INFO, myProcessPresentation, UsageViewManagerImpl.this.myProject, lines);
findStartedBalloonShown.set(false);
}
else {
List<String> titles = new ArrayList<String>(notFoundActions.size() + 1);
titles.add(UsageViewBundle.message("dialog.button.ok"));
for (Action action : notFoundActions) {
Object value = action.getValue(FindUsagesProcessPresentation.NAME_WITH_MNEMONIC_KEY);
if (value == null) value = action.getValue(Action.NAME);
titles.add((String)value);
}
int option = Messages.showDialog(myProject, message, UsageViewBundle.message("dialog.title.information"),
ArrayUtil.toStringArray(titles), 0, Messages.getInformationIcon());
if (option > 0) {
notFoundActions.get(option - 1).actionPerformed(new ActionEvent(this, 0, titles.get(option)));
}
}
}
}, ModalityState.NON_MODAL, myProject.getDisposed());
}
else if (usageCount == 1 && !myProcessPresentation.isShowPanelIfOnlyOneUsage()) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
Usage usage = myFirstUsage.get();
if (usage.canNavigate()) {
usage.navigate(true);
flashUsageScriptaculously(usage);
}
notifyByFindBalloon(createGotToOptionsListener(mySearchFor),
MessageType.INFO, myProcessPresentation, UsageViewManagerImpl.this.myProject,"Only one usage found.", createOptionsHtml(
mySearchFor));
}
}, ModalityState.NON_MODAL, myProject.getDisposed());
}
else {
final UsageViewImpl usageView = myUsageViewRef.get();
if (usageView != null) {
usageView.drainQueuedUsageNodes();
usageView.setSearchInProgress(false);
}
if (!myProcessPresentation.getLargeFiles().isEmpty()) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
notifyByFindBalloon(null, MessageType.INFO, myProcessPresentation, UsageViewManagerImpl.this.myProject);
}
}, ModalityState.NON_MODAL, myProject.getDisposed());
}
}
if (myListener != null) {
myListener.findingUsagesFinished(myUsageViewRef.get());
}
}
}
private static void notifyByFindBalloon(final HyperlinkListener listener,
@NotNull final MessageType info,
@NotNull FindUsagesProcessPresentation processPresentation,
@NotNull final Project project,
@NotNull String... sLines) {
com.intellij.usageView.UsageViewManager.getInstance(project); // in case tool window not registered
final List<String> lines = new ArrayList<String>(Arrays.asList(sLines));
final Collection<PsiFile> largeFiles = processPresentation.getLargeFiles();
List<String> resultLines = new ArrayList<String>(lines);
HyperlinkListener resultListener = listener;
if (!largeFiles.isEmpty()) {
String shortMessage = "(<a href='" + LARGE_FILES_HREF_TARGET + "'>"
+ UsageViewBundle.message("large.files.were.ignored", largeFiles.size()) + "</a>)";
resultLines.add(shortMessage);
resultListener = new HyperlinkAdapter(){
@Override
protected void hyperlinkActivated(HyperlinkEvent e) {
if (e.getDescription().equals(LARGE_FILES_HREF_TARGET)) {
String detailedMessage = detailedLargeFilesMessage(largeFiles);
List<String> strings = new ArrayList<String>(lines);
strings.add(detailedMessage);
ToolWindowManager.getInstance(project).notifyByBalloon(ToolWindowId.FIND, info, wrapInHtml(strings), AllIcons.Actions.Find, listener);
}
else if (listener != null) {
listener.hyperlinkUpdate(e);
}
}
};
}
ToolWindowManager.getInstance(project).notifyByBalloon(ToolWindowId.FIND, info, wrapInHtml(resultLines), AllIcons.Actions.Find, resultListener);
}
@NotNull
private static String wrapInHtml(@NotNull List<String> strings) {
return XmlStringUtil.wrapInHtml(StringUtil.join(strings, "<br>"));
}
@NotNull
private static String detailedLargeFilesMessage(@NotNull Collection<PsiFile> largeFiles) {
String message = "";
if (largeFiles.size() == 1) {
final VirtualFile vFile = largeFiles.iterator().next().getVirtualFile();
message += "File " + presentableFileInfo(vFile) + " is ";
}
else {
message += "Files<br> ";
int counter = 0;
for (PsiFile file : largeFiles) {
final VirtualFile vFile = file.getVirtualFile();
message += presentableFileInfo(vFile) + "<br> ";
if (counter++ > 10) break;
}
message += "are ";
}
message += "too large and cannot be scanned";
return message;
}
@NotNull
private static String presentableFileInfo(@NotNull VirtualFile vFile) {
return getPresentablePath(vFile)
+ "&nbsp;("
+ presentableSize(getFileLength(vFile))
+ ")";
}
@NotNull
public static String presentableSize(long bytes) {
long megabytes = bytes / (1024 * 1024);
return UsageViewBundle.message("find.file.size.megabytes", Long.toString(megabytes));
}
public static long getFileLength(@NotNull final VirtualFile virtualFile) {
final long[] length = {-1L};
ApplicationManager.getApplication().runReadAction(new Runnable() {
@@ -550,52 +256,22 @@ public class UsageViewManagerImpl extends UsageViewManager {
}
@NotNull
private static String getPresentablePath(@NotNull final VirtualFile virtualFile) {
return "'" + ApplicationManager.getApplication().runReadAction(new Computable<String>() {
@Override
public String compute() {
return virtualFile.getPresentableUrl();
}
}) + "'";
public static String presentableSize(long bytes) {
long megabytes = bytes / (1024 * 1024);
return UsageViewBundle.message("find.file.size.megabytes", Long.toString(megabytes));
}
public static boolean isInScope(@NotNull Usage usage, @NotNull SearchScope searchScope) {
VirtualFile file = usage instanceof UsageInFile ? ((UsageInFile)usage).getFile() : usage instanceof PsiElementUsage ? PsiUtilCore
.getVirtualFile(((PsiElementUsage)usage).getElement()) : null;
return file != null && (searchScope instanceof LocalSearchScope
? ((LocalSearchScope)searchScope).isInScope(file) : ((GlobalSearchScope)searchScope).contains(file));
}
@NotNull
private HyperlinkListener createGotToOptionsListener(@NotNull final UsageTarget[] targets) {
return new HyperlinkAdapter() {
@Override
protected void hyperlinkActivated(HyperlinkEvent e) {
if (e.getDescription().equals(FIND_OPTIONS_HREF_TARGET)) {
FindManager.getInstance(myProject).showSettingsAndFindUsages(targets);
}
}
};
public static String outOfScopeMessage(int nUsages, @NotNull SearchScope searchScope) {
return (nUsages == 1 ? "One usage is" : nUsages + " usages are") +
" out of scope '"+ searchScope.getDisplayName()+"'";
}
@NotNull
private static String createOptionsHtml(@NonNls UsageTarget[] searchFor) {
KeyboardShortcut shortcut = UsageViewImpl.getShowUsagesWithSettingsShortcut(searchFor);
String shortcutText = "";
if (shortcut != null) {
shortcutText = "&nbsp;(" + KeymapUtil.getShortcutText(shortcut) + ")";
}
return "<a href='" + FIND_OPTIONS_HREF_TARGET + "'>Find Options...</a>" + shortcutText;
}
private static void flashUsageScriptaculously(@NotNull final Usage usage) {
if (!(usage instanceof UsageInfo2UsageAdapter)) {
return;
}
UsageInfo2UsageAdapter usageInfo = (UsageInfo2UsageAdapter)usage;
Editor editor = usageInfo.openTextEditor(true);
if (editor == null) return;
TextAttributes attributes = EditorColorsManager.getInstance().getGlobalScheme().getAttributes(CodeInsightColors.BLINKING_HIGHLIGHTS_ATTRIBUTES);
RangeBlinker rangeBlinker = new RangeBlinker(editor, attributes, 6);
List<Segment> segments = new ArrayList<Segment>();
CommonProcessors.CollectProcessor<Segment> processor = new CommonProcessors.CollectProcessor<Segment>(segments);
usageInfo.processRangeMarkers(processor);
rangeBlinker.resetMarkers(segments);
rangeBlinker.startBlinking();
}
}
+3 -3
View File
@@ -147,8 +147,8 @@ public class Patches {
public static final boolean USE_REFLECTION_TO_ACCESS_JDK7 = true;
/**
* Marker field to find all usages of workarounds
* which will not be needed when migrated to JDK 8+
* AtomicIntegerFieldUpdater does not work when SecurityManager is installed
* fixed in JDK8
*/
public static final boolean HACK_USED_WHICH_IS_FIXED_IN_JDK8 = true;
public static final boolean JDK_BUG_ID_7103570 = true;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 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.
@@ -28,6 +28,8 @@ import java.awt.*;
* @author max
*/
public class EngravedLabel extends JLabel {
private Color myShadowColor = EngravedTextGraphics.SHADOW_COLOR;
public EngravedLabel(String text) {
super(text);
setOpaque(false);
@@ -38,7 +40,18 @@ public class EngravedLabel extends JLabel {
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(UIUtil.isUnderDarcula() ? g : new EngravedTextGraphics((Graphics2D)g));
protected void paintComponent(Graphics graphics) {
if (!UIUtil.isUnderDarcula()) {
graphics = new EngravedTextGraphics((Graphics2D)graphics, 0, 1, getShadowColor());
}
super.paintComponent(graphics);
}
public Color getShadowColor() {
return myShadowColor == null ? EngravedTextGraphics.SHADOW_COLOR : myShadowColor;
}
public void setShadowColor(Color shadowColor) {
myShadowColor = shadowColor;
}
}
@@ -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.
@@ -25,7 +25,7 @@ import java.awt.*;
import java.text.AttributedCharacterIterator;
public class EngravedTextGraphics extends Graphics2DDelegate {
private static final Color SHADOW_COLOR = Gray._250.withAlpha(140);
public static final Color SHADOW_COLOR = Gray._250.withAlpha(140);
private static final boolean ALLOW_ENGRAVEMENT = SystemInfo.isMac;
private Color myShadowColor;
private int myXOffset;
@@ -58,8 +58,17 @@ class JarLoader extends Loader {
}
void preloadClasses() {
ZipFile zipFile;
try {
zipFile = acquireZipFile();
}
catch (Exception e) {
LOG.debug("url: " + myURL, e);
return;
}
try {
ZipFile zipFile = acquireZipFile();
try {
JarMemoryLoader loader = JarMemoryLoader.load(zipFile, getBaseURL());
if (loader != null) {
@@ -17,15 +17,18 @@ package com.intellij.util.containers;
import com.intellij.openapi.util.text.StringUtil;
import gnu.trove.TObjectHashingStrategy;
import junit.framework.TestCase;
import org.junit.Test;
import java.lang.ref.SoftReference;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class ConcurrentMapsTest extends TestCase {
public static final TObjectHashingStrategy<String> CUSTOM_STRATEGY = new TObjectHashingStrategy<String>() {
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class ConcurrentMapsTest {
private static final TObjectHashingStrategy<String> CUSTOM_STRATEGY = new TObjectHashingStrategy<String>() {
@Override
public int computeHashCode(String object) {
return Character.toLowerCase(object.charAt(object.length() - 1));
@@ -37,8 +40,9 @@ public class ConcurrentMapsTest extends TestCase {
}
};
@Test
public void testKeysRemovedWhenIdentityStrategyIsUsed() {
ConcurrentWeakHashMap<Object, Object> map = new ConcurrentWeakHashMap<Object, Object>(TObjectHashingStrategy.IDENTITY);
@SuppressWarnings("unchecked") ConcurrentWeakHashMap<Object, Object> map = new ConcurrentWeakHashMap<Object, Object>(TObjectHashingStrategy.IDENTITY);
map.put(new Object(), new Object());
tryGcSoftlyReachableObjects(); // sometimes weak references are not collected under linux, try to stress gc to force them
@@ -50,6 +54,7 @@ public class ConcurrentMapsTest extends TestCase {
assertEquals(1, map.underlyingMapSize());
}
@Test
public void testRemoveFromSoftEntrySet() {
ConcurrentSoftHashMap<Object, Object> map = new ConcurrentSoftHashMap<Object, Object>();
map.put(this, this);
@@ -61,6 +66,7 @@ public class ConcurrentMapsTest extends TestCase {
assertTrue(map.isEmpty());
}
@Test
public void testRemoveFromWeakEntrySet() {
ConcurrentWeakHashMap<Object, Object> map = new ConcurrentWeakHashMap<Object, Object>();
map.put(this, this);
@@ -72,6 +78,7 @@ public class ConcurrentMapsTest extends TestCase {
assertTrue(map.isEmpty());
}
@Test
public void testTossedWeakKeysAreRemoved() {
ConcurrentWeakHashMap<Object, Object> map = new ConcurrentWeakHashMap<Object, Object>();
map.put(new Object(), new Object());
@@ -87,13 +94,14 @@ public class ConcurrentMapsTest extends TestCase {
}
public static void tryGcSoftlyReachableObjects() {
SoftReference reference = new SoftReference(new Object());
SoftReference<?> reference = new SoftReference<Object>(new Object());
List<Object> list = ContainerUtil.newArrayList();
while (reference.get() != null) {
list.add(new SoftReference<byte[]>(new byte[(int)Runtime.getRuntime().freeMemory() / 2]));
}
}
@Test
public void testTossedSoftKeysAreRemoved() {
ConcurrentSoftHashMap<Object, Object> map = new ConcurrentSoftHashMap<Object, Object>();
map.put(new Object(), new Object());
@@ -108,6 +116,7 @@ public class ConcurrentMapsTest extends TestCase {
assertEquals(1, map.underlyingMapSize());
}
@Test
public void testTossedWeakValueIsRemoved() {
ConcurrentWeakValueHashMap<Object, Object> map = new ConcurrentWeakValueHashMap<Object, Object>();
map.put(new Object(), new Object());
@@ -121,6 +130,7 @@ public class ConcurrentMapsTest extends TestCase {
map.put(this, this);
assertEquals(1, map.underlyingMapSize());
}
@Test
public void testTossedSoftValueIsRemoved() {
ConcurrentSoftValueHashMap<Object, Object> map = new ConcurrentSoftValueHashMap<Object, Object>();
map.put(new Object(), new Object());
@@ -135,6 +145,7 @@ public class ConcurrentMapsTest extends TestCase {
assertEquals(1, map.underlyingMapSize());
}
@Test
public void testCustomStrategy() {
SoftHashMap<String, String> map = new SoftHashMap<String, String>(CUSTOM_STRATEGY);
@@ -145,6 +156,7 @@ public class ConcurrentMapsTest extends TestCase {
assertTrue(map.isEmpty());
}
@Test
public void testCustomStrategyForConcurrentSoft() {
ConcurrentSoftHashMap<String, String> map = new ConcurrentSoftHashMap<String, String>(CUSTOM_STRATEGY);
@@ -156,6 +168,7 @@ public class ConcurrentMapsTest extends TestCase {
assertTrue(map.isEmpty());
}
@Test
public void testCustomStrategyForConcurrentWeakSoft() {
ConcurrentWeakKeySoftValueHashMap<String, String> map = new ConcurrentWeakKeySoftValueHashMap<String, String>(1,1,1,CUSTOM_STRATEGY);
@@ -167,6 +180,7 @@ public class ConcurrentMapsTest extends TestCase {
assertTrue(map.isEmpty());
}
@Test
public void testTossedSoftKeyAndValue() {
SoftKeySoftValueHashMap<Object, Object> map = new SoftKeySoftValueHashMap<Object, Object>();
map.put(new Object(), new Object());
@@ -179,6 +193,7 @@ public class ConcurrentMapsTest extends TestCase {
assertTrue(map.isEmpty());
}
@Test
public void testTossedWeakKeyAndValue() {
WeakKeyWeakValueHashMap<Object, Object> map = new WeakKeyWeakValueHashMap<Object, Object>();
map.put(new Object(), new Object());
@@ -173,14 +173,12 @@ public class LineStatusTracker {
@SuppressWarnings({"AutoBoxing"})
private RangeHighlighter createHighlighter(final Range range) {
LOG.assertTrue(!myReleased, "Already released");
int first =
range.getOffset1() >= myDocument.getLineCount() ? myDocument.getTextLength() : myDocument.getLineStartOffset(range.getOffset1());
int second =
range.getOffset2() >= myDocument.getLineCount() ? myDocument.getTextLength() : myDocument.getLineStartOffset(range.getOffset2());
TextRange textRange = getCurrentTextRange(range);
final RangeHighlighter highlighter = DocumentMarkupModel.forDocument(myDocument, myProject, true)
.addRangeHighlighter(first, second, HighlighterLayer.FIRST - 1, null, HighlighterTargetArea.LINES_IN_RANGE);
.addRangeHighlighter(textRange.getStartOffset(), textRange.getEndOffset(), HighlighterLayer.FIRST - 1, null,
HighlighterTargetArea.LINES_IN_RANGE);
final TextAttributes attr = LineStatusTrackerDrawing.getAttributesFor(range);
highlighter.setErrorStripeMarkColor(attr.getErrorStripeColor());
highlighter.setThinErrorStripeMark(true);
@@ -188,14 +186,21 @@ public class LineStatusTracker {
highlighter.setGreedyToRight(true);
highlighter.setLineMarkerRenderer(LineStatusTrackerDrawing.createRenderer(range, this));
highlighter.setEditorFilter(MarkupEditorFilterFactory.createIsNotDiffFilter());
final int line1 = myDocument.getLineNumber(first);
final int line2 = myDocument.getLineNumber(second);
final String tooltip;
if (line1 == line2) {
tooltip = VcsBundle.message("tooltip.text.line.changed", line1);
if (range.getOffset1() == range.getOffset2()) {
if (range.getUOffset1() + 1 == range.getUOffset2()) {
tooltip = VcsBundle.message("tooltip.text.line.before.deleted", range.getOffset1() + 1);
}
else {
tooltip = VcsBundle.message("tooltip.text.lines.before.deleted", range.getOffset1() + 1, range.getUOffset2() - range.getUOffset1());
}
}
else if (range.getOffset1() + 1 == range.getOffset2()) {
tooltip = VcsBundle.message("tooltip.text.line.changed", range.getOffset1() + 1);
}
else {
tooltip = VcsBundle.message("tooltip.text.lines.changed", line1, line2);
tooltip = VcsBundle.message("tooltip.text.lines.changed", range.getOffset1() + 1, range.getOffset2());
}
highlighter.setErrorStripeTooltip(tooltip);
@@ -168,9 +168,9 @@ public class XDebugSessionTab extends DebuggerSessionTabBase {
}
DefaultActionGroup leftToolbar = new DefaultActionGroup();
final Executor executor = DefaultDebugExecutor.getDebugExecutorInstance();
final Executor debugExecutor = DefaultDebugExecutor.getDebugExecutorInstance();
if (runner != null && environment != null) {
RestartAction restartAction = new RestartAction(executor, runner, myRunContentDescriptor, environment);
RestartAction restartAction = new RestartAction(debugExecutor, runner, myRunContentDescriptor, environment);
leftToolbar.add(restartAction);
restartAction.registerShortcut(myUi.getComponent());
@@ -221,8 +221,8 @@ public class XDebugSessionTab extends DebuggerSessionTabBase {
leftToolbar.addSeparator();
leftToolbar.add(PinToolwindowTabAction.getPinAction());
leftToolbar.add(new CloseAction(executor, myRunContentDescriptor, getProject()));
leftToolbar.add(new ContextHelpAction(executor.getHelpId()));
leftToolbar.add(new CloseAction(environment != null ? environment.getExecutor() : debugExecutor, myRunContentDescriptor, getProject()));
leftToolbar.add(new ContextHelpAction(debugExecutor.getHelpId()));
DefaultActionGroup topToolbar = new DefaultActionGroup();
topToolbar.addAll(getCustomizedActionGroup(XDebuggerActions.TOOL_WINDOW_TOP_TOOLBAR_GROUP));
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -22,6 +22,7 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.ContentRevision;
import com.intellij.openapi.vcs.changes.committed.DecoratorManager;
import com.intellij.openapi.vcs.changes.committed.VcsCommittedListsZipper;
import com.intellij.openapi.vcs.changes.committed.VcsCommittedViewAuxiliary;
@@ -197,7 +198,14 @@ public class GitCommittedChangeListProvider implements CommittedChangesProvider<
final Collection<Change> changes = commit.getChanges();
if (changes.size() == 1) {
return Pair.create(commit, changes.iterator().next().getAfterRevision().getFile());
Change change = changes.iterator().next();
ContentRevision revision = change.getAfterRevision();
if (revision == null) {
revision = change.getBeforeRevision();
}
assert revision != null : "Revision can't be null in " + change;
FilePath filePathInRevision = revision.getFile();
return Pair.create(commit, filePathInRevision);
}
for (Change change : changes) {
if (change.getAfterRevision() != null && FileUtil.filesEqual(filePath.getIOFile(), change.getAfterRevision().getFile().getIOFile())) {
@@ -205,7 +205,7 @@ class GitBranchWorkerTest extends GitPlatformTest {
boolean notificationShown = false;
checkoutOrMerge operation, "feature", [
showUntrackedFilesNotification : { String s, Collection c -> notificationShown = true }
showUntrackedFilesNotification: { String s, VirtualFile root, Collection c -> notificationShown = true }
]
assertTrue "Untracked files notification was not shown", notificationShown
@@ -224,15 +224,15 @@ class GitBranchWorkerTest extends GitPlatformTest {
def untracked = ["untracked.txt"]
untrackedFileOverwrittenBy(myCommunity, "feature", untracked)
Collection<VirtualFile> untrackedFiles = null;
Collection<String> untrackedPaths = null;
checkoutOrMerge operation, "feature", [
showUntrackedFilesDialogWithRollback : { String s, String p, Collection files -> untrackedFiles = files; false }
showUntrackedFilesDialogWithRollback: {
String s, String p, VirtualFile root, Collection<String> files -> untrackedPaths = files; false
}
]
assertTrue "Untracked files dialog was not shown", untrackedFiles != null
assertEquals "Incorrect set of untracked files was shown in the dialog",
untracked,
untrackedFiles.collect { FileUtil.getRelativePath(myCommunity.root.path, it.path, '/'.toCharacter()) }
assertTrue "Untracked files dialog was not shown", untrackedPaths != null
assertEquals "Incorrect set of untracked files was shown in the dialog", untracked.asList(), untrackedPaths.asList()
}
public void "test checkout with local changes overwritten by checkout should show smart checkout dialog"() {
@@ -252,7 +252,7 @@ class GitBranchWorkerTest extends GitPlatformTest {
List<Change> changes = null;
checkoutOrMerge(operation, "feature", [
showSmartOperationDialog: { Project p, List<Change> cs, String op, boolean force ->
showSmartOperationDialog: { Project p, List<Change> cs, Collection<String> paths, String op, boolean force ->
changes = cs
DialogWrapper.CANCEL_EXIT_CODE
}
@@ -349,7 +349,9 @@ class GitBranchWorkerTest extends GitPlatformTest {
prepareLocalChangesOverwrittenBy(myUltimate)
checkoutOrMerge(operation, "feature", [
showSmartOperationDialog : { Project p, List<Change> cs, String op, boolean f -> GitSmartOperationDialog.CANCEL_EXIT_CODE },
showSmartOperationDialog: { Project p, List<Change> cs, Collection<String> paths, String op, boolean f
-> GitSmartOperationDialog.CANCEL_EXIT_CODE
},
] as GitBranchUiHandler )
assertNull "Notification was unexpectedly shown:" + myVcsNotifier.lastNotification, myVcsNotifier.lastNotification
@@ -372,8 +374,10 @@ class GitBranchWorkerTest extends GitPlatformTest {
def rollbackMsg = null
checkoutOrMerge(operation, "feature", [
showSmartOperationDialog : { Project p, List<Change> cs, String op, boolean f -> GitSmartOperationDialog.CANCEL_EXIT_CODE },
notifyErrorWithRollbackProposal: { String t, String m, String rp -> rollbackMsg = m ; false }
showSmartOperationDialog : {
Project p, List<Change> cs, Collection<String> paths, String op, boolean f -> GitSmartOperationDialog.CANCEL_EXIT_CODE
},
notifyErrorWithRollbackProposal: { String t, String m, String rp -> rollbackMsg = m; false }
] as GitBranchUiHandler )
assertNotNull "Rollback proposal was not shown", rollbackMsg
@@ -384,7 +388,7 @@ class GitBranchWorkerTest extends GitPlatformTest {
prepareLocalChangesOverwrittenBy(myUltimate)
def uiHandler = [
showSmartOperationDialog: { Project p, List<Change> cs, String op, boolean force ->
showSmartOperationDialog: { Project p, List<Change> cs, Collection<String> paths, String op, boolean force ->
GitSmartOperationDialog.FORCE_EXIT_CODE;
},
] as GitBranchUiHandler
@@ -144,7 +144,7 @@ public class InconsistentResourceBundleInspection extends GlobalSimpleInspection
ResourceBundle resourceBundle = propertiesFile.getResourceBundle();
assert visitedBundles != null;
if (!visitedBundles.add(resourceBundle)) return;
List<PropertiesFile> files = resourceBundle.getPropertiesFiles(manager.getProject());
List<PropertiesFile> files = resourceBundle.getPropertiesFiles();
if (files.size() < 2) return;
BidirectionalMap<PropertiesFile, PropertiesFile> parents = new BidirectionalMap<PropertiesFile, PropertiesFile>();
for (PropertiesFile f : files) {
@@ -4,7 +4,9 @@ properties.files.file.type.description=Properties files
remove.property.intention.text=Remove property
rename.bundle.enter.new.resource.bundle.base.name.prompt.text=Enter new resource bundle base name
rename.bundle.enter.new.resource.bundle.key.name.prompt.text=Enter new resource bundle key name
rename.bundle.enter.new.resource.bundle.section.name.prompt.text=Enter new resource bundle section name
rename.resource.bundle.dialog.title=Rename Resource Bundle
rename.resource.bundle.section.dialog.title=Rename Resource Bundle Section
rename.resource.bundle.key.dialog.title=Rename Resource Bundle Key
properties.files.inspection.group.display.name=Properties Files
unused.property.inspection.display.name=Unused Property
@@ -40,4 +42,12 @@ options.properties.attribute.descriptor.property.value=Property value
options.properties.attribute.descriptor.key.value.separator=Key/value separator
options.properties.attribute.descriptor.comment=Comment
options.properties.attribute.descriptor.valid.string.escape=Valid string escape
options.properties.attribute.descriptor.invalid.string.escape=Invalid string escape
options.properties.attribute.descriptor.invalid.string.escape=Invalid string escape
new.property.dialog.title=New Property Key
new.property.dialog.name.prompt.text=Enter new property key name
resource.bundle.renamer=Rename resource bundle properties files
resource.bundle.renamer.dialog.description=Rename resource bundle properties files with the following names to:
resource.bundle.renamer.entity.name=Resource bundle
resource.bundle.renamer.option=Rename bound &resource bundle
@@ -18,6 +18,7 @@ package com.intellij.lang.properties;
import com.intellij.lang.properties.psi.PropertiesFile;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
@@ -31,15 +32,29 @@ public class EmptyResourceBundle {
private static class Holder {
private static final ResourceBundle NULL = new ResourceBundle() {
@NotNull
public List<PropertiesFile> getPropertiesFiles(final Project project) {
@Override
public List<PropertiesFile> getPropertiesFiles() {
return Collections.emptyList();
}
@NotNull
public PropertiesFile getDefaultPropertiesFile(final Project project) {
@Override
public List<PropertiesFile> getPropertiesFiles(final Project project) {
return getPropertiesFiles();
}
@NotNull
@Override
public PropertiesFile getDefaultPropertiesFile() {
throw new IllegalStateException();
}
@NotNull
@Override
public PropertiesFile getDefaultPropertiesFile(final Project project) {
return getDefaultPropertiesFile();
}
@NotNull
public String getBaseName() {
return "";
@@ -49,6 +64,12 @@ public class EmptyResourceBundle {
public VirtualFile getBaseDirectory() {
throw new IllegalStateException();
}
@NotNull
@Override
public Project getProject() {
throw new IllegalStateException();
}
};
}
public static ResourceBundle getInstance() {
@@ -24,6 +24,7 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiFile;
import com.intellij.util.SmartList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -41,8 +42,16 @@ public class PropertiesUtil {
private final static Locale DEFAULT_LOCALE = new Locale("", "", "");
public static boolean isPropertyComplete(final Project project, ResourceBundle resourceBundle, String propertyName) {
List<PropertiesFile> propertiesFiles = resourceBundle.getPropertiesFiles(project);
/**
* @deprecated use PropertiesUtil.isPropertyComplete(ResourceBundle resourceBundle, String propertyName)
*/
@Deprecated
public static boolean isPropertyComplete(final Project project, final ResourceBundle resourceBundle, final String propertyName) {
return isPropertyComplete(resourceBundle, propertyName);
}
public static boolean isPropertyComplete(final ResourceBundle resourceBundle, final String propertyName) {
List<PropertiesFile> propertiesFiles = resourceBundle.getPropertiesFiles();
for (PropertiesFile propertiesFile : propertiesFiles) {
if (propertiesFile.findPropertyByKey(propertyName) == null) return false;
}
@@ -50,8 +59,13 @@ public class PropertiesUtil {
}
@NotNull
public static String getBaseName(@NotNull VirtualFile virtualFile) {
String name = virtualFile.getName();
public static String getBaseName(@NotNull PsiFile file) {
return getBaseName(file.getContainingFile().getVirtualFile());
}
@NotNull
public static String getBaseName(@NotNull VirtualFile file) {
final String name = file.getName();
final Matcher matcher = LOCALE_PATTERN.matcher(name);
final String baseNameWithExtension;
if (matcher.find()) {
@@ -92,10 +106,10 @@ public class PropertiesUtil {
}
@Nullable
public static String getFullName(final PropertiesFile psiFile) {
public static String getFullName(final PropertiesFile propertiesFile) {
return ApplicationManager.getApplication().runReadAction(new NullableComputable<String>() {
public String compute() {
PsiDirectory directory = psiFile.getParent();
PsiDirectory directory = propertiesFile.getParent();
String packageQualifiedName = getPackageQualifiedName(directory);
if (packageQualifiedName == null) {
return null;
@@ -104,9 +118,7 @@ public class PropertiesUtil {
if (qName.length() > 0) {
qName.append(".");
}
final VirtualFile virtualFile = psiFile.getVirtualFile();
assert virtualFile != null;
qName.append(getBaseName(virtualFile));
qName.append(getBaseName(propertiesFile.getContainingFile()));
return qName.toString();
}
});
@@ -132,7 +144,7 @@ public class PropertiesUtil {
@NotNull
public static List<IProperty> findAllProperties(Project project, @NotNull ResourceBundle resourceBundle, String key) {
List<IProperty> result = new SmartList<IProperty>();
List<PropertiesFile> propertiesFiles = resourceBundle.getPropertiesFiles(project);
List<PropertiesFile> propertiesFiles = resourceBundle.getPropertiesFiles();
for (PropertiesFile propertiesFile : propertiesFiles) {
result.addAll(propertiesFile.findPropertiesByKey(key));
}
@@ -26,6 +26,7 @@ import com.intellij.lang.properties.psi.PropertiesFile;
import com.intellij.openapi.actionSystem.DataKey;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import org.jetbrains.annotations.NotNull;
import java.util.List;
@@ -33,9 +34,23 @@ import java.util.List;
public abstract class ResourceBundle {
public static final DataKey<ResourceBundle[]> ARRAY_DATA_KEY = DataKey.create("resource.bundle.array");
@NotNull
public abstract List<PropertiesFile> getPropertiesFiles();
/**
* @deprecated, use getPropertiesFiles() instead this method
*/
@Deprecated
@NotNull
public abstract List<PropertiesFile> getPropertiesFiles(final Project project);
@NotNull
public abstract PropertiesFile getDefaultPropertiesFile();
/**
* @deprecated, use getDefaultPropertiesFile() instead this method
*/
@Deprecated
@NotNull
public abstract PropertiesFile getDefaultPropertiesFile(final Project project);
@@ -44,4 +59,7 @@ public abstract class ResourceBundle {
@NotNull
public abstract VirtualFile getBaseDirectory();
@NotNull
public abstract Project getProject();
}
@@ -15,7 +15,6 @@
*/
package com.intellij.lang.properties;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.Nullable;
@@ -26,11 +25,6 @@ public interface BundleNameEvaluator {
@Nullable
public String evaluateBundleName(final PsiFile psiFile) {
final VirtualFile virtualFile = psiFile == null ? null : psiFile.getOriginalFile().getVirtualFile();
if (virtualFile == null) {
return null;
}
final PsiDirectory directory = psiFile.getParent();
if (directory == null) {
return null;
@@ -43,7 +37,7 @@ public interface BundleNameEvaluator {
if (qName.length() > 0) {
qName.append(".");
}
qName.append(PropertiesUtil.getBaseName(virtualFile));
qName.append(PropertiesUtil.getBaseName(psiFile));
return qName.toString();
}
return null;
@@ -23,44 +23,64 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.indexing.FileBasedIndex;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.*;
/**
* @author Konstantin Bulenkov
*/
public class PropertiesImplUtil extends PropertiesUtil {
public static ResourceBundle getResourceBundle(final PsiFile containingFile) {
VirtualFile virtualFile = containingFile.getVirtualFile();
if (!containingFile.isValid() || virtualFile == null) {
@Nullable
public static ResourceBundle getResourceBundle(@NotNull final PropertiesFile representative) {
final PsiFile containingFile = representative.getContainingFile();
if (!containingFile.isValid()) {
return EmptyResourceBundle.getInstance();
}
String baseName = getBaseName(virtualFile);
PsiDirectory directory = ApplicationManager.getApplication().runReadAction(new Computable<PsiDirectory>() {
final String baseName = getBaseName(containingFile);
final PsiDirectory directory = ApplicationManager.getApplication().runReadAction(new Computable<PsiDirectory>() {
@Nullable
public PsiDirectory compute() {
return containingFile.getContainingDirectory();
}});
if (directory == null) return EmptyResourceBundle.getInstance();
return new ResourceBundleImpl(directory.getVirtualFile(), baseName);
return getResourceBundle(baseName, directory);
}
public static boolean isPropertiesFile(VirtualFile file, Project project) {
@Nullable
private static ResourceBundle getResourceBundle(@NotNull final String baseName, @NotNull final PsiDirectory baseDirectory) {
PropertiesFile defaultPropertiesFile = null;
for (final PsiFile psiFile : baseDirectory.getFiles()) {
if (baseName.equals(getBaseName(psiFile))) {
final PropertiesFile propertiesFile = getPropertiesFile(psiFile);
if (propertiesFile != null) {
if (defaultPropertiesFile == null || defaultPropertiesFile.getName().compareTo(propertiesFile.getName()) < 0) {
defaultPropertiesFile = propertiesFile;
}
}
}
}
if (defaultPropertiesFile == null) {
return null;
}
return new ResourceBundleImpl(defaultPropertiesFile);
}
public static boolean isPropertiesFile(@NotNull VirtualFile file, @NotNull Project project) {
return getPropertiesFile(PsiManager.getInstance(project).findFile(file)) != null;
}
public static boolean isPropertiesFile(PsiFile file) {
public static boolean isPropertiesFile(@Nullable PsiFile file) {
return getPropertiesFile(file) != null;
}
@@ -70,8 +90,6 @@ public class PropertiesImplUtil extends PropertiesUtil {
return file instanceof PropertiesFile ? (PropertiesFile)file : XmlPropertiesFileImpl.getPropertiesFile(file);
}
@NotNull
public static List<IProperty> findPropertiesByKey(final Project project, final String key) {
final GlobalSearchScope scope = GlobalSearchScope.allScope(project);
@@ -94,4 +112,23 @@ public class PropertiesImplUtil extends PropertiesUtil {
return properties;
}
@Nullable
public static ResourceBundle createByUrl(final @NotNull String url, final @NotNull Project project) {
if (!url.startsWith(ResourceBundleImpl.RESOURCE_BUNDLE_PREFIX)) return null;
final String defaultPropertiesUrl = url.substring(ResourceBundleImpl.RESOURCE_BUNDLE_PREFIX.length());
final int idx = defaultPropertiesUrl.lastIndexOf('/');
if (idx == -1) return null;
final String baseDirectoryName = defaultPropertiesUrl.substring(0, idx);
final String baseName = defaultPropertiesUrl.substring(idx + 1);
final VirtualFile baseDirectoryVirtualFile = VirtualFileManager.getInstance().findFileByUrl(baseDirectoryName);
if (baseDirectoryVirtualFile == null) {
return null;
}
final PsiFile baseDirectory = PsiManager.getInstance(project).findFile(baseDirectoryVirtualFile);
if (baseDirectory == null || !(baseDirectory instanceof PsiDirectory)) {
return null;
}
return getResourceBundle(baseName, (PsiDirectory)baseDirectory);
}
}
@@ -23,36 +23,32 @@ import com.intellij.lang.properties.psi.PropertiesFile;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.psi.PsiManager;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiFile;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Comparator;
import java.util.List;
public class ResourceBundleImpl extends ResourceBundle {
@NonNls private static final String RESOURCE_BUNDLE_PREFIX = "resourceBundle:";
@NotNull protected final VirtualFile myBaseDirectory;
@NotNull protected final String myBaseName;
@NonNls public static final String RESOURCE_BUNDLE_PREFIX = "resourceBundle:";
@NotNull private final PropertiesFile myDefaultPropertiesFile;
public ResourceBundleImpl(@NotNull VirtualFile baseDirectory, @NotNull String baseName) {
myBaseDirectory = baseDirectory;
myBaseName = baseName;
public ResourceBundleImpl(@NotNull final PropertiesFile defaultPropertiesFile) {
myDefaultPropertiesFile = defaultPropertiesFile;
}
@NotNull
public List<PropertiesFile> getPropertiesFiles(final Project project) {
VirtualFile[] children = myBaseDirectory.getChildren();
@Override
public List<PropertiesFile> getPropertiesFiles() {
PsiFile[] children = myDefaultPropertiesFile.getParent().getFiles();
final String baseName = getBaseName();
List<PropertiesFile> result = new SmartList<PropertiesFile>();
PsiManager psiManager = PsiManager.getInstance(project);
for (VirtualFile file : children) {
if (!file.isValid() || file.getExtension() == null) continue;
if (Comparing.strEqual(PropertiesUtil.getBaseName(file), myBaseName)) {
PropertiesFile propertiesFile = PropertiesImplUtil.getPropertiesFile(psiManager.findFile(file));
for (PsiFile file : children) {
if (!file.isValid() || file.getVirtualFile().getExtension() == null) continue;
if (Comparing.strEqual(PropertiesUtil.getBaseName(file), baseName)) {
PropertiesFile propertiesFile = PropertiesImplUtil.getPropertiesFile(file);
if (propertiesFile != null) {
result.add(propertiesFile);
}
@@ -62,20 +58,38 @@ public class ResourceBundleImpl extends ResourceBundle {
}
@NotNull
public PropertiesFile getDefaultPropertiesFile(final Project project) {
List<PropertiesFile> files = getPropertiesFiles(project);
// put default properties file first
ContainerUtil.quickSort(files, new Comparator<PropertiesFile>() {
public int compare(final PropertiesFile o1, final PropertiesFile o2) {
return Comparing.compare(o1.getName(), o2.getName());
}
});
return files.get(0);
@Override
public List<PropertiesFile> getPropertiesFiles(final Project project) {
return getPropertiesFiles();
}
@NotNull
@Override
public PropertiesFile getDefaultPropertiesFile() {
return myDefaultPropertiesFile;
}
@NotNull
@Override
public PropertiesFile getDefaultPropertiesFile(final Project project) {
return getDefaultPropertiesFile();
}
@NotNull
@Override
public String getBaseName() {
return myBaseName;
return PropertiesUtil.getBaseName(myDefaultPropertiesFile.getContainingFile());
}
@NotNull
public VirtualFile getBaseDirectory() {
return myDefaultPropertiesFile.getParent().getVirtualFile();
}
@NotNull
@Override
public Project getProject() {
return myDefaultPropertiesFile.getProject();
}
public boolean equals(final Object o) {
@@ -83,42 +97,15 @@ public class ResourceBundleImpl extends ResourceBundle {
if (o == null || getClass() != o.getClass()) return false;
final ResourceBundleImpl resourceBundle = (ResourceBundleImpl)o;
if (!myBaseDirectory.equals(resourceBundle.myBaseDirectory)) return false;
if (!myBaseName.equals(resourceBundle.myBaseName)) return false;
if (!myDefaultPropertiesFile.equals(resourceBundle.myDefaultPropertiesFile)) return false;
return true;
}
public int hashCode() {
int result = myBaseDirectory.hashCode();
result = 29 * result + myBaseName.hashCode();
return result;
}
@Nullable
public static ResourceBundle createByUrl(String url) {
if (!url.startsWith(RESOURCE_BUNDLE_PREFIX)) return null;
String defaultPropertiesUrl = url.substring(RESOURCE_BUNDLE_PREFIX.length());
final int idx = defaultPropertiesUrl.lastIndexOf('/');
if (idx == -1) return null;
String baseDir = defaultPropertiesUrl.substring(0, idx);
String baseName = defaultPropertiesUrl.substring(idx + 1);
VirtualFile baseDirectory = VirtualFileManager.getInstance().findFileByUrl(baseDir);
if (baseDirectory != null) {
return new ResourceBundleImpl(baseDirectory, baseName);
}
return null;
return myDefaultPropertiesFile.hashCode();
}
public String getUrl() {
return RESOURCE_BUNDLE_PREFIX +getBaseDirectory() + "/" + getBaseName();
return RESOURCE_BUNDLE_PREFIX + getBaseDirectory() + "/" + getBaseName();
}
@NotNull
public VirtualFile getBaseDirectory() {
return myBaseDirectory;
}
}
@@ -19,31 +19,50 @@
*/
package com.intellij.lang.properties.editor;
import com.intellij.ide.presentation.Presentation;
import com.intellij.lang.properties.PropertiesImplUtil;
import com.intellij.lang.properties.PropertiesUtil;
import com.intellij.lang.properties.ResourceBundle;
import com.intellij.lang.properties.psi.PropertiesFile;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileSystem;
import com.intellij.psi.PsiManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@Presentation(icon = "AllIcons.Nodes.ResourceBundle")
public class ResourceBundleAsVirtualFile extends VirtualFile {
private final ResourceBundle myResourceBundle;
private final VirtualFile myBasePropertiesFile;
public ResourceBundleAsVirtualFile(@NotNull ResourceBundle resourceBundle) {
myResourceBundle = resourceBundle;
private ResourceBundleAsVirtualFile(@NotNull final VirtualFile basePropertiesFile) {
myBasePropertiesFile = basePropertiesFile;
}
@NotNull
public ResourceBundle getResourceBundle() {
return myResourceBundle;
public static ResourceBundleAsVirtualFile fromResourceBundle(final @NotNull ResourceBundle resourceBundle) {
return new ResourceBundleAsVirtualFile(resourceBundle.getDefaultPropertiesFile().getVirtualFile());
}
@Nullable
public ResourceBundle getResourceBundle(final Project project) {
final PsiManager psiManager = PsiManager.getInstance(project);
final PropertiesFile file = PropertiesImplUtil.getPropertiesFile(psiManager.findFile(myBasePropertiesFile));
if (file == null) {
return null;
}
return PropertiesImplUtil.getResourceBundle(file);
}
@Override
@NotNull
public VirtualFileSystem getFileSystem() {
return myResourceBundle.getBaseDirectory().getFileSystem();
return LocalFileSystem.getInstance();
}
@Override
@@ -55,7 +74,7 @@ public class ResourceBundleAsVirtualFile extends VirtualFile {
@Override
@NotNull
public String getName() {
return myResourceBundle.getBaseName();
return PropertiesUtil.getBaseName(myBasePropertiesFile);
}
public boolean equals(final Object o) {
@@ -64,17 +83,18 @@ public class ResourceBundleAsVirtualFile extends VirtualFile {
final ResourceBundleAsVirtualFile resourceBundleAsVirtualFile = (ResourceBundleAsVirtualFile)o;
if (!myResourceBundle.equals(resourceBundleAsVirtualFile.myResourceBundle)) return false;
if (!myBasePropertiesFile.equals(resourceBundleAsVirtualFile.myBasePropertiesFile)) return false;
return true;
}
public int hashCode() {
return myResourceBundle.hashCode();
return myBasePropertiesFile.hashCode();
}
@Override
public void rename(Object requestor, @NotNull String newName) throws IOException {
throw new UnsupportedOperationException();
}
@Override
@@ -94,7 +114,7 @@ public class ResourceBundleAsVirtualFile extends VirtualFile {
@Override
public VirtualFile getParent() {
return myResourceBundle.getBaseDirectory();
return myBasePropertiesFile.getParent();
}
@Override
@@ -0,0 +1,30 @@
/*
* 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.lang.properties.editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
/**
* @author Dmitry Batkovich
*/
public interface ResourceBundleEditorViewElement {
PsiElement[] getPsiElements(@NotNull Project project);
}
@@ -26,6 +26,9 @@ import com.intellij.lang.properties.ResourceBundle;
import com.intellij.lang.properties.psi.PropertiesFile;
import com.intellij.navigation.ItemPresentation;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -34,36 +37,35 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class ResourceBundleFileStructureViewElement implements StructureViewTreeElement {
private final Project myProject;
public class ResourceBundleFileStructureViewElement implements StructureViewTreeElement, ResourceBundleEditorViewElement {
private final ResourceBundle myResourceBundle;
public ResourceBundleFileStructureViewElement(final Project project, final ResourceBundle resourceBundle) {
myProject = project;
public ResourceBundleFileStructureViewElement(final ResourceBundle resourceBundle) {
myResourceBundle = resourceBundle;
}
@Override
public ResourceBundle getValue() {
return myResourceBundle;
}
@NotNull
public StructureViewTreeElement[] getChildren() {
List<PropertiesFile> propertiesFiles = myResourceBundle.getPropertiesFiles(myProject);
List<PropertiesFile> propertiesFiles = myResourceBundle.getPropertiesFiles();
Map<String, IProperty> propertyNames = new LinkedHashMap<String, IProperty>();
for (PropertiesFile propertiesFile : propertiesFiles) {
List<IProperty> properties = propertiesFile.getProperties();
for (IProperty property : properties) {
String name = property.getUnescapedKey();
String name = property.getKey();
if (!propertyNames.containsKey(name)) {
propertyNames.put(name, property);
}
}
}
List<StructureViewTreeElement> result = new ArrayList<StructureViewTreeElement>(propertyNames.size());
for (String property : propertyNames.keySet()) {
//result.add(new PropertiesStructureViewElement(property));
result.add(new ResourceBundlePropertyStructureViewElement(myProject, myResourceBundle, property));
for (Map.Entry<String, IProperty> propertyEntry : propertyNames.entrySet()) {
//result.add(new PropertiesStructureViewElement(propertyEntry));
result.add(new ResourceBundlePropertyStructureViewElement(myResourceBundle, propertyEntry.getValue()));
}
return result.toArray(new StructureViewTreeElement[result.size()]);
}
@@ -85,6 +87,17 @@ public class ResourceBundleFileStructureViewElement implements StructureViewTree
};
}
@Override
public PsiElement[] getPsiElements(@NotNull Project project) {
final List<PropertiesFile> propertiesFiles = getValue().getPropertiesFiles();
return ContainerUtil.map2Array(propertiesFiles, new PsiElement[propertiesFiles.size()], new Function<PropertiesFile, PsiElement>() {
@Override
public PsiElement fun(PropertiesFile propertiesFile) {
return propertiesFile.getContainingFile();
}
});
}
public void navigate(boolean requestFocus) {
}
@@ -20,6 +20,7 @@
package com.intellij.lang.properties.editor;
import com.intellij.ide.structureView.StructureViewTreeElement;
import com.intellij.lang.properties.IProperty;
import com.intellij.lang.properties.PropertiesHighlighter;
import com.intellij.lang.properties.PropertiesUtil;
import com.intellij.lang.properties.ResourceBundle;
@@ -29,16 +30,16 @@ import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.util.PlatformIcons;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
public class ResourceBundlePropertyStructureViewElement implements StructureViewTreeElement {
private final String myPropertyName;
private final Project myProject;
public class ResourceBundlePropertyStructureViewElement implements StructureViewTreeElement, ResourceBundleEditorViewElement {
private final ResourceBundle myResourceBundle;
private final IProperty myProperty;
private String myPresentableName;
private static final TextAttributesKey INCOMPLETE_PROPERTY_KEY;
@@ -49,10 +50,19 @@ public class ResourceBundlePropertyStructureViewElement implements StructureView
INCOMPLETE_PROPERTY_KEY = TextAttributesKey.createTextAttributesKey("INCOMPLETE_PROPERTY_KEY", textAttributes);
}
public ResourceBundlePropertyStructureViewElement(final Project project, final ResourceBundle resourceBundle, String propertyName) {
myProject = project;
public ResourceBundlePropertyStructureViewElement(final ResourceBundle resourceBundle, final IProperty property) {
myResourceBundle = resourceBundle;
myPropertyName = propertyName;
myProperty = property;
}
public IProperty getProperty() {
return myProperty;
}
@Override
public PsiElement[] getPsiElements(final @NotNull Project project) {
return new PsiElement[] {getProperty().getPsiElement()};
}
public void setPresentableName(final String presentableName) {
@@ -61,7 +71,7 @@ public class ResourceBundlePropertyStructureViewElement implements StructureView
@Override
public String getValue() {
return myPropertyName;
return myProperty.getName();
}
@Override
@@ -76,7 +86,7 @@ public class ResourceBundlePropertyStructureViewElement implements StructureView
return new ColoredItemPresentation() {
@Override
public String getPresentableText() {
return myPresentableName == null ? myPropertyName : myPresentableName;
return myPresentableName == null ? myProperty.getName() : myPresentableName;
}
@Override
@@ -91,7 +101,7 @@ public class ResourceBundlePropertyStructureViewElement implements StructureView
@Override
public TextAttributesKey getTextAttributesKey() {
boolean isComplete = PropertiesUtil.isPropertyComplete(myProject, myResourceBundle, myPropertyName);
boolean isComplete = PropertiesUtil.isPropertyComplete(myResourceBundle, myProperty.getName());
if (isComplete) {
return PropertiesHighlighter.PROPERTY_KEY;
@@ -115,5 +125,4 @@ public class ResourceBundlePropertyStructureViewElement implements StructureView
public boolean canNavigateToSource() {
return false;
}
}
@@ -25,7 +25,6 @@ import com.intellij.ide.util.treeView.smartTree.Sorter;
import com.intellij.lang.properties.ResourceBundle;
import com.intellij.lang.properties.structureView.GroupByWordPrefixes;
import com.intellij.lang.properties.structureView.PropertiesSeparatorManager;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
/**
@@ -33,23 +32,24 @@ import org.jetbrains.annotations.NotNull;
*/
public class ResourceBundleStructureViewModel implements PropertiesGroupingStructureViewModel, StructureViewModel.ExpandInfoProvider {
private final ResourceBundle myResourceBundle;
private final GroupByWordPrefixes myGroupByWordPrefixes;
private final GroupByWordPrefixes myByWordPrefixesGrouper;
private final StructureViewTreeElement myRoot;
public ResourceBundleStructureViewModel(final Project project, ResourceBundle root) {
public ResourceBundleStructureViewModel(ResourceBundle root) {
myResourceBundle = root;
String separator = PropertiesSeparatorManager.getInstance().getSeparator(project, new ResourceBundleAsVirtualFile(myResourceBundle));
myGroupByWordPrefixes = new GroupByWordPrefixes(separator);
myRoot = new ResourceBundleFileStructureViewElement(project, myResourceBundle);
String separator = PropertiesSeparatorManager.getInstance(root.getProject()).
getSeparator(myResourceBundle);
myByWordPrefixesGrouper = new GroupByWordPrefixes(separator);
myRoot = new ResourceBundleFileStructureViewElement(myResourceBundle);
}
public void setSeparator(String separator) {
myGroupByWordPrefixes.setSeparator(separator);
PropertiesSeparatorManager.getInstance().setSeparator(new ResourceBundleAsVirtualFile(myResourceBundle), separator);
myByWordPrefixesGrouper.setSeparator(separator);
PropertiesSeparatorManager.getInstance(myResourceBundle.getProject()).setSeparator(myResourceBundle, separator);
}
public String getSeparator() {
return myGroupByWordPrefixes.getSeparator();
return myByWordPrefixesGrouper.getSeparator();
}
@NotNull
@@ -59,7 +59,7 @@ public class ResourceBundleStructureViewModel implements PropertiesGroupingStruc
@NotNull
public Grouper[] getGroupers() {
return new Grouper[]{myGroupByWordPrefixes};
return new Grouper[]{myByWordPrefixesGrouper};
}
@NotNull
@@ -54,10 +54,10 @@ public class ResourceBundleUtil {
if (virtualFile == null) {
return null;
}
if (virtualFile instanceof ResourceBundleAsVirtualFile) {
return ((ResourceBundleAsVirtualFile)virtualFile).getResourceBundle();
final Project project = CommonDataKeys.PROJECT.getData(dataContext);
if (virtualFile instanceof ResourceBundleAsVirtualFile && project != null) {
return ((ResourceBundleAsVirtualFile)virtualFile).getResourceBundle(project);
}
Project project = CommonDataKeys.PROJECT.getData(dataContext);
if (project != null) {
final PsiFile psiFile = PsiManager.getInstance(project).findFile(virtualFile);
if (psiFile instanceof PropertiesFile) {
@@ -114,7 +114,7 @@ public class PropertiesFileImpl extends PsiFileBase implements PropertiesFile {
@Override
@NotNull
public ResourceBundle getResourceBundle() {
return PropertiesImplUtil.getResourceBundle(getContainingFile());
return PropertiesImplUtil.getResourceBundle(this);
}
@Override

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