Merge remote-tracking branch 'origin/master'

This commit is contained in:
Kirill Likhodedov
2011-12-19 17:30:03 +03:00
425 changed files with 11268 additions and 2516 deletions
+1
View File
@@ -79,6 +79,7 @@
<module fileurl="file://$PROJECT_DIR$/platform/platform-main/platform-main.iml" filepath="$PROJECT_DIR$/platform/platform-main/platform-main.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/platform/platform-resources/platform-resources.iml" filepath="$PROJECT_DIR$/platform/platform-resources/platform-resources.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/platform/platform-resources-en/platform-resources-en.iml" filepath="$PROJECT_DIR$/platform/platform-resources-en/platform-resources-en.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/platform/platform-tests/platform-tests.iml" filepath="$PROJECT_DIR$/platform/platform-tests/platform-tests.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/plugins/properties/properties.iml" filepath="$PROJECT_DIR$/plugins/properties/properties.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/xml/relaxng/relaxng.iml" filepath="$PROJECT_DIR$/xml/relaxng/relaxng.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/resources/resources.iml" filepath="$PROJECT_DIR$/resources/resources.iml" />
@@ -48,6 +48,7 @@ public class DebuggerDataViewsConfigurable implements SearchableConfigurable {
private JCheckBox myCbHideNullArrayElements;
private JCheckBox myCbShowStatic;
private JCheckBox myCbShowDeclaredType;
private JCheckBox myCbShowFQNames;
private JCheckBox myCbShowObjectId;
private StateRestoringCheckBox myCbShowStaticFinalFields;
@@ -102,6 +103,7 @@ public class DebuggerDataViewsConfigurable implements SearchableConfigurable {
}
});
myCbShowDeclaredType = new JCheckBox(DebuggerBundle.message("label.base.renderer.configurable.show.declared.type"));
myCbShowFQNames = new JCheckBox(DebuggerBundle.message("label.base.renderer.configurable.show.fq.names"));
myCbShowObjectId = new JCheckBox(DebuggerBundle.message("label.base.renderer.configurable.show.object.id"));
myCbEnableToString = new JCheckBox(DebuggerBundle.message("label.base.renderer.configurable.enable.tostring"));
@@ -149,7 +151,8 @@ public class DebuggerDataViewsConfigurable implements SearchableConfigurable {
showPanel.add(myCbShowObjectId, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(4, 0, 0, 0), 0, 0));
showPanel.add(myCbShowSyntheticFields, new GridBagConstraints(1, GridBagConstraints.RELATIVE, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 10, 0, 0), 0, 0));
showPanel.add(myCbShowStatic, new GridBagConstraints(1, GridBagConstraints.RELATIVE, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(4, 10, 0, 0), 0, 0));
showPanel.add(myCbShowStaticFinalFields, new GridBagConstraints(2, 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(4, 10, 0, 0), 0, 0));
showPanel.add(myCbShowStaticFinalFields, new GridBagConstraints(2, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(4, 10, 0, 0), 0, 0));
showPanel.add(myCbShowFQNames, new GridBagConstraints(3, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 10, 0, 0), 0, 0));
panel.add(showPanel, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 3, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(4, 0, 0, 0), 0, 0));
@@ -193,6 +196,7 @@ public class DebuggerDataViewsConfigurable implements SearchableConfigurable {
classRenderer.SHOW_STATIC_FINAL = myCbShowStaticFinalFields.isSelectedWhenSelectable();
classRenderer.SHOW_SYNTHETICS = myCbShowSyntheticFields.isSelected();
classRenderer.SHOW_DECLARED_TYPE = myCbShowDeclaredType.isSelected();
classRenderer.SHOW_FQ_TYPE_NAMES = myCbShowFQNames.isSelected();
classRenderer.SHOW_OBJECT_ID = myCbShowObjectId.isSelected();
final ToStringRenderer toStringRenderer = rendererSettings.getToStringRenderer();
@@ -226,6 +230,7 @@ public class DebuggerDataViewsConfigurable implements SearchableConfigurable {
myCbShowStaticFinalFields.makeUnselectable(false);
}
myCbShowDeclaredType.setSelected(classRenderer.SHOW_DECLARED_TYPE);
myCbShowFQNames.setSelected(classRenderer.SHOW_FQ_TYPE_NAMES);
myCbShowObjectId.setSelected(classRenderer.SHOW_OBJECT_ID);
final ToStringRenderer toStringRenderer = rendererSettings.getToStringRenderer();
@@ -275,6 +280,7 @@ public class DebuggerDataViewsConfigurable implements SearchableConfigurable {
(classRenderer.SHOW_STATIC_FINAL != myCbShowStaticFinalFields.isSelectedWhenSelectable()) ||
(classRenderer.SHOW_SYNTHETICS != myCbShowSyntheticFields.isSelected()) ||
(classRenderer.SHOW_DECLARED_TYPE != myCbShowDeclaredType.isSelected()) ||
(classRenderer.SHOW_FQ_TYPE_NAMES != myCbShowFQNames.isSelected()) ||
(classRenderer.SHOW_OBJECT_ID != myCbShowObjectId.isSelected());
if (isClassRendererModified) {
return true;
@@ -158,7 +158,7 @@ public class FieldDescriptorImpl extends ValueDescriptorImpl implements FieldDes
buf.append(getName());
if (classRenderer.SHOW_DECLARED_TYPE) {
buf.append(": ");
buf.append(myField.typeName());
buf.append(classRenderer.renderTypeName(myField.typeName()));
}
return buf.toString();
}
@@ -121,7 +121,7 @@ public class LocalVariableDescriptorImpl extends ValueDescriptorImpl implements
buf.append(getName());
if (classRenderer.SHOW_DECLARED_TYPE) {
buf.append(": ");
buf.append(myTypeName);
buf.append(classRenderer.renderTypeName(myTypeName));
}
return buf.toString();
}
@@ -23,7 +23,9 @@ package com.intellij.debugger.ui.impl.watch;
import com.intellij.debugger.engine.DebuggerManagerThreadImpl;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
import com.intellij.debugger.settings.NodeRendererSettings;
import com.intellij.debugger.ui.tree.StaticDescriptor;
import com.intellij.debugger.ui.tree.render.ClassRenderer;
import com.intellij.debugger.ui.tree.render.DescriptorLabelListener;
import com.sun.jdi.Field;
import com.sun.jdi.ReferenceType;
@@ -64,6 +66,7 @@ public class StaticDescriptorImpl extends NodeDescriptorImpl implements StaticDe
protected String calcRepresentation(EvaluationContextImpl context, DescriptorLabelListener descriptorLabelListener) throws EvaluateException {
DebuggerManagerThreadImpl.assertIsManagerThread();
return getName() + " = " + myType.name();
final ClassRenderer classRenderer = NodeRendererSettings.getInstance().getClassRenderer();
return getName() + " = " + classRenderer.renderTypeName(myType.name());
}
}
@@ -27,7 +27,9 @@ import com.intellij.debugger.engine.evaluation.EvaluateExceptionUtil;
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
import com.intellij.debugger.engine.evaluation.TextWithImports;
import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.debugger.settings.NodeRendererSettings;
import com.intellij.debugger.ui.tree.UserExpressionDescriptor;
import com.intellij.debugger.ui.tree.render.ClassRenderer;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiCodeFragment;
@@ -57,8 +59,10 @@ public class UserExpressionDescriptorImpl extends EvaluationDescriptor implement
try {
buffer.append(getName());
buffer.append(": ");
if(getValue() != null) {
buffer.append(getValue().type().name());
final Value value = getValue();
if(value != null) {
final ClassRenderer classRenderer = NodeRendererSettings.getInstance().getClassRenderer();
buffer.append(classRenderer.renderTypeName(value.type().name()));
}
return buffer.toString();
@@ -378,7 +378,7 @@ public abstract class ValueDescriptorImpl extends NodeDescriptorImpl implements
if (showConcreteType || classRenderer.SHOW_OBJECT_ID) {
buf.append('{');
if (showConcreteType) {
buf.append(objRef.type().name());
buf.append(classRenderer.renderTypeName(objRef.type().name()));
}
if (classRenderer.SHOW_OBJECT_ID) {
buf.append('@');
@@ -63,6 +63,7 @@ public class ClassRenderer extends NodeRendererImpl{
public boolean SHOW_STATIC = false;
public boolean SHOW_STATIC_FINAL = false;
public boolean SHOW_FQ_TYPE_NAMES = true;
public boolean SHOW_DECLARED_TYPE = false;
public boolean SHOW_OBJECT_ID = true;
@@ -70,6 +71,17 @@ public class ClassRenderer extends NodeRendererImpl{
myProperties.setEnabled(true);
}
public final String renderTypeName(final String typeName) {
if (SHOW_FQ_TYPE_NAMES) {
return typeName;
}
final int dotIndex = typeName.lastIndexOf('.');
if (dotIndex > 0) {
return typeName.substring(dotIndex + 1);
}
return typeName;
}
public String getUniqueId() {
return UNIQUE_ID;
}
@@ -36,6 +36,7 @@ import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStr
import com.intellij.openapi.ui.DetailsComponent;
import com.intellij.openapi.ui.NamedConfigurable;
import com.intellij.openapi.util.IconLoader;
import com.intellij.ui.treeStructure.filtered.FilteringTreeBuilder;
import com.intellij.util.ui.tree.TreeUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -43,6 +44,8 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.*;
import java.util.List;
@@ -55,6 +58,7 @@ public class FacetStructureConfigurable extends BaseStructureConfigurable {
private final Map<FacetType<?, ?>, FacetTypeEditor> myFacetTypeEditors = new HashMap<FacetType<?,?>, FacetTypeEditor>();
private MultipleFacetSettingsEditor myCurrentMultipleSettingsEditor;
@NonNls private static final String NO_FRAMEWORKS_NODE = "No facets are configured";
private boolean myTreeWasInitialized;
public FacetStructureConfigurable(final Project project, ModuleManager moduleManager) {
super(project);
@@ -77,7 +81,30 @@ public class FacetStructureConfigurable extends BaseStructureConfigurable {
@Override
protected void initTree() {
super.initTree();
myTree.setCellRenderer(new FacetsTreeCellRenderer());
if (!myTreeWasInitialized) {
myTreeWasInitialized = true;
myTree.setCellRenderer(new FacetsTreeCellRenderer());
myTree.addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
revalidateTree();
}
@Override
public void componentMoved(ComponentEvent e) {
revalidateTree();
}
@Override
public void componentShown(ComponentEvent e) {
revalidateTree();
}
});
}
}
private void revalidateTree() {
FilteringTreeBuilder.revalidateTree(myTree);
}
protected void loadTree() {
@@ -56,8 +56,8 @@ public class FacetsTreeCellRenderer extends GroupedElementsRenderer.Tree impleme
final Icon icon = configurable.getIcon(expanded);
final boolean showSeparator = configurable instanceof FrameworkDetectionConfigurable;
int width = -1;
if (showSeparator) {
final int treeWidth = tree.getSize().width;
if (showSeparator && tree.isVisible()) {
final int treeWidth = tree.getVisibleRect().width - 4;
if (treeWidth > 0) {
width = treeWidth;
}
@@ -21,6 +21,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.patterns.ElementPattern;
import com.intellij.patterns.PsiJavaPatterns;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
@@ -103,7 +104,8 @@ public class JavaMemberNameCompletionContributor extends CompletionContributor {
private static void completeLocalVariableName(Set<LookupElement> set, PrefixMatcher matcher, PsiVariable var, boolean includeOverlapped) {
FeatureUsageTracker.getInstance().triggerFeatureUsed("editing.completion.variable.name");
final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(var.getProject());
Project project = var.getProject();
final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project);
final VariableKind variableKind = codeStyleManager.getVariableKind(var);
String propertyName = null;
@@ -119,7 +121,7 @@ public class JavaMemberNameCompletionContributor extends CompletionContributor {
SuggestedNameInfo suggestedNameInfo = codeStyleManager.suggestVariableName(variableKind, propertyName, null, type, StringUtil.isEmpty(matcher.getPrefix()));
suggestedNameInfo = codeStyleManager.suggestUniqueVariableName(suggestedNameInfo, var, false);
final String[] suggestedNames = suggestedNameInfo.names;
addLookupItems(set, suggestedNameInfo, matcher, suggestedNames);
addLookupItems(set, suggestedNameInfo, matcher, project, suggestedNames);
if (set.isEmpty()) {
if (type.equalsToText(CommonClassNames.JAVA_LANG_OBJECT) && matcher.prefixMatches("object")) {
set.add(LookupElementBuilder.create("object"));
@@ -130,16 +132,16 @@ public class JavaMemberNameCompletionContributor extends CompletionContributor {
}
if (set.isEmpty() && includeOverlapped) {
addLookupItems(set, null, matcher, getOverlappedNameVersions(matcher.getPrefix(), suggestedNames, ""));
addLookupItems(set, null, matcher, project, getOverlappedNameVersions(matcher.getPrefix(), suggestedNames, ""));
}
PsiElement parent = PsiTreeUtil.getParentOfType(var, PsiCodeBlock.class);
if(parent == null) parent = PsiTreeUtil.getParentOfType(var, PsiMethod.class);
addLookupItems(set, suggestedNameInfo, matcher, getUnresolvedReferences(parent, false));
addLookupItems(set, suggestedNameInfo, matcher, project, getUnresolvedReferences(parent, false));
PsiExpression initializer = var.getInitializer();
if (initializer != null) {
SuggestedNameInfo initializerSuggestions = IntroduceVariableBase.getSuggestedName(type, initializer);
addLookupItems(set, initializerSuggestions, matcher, initializerSuggestions.names);
addLookupItems(set, initializerSuggestions, matcher, project, initializerSuggestions.names);
}
}
@@ -216,18 +218,19 @@ public class JavaMemberNameCompletionContributor extends CompletionContributor {
private static void completeFieldName(Set<LookupElement> set, PsiField var, final PrefixMatcher matcher, boolean includeOverlapped) {
FeatureUsageTracker.getInstance().triggerFeatureUsed("editing.completion.variable.name");
JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(var.getProject());
final VariableKind variableKind = JavaCodeStyleManager.getInstance(var.getProject()).getVariableKind(var);
Project project = var.getProject();
JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project);
final VariableKind variableKind = JavaCodeStyleManager.getInstance(project).getVariableKind(var);
final String prefix = matcher.getPrefix();
if (PsiType.VOID.equals(var.getType()) || psiField().inClass(psiClass().isInterface()).accepts(var)) {
completeVariableNameForRefactoring(var.getProject(), set, matcher, var.getType(), variableKind, includeOverlapped, true);
completeVariableNameForRefactoring(project, set, matcher, var.getType(), variableKind, includeOverlapped, true);
return;
}
SuggestedNameInfo suggestedNameInfo = codeStyleManager.suggestVariableName(variableKind, null, null, var.getType());
final String[] suggestedNames = suggestedNameInfo.names;
addLookupItems(set, suggestedNameInfo, matcher, suggestedNames);
addLookupItems(set, suggestedNameInfo, matcher, project, suggestedNames);
if (set.isEmpty() && includeOverlapped) {
// use suggested names as suffixes
@@ -238,17 +241,17 @@ public class JavaMemberNameCompletionContributor extends CompletionContributor {
}
addLookupItems(set, null, matcher, getOverlappedNameVersions(prefix, suggestedNames, requiredSuffix));
addLookupItems(set, null, matcher, project, getOverlappedNameVersions(prefix, suggestedNames, requiredSuffix));
}
addLookupItems(set, suggestedNameInfo, matcher, getUnresolvedReferences(var.getParent(), false));
addLookupItems(set, suggestedNameInfo, matcher, project, getUnresolvedReferences(var.getParent(), false));
PsiExpression initializer = var.getInitializer();
PsiClass containingClass = var.getContainingClass();
if (initializer != null && containingClass != null) {
SuggestedNameInfo initializerSuggestions = InplaceIntroduceFieldPopup.
suggestFieldName(var.getType(), null, initializer, var.hasModifierProperty(PsiModifier.STATIC), containingClass);
addLookupItems(set, initializerSuggestions, matcher, initializerSuggestions.names);
addLookupItems(set, initializerSuggestions, matcher, project, initializerSuggestions.names);
}
}
@@ -261,7 +264,7 @@ public class JavaMemberNameCompletionContributor extends CompletionContributor {
SuggestedNameInfo suggestedNameInfo = codeStyleManager.suggestVariableName(varKind, null, null, varType);
final String[] strings = completeVariableNameForRefactoring(codeStyleManager, matcher, varType, varKind, suggestedNameInfo,
includeOverlapped, methodPrefix);
addLookupItems(set, suggestedNameInfo, matcher, strings);
addLookupItems(set, suggestedNameInfo, matcher, project, strings);
}
public static String[] completeVariableNameForRefactoring(JavaCodeStyleManager codeStyleManager,
@@ -303,7 +306,7 @@ public class JavaMemberNameCompletionContributor extends CompletionContributor {
if (containingClass != null) {
final String name = containingClass.getName();
if (StringUtil.isNotEmpty(name)) {
addLookupItems(set, null, matcher, name);
addLookupItems(set, null, matcher, element.getProject(), name);
}
}
return;
@@ -312,9 +315,9 @@ public class JavaMemberNameCompletionContributor extends CompletionContributor {
PsiClass ourClassParent = PsiTreeUtil.getParentOfType(element, PsiClass.class);
if (ourClassParent == null) return;
addLookupItems(set, null, matcher, getUnresolvedReferences(ourClassParent, true));
addLookupItems(set, null, matcher, element.getProject(), getUnresolvedReferences(ourClassParent, true));
addLookupItems(set, null, matcher, getPropertiesHandlersNames(
addLookupItems(set, null, matcher, element.getProject(), getPropertiesHandlersNames(
ourClassParent,
((PsiModifierListOwner)element).hasModifierProperty(PsiModifier.STATIC),
PsiUtil.getTypeByPsiElement(element), element));
@@ -360,11 +363,11 @@ public class JavaMemberNameCompletionContributor extends CompletionContributor {
return result.result;
}
private static void addLookupItems(Set<LookupElement> lookupElements, @Nullable final SuggestedNameInfo callback, PrefixMatcher matcher, String... strings) {
private static void addLookupItems(Set<LookupElement> lookupElements, @Nullable final SuggestedNameInfo callback, PrefixMatcher matcher, Project project, String... strings) {
outer:
for (int i = 0; i < strings.length; i++) {
String name = strings[i];
if (!matcher.prefixMatches(name)) {
if (!matcher.prefixMatches(name) || !JavaPsiFacade.getInstance(project).getNameHelper().isIdentifier(name, LanguageLevel.HIGHEST)) {
continue;
}
@@ -17,54 +17,38 @@ package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.openapi.util.Ref;
import com.intellij.util.Consumer;
/**
* @author peter
*/
public class JavaNoVariantsDelegator extends CompletionContributor {
public class JavaNoVariantsDelegator extends NoVariantsDelegator {
@Override
public void fillCompletionVariants(final CompletionParameters parameters, final CompletionResultSet result) {
final Ref<Boolean> empty = Ref.create(true);
Consumer<CompletionResult> passResult = new Consumer<CompletionResult>() {
public void consume(final CompletionResult lookupElement) {
empty.set(false);
result.passResult(lookupElement);
}
};
result.runRemainingContributors(parameters, passResult);
protected void delegate(CompletionParameters parameters, CompletionResultSet result, Consumer<CompletionResult> passResult) {
if (parameters.getCompletionType() == CompletionType.BASIC &&
parameters.getInvocationCount() <= 1 &&
JavaCompletionContributor.mayStartClassName(result, false) &&
JavaCompletionContributor.isClassNamePossible(parameters.getPosition())) {
final ClassByNameMerger merger = new ClassByNameMerger(parameters.getInvocationCount() == 0, result);
if (!empty.get() && parameters.getInvocationCount() == 0) {
result.restartCompletionWhenNothingMatches();
}
if (empty.get()) {
if (parameters.getCompletionType() == CompletionType.BASIC &&
parameters.getInvocationCount() <= 1 &&
JavaCompletionContributor.mayStartClassName(result, false) &&
JavaCompletionContributor.isClassNamePossible(parameters.getPosition())) {
final ClassByNameMerger merger = new ClassByNameMerger(parameters.getInvocationCount() == 0, result);
JavaClassNameCompletionContributor.addAllClasses(parameters, JavaCompletionSorting.addJavaSorting(parameters, result),
true, new Consumer<LookupElement>() {
@Override
public void consume(LookupElement element) {
JavaPsiClassReferenceElement classElement = element.as(JavaPsiClassReferenceElement.CLASS_CONDITION_KEY);
if (classElement != null) {
classElement.setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE);
}
merger.consume(classElement);
JavaClassNameCompletionContributor.addAllClasses(parameters, JavaCompletionSorting.addJavaSorting(parameters, result),
true, new Consumer<LookupElement>() {
@Override
public void consume(LookupElement element) {
JavaPsiClassReferenceElement classElement = element.as(JavaPsiClassReferenceElement.CLASS_CONDITION_KEY);
if (classElement != null) {
classElement.setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE);
}
});
merger.finishedClassProcessing();
merger.consume(classElement);
}
});
} else if (parameters.getCompletionType() == CompletionType.SMART && parameters.getInvocationCount() == 2) {
result.runRemainingContributors(parameters.withInvocationCount(3), passResult);
}
merger.finishedClassProcessing();
} else if (parameters.getCompletionType() == CompletionType.SMART && parameters.getInvocationCount() == 2) {
result.runRemainingContributors(parameters.withInvocationCount(3), passResult);
}
}
}
@@ -18,6 +18,8 @@ package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.CodeInsightUtilBase;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement;
import com.intellij.ide.util.SuperMethodWarningUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.undo.UndoUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
@@ -25,10 +27,16 @@ import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.changeSignature.ChangeSignatureProcessor;
import com.intellij.refactoring.changeSignature.JavaChangeSignatureDialog;
import com.intellij.refactoring.changeSignature.ParameterInfoImpl;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
public class VariableTypeFix extends LocalQuickFixAndIntentionActionOnPsiElement {
static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.quickfix.VariableTypeFix");
@@ -76,6 +84,7 @@ public class VariableTypeFix extends LocalQuickFixAndIntentionActionOnPsiElement
@NotNull PsiElement startElement,
@NotNull PsiElement endElement) {
final PsiVariable myVariable = (PsiVariable)startElement;
if (changeMethodSignatureIfNeeded(myVariable)) return;
if (!CodeInsightUtilBase.prepareFileForWrite(myVariable.getContainingFile())) return;
try {
myVariable.normalizeDeclaration();
@@ -88,6 +97,42 @@ public class VariableTypeFix extends LocalQuickFixAndIntentionActionOnPsiElement
}
}
private boolean changeMethodSignatureIfNeeded(PsiVariable myVariable) {
if (myVariable instanceof PsiParameter) {
final PsiElement scope = ((PsiParameter)myVariable).getDeclarationScope();
if (scope instanceof PsiMethod) {
final PsiMethod method = (PsiMethod)scope;
final PsiMethod psiMethod = SuperMethodWarningUtil.checkSuperMethod(method, RefactoringBundle.message("to.refactor"));
if (psiMethod == null) return true;
final int parameterIndex = method.getParameterList().getParameterIndex((PsiParameter)myVariable);
if (!CodeInsightUtilBase.prepareFileForWrite(psiMethod.getContainingFile())) return true;
final ArrayList<ParameterInfoImpl> infos = new ArrayList<ParameterInfoImpl>();
int i = 0;
for (PsiParameter parameter : psiMethod.getParameterList().getParameters()) {
final boolean changeType = i == parameterIndex;
infos.add(new ParameterInfoImpl(i++, parameter.getName(), changeType ? getReturnType() : parameter.getType()));
}
if (!ApplicationManager.getApplication().isUnitTestMode()) {
final JavaChangeSignatureDialog dialog = new JavaChangeSignatureDialog(psiMethod.getProject(), psiMethod, false, myVariable);
dialog.setParameterInfos(infos);
dialog.show();
}
else {
ChangeSignatureProcessor processor = new ChangeSignatureProcessor(psiMethod.getProject(),
psiMethod,
false, null,
psiMethod.getName(),
psiMethod.getReturnType(),
infos.toArray(new ParameterInfoImpl[infos.size()]));
processor.run();
}
return true;
}
}
return false;
}
protected PsiType getReturnType() {
return myReturnType;
}
@@ -322,16 +322,26 @@ public class GenerateDelegateHandler implements LanguageCodeInsightActionHandler
int offset = editor.getCaretModel().getOffset();
PsiElement element = file.findElementAt(offset);
if (element == null) return null;
final PsiClass aClass = PsiTreeUtil.getParentOfType(element, PsiClass.class);
PsiClass aClass = PsiTreeUtil.getParentOfType(element, PsiClass.class);
if (aClass == null) return null;
List<PsiElementClassMember> result = new ArrayList<PsiElementClassMember>();
while (aClass != null) {
collectTargetsInClass(element, aClass, result);
if (aClass.hasModifierProperty(PsiModifier.STATIC)) break;
aClass = PsiTreeUtil.getParentOfType(aClass, PsiClass.class, true);
}
return result.toArray(new PsiElementClassMember[result.size()]);
}
private static void collectTargetsInClass(PsiElement element, final PsiClass aClass, List<PsiElementClassMember> result) {
final PsiField[] fields = aClass.getAllFields();
PsiResolveHelper helper = JavaPsiFacade.getInstance(aClass.getProject()).getResolveHelper();
for (PsiField field : fields) {
final PsiType type = field.getType();
if (helper.isAccessible(field, aClass, aClass) && type instanceof PsiClassType) {
if (helper.isAccessible(field, aClass, aClass) && type instanceof PsiClassType && !PsiTreeUtil.isAncestor(field, element, false)) {
result.add(new PsiFieldMember(field));
}
}
@@ -341,7 +351,7 @@ public class GenerateDelegateHandler implements LanguageCodeInsightActionHandler
if (CommonClassNames.JAVA_LANG_OBJECT.equals(method.getContainingClass().getQualifiedName())) continue;
final PsiType returnType = method.getReturnType();
if (returnType != null && PropertyUtil.isSimplePropertyGetter(method) && helper.isAccessible(method, aClass, aClass) &&
returnType instanceof PsiClassType) {
returnType instanceof PsiClassType && !PsiTreeUtil.isAncestor(method, element, false)) {
result.add(new PsiMethodMember(method));
}
}
@@ -373,8 +383,5 @@ public class GenerateDelegateHandler implements LanguageCodeInsightActionHandler
}
}
}
return result.toArray(new PsiElementClassMember[result.size()]);
}
}
@@ -176,7 +176,8 @@ public class GenerateEqualsWizard extends AbstractWizard {
equalsFieldsSelected();
}
else if (getCurrentStep() == myHashcodeStepCode && myHashCodePanel != null) {
Collection<MemberInfo> selectedMemberInfos = myHashCodePanel.getTable().getSelectedMemberInfos();
Collection<MemberInfo> selectedMemberInfos = myEqualsPanel != null ? myEqualsPanel.getTable().getSelectedMemberInfos()
: myHashCodePanel.getTable().getSelectedMemberInfos();
updateNonNullMemberInfos(selectedMemberInfos);
}
@@ -18,21 +18,16 @@ package com.intellij.codeInspection;
import com.intellij.CommonBundle;
import com.intellij.codeInsight.CodeInsightUtilBase;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.ide.util.PackageUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.refactoring.PackageWrapper;
import com.intellij.refactoring.move.moveClassesOrPackages.AutocreatingSingleSourceRootMoveDestination;
import com.intellij.refactoring.move.moveClassesOrPackages.MoveClassesOrPackagesProcessor;
import com.intellij.refactoring.move.moveClassesOrPackages.MoveClassesOrPackagesUtil;
import com.intellij.refactoring.move.moveClassesOrPackages.SingleSourceRootMoveDestination;
import com.intellij.refactoring.util.RefactoringMessageUtil;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
@@ -79,7 +74,7 @@ public class MoveToPackageFix implements LocalQuickFix {
private void chooseDirectoryAndMove(Project project, PsiFile myFile) {
try {
PsiDirectory directory = MoveClassesOrPackagesUtil.chooseDestinationPackage(project, myTargetPackage, null);
PsiDirectory directory = MoveClassesOrPackagesUtil.chooseDestinationPackage(project, myTargetPackage, myFile.getContainingDirectory());
if (directory == null) {
return;
@@ -128,7 +128,9 @@ public class CopyClassesHandler extends CopyHandlerDelegateBase {
if (classes != null) {
topLevelClasses = ArrayUtil.mergeArrays(classes, topLevelClasses, PsiClass.ARRAY_FACTORY);
}
result.put(containingFile, topLevelClasses);
if (topLevelClasses != null) {
result.put(containingFile, topLevelClasses);
}
}
public void doCopy(PsiElement[] elements, PsiDirectory defaultTargetDirectory) {
@@ -22,14 +22,15 @@ import com.intellij.psi.PsiReferenceExpression;
import com.intellij.psi.PsiSubstitutor;
import com.intellij.psi.util.PsiFormatUtil;
import com.intellij.refactoring.HelpID;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.JavaRefactoringSettings;
import com.intellij.refactoring.RefactoringBundle;
public class InlineFieldDialog extends InlineOptionsDialog {
public static final String REFACTORING_NAME = RefactoringBundle.message("inline.field.title");
private final PsiReferenceExpression myReferenceExpression;
private final PsiField myField;
protected final int myOccurrencesNumber;
public InlineFieldDialog(Project project, PsiField field, PsiReferenceExpression ref) {
super(project, true, field);
@@ -38,7 +39,7 @@ public class InlineFieldDialog extends InlineOptionsDialog {
myInvokedOnReference = myReferenceExpression != null;
setTitle(REFACTORING_NAME);
myOccurrencesNumber = initOccurrencesNumber(myField);
init();
}
@@ -56,7 +57,8 @@ public class InlineFieldDialog extends InlineOptionsDialog {
}
protected String getInlineAllText() {
return RefactoringBundle.message("all.references.and.remove.the.field");
final String occurrencesString = myOccurrencesNumber > -1 ? " (" + myOccurrencesNumber + " occurrence" + (myOccurrencesNumber == 1 ? ")" : "s)") : "";
return RefactoringBundle.message("all.references.and.remove.the.field") + occurrencesString;
}
protected boolean isInlineThis() {
@@ -17,18 +17,14 @@ package com.intellij.refactoring.inline;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.help.HelpManager;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiJavaCodeReferenceElement;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiSubstitutor;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiSearchHelper;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiFormatUtil;
import com.intellij.refactoring.HelpID;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.JavaRefactoringSettings;
import com.intellij.refactoring.RefactoringBundle;
public class InlineMethodDialog extends InlineOptionsDialog {
public static final String REFACTORING_NAME = RefactoringBundle.message("inline.method.title");
@@ -50,21 +46,10 @@ public class InlineMethodDialog extends InlineOptionsDialog {
myInvokedOnReference = ref != null;
setTitle(REFACTORING_NAME);
initOccurrencesNumber(method);
myOccurrencesNumber = initOccurrencesNumber(method);
init();
}
private void initOccurrencesNumber(PsiMethod method) {
final ProgressManager progressManager = ProgressManager.getInstance();
final PsiSearchHelper searchHelper = PsiSearchHelper.SERVICE.getInstance(method.getProject());
final GlobalSearchScope scope = GlobalSearchScope.projectScope(method.getProject());
final boolean isCheapToSearch =
searchHelper.isCheapEnoughToSearch(method.getName(), scope, null, progressManager.getProgressIndicator()) != PsiSearchHelper.SearchCostResult.TOO_MANY_OCCURRENCES;
if (isCheapToSearch) {
myOccurrencesNumber = ReferencesSearch.search(method).findAll().size();
}
}
protected String getNameLabelText() {
String methodText = PsiFormatUtil.formatMethod(myMethod,
PsiSubstitutor.EMPTY, PsiFormatUtil.SHOW_NAME | PsiFormatUtil.SHOW_PARAMETERS, PsiFormatUtil.SHOW_TYPE);
@@ -195,7 +195,7 @@ public class InlineMethodProcessor extends BaseRefactoringProcessor {
final ReferencedElementsCollector collector,
final MultiMap<PsiElement, String> conflicts) {
element.accept(collector);
final Map<PsiMember, Set<PsiMember>> containersToReferenced = getInaccessible(collector.myReferencedMembers, usages);
final Map<PsiMember, Set<PsiMember>> containersToReferenced = getInaccessible(collector.myReferencedMembers, usages, element);
final Set<PsiMember> containers = containersToReferenced.keySet();
for (PsiMember container : containers) {
@@ -216,12 +216,17 @@ public class InlineMethodProcessor extends BaseRefactoringProcessor {
*
* @param referencedElements
* @param usages
* @param elementToInline
*/
private static Map<PsiMember, Set<PsiMember>> getInaccessible(HashSet<PsiMember> referencedElements, UsageInfo[] usages) {
private static Map<PsiMember, Set<PsiMember>> getInaccessible(HashSet<PsiMember> referencedElements,
UsageInfo[] usages,
PsiElement elementToInline) {
Map<PsiMember, Set<PsiMember>> result = new HashMap<PsiMember, Set<PsiMember>>();
for (UsageInfo usage : usages) {
final PsiElement container = ConflictsUtil.getContainer(usage.getElement());
final PsiElement usageElement = usage.getElement();
if (usageElement == null) continue;
final PsiElement container = ConflictsUtil.getContainer(usageElement);
if (!(container instanceof PsiMember)) continue; // usage in import statement
PsiMember memberContainer = (PsiMember)container;
Set<PsiMember> inaccessibleReferenced = result.get(memberContainer);
@@ -229,7 +234,8 @@ public class InlineMethodProcessor extends BaseRefactoringProcessor {
inaccessibleReferenced = new HashSet<PsiMember>();
result.put(memberContainer, inaccessibleReferenced);
for (PsiMember member : referencedElements) {
if (!PsiUtil.isAccessible(member, usage.getElement(), null)) {
if (PsiTreeUtil.isAncestor(elementToInline, member, false)) continue;
if (!PsiUtil.isAccessible(member, usageElement, null)) {
inaccessibleReferenced.add(member);
}
}
@@ -18,7 +18,10 @@ package com.intellij.refactoring.introduceField;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.introduceParameter.AbstractJavaInplaceIntroducer;
import com.intellij.refactoring.ui.TypeSelectorManagerImpl;
@@ -73,6 +76,11 @@ public abstract class AbstractInplaceIntroduceFieldPopup extends AbstractJavaInp
return myParentClass;
}
@Override
protected SearchScope getReferencesSearchScope(VirtualFile file) {
return new LocalSearchScope(myParentClass);
}
protected PsiElement getAnchorElement() {
if (myAnchorIdx != -1 && myOccurrences[myAnchorIdx] != null) {
return myOccurrences[myAnchorIdx].getParent();
@@ -248,7 +248,7 @@ public class MoveInstanceMethodProcessor extends BaseRefactoringProcessor{
if (!methodExpression.isReferenceTo(myMethod)) return;
final PsiExpression oldQualifier = methodExpression.getQualifierExpression();
PsiExpression newQualifier = null;
final PsiClass classReferencedByThis = MoveInstanceMembersUtil.getClassReferencedByThis(methodExpression);
if (myTargetVariable instanceof PsiParameter) {
final int index = myMethod.getParameterList().getParameterIndex((PsiParameter)myTargetVariable);
final PsiExpression[] arguments = expression.getArgumentList().getExpressions();
@@ -264,7 +264,6 @@ public class MoveInstanceMethodProcessor extends BaseRefactoringProcessor{
PsiExpression newArgument = null;
final PsiClass classReferencedByThis = MoveInstanceMembersUtil.getClassReferencedByThis(methodExpression);
if (classReferencedByThis != null) {
@NonNls String thisArgumentText = null;
if (manager.areElementsEquivalent(myMethod.getContainingClass(), classReferencedByThis)) {
@@ -169,9 +169,32 @@ public class PsiDiamondTypeImpl extends PsiDiamondType {
final Project project = newExpression.getProject();
final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
final PsiResolveHelper resolveHelper = facade.getResolveHelper();
final PsiExpression newExpressionQualifier = newExpression.getQualifier();
final PsiElement qualifierElement = classReference.getQualifier();
final String qualifier = qualifierElement != null ? qualifierElement.getText() : "";
return resolveHelper.resolveReferencedClass(StringUtil.getQualifiedName(qualifier, text), newExpression);
final String qualifiedName = StringUtil.getQualifiedName(qualifier, text);
if (newExpressionQualifier != null) {
final String newExpressionQualifierText = newExpressionQualifier.getText();
if (newExpressionQualifier instanceof PsiReferenceExpression) {
final PsiVariable variable = resolveHelper.resolveReferencedVariable(newExpressionQualifierText, newExpression);
if (variable != null) {
final PsiClass aClass = PsiUtil.resolveClassInType(variable.getType());
if (aClass != null) {
return aClass.findInnerClassByName(qualifiedName, false);
}
}
} else if (newExpressionQualifier instanceof PsiCallExpression) {
final JavaResolveResult resolveResult = ((PsiCallExpression)newExpressionQualifier).resolveMethodGenerics();
final PsiElement method = resolveResult.getElement();
if (method instanceof PsiMethod) {
final PsiClass aClass = PsiUtil.resolveClassInType(resolveResult.getSubstitutor().substitute(((PsiMethod)method).getReturnType()));
if (aClass != null) {
return aClass.findInnerClassByName(qualifiedName, false);
}
}
}
}
return resolveHelper.resolveReferencedClass(qualifiedName, newExpression);
} else {
return null;
}
+1
View File
@@ -28,6 +28,7 @@
<orderEntry type="module" module-name="execution-openapi" />
<orderEntry type="module" module-name="IntentionPowerPackPlugin" />
<orderEntry type="module" module-name="InspectionGadgetsPlugin" />
<orderEntry type="module" module-name="platform-tests" scope="TEST" />
</component>
</module>
@@ -0,0 +1,5 @@
public class TestSource7 {
public void foo(){
Class c<caret>
}
}
@@ -181,3 +181,26 @@ class PredefinedErrorsOverRaw<T> {
PredefinedErrorsOverRaw mc = new <Boolean>PredefinedErrorsOverRaw<<error descr="Cannot use diamonds with explicit type parameters for constructor"></error>>("");
}
}
class Outer {
class Inner<T> {}
}
class Outer1 {}
class Another {
public static void main(String[] args) {
Outer o = new Outer();
Outer.Inner<String> i = o.new Inner<>();
Outer.Inner<String> i1 = m().new Inner<>();
Outer.Inner<String> i2 = m1().new Inner<>();
Outer.Inner<String> i3 = m2().new <error descr="Cannot resolve symbol 'Inner'">Inner</error><>();
System.out.println(i);
}
static Outer m() {return null;}
static <T extends Outer> T m1() {return null;}
static <T> T m2() {return null;}
}
@@ -0,0 +1,12 @@
// "Change 'i' type to 'java.lang.String'" "true"
class Base {
void foo(String i) {}
}
class Ex extends Base {
@Override
void foo(String i) {
i = "abc"; // when I invoke "Change type of 'i' to 'String'", base method is ignored so method overriding is lost
}
}
@@ -0,0 +1,12 @@
// "Change 'i' type to 'java.lang.String'" "true"
class Base {
void foo(int i) {}
}
class Ex extends Base {
@Override
void foo(int i) {
i = <caret>"abc"; // when I invoke "Change type of 'i' to 'String'", base method is ignored so method overriding is lost
}
}
@@ -0,0 +1,8 @@
<root>
<item name='p.TestDeannotation java.lang.String get()'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item name='p.TestDeannotation1 java.lang.String get(java.lang.String) 0'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
</root>
@@ -0,0 +1,10 @@
<root>
<item name='suppressed.ExistingExternalName java.lang.String foo()'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item name='suppressed.SecondSuppression void second()'>
<annotation name='java.lang.SuppressWarnings'>
<val val="{DoesntMatterWhat}"/>
</annotation>
</item>
</root>
@@ -0,0 +1,13 @@
<root>
<item name='suppressed.ExistingExternalName java.lang.String foo()'>
<annotation name='org.jetbrains.annotations.NotNull'/>
<annotation name='java.lang.SuppressWarnings'>
<val val="&quot;SillyAssignment&quot;"/>
</annotation>
</item>
<item name='suppressed.SecondSuppression void second()'>
<annotation name='java.lang.SuppressWarnings'>
<val val="{DoesntMatterWhat}"/>
</annotation>
</item>
</root>
@@ -0,0 +1,15 @@
<root>
<item name='suppressed.ExistingExternalName java.lang.String foo()'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item name='suppressed.SecondSuppression void second()'>
<annotation name='java.lang.SuppressWarnings'>
<val val="{DoesntMatterWhat}"/>
</annotation>
</item>
<item name='suppressed.NewSuppress void barr()'>
<annotation name='java.lang.SuppressWarnings'>
<val val="&quot;SillyAssignment&quot;"/>
</annotation>
</item>
</root>
@@ -0,0 +1,10 @@
<root>
<item name='suppressed.ExistingExternalName java.lang.String foo()'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item name='suppressed.SecondSuppression void second()'>
<annotation name='java.lang.SuppressWarnings'>
<val val="{DoesntMatterWhat, &quot;SillyAssignment&quot;}"/>
</annotation>
</item>
</root>
@@ -0,0 +1,6 @@
package p;
class Test {
String g<caret>et() {
return null;
}
}
@@ -0,0 +1,11 @@
package p;
import org.jetbrains.annotations.NotNull;
class Test {
@NotNull
String g<caret>et() {
return null;
}
}
@@ -0,0 +1,8 @@
package p;
public class TestDeannotation {
String g<caret>et() {
return null;
}
}
@@ -0,0 +1,8 @@
package p;
public class TestDeannotation1 {
String get(String s<caret>s) {
return null;
}
}
@@ -0,0 +1,6 @@
package p;
class Test {
boolean g<caret>et() {
return false;
}
}
@@ -0,0 +1,8 @@
package suppressed;
class ExistingExternalName {
String foo(){
String str = "";
s<caret>tr = str;
return str;
}
}
@@ -0,0 +1,7 @@
package suppressed;
class NewSuppress {
void barr() {
String str = "";
st<caret>r = str;
}
}
@@ -0,0 +1,7 @@
package suppressed;
class SecondSuppression {
void second() {
String str = "";
st<caret>r = str;
}
}
@@ -0,0 +1,24 @@
public class Foo {
public static void f<caret>oo() {
bar(new Runnable() {
@Override
public void run() {
doRun();
}
private void doRun() {
// Woo-hoo
}
});
}
public static void bar(final Runnable runnable) {
runnable.run();
}
}
class Bar {
public static void main(String[] args) {
Foo.foo();
}
}
@@ -0,0 +1,21 @@
public class Foo {
public static void bar(final Runnable runnable) {
runnable.run();
}
}
class Bar {
public static void main(String[] args) {
Foo.bar(new Runnable() {
@Override
public void run() {
doRun();
}
private void doRun() {
// Woo-hoo
}
});
}
}
@@ -0,0 +1,18 @@
public class A {
public void m<caret>(B b){
System.out.println(this);
}
public void show(B b){
m(b);
}
public void m (C c){
System.out.println(this);
}
}
class B{}
class C{}
@@ -0,0 +1,18 @@
public class A {
public void show(B b){
b.m(this);
}
public void m (C c){
System.out.println(this);
}
}
class B{
public void m(A a){
System.out.println(a);
}
}
class C{}
@@ -0,0 +1,179 @@
/*
* User: anna
* Date: 27-Jun-2007
*/
package com.intellij.codeInsight;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.impl.DeannotateIntentionAction;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.application.ex.PathManagerEx;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.AnnotationOrderRootType;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiModifierListOwner;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.testFramework.IdeaTestCase;
import com.intellij.testFramework.PsiTestUtil;
import com.intellij.testFramework.UsefulTestCase;
import com.intellij.testFramework.builders.JavaModuleFixtureBuilder;
import com.intellij.testFramework.fixtures.*;
import org.jetbrains.annotations.NonNls;
import java.util.List;
public class AddAnnotationFixTest extends UsefulTestCase {
private CodeInsightTestFixture myFixture;
private Module myModule;
public AddAnnotationFixTest() {
IdeaTestCase.initPlatformPrefix();
}
@Override
public void setUp() throws Exception {
super.setUp();
final TestFixtureBuilder<IdeaProjectTestFixture> projectBuilder = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder();
myFixture = JavaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(projectBuilder.getFixture());
final String dataPath = PathManagerEx.getTestDataPath() + "/codeInsight/externalAnnotations";
myFixture.setTestDataPath(dataPath);
final JavaModuleFixtureBuilder builder = projectBuilder.addModule(JavaModuleFixtureBuilder.class);
builder.setMockJdkLevel(JavaModuleFixtureBuilder.MockJdkLevel.jdk15);
myFixture.setUp();
myModule = builder.getFixture().getModule();
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
myFixture.tearDown();
myFixture = null;
myModule = null;
}
protected void addLibrary() {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
final ModifiableRootModel model = ModuleRootManager.getInstance(myModule).getModifiableModel();
final LibraryTable libraryTable = model.getModuleLibraryTable();
final Library library = libraryTable.createLibrary("test");
final Library.ModifiableModel libraryModel = library.getModifiableModel();
libraryModel.addRoot(VfsUtil.pathToUrl(myFixture.getTempDirPath() + "/lib"), OrderRootType.SOURCES);
libraryModel.addRoot(VfsUtil.pathToUrl(myFixture.getTempDirPath() + "/content/anno"), AnnotationOrderRootType.getInstance());
libraryModel.commit();
model.commit();
}
});
}
public void testAnnotateLibrary() throws Throwable {
addLibrary();
myFixture.configureByFiles("lib/p/TestPrimitive.java", "content/anno/p/annotations.xml");
myFixture.configureByFiles("lib/p/Test.java");
final Project project = myFixture.getProject();
final PsiFile file = myFixture.getFile();
final Editor editor = myFixture.getEditor();
final IntentionAction fix = myFixture.findSingleIntention("Annotate method 'get' as @NotNull");
assertTrue(fix.isAvailable(project, editor, file));
new WriteCommandAction(project){
@Override
protected void run(final Result result) throws Throwable {
fix.invoke(project, editor, file);
}
}.execute();
FileDocumentManager.getInstance().saveAllDocuments();
final PsiElement psiElement = file.findElementAt(editor.getCaretModel().getOffset());
assertNotNull(psiElement);
final PsiModifierListOwner listOwner = PsiTreeUtil.getParentOfType(psiElement, PsiModifierListOwner.class);
assertNotNull(listOwner);
assertNotNull(ExternalAnnotationsManager.getInstance(project).findExternalAnnotation(listOwner, AnnotationUtil.NOT_NULL));
}
public void testPrimitive() throws Throwable {
PsiFile psiFile = myFixture.configureByFile("lib/p/TestPrimitive.java");
PsiTestUtil.addSourceRoot(myModule, psiFile.getVirtualFile().getParent());
assertNotAvailable("Annotate method 'get' as @NotNull");
}
private void assertNotAvailable(String hint) {
List<IntentionAction> actions = myFixture.filterAvailableIntentions(hint);
assertEmpty(actions);
}
public void testAnnotated() throws Throwable {
PsiFile psiFile = myFixture.configureByFile("lib/p/TestAnnotated.java");
PsiTestUtil.addSourceRoot(myModule, psiFile.getVirtualFile().getParent());
final Project project = myFixture.getProject();
final PsiFile file = myFixture.getFile();
final Editor editor = myFixture.getEditor();
assertNotAvailable("Annotate method 'get' as @NotNull");
assertNotAvailable("Annotate method 'get' as @Nullable");
final DeannotateIntentionAction deannotateFix = new DeannotateIntentionAction();
assertFalse(deannotateFix.isAvailable(project, editor, file));
}
public void testDeannotation() throws Throwable {
addLibrary();
myFixture.configureByFiles("lib/p/TestPrimitive.java", "content/anno/p/annotations.xml");
doDeannotate("lib/p/TestDeannotation.java", "Annotate method 'get' as @NotNull", "Annotate method 'get' as @Nullable");
}
public void testDeannotation1() throws Throwable {
addLibrary();
myFixture.configureByFiles("lib/p/TestPrimitive.java", "content/anno/p/annotations.xml");
doDeannotate("lib/p/TestDeannotation1.java", "Annotate parameter 'ss' as @NotNull", "Annotate parameter 'ss' as @Nullable");
}
private void doDeannotate(@NonNls final String testPath, String hint1, String hint2) throws Throwable {
myFixture.configureByFile(testPath);
final Project project = myFixture.getProject();
final PsiFile file = myFixture.getFile();
final Editor editor = myFixture.getEditor();
assertNotAvailable(hint1);
assertNotAvailable(hint2);
final DeannotateIntentionAction deannotateFix = new DeannotateIntentionAction();
assertTrue(deannotateFix.isAvailable(project, editor, file));
new WriteCommandAction(project){
@Override
protected void run(final Result result) throws Throwable {
ExternalAnnotationsManager.getInstance(project).deannotate(DeannotateIntentionAction.getContainer(editor, file), AnnotationUtil.NOT_NULL);
}
}.execute();
FileDocumentManager.getInstance().saveAllDocuments();
IntentionAction fix = myFixture.findSingleIntention(hint1);
assertNotNull(fix);
fix = myFixture.findSingleIntention(hint2);
assertNotNull(fix);
assertFalse(deannotateFix.isAvailable(project, editor, file));
}
}
@@ -0,0 +1,100 @@
/*
* User: anna
* Date: 17-Jun-2010
*/
package com.intellij.codeInsight;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.sillyAssignment.SillyAssignmentInspection;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ex.PathManagerEx;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.AnnotationOrderRootType;
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.testFramework.IdeaTestCase;
import com.intellij.testFramework.UsefulTestCase;
import com.intellij.testFramework.builders.JavaModuleFixtureBuilder;
import com.intellij.testFramework.fixtures.*;
import java.io.File;
import java.io.IOException;
public class SuppressExternalTest extends UsefulTestCase {
protected CodeInsightTestFixture myFixture;
private LanguageLevel myLanguageLevel;
public SuppressExternalTest() {
IdeaTestCase.initPlatformPrefix();
}
@Override
public void setUp() throws Exception {
super.setUp();
final IdeaTestFixtureFactory fixtureFactory = IdeaTestFixtureFactory.getFixtureFactory();
final TestFixtureBuilder<IdeaProjectTestFixture> testFixtureBuilder = fixtureFactory.createFixtureBuilder();
myFixture = JavaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(testFixtureBuilder.getFixture());
myFixture.setTestDataPath(PathManagerEx.getTestDataPath() + "/codeInsight/externalAnnotations");
final JavaModuleFixtureBuilder builder = testFixtureBuilder.addModule(JavaModuleFixtureBuilder.class);
new File(myFixture.getTempDirPath() + "/src/").mkdir();
builder.addContentRoot(myFixture.getTempDirPath()).addSourceRoot("src");
builder.setMockJdkLevel(JavaModuleFixtureBuilder.MockJdkLevel.jdk15);
myFixture.enableInspections(new SillyAssignmentInspection());
myFixture.setUp();
addAnnotationsModuleRoot();
final JavaPsiFacade facade = JavaPsiFacade.getInstance(myFixture.getProject());
myLanguageLevel = LanguageLevelProjectExtension.getInstance(facade.getProject()).getLanguageLevel();
LanguageLevelProjectExtension.getInstance(facade.getProject()).setLanguageLevel(LanguageLevel.JDK_1_5);
}
private void addAnnotationsModuleRoot() throws IOException {
myFixture.copyDirectoryToProject("content/anno/suppressed", "content/anno/suppressed");
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
final Module module = myFixture.getModule();
final ModifiableRootModel model = ModuleRootManager.getInstance(module).getModifiableModel();
model.setRootUrls(AnnotationOrderRootType.getInstance(), new String[]{VfsUtil.pathToUrl(myFixture.getTempDirPath() + "/content/anno")});
model.commit();
}
});
}
@Override
public void tearDown() throws Exception {
LanguageLevelProjectExtension.getInstance(myFixture.getProject()).setLanguageLevel(myLanguageLevel);
myFixture.tearDown();
myFixture = null;
super.tearDown();
}
private void doTest(String testName) throws Exception {
final IntentionAction action = myFixture.getAvailableIntention("Suppress for method", "src/suppressed/" + testName + ".java");
assertNotNull(action);
myFixture.launchAction(action);
myFixture.checkResultByFile("content/anno/suppressed/annotations.xml", "content/anno/suppressed/annotations" + testName + "_after.xml", true);
}
public void testNewSuppress() throws Throwable {
doTest("NewSuppress");
}
public void testExistingExternalName() throws Exception {
doTest("ExistingExternalName");
}
public void testSecondSuppression() throws Exception {
doTest("SecondSuppression");
}
}
@@ -640,6 +640,21 @@ public interface Test {
assert !lookup
}
public void testTemplatesWithNonImportedClasses() {
CodeInsightSettings.instance.COMPLETION_CASE_SENSITIVE = CodeInsightSettings.NONE
myFixture.addClass("package foo.bar; public class LayoutStore {}")
try {
myFixture.configureByText 'a.java', 'class Foo {{ foo(<caret>) }}'
type 'lst'
assert lookup
assert 'lst' in myFixture.lookupElementStrings
assert 'LayoutStore' in myFixture.lookupElementStrings
}
finally {
CodeInsightSettings.instance.COMPLETION_CASE_SENSITIVE = CodeInsightSettings.FIRST_LETTER
}
}
public void testTemplateSelectionByComma() {
myFixture.configureByText("a.java", """
class Foo {
@@ -70,6 +70,12 @@ public class VariablesCompletionTest extends LightFixtureCompletionTestCase {
doTest("LocalReserved.java", "LocalReserved_after.java");
}
public void testLocalReserved2() throws Exception {
configureByFile(FILE_PREFIX + "locals/" + "LocalReserved2.java")
checkResultByFile(FILE_PREFIX + "locals/" + "LocalReserved2.java");
assert !myFixture.lookupElementStrings
}
public void testUniqueNameInFor() throws Exception {
doTest(getTestName(false) + ".java", getTestName(false) + "_after.java");
}
@@ -0,0 +1,232 @@
package com.intellij.lang.psi;
import com.intellij.lang.*;
import com.intellij.lang.impl.PsiBuilderImpl;
import com.intellij.lexer.JavaLexer;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.JavaTokenType;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.java.stubs.JavaStubElementTypes;
import com.intellij.psi.impl.source.DummyHolder;
import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.impl.source.tree.SharedImplUtil;
import com.intellij.psi.impl.source.tree.TreeElement;
import com.intellij.psi.text.BlockSupport;
import com.intellij.testFramework.LightIdeaTestCase;
import junit.framework.AssertionFailedError;
/**
* Date: Jan 21, 2005
* @author max
*/
public class PsiBuilderTest extends LightIdeaTestCase {
private PsiBuilderImpl myBuilder;
public void testEmptyProgram() throws Exception {
myBuilder = createBuilder("");
final PsiBuilder.Marker fileMarker = myBuilder.mark();
fileMarker.done(JavaStubElementTypes.JAVA_FILE);
ASTNode fileNode = myBuilder.getTreeBuilt();
assertNotNull(fileNode);
assertEquals("", fileNode.getText());
}
public void testProgramWithSingleKeyword() throws Exception {
myBuilder = createBuilder("package");
final PsiBuilder.Marker fileMarker = myBuilder.mark();
assertEquals("package", myBuilder.getTokenText());
assertEquals(JavaTokenType.PACKAGE_KEYWORD, myBuilder.getTokenType());
final PsiBuilder.Marker packageStatementMarker = myBuilder.mark();
myBuilder.advanceLexer();
assertTrue(myBuilder.eof());
packageStatementMarker.done(JavaElementType.PACKAGE_STATEMENT);
fileMarker.done(JavaStubElementTypes.JAVA_FILE);
ASTNode fileNode = myBuilder.getTreeBuilt();
assertNotNull(fileNode);
assertEquals("package", fileNode.getText());
assertSame(fileNode.getFirstChildNode(), fileNode.getLastChildNode());
ASTNode packageNode = fileNode.getFirstChildNode();
assertNotNull(packageNode);
assertEquals("package", packageNode.getText());
assertEquals(JavaElementType.PACKAGE_STATEMENT, packageNode.getElementType());
ASTNode leaf = packageNode.getFirstChildNode();
assertNotNull(leaf);
assertEquals(JavaTokenType.PACKAGE_KEYWORD, leaf.getElementType());
}
private static PsiBuilderImpl createBuilder(final String text) {
return createBuilder(text,null);
}
private static PsiBuilderImpl createBuilder(final String text, ASTNode originalTree) {
final Language lang = StdFileTypes.JAVA.getLanguage();
final ParserDefinition parserDefinition = LanguageParserDefinitions.INSTANCE.forLanguage(lang);
assertNotNull(parserDefinition);
PsiFile psiFile = createFile("x.java", text);
return new PsiBuilderImpl(getProject(), psiFile, parserDefinition, new JavaLexer(LanguageLevel.JDK_1_5),
SharedImplUtil.findCharTableByTree(psiFile.getNode()), text, originalTree, null);
}
public void testTrailingWhitespaces() throws Exception {
myBuilder = createBuilder("foo\n\nx");
final PsiBuilder.Marker marker = myBuilder.mark();
while (!myBuilder.eof()) {
myBuilder.advanceLexer();
}
marker.done(JavaStubElementTypes.JAVA_FILE);
assertEquals("foo\n\nx", myBuilder.getTreeBuilt().getText());
}
public void testRollback() throws Exception {
myBuilder = createBuilder("package");
PsiBuilder.Marker fileMarker = myBuilder.mark();
assertEquals("package", myBuilder.getTokenText());
assertEquals(JavaTokenType.PACKAGE_KEYWORD, myBuilder.getTokenType());
PsiBuilder.Marker packageStatementMarker = myBuilder.mark();
myBuilder.advanceLexer();
assertTrue(myBuilder.eof());
packageStatementMarker.done(JavaElementType.PACKAGE_STATEMENT);
fileMarker.rollbackTo();
fileMarker = myBuilder.mark();
assertEquals("package", myBuilder.getTokenText());
assertEquals(JavaTokenType.PACKAGE_KEYWORD, myBuilder.getTokenType());
packageStatementMarker = myBuilder.mark();
myBuilder.advanceLexer();
assertTrue(myBuilder.eof());
packageStatementMarker.done(JavaElementType.PACKAGE_STATEMENT);
fileMarker.done(JavaStubElementTypes.JAVA_FILE);
ASTNode fileNode = myBuilder.getTreeBuilt();
assertNotNull(fileNode);
assertEquals("package", fileNode.getText());
assertSame(fileNode.getFirstChildNode(), fileNode.getLastChildNode());
ASTNode packageNode = fileNode.getFirstChildNode();
assertNotNull(packageNode);
assertEquals("package", packageNode.getText());
assertEquals(JavaElementType.PACKAGE_STATEMENT, packageNode.getElementType());
ASTNode leaf = packageNode.getFirstChildNode();
assertNotNull(leaf);
assertEquals(JavaTokenType.PACKAGE_KEYWORD, leaf.getElementType());
}
public void testDrop() throws Exception {
myBuilder = createBuilder("package");
final PsiBuilder.Marker fileMarker = myBuilder.mark();
assertEquals("package", myBuilder.getTokenText());
assertEquals(JavaTokenType.PACKAGE_KEYWORD, myBuilder.getTokenType());
final PsiBuilder.Marker packageStatementMarker = myBuilder.mark();
myBuilder.advanceLexer();
assertTrue(myBuilder.eof());
packageStatementMarker.drop();
fileMarker.done(JavaStubElementTypes.JAVA_FILE);
ASTNode fileNode = myBuilder.getTreeBuilt();
assertNotNull(fileNode);
assertEquals("package", fileNode.getText());
assertSame(fileNode.getFirstChildNode(), fileNode.getLastChildNode());
ASTNode leaf = fileNode.getFirstChildNode();
assertNotNull(leaf);
assertEquals(JavaTokenType.PACKAGE_KEYWORD, leaf.getElementType());
assertEquals("package", leaf.getText());
assertNull(leaf.getFirstChildNode());
}
public void testAdvanceBeyondEof() {
myBuilder = createBuilder("package");
for(int i=0; i<20; i++) {
myBuilder.eof();
myBuilder.advanceLexer();
}
assertTrue(myBuilder.eof());
}
public void testAssertionFailureOnUnbalancedMarkers() {
myBuilder = createBuilder("foo");
myBuilder.setDebugMode(true);
final PsiBuilder.Marker m = myBuilder.mark();
final PsiBuilder.Marker m1 = myBuilder.mark();
myBuilder.getTokenType();
myBuilder.advanceLexer();
try {
m.done(JavaTokenType.PACKAGE_KEYWORD);
fail("Assertion must fire");
}
catch (AssertionFailedError e) {
throw e;
}
catch (Throwable e) {
if (!e.getMessage().startsWith("Another not done marker")) {
fail("Wrong assertion message");
}
}
}
public void testNotAllTokensProcessed() {
myBuilder = createBuilder("foo");
myBuilder.setDebugMode(true);
final PsiBuilder.Marker m = myBuilder.mark();
m.done(JavaTokenType.PACKAGE_KEYWORD);
try {
myBuilder.getTreeBuilt();
fail("Assertion must fire");
}
catch (AssertionFailedError e) {
throw e;
}
catch (Throwable e) {
if (!e.getMessage().startsWith("Tokens [IDENTIFIER] were not inserted into the tree")) {
fail("Wrong assertion message");
}
}
}
public void testMergeWhenEmptyElementAfterWhitespaceIsLastChild() throws Throwable {
myBuilder = createBuilder(" foo bar");
parseWhenEmptyElementAfterWhitespaceIsLastChild();
final ASTNode tree = myBuilder.getTreeBuilt();
new DummyHolder(getPsiManager(), (TreeElement)tree, null);
myBuilder = createBuilder(" bar", tree);
parseWhenEmptyElementAfterWhitespaceIsLastChild();
try {
myBuilder.getTreeBuilt();
fail();
}
catch (BlockSupport.ReparsedSuccessfullyException e) {
e.getDiffLog().performActualPsiChange(tree.getPsi().getContainingFile());
}
assertEquals(" bar", tree.getText());
}
private void parseWhenEmptyElementAfterWhitespaceIsLastChild() {
final PsiBuilder.Marker root = myBuilder.mark();
final PsiBuilder.Marker composite = myBuilder.mark();
final PsiBuilder.Marker backup = myBuilder.mark();
if ("foo".equals(myBuilder.getTokenText())) {
myBuilder.advanceLexer();
myBuilder.getTokenType();
myBuilder.mark().done(JavaStubElementTypes.TYPE_PARAMETER_LIST);
backup.done(JavaStubElementTypes.ANNOTATION_METHOD);
} else {
backup.rollbackTo();
}
composite.done(JavaStubElementTypes.ANONYMOUS_CLASS);
myBuilder.getTokenType();
myBuilder.advanceLexer();
root.done(JavaStubElementTypes.ENUM_CONSTANT_INITIALIZER);
}
}
@@ -0,0 +1,110 @@
package com.intellij.lexer;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.JavaTokenType;
import com.intellij.psi.tree.IElementType;
import junit.framework.TestCase;
/**
* @author max
*/
public class LayeredLexerTest extends TestCase {
public void testInTheMiddle() throws Exception {
Lexer lexer = setupLexer("s=\"abc\\ndef\";");
assertEquals("s", nextToken(lexer));
assertEquals("=", nextToken(lexer));
assertEquals("\"abc", nextToken(lexer));
assertEquals("\\n", nextToken(lexer));
assertEquals("def\"", nextToken(lexer));
assertEquals(";", nextToken(lexer));
assertEquals(null, lexer.getTokenType());
}
public void testModification() throws Exception {
Lexer lexer = setupLexer("s=\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\";");
assertEquals("s", nextToken(lexer));
assertEquals("=", nextToken(lexer));
assertEquals("\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"", nextToken(lexer));
assertEquals(";", nextToken(lexer));
assertEquals(null, lexer.getTokenType());
lexer.start(lexer.getBufferSequence(), 2, lexer.getBufferEnd(), (short) 1);
assertEquals("\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"", nextToken(lexer));
assertEquals(";", nextToken(lexer));
assertEquals(null, lexer.getTokenType());
}
public void testInTheAtStartup() throws Exception {
Lexer lexer = setupLexer("s=\"\\ndef\";");
assertEquals("s", nextToken(lexer));
assertEquals("=", nextToken(lexer));
assertEquals("\"", nextToken(lexer));
assertEquals("\\n", nextToken(lexer));
assertEquals("def\"", nextToken(lexer));
assertEquals(";", nextToken(lexer));
assertEquals(null, lexer.getTokenType());
}
public void testInTheAtEnd() throws Exception {
Lexer lexer = setupLexer("s=\"abc\\n\";");
assertEquals("s", nextToken(lexer));
assertEquals("=", nextToken(lexer));
assertEquals("\"abc", nextToken(lexer));
assertEquals("\\n", nextToken(lexer));
assertEquals("\"", nextToken(lexer));
assertEquals(";", nextToken(lexer));
assertEquals(null, lexer.getTokenType());
}
public void testNonTerminated() throws Exception {
Lexer lexer = setupLexer("s=\"abc\\n");
assertEquals("s", nextToken(lexer));
assertEquals("=", nextToken(lexer));
assertEquals("\"abc", nextToken(lexer));
assertEquals("\\n", nextToken(lexer));
assertEquals(null, lexer.getTokenType());
}
public void testNonTerminated2() throws Exception {
Lexer lexer = setupLexer("s=\"abc\\");
assertEquals("s", nextToken(lexer));
assertEquals("=", nextToken(lexer));
assertEquals("\"abc", nextToken(lexer));
assertEquals("\\", nextToken(lexer));
assertEquals(null, lexer.getTokenType());
}
public void testUnicode() throws Exception {
Lexer lexer = setupLexer("s=\"\\uFFFF\";");
assertEquals("s", nextToken(lexer));
assertEquals("=", nextToken(lexer));
assertEquals("\"", nextToken(lexer));
assertEquals("\\uFFFF", nextToken(lexer));
assertEquals("\"", nextToken(lexer));
assertEquals(";", nextToken(lexer));
assertEquals(null, lexer.getTokenType());
}
private Lexer setupLexer(String text) {
LayeredLexer lexer = new LayeredLexer(new JavaLexer(LanguageLevel.JDK_1_3));
lexer.registerSelfStoppingLayer(new StringLiteralLexer('\"', JavaTokenType.STRING_LITERAL),
new IElementType[]{JavaTokenType.STRING_LITERAL},
IElementType.EMPTY_ARRAY);
lexer.start(text);
return lexer;
}
private String nextToken(Lexer lexer) {
assertTrue(lexer.getTokenType() != null);
final String s = lexer.getBufferSequence().subSequence(lexer.getTokenStart(), lexer.getTokenEnd()).toString();
lexer.advance();
return s;
}
}
@@ -0,0 +1,75 @@
/*
* Created by IntelliJ IDEA.
* User: mike
* Date: Jun 14, 2002
* Time: 8:05:58 PM
* To change template for new class use
* Code Style | Class Templates options (Tools | IDE Options).
*/
package com.intellij.psi.util;
import com.intellij.psi.*;
import com.intellij.testFramework.LightCodeInsightTestCase;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NonNls;
public class PropertyUtilTest extends LightCodeInsightTestCase {
public void testSuggestGetterName() throws Exception {
assertEquals("isValid", PropertyUtil.suggestGetterName("valid", getType("boolean")));
assertEquals("getValid", PropertyUtil.suggestGetterName("valid", getType("Object")));
assertEquals("isValid", PropertyUtil.suggestGetterName(ourProject, createField("valid", "boolean")));
assertEquals("getValid", PropertyUtil.suggestGetterName(ourProject, createField("valid", "Object")));
assertEquals("getURL", PropertyUtil.suggestGetterName("URL", getType("Object")));
assertEquals("getURL", PropertyUtil.suggestGetterName(ourProject, createField("URL", "Object")));
assertEquals("isaURL", PropertyUtil.suggestGetterName(ourProject, createField("aURL", "boolean")));
assertEquals("getaURL", PropertyUtil.suggestGetterName(ourProject, createField("aURL", "Object")));
assertEquals("getBool", PropertyUtil.suggestGetterName(ourProject, createField("bool", "java.lang.Boolean")));
}
public void testSuggestSetterName() throws Exception {
assertEquals("setValid", PropertyUtil.suggestSetterName("valid"));
assertEquals("setValid", PropertyUtil.suggestSetterName(ourProject, createField("valid", "Object")));
assertEquals("setURL", PropertyUtil.suggestSetterName("URL"));
assertEquals("setURL", PropertyUtil.suggestSetterName(ourProject, createField("URL", "Object")));
assertEquals("setaURL", PropertyUtil.suggestSetterName("aURL"));
assertEquals("setaURL", PropertyUtil.suggestSetterName(ourProject, createField("aURL", "Object")));
assertEquals("setBool", PropertyUtil.suggestSetterName(ourProject, createField("bool", "java.lang.Boolean")));
}
public void testSuggestPropertyName() throws Exception {
assertEquals("valid", PropertyUtil.getPropertyName("isValid"));
assertEquals("valid", PropertyUtil.getPropertyName("getValid"));
assertEquals("valid", PropertyUtil.getPropertyName("setValid"));
assertEquals("URL", PropertyUtil.getPropertyName("isURL"));
assertEquals("URL", PropertyUtil.getPropertyName("getURL"));
assertEquals("URL", PropertyUtil.getPropertyName("setURL"));
assertEquals("aURL", PropertyUtil.getPropertyName("isaURL"));
assertEquals("aURL", PropertyUtil.getPropertyName("getaURL"));
assertEquals("aURL", PropertyUtil.getPropertyName("setaURL"));
}
public void testBooleanPropertyGetters() {
assertTrue(PropertyUtil.hasGetterName(createMethod("isOk", "boolean")));
assertFalse(PropertyUtil.hasGetterName(createMethod("isOk", CommonClassNames.JAVA_LANG_BOOLEAN)));
assertTrue(PropertyUtil.hasGetterName(createMethod("getOk", CommonClassNames.JAVA_LANG_BOOLEAN)));
assertFalse(PropertyUtil.hasGetterName(createMethod("isOk", "int")));
}
private static PsiType getType(@NonNls String type) throws IncorrectOperationException {
return PsiElementFactory.SERVICE.getInstance(ourProject).createTypeFromText(type, null);
}
private static PsiField createField(@NonNls String name, @NonNls String type) throws IncorrectOperationException {
return PsiElementFactory.SERVICE.getInstance(ourProject).createField(name, getType(type));
}
private static PsiMethod createMethod(@NonNls String name, String type) throws IncorrectOperationException {
return PsiElementFactory.SERVICE.getInstance(ourProject).createMethod(name, getType(type));
}
}
@@ -0,0 +1,57 @@
package com.intellij.psi.util;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElementFactory;
import com.intellij.psi.PsiTypeParameter;
import com.intellij.testFramework.LightCodeInsightTestCase;
import com.intellij.util.IncorrectOperationException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
/**
* @author dsl
*/
public class PsiUtilTest extends LightCodeInsightTestCase {
public void testTypeParameterIterator() throws Exception {
PsiClass classA = createClass("class A<T> {}");
final Iterator<PsiTypeParameter> iterator = PsiUtil.typeParametersIterator(classA);
compareIterator(new String[]{"T"}, iterator);
}
private static PsiClass createClass(String text) throws IncorrectOperationException {
final PsiElementFactory factory = JavaPsiFacade.getInstance(ourProject).getElementFactory();
final PsiClass classA = factory.createClassFromText(text, null).getInnerClasses()[0];
return classA;
}
public void testTypeParameterIterator1() throws Exception {
final PsiClass classA = createClass("class A<T> { class B<X> {}}");
final Iterator<PsiTypeParameter> iterator = PsiUtil.typeParametersIterator(classA.getInnerClasses()[0]);
compareIterator(new String[]{"X","T"}, iterator);
}
public void testTypeParameterIterator2() throws Exception {
final PsiClass classA = createClass("class A<T> { static class B<X> {}}");
final Iterator<PsiTypeParameter> iterator = PsiUtil.typeParametersIterator(classA.getInnerClasses()[0]);
compareIterator(new String[]{"X"}, iterator);
}
public void testTypeParameterIterator3() throws Exception {
final PsiClass classA = createClass("class A<T> { class B<X, Y> {}}");
final Iterator<PsiTypeParameter> iterator = PsiUtil.typeParametersIterator(classA.getInnerClasses()[0]);
compareIterator(new String[]{"Y", "X", "T"}, iterator);
}
private static void compareIterator(String[] expected, Iterator<PsiTypeParameter> it) {
final ArrayList<String> actual = new ArrayList<String>();
while (it.hasNext()) {
PsiTypeParameter typeParameter = it.next();
actual.add(typeParameter.getName());
}
assertEquals(Arrays.asList(expected).toString(), actual.toString());
}
}
@@ -0,0 +1,50 @@
/*
* Copyright (c) 2000-2005 by JetBrains s.r.o. All Rights Reserved.
* Use is subject to license terms.
*/
package com.intellij.psi.util.proximity;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.PsiTestUtil;
import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory;
import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase;
import com.intellij.testFramework.fixtures.TempDirTestFixture;
/**
* @author peter
*/
public class ProximityTest extends JavaCodeInsightFixtureTestCase {
public void testSameSourceRoot() throws Throwable {
final TempDirTestFixture root1 = IdeaTestFixtureFactory.getFixtureFactory().createTempDirTestFixture();
final TempDirTestFixture root2 = IdeaTestFixtureFactory.getFixtureFactory().createTempDirTestFixture();
root1.setUp();
root2.setUp();
try {
new WriteCommandAction(getProject()) {
@Override
protected void run(Result result) throws Throwable {
PsiTestUtil.addSourceContentToRoots(myModule, root1.getFile(""));
PsiTestUtil.addSourceContentToRoots(myModule, root2.getFile(""));
}
}.execute();
final VirtualFile file1 = root1.createFile("buy.txt", "");
final VirtualFile file2 = root2.createFile("buy.txt", "");
final VirtualFile ctx = root2.createFile("ctx.txt", "");
final PsiProximityComparator comparator = new PsiProximityComparator(getPsiManager().findFile(ctx));
assertTrue(comparator.compare(getPsiManager().findFile(file1), getPsiManager().findFile(file2)) > 0);
assertTrue(comparator.compare(getPsiManager().findFile(file2), getPsiManager().findFile(file1)) < 0);
}
finally {
root1.tearDown();
root2.tearDown();
}
}
}
@@ -0,0 +1,58 @@
package com.intellij.refactoring;
import com.intellij.FileSetTestCase;
import com.intellij.psi.*;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.util.containers.HashSet;
import junit.framework.Test;
import java.io.File;
import java.net.URL;
import java.util.Arrays;
import java.util.Set;
/**
* @author dsl
*/
public abstract class FixMethodJavadocTest extends FileSetTestCase {
FixMethodJavadocTest() {
super(findPath());
}
private static String findPath() {
final URL res = FixMethodJavadocTest.class.getResource("/" + FixMethodJavadocTest.class.getName().replace('.', '/') + ".class");
File f = new File(res.getFile());
String result = f.getParent() + File.separatorChar + "methodJavaDocData";
result = result.replaceAll("classes", "");
return result;
}
@Override
public String transform(String testName, String[] data) throws Exception {
final PsiManager manager = PsiManager.getInstance(myProject);
final PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
final PsiMethod method = factory.createMethodFromText(data[0], null);
final HashSet<PsiParameter> newParameters = new HashSet<PsiParameter>();
if (data.length == 2) {
final String[] strings = data[1].split("\\s+");
collectNewParameters(method, strings, newParameters);
}
RefactoringUtil.fixJavadocsForParams(method, newParameters);
return method.getText();
}
private void collectNewParameters(PsiMethod method, String[] names, Set<PsiParameter> newParameters) {
Set<String> newNames = new HashSet<String>(Arrays.asList(names));
final PsiParameter[] parameters = method.getParameterList().getParameters();
for (int i = 0; i < parameters.length; i++) {
PsiParameter parameter = parameters[i];
if (newNames.contains(parameter.getName())) {
newParameters.add(parameter);
}
}
}
public static Test suite() {
return new FixMethodJavadocTest(){};
}
}
@@ -0,0 +1,63 @@
package com.intellij.refactoring;
import com.intellij.codeInsight.CodeInsightTestCase;
import com.intellij.openapi.application.ex.PathManagerEx;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.projectRoots.impl.JavaSdkImpl;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiPackage;
import com.intellij.refactoring.rename.RenameProcessor;
import com.intellij.testFramework.IdeaTestUtil;
import com.intellij.testFramework.PsiTestUtil;
import java.io.File;
public class RenamePackageTest extends CodeInsightTestCase {
public void testJspImport() throws Exception {
doTest("jspImport", "pack1", "pack2");
}
public void testNonJava() throws Exception {
doTest("nonJava", "com.foo", "fooNew");
}
public void testInBrokenXml() throws Exception {
doTest("inBrokenXml", "somepckg", "somepckg1");
}
public void testJsp() throws Exception {
doTest("jsp", "pack1", "pack2");
}
private void doTest(String testName, String packageName, String newPackageName) throws Exception {
String root = PathManagerEx.getTestDataPath()+ "/refactoring/renamePackage/" + testName;
String rootBefore = root + "/before";
PsiTestUtil.removeAllRoots(myModule, JavaSdkImpl.getMockJdk17());
VirtualFile rootDir = PsiTestUtil.createTestProjectStructure(myProject, myModule, rootBefore, myFilesToDelete);
performAction(packageName, newPackageName);
String rootAfter = root + "/after";
VirtualFile rootDir2 = LocalFileSystem.getInstance().findFileByPath(rootAfter.replace(File.separatorChar, '/'));
IdeaTestUtil.assertDirectoriesEqual(rootDir2, rootDir, IdeaTestUtil.CVS_FILE_FILTER);
}
private void performAction(String packageName, String newPackageName) throws Exception {
PsiPackage aPackage = JavaPsiFacade.getInstance(myPsiManager.getProject()).findPackage(packageName);
assertNotNull("Package " + packageName + " not found", aPackage);
//PsiDirectory dir = aPackage.getDirectories()[0];
//it is now impossible to rename dir without renaming corresponding package via rename processor - move processor would be used instead
new RenameProcessor(myProject, aPackage, newPackageName, true, true).run();
FileDocumentManager.getInstance().saveAllDocuments();
}
@Override
protected boolean isRunInWriteAction() {
return false;
}
}
@@ -170,6 +170,10 @@ public class InlineMethodTest extends LightRefactoringTestCase {
public void testSuperMethodInAnonymousClass() throws Exception {
doTest();
}
public void testInlineAnonymousClassWithPrivateMethodInside() throws Exception {
doTest();
}
private void doTest() throws Exception {
String name = getTestName(false);
@@ -51,6 +51,8 @@ public class MoveInstanceMethodTest extends LightRefactoringTestCase {
public void testThisInAnonymous() throws Exception { doTest(true, 0); }
public void testOverloadingMethods() throws Exception { doTest(true, 0); }
public void testEscalateVisibility() throws Exception {
doTest(true, 0, VisibilityUtil.ESCALATE_VISIBILITY);
}
@@ -0,0 +1,116 @@
package com.intellij.unscramble;
import junit.framework.TestCase;
import org.jetbrains.annotations.NonNls;
/**
* @author cdr
*/
public class NormalizeTextTest extends TestCase {
public void testCausedBy() {
doTest("javax.faces.FacesException: Error calling action method of component with id _id6:_id10\n" +
" at java.lang.Th\n" +
"read.run(Thread.java:626)\n" +
"Caused by: javax.faces.el.EvaluationException: Exception while invoking expression #{_loginAction.login}\n" +
" at org.apache.myfaces.el.MethodBindingImpl.invoke(MethodBindingImpl.java:153)\n" +
" at org.apache.myfaces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:63)\n",
"javax.faces.FacesException: Error calling action method of component with id _id6:_id10\n" +
" at java.lang.Thread.run(Thread.java:626)\n" +
"Caused by: javax.faces.el.EvaluationException: Exception while invoking expression #{_loginAction.login}\n" +
" at org.apache.myfaces.el.MethodBindingImpl.invoke(MethodBindingImpl.java:153)\n" +
" at org.apache.myfaces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:63)"
);
}
public void testThreadNames() {
doTest("\"Background process\" prio=6 tid=0x21193b88 nid=0x11ea4 waiting on condition [0x2\n" + "2cbf000..0x22cbfd68]\n" +
" at java.lang.Thread.sleep(Native Method)\n" + " at com.intellij.util.ui.Timer$1.run(Timer.java:23)\n" + "\n" +
"\"Alarm pool\" prio=6 tid=0x37cacbe0 nid=0x7940 waiting on condition [0x3972f000..\n" + "0x3972fae8]\n" +
" at sun.misc.Unsafe.park(Native Method)\n" +
" at java.util.concurrent.locks.LockSupport.park(LockSupport.java:118)\n" +
" at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject\n" +
".await(AbstractQueuedSynchronizer.java:1767)\n\n" +
" at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.jav\n" + "a:359)\n" +
" at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.ja\n" + "va:470)\n" +
" at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor\n" + ".java:674)\n" +
" at java.lang.Thread.run(Thread.java:595)",
"\"Background process\" prio=6 tid=0x21193b88 nid=0x11ea4 waiting on condition [0x22cbf000..0x22cbfd68]\n" +
" at java.lang.Thread.sleep(Native Method)\n" +
" at com.intellij.util.ui.Timer$1.run(Timer.java:23)\n" +
"\n" +
"\"Alarm pool\" prio=6 tid=0x37cacbe0 nid=0x7940 waiting on condition [0x3972f000..0x3972fae8]\n" +
" at sun.misc.Unsafe.park(Native Method)\n" +
" at java.util.concurrent.locks.LockSupport.park(LockSupport.java:118)\n" +
" at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1767)\n" +
" at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:359)\n" +
" at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:470)\n" +
" at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:674)\n" +
" at java.lang.Thread.run(Thread.java:595)"
);
}
public void testLocked() {
doTest(" at com.intellij.lang.jsp.JspFileViewProviderImpl.getKeyPrefixes(JspFileV\n" + "iewProviderImpl.java:76)\n" +
" at com.intellij.lang.jsp.JspFileViewProviderImpl.getKnownTaglibPrefixes(\n" + "JspFileViewProviderImpl.java:89)\n" +
" - locked <0x04cc0768> (a java.lang.Object)\n" +
" at com.intellij.psi.impl.source.parsing.jsp.JspLexer.doInitOriginal(JspL\n" + "exer.java:39)\n" +
" at com.intellij.psi.impl.source.parsing.jsp.JspLexer.start(JspLexer.java\n" + ":49)",
" at com.intellij.lang.jsp.JspFileViewProviderImpl.getKeyPrefixes(JspFileViewProviderImpl.java:76)\n" +
" at com.intellij.lang.jsp.JspFileViewProviderImpl.getKnownTaglibPrefixes(JspFileViewProviderImpl.java:89)\n" +
" - locked <0x04cc0768> (a java.lang.Object)\n" +
" at com.intellij.psi.impl.source.parsing.jsp.JspLexer.doInitOriginal(JspLexer.java:39)\n" +
" at com.intellij.psi.impl.source.parsing.jsp.JspLexer.start(JspLexer.java:49)");
}
public void testAtSplit() {
doTest("java.lang.Throwable\n" +
"at\n" +
"com.intellij.openapi.util.objectTree.ObjectNode.<init>(ObjectNode.jav\n" + "a:31)\n" +
"at\n" +
"com.intellij.openapi.util.objectTree.ObjectTree.getNodeFor(ObjectTree\n" + ".java:79)",
"java.lang.Throwable\n" +
"at com.intellij.openapi.util.objectTree.ObjectNode.<init>(ObjectNode.java:31)\n" +
"at com.intellij.openapi.util.objectTree.ObjectTree.getNodeFor(ObjectTree.java:79)");
}
public void testSplitMergedLines() {
doTest("org.apache.velocity.exception.MethodInvocationException " +
"at org.apache.velocity.runtime.parser.node.ASTMethod.execute(ASTMethod.java:246) " +
"at org.apache.velocity.runtime.parser.node.ASTReference.execute(ASTReference.java:175) " +
"at org.apache.velocity.runtime.parser.node.ASTReference.value(ASTReference.java:327) " +
"at org.apache.velocity.runtime.parser.node.ASTExpression.value(ASTExpression.java:51) " +
"at org.apache.velocity.runtime.parser.node.ASTSetDirective.render(ASTSetDirective.java:95) " +
"at org.apache.velocity.runtime.parser.node.ASTBlock.render(ASTBlock.java:55) " +
"at org.apache.velocity.runtime.directive.Foreach.render(Foreach.java:166) " +
"at org.apache.velocity.runtime.parser.node.ASTDirective.render(ASTDirective.java:114) " +
"at org.apache.velocity.runtime.parser.node.SimpleNode.render(SimpleNode.java:230) " +
"at org.apache.velocity.runtime.directive.VelocimacroProxy.render(VelocimacroProxy.java:172) " +
"at org.apache.velocity.runtime.parser.node.ASTDirective.render(ASTDirective.java:114) " +
"at org.apache.velocity.runtime.parser.node.SimpleNode.render(SimpleNode.java:230) " +
"at org.apache.velocity.Template.merge(Template.java:256)",
"org.apache.velocity.exception.MethodInvocationException\n" +
"at org.apache.velocity.runtime.parser.node.ASTMethod.execute(ASTMethod.java:246)\n" +
"at org.apache.velocity.runtime.parser.node.ASTReference.execute(ASTReference.java:175)\n" +
"at org.apache.velocity.runtime.parser.node.ASTReference.value(ASTReference.java:327)\n" +
"at org.apache.velocity.runtime.parser.node.ASTExpression.value(ASTExpression.java:51)\n" +
"at org.apache.velocity.runtime.parser.node.ASTSetDirective.render(ASTSetDirective.java:95)\n" +
"at org.apache.velocity.runtime.parser.node.ASTBlock.render(ASTBlock.java:55)\n" +
"at org.apache.velocity.runtime.directive.Foreach.render(Foreach.java:166)\n" +
"at org.apache.velocity.runtime.parser.node.ASTDirective.render(ASTDirective.java:114)\n" +
"at org.apache.velocity.runtime.parser.node.SimpleNode.render(SimpleNode.java:230)\n" +
"at org.apache.velocity.runtime.directive.VelocimacroProxy.render(VelocimacroProxy.java:172)\n" +
"at org.apache.velocity.runtime.parser.node.ASTDirective.render(ASTDirective.java:114)\n" +
"at org.apache.velocity.runtime.parser.node.SimpleNode.render(SimpleNode.java:230)\n" +
"at org.apache.velocity.Template.merge(Template.java:256)");
}
private static void doTest(@NonNls String stackTrace, @NonNls String expected) {
String normalized = UnscrambleDialog.normalizeText(stackTrace);
assertEquals(expected, normalized);
}
}
@@ -57,16 +57,6 @@ public class LanguageLevelModuleExtension extends ModuleExtension<LanguageLevelM
public void setLanguageLevel(final LanguageLevel languageLevel) {
LOG.assertTrue(myWritable, "Writable model can be retrieved from writable ModifiableRootModel");
if (mySource != null && myModule.isLoaded()) { //do not reload project for non-commited modules: j2me|project imports
if (myLanguageLevel != languageLevel) {
final LanguageLevelProjectExtension languageLevelProjectExtension = LanguageLevelProjectExtension.getInstance(myModule.getProject());
final LanguageLevel projectLanguageLevel = languageLevelProjectExtension.getLanguageLevel();
if (!(languageLevel == null && myLanguageLevel == projectLanguageLevel ||
myLanguageLevel == null && languageLevel == projectLanguageLevel)) {
languageLevelProjectExtension.reloadProjectOnLanguageLevelChange(languageLevel == null ? projectLanguageLevel : languageLevel, true);
}
}
}
myLanguageLevel = languageLevel;
}
@@ -103,6 +93,18 @@ public class LanguageLevelModuleExtension extends ModuleExtension<LanguageLevelM
@Override
public void commit() {
if (mySource != null && mySource.myLanguageLevel != myLanguageLevel) {
if (myModule.isLoaded()) { //do not reload project for non-committed modules: j2me|project imports
if (mySource.myLanguageLevel != myLanguageLevel) {
final LanguageLevelProjectExtension languageLevelProjectExtension =
LanguageLevelProjectExtension.getInstance(myModule.getProject());
final LanguageLevel projectLanguageLevel = languageLevelProjectExtension.getLanguageLevel();
final boolean explicit2ImplicitProjectLevel = myLanguageLevel == null && mySource.myLanguageLevel == projectLanguageLevel;
final boolean implicit2ExplicitProjectLevel = mySource.myLanguageLevel == null && myLanguageLevel == projectLanguageLevel;
if (!(explicit2ImplicitProjectLevel || implicit2ExplicitProjectLevel)) {
languageLevelProjectExtension.reloadProjectOnLanguageLevelChange(myLanguageLevel == null ? projectLanguageLevel : myLanguageLevel, true);
}
}
}
mySource.myLanguageLevel = myLanguageLevel;
}
}
@@ -0,0 +1,137 @@
/*
* Copyright (c) 2000-2006 JetBrains s.r.o. All Rights Reserved.
*/
package com.intellij.mock;
import com.intellij.navigation.ItemPresentation;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.search.PsiElementProcessor;
import com.intellij.util.IncorrectOperationException;
import com.intellij.lang.Language;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author peter
*/
public class MockPsiDirectory extends MockPsiElement implements PsiDirectory {
private final PsiPackage myPackage;
public MockPsiDirectory(final PsiPackage aPackage, @NotNull Disposable parentDisposable) {
super(parentDisposable);
myPackage = aPackage;
}
@Override
public boolean isDirectory() {
return true;
}
@NotNull
@Override
public Language getLanguage() {
return Language.ANY;
}
@Override
public void checkCreateFile(@NotNull final String name) throws IncorrectOperationException {
throw new IncorrectOperationException("Method checkCreateFile is not yet implemented in " + getClass().getName());
}
@Override
public void checkCreateSubdirectory(@NotNull final String name) throws IncorrectOperationException {
throw new IncorrectOperationException("Method checkCreateSubdirectory is not yet implemented in " + getClass().getName());
}
@Override
public PsiDirectory getParent() {
return getParentDirectory();
}
@Override
@NotNull
public PsiFile createFile(@NotNull final String name) throws IncorrectOperationException {
throw new IncorrectOperationException("Method createFile is not yet implemented in " + getClass().getName());
}
@Override
@NotNull
public PsiFile copyFileFrom(@NotNull final String newName, @NotNull final PsiFile originalFile) throws IncorrectOperationException {
throw new IncorrectOperationException("Method copyFileFrom is not yet implemented in " + getClass().getName());
}
@Override
@NotNull
public PsiDirectory createSubdirectory(@NotNull final String name) throws IncorrectOperationException {
throw new IncorrectOperationException("Method createSubdirectory is not yet implemented in " + getClass().getName());
}
@Override
@Nullable
public PsiFile findFile(@NotNull @NonNls final String name) {
throw new UnsupportedOperationException("Method findFile is not yet implemented in " + getClass().getName());
}
@Override
@Nullable
public PsiDirectory findSubdirectory(@NotNull final String name) {
throw new UnsupportedOperationException("Method findSubdirectory is not yet implemented in " + getClass().getName());
}
@Override
@NotNull
public PsiFile[] getFiles() {
throw new UnsupportedOperationException("Method getFiles is not yet implemented in " + getClass().getName());
}
@Override
@NotNull
public String getName() {
throw new UnsupportedOperationException("Method getName is not yet implemented in " + getClass().getName());
}
@Override
@Nullable
public PsiDirectory getParentDirectory() {
final PsiPackage psiPackage = myPackage.getParentPackage();
return psiPackage == null ? null : new MockPsiDirectory(psiPackage, getProject());
}
@Override
@NotNull
public PsiDirectory[] getSubdirectories() {
throw new UnsupportedOperationException("Method getSubdirectories is not yet implemented in " + getClass().getName());
}
@Override
@NotNull
public VirtualFile getVirtualFile() {
throw new UnsupportedOperationException("Method getVirtualFile is not yet implemented in " + getClass().getName());
}
@Override
public boolean processChildren(final PsiElementProcessor<PsiFileSystemItem> processor) {
throw new UnsupportedOperationException("Method processChildren is not yet implemented in " + getClass().getName());
}
@Override
@NotNull
public PsiElement setName(@NotNull final String name) throws IncorrectOperationException {
throw new IncorrectOperationException("Method setName is not yet implemented in " + getClass().getName());
}
@Override
public void checkSetName(final String name) throws IncorrectOperationException {
throw new IncorrectOperationException("Method checkSetName is not yet implemented in " + getClass().getName());
}
@Override
@Nullable
public ItemPresentation getPresentation() {
throw new UnsupportedOperationException("Method getPresentation is not yet implemented in " + getClass().getName());
}
}
@@ -15,40 +15,12 @@
*/
package com.intellij.testFramework;
import com.intellij.ide.util.treeView.AbstractTreeNode;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.LanguageLevelModuleExtension;
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
import com.intellij.openapi.ui.Queryable;
import com.intellij.pom.java.LanguageLevel;
import java.util.Comparator;
public class IdeaTestUtil extends PlatformTestUtil {
public static Comparator<AbstractTreeNode> createComparator(final Queryable.PrintInfo printInfo) {
return new Comparator<AbstractTreeNode>() {
@Override
public int compare(final AbstractTreeNode o1, final AbstractTreeNode o2) {
String displayText1 = o1.toTestString(printInfo);
String displayText2 = o2.toTestString(printInfo);
return displayText1.compareTo(displayText2);
}
};
}
/**
* Use {@link #createComparator(com.intellij.openapi.ui.Queryable.PrintInfo)} instead.
*/
@Deprecated
public static final Comparator<AbstractTreeNode> DEFAULT_COMPARATOR = new Comparator<AbstractTreeNode>() {
@Override
public int compare(AbstractTreeNode o1, AbstractTreeNode o2) {
String displayText1 = o1.getTestPresentation();
String displayText2 = o2.getTestPresentation();
return displayText1.compareTo(displayText2);
}
};
public static void main(String[] args) {
printDetectedPerformanceTimings();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,6 +30,8 @@ import com.intellij.util.ThrowableRunnable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
/**
* Service for reformatting code fragments, getting names for elements
* according to the user's code style and working with import statements and full-qualified names.
@@ -123,9 +125,7 @@ public abstract class CodeStyleManager {
boolean canChangeWhiteSpacesOnly) throws IncorrectOperationException;
/**
* Reformats a range of text in the specified file. This method works faster than
* {@link #reformatRange(com.intellij.psi.PsiElement, int, int)} but invalidates the
* PSI structure for the file.
* Delegates to the {@link #reformatText(PsiFile, Collection)} with the single range defined by the given offsets.
*
* @param element the file to reformat.
* @param startOffset the start of the text range to reformat.
@@ -135,7 +135,18 @@ public abstract class CodeStyleManager {
public abstract void reformatText(@NotNull PsiFile element, int startOffset, int endOffset) throws IncorrectOperationException;
/**
* Reformats the specified range of a file, modifying only line indents and leaving
* Re-formats a ranges of text in the specified file. This method works faster than
* {@link #reformatRange(com.intellij.psi.PsiElement, int, int)} but invalidates the
* PSI structure for the file.
*
* @param element the file to reformat
* @param ranges ranges to process
* @throws IncorrectOperationException if the file to reformat is read-only.
*/
public abstract void reformatText(@NotNull PsiFile element, @NotNull Collection<TextRange> ranges) throws IncorrectOperationException;
/**
* Re-formats the specified range of a file, modifying only line indents and leaving
* all other whitespace intact.
*
* @param file the file to reformat.
@@ -776,6 +776,7 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
@Override
public final void setInBulkUpdate(boolean value) {
ApplicationManager.getApplication().assertIsDispatchThread();
myDoingBulkUpdate = value;
myText.setDeferredChangeMode(value);
if (value) {
@@ -20,7 +20,11 @@
package com.intellij.lang;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class LanguageImportStatements extends LanguageExtension<ImportOptimizer> {
public static final LanguageImportStatements INSTANCE = new LanguageImportStatements();
@@ -29,9 +33,15 @@ public class LanguageImportStatements extends LanguageExtension<ImportOptimizer>
super("com.intellij.lang.importOptimizer");
}
@Nullable
public ImportOptimizer forFile(PsiFile file) {
ImportOptimizer optimizer = forLanguage(file.getLanguage());
return optimizer != null && optimizer.supports(file) ? optimizer : null;
public List<Runnable> forFile(PsiFile file) {
List<Runnable> runnables = new ArrayList<Runnable>();
Set<ImportOptimizer> optimizers = new HashSet<ImportOptimizer>();
for (PsiFile psiFile : file.getViewProvider().getAllFiles()) {
ImportOptimizer optimizer = forLanguage(psiFile.getLanguage());
if (optimizer != null && optimizer.supports(psiFile) && optimizers.add(optimizer)) {
runnables.add(optimizer.processFile(psiFile));
}
}
return runnables;
}
}
@@ -125,6 +125,9 @@ public class ModuleUtil {
if (orderEntries.isEmpty()) {
return null;
}
if (orderEntries.size() == 1) {
return orderEntries.get(0).getOwnerModule();
}
Set<Module> modules = new HashSet<Module>();
for (OrderEntry orderEntry : orderEntries) {
modules.add(orderEntry.getOwnerModule());
@@ -59,7 +59,7 @@ public class CommonRefactoringUtil {
}
}
public static void showErrorHint(Project project, @Nullable Editor editor, String message, String title, String helpId) {
public static void showErrorHint(Project project, @Nullable Editor editor, String message, String title, @Nullable @NonNls String helpId) {
if (ApplicationManager.getApplication().isUnitTestMode()) throw new RefactoringErrorHintException(message);
if (editor == null) {
-3
View File
@@ -4,7 +4,6 @@
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/testSrc" isTestSource="true" />
</content>
<orderEntry type="module" module-name="boot" />
<orderEntry type="inheritedJdk" />
@@ -19,11 +18,9 @@
<orderEntry type="module" module-name="platform-impl" exported="" />
<orderEntry type="module" module-name="usageView" exported="" />
<orderEntry type="library" name="Guava" level="project" />
<orderEntry type="library" scope="TEST" name="Mocks" level="project" />
<orderEntry type="module" module-name="xdebugger-api" />
<orderEntry type="library" name="xpp3-1.1.4-min" level="project" />
<orderEntry type="library" exported="" name="cli-parser" level="project" />
<orderEntry type="module" module-name="testFramework" scope="TEST" />
<orderEntry type="library" name="http-client-3.1" level="project" />
</component>
</module>
@@ -66,18 +66,18 @@ public abstract class AbstractLayoutCodeProcessor {
private final String myProgressText;
private final String myCommandName;
private final Runnable myPostRunnable;
private final boolean myProcessChangedTextOnly;
protected AbstractLayoutCodeProcessor(Project project, String commandName, String progressText) {
myProject = project;
myModule = null;
myDirectory = null;
myIncludeSubdirs = true;
myCommandName = commandName;
myProgressText = progressText;
myPostRunnable = null;
protected AbstractLayoutCodeProcessor(Project project, String commandName, String progressText, boolean processChangedTextOnly) {
this(project, (Module)null, commandName, progressText, processChangedTextOnly);
}
protected AbstractLayoutCodeProcessor(Project project, Module module, String commandName, String progressText) {
protected AbstractLayoutCodeProcessor(Project project,
@Nullable Module module,
String commandName,
String progressText,
boolean processChangedTextOnly)
{
myProject = project;
myModule = module;
myDirectory = null;
@@ -85,9 +85,16 @@ public abstract class AbstractLayoutCodeProcessor {
myCommandName = commandName;
myProgressText = progressText;
myPostRunnable = null;
myProcessChangedTextOnly = processChangedTextOnly;
}
protected AbstractLayoutCodeProcessor(Project project, PsiDirectory directory, boolean includeSubdirs, String progressText, String commandName) {
protected AbstractLayoutCodeProcessor(Project project,
PsiDirectory directory,
boolean includeSubdirs,
String progressText,
String commandName,
boolean processChangedTextOnly)
{
myProject = project;
myModule = null;
myDirectory = directory;
@@ -95,24 +102,38 @@ public abstract class AbstractLayoutCodeProcessor {
myProgressText = progressText;
myCommandName = commandName;
myPostRunnable = null;
myProcessChangedTextOnly = processChangedTextOnly;
}
protected AbstractLayoutCodeProcessor(Project project, PsiFile file, String progressText, String commandName) {
protected AbstractLayoutCodeProcessor(Project project,
PsiFile file,
String progressText,
String commandName,
boolean processChangedTextOnly)
{
myProject = project;
myModule = null;
myFile = file;
myProgressText = progressText;
myCommandName = commandName;
myPostRunnable = null;
myProcessChangedTextOnly = processChangedTextOnly;
}
protected AbstractLayoutCodeProcessor(Project project, PsiFile[] files, String progressText, String commandName, Runnable postRunnable) {
protected AbstractLayoutCodeProcessor(Project project,
PsiFile[] files,
String progressText,
String commandName,
@Nullable Runnable postRunnable,
boolean processChangedTextOnly)
{
myProject = project;
myModule = null;
myFiles = filterFiles(files);
myProgressText = progressText;
myCommandName = commandName;
myPostRunnable = postRunnable;
myProcessChangedTextOnly = processChangedTextOnly;
}
private static PsiFile[] filterFiles(PsiFile[] files){
@@ -128,13 +149,15 @@ public abstract class AbstractLayoutCodeProcessor {
/**
* Ensures that given file is ready to reformatting and prepares it if necessary.
*
* @param file file to process
* @param file file to process
* @param processChangedTextOnly flag that defines is only the changed text (in terms of VCS change) should be processed
* @return task that triggers formatting of the given file. Returns value of that task indicates whether formatting
* is finished correctly or not (exception occurred, user cancelled formatting etc)
* @throws IncorrectOperationException if unexpected exception occurred during formatting
*/
@NotNull
protected abstract FutureTask<Boolean> preprocessFile(PsiFile file) throws IncorrectOperationException;
protected abstract FutureTask<Boolean> preprocessFile(@NotNull PsiFile file, boolean processChangedTextOnly)
throws IncorrectOperationException;
public void run() {
if (myDirectory != null){
@@ -154,7 +177,7 @@ public abstract class AbstractLayoutCodeProcessor {
}
}
private void runProcessFile(final PsiFile file) {
private void runProcessFile(@NotNull final PsiFile file) {
Document document = PsiDocumentManager.getInstance(myProject).getDocument(file);
if (document == null) {
@@ -174,7 +197,7 @@ public abstract class AbstractLayoutCodeProcessor {
public void run() {
if (!checkFileWritable(file)) return;
try{
resultRunnable[0] = preprocessFile(file);
resultRunnable[0] = preprocessFile(file, myProcessChangedTextOnly);
}
catch(IncorrectOperationException e){
LOG.error(e);
@@ -223,7 +246,7 @@ public abstract class AbstractLayoutCodeProcessor {
}
if (file.isWritable()){
try{
tasks.add(preprocessFile(file));
tasks.add(preprocessFile(file, myProcessChangedTextOnly));
}
catch(IncorrectOperationException e){
LOG.error(e);
@@ -487,7 +510,7 @@ public abstract class AbstractLayoutCodeProcessor {
}
public void runWithoutProgress() throws IncorrectOperationException {
final Runnable runnable = preprocessFile(myFile);
final Runnable runnable = preprocessFile(myFile, myProcessChangedTextOnly);
runnable.run();
}
@@ -0,0 +1,211 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.actions;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.module.ModifiableModuleModel;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.ChangeListManager;
import com.intellij.openapi.vcs.ex.LineStatusTracker;
import com.intellij.openapi.vcs.ex.Range;
import com.intellij.openapi.vcs.impl.LineStatusTrackerManager;
import com.intellij.openapi.vcs.impl.LineStatusTrackerManagerI;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import java.util.*;
/**
* Contains utility methods for 'format only changed text' (in terms of VCS changes).
*
* @author Denis Zhdanov
* @since 12/19/11 10:55 AM
*/
public class FormatChangedTextUtil {
private FormatChangedTextUtil() {
}
/**
* Allows to answer if given file has changes in comparison with VCS.
*
* @param file target file
* @return <code>true</code> if given file has changes; <code>false</code> otherwise
*/
public static boolean hasChanges(@NotNull PsiFile file) {
final Project project = file.getProject();
final VirtualFile virtualFile = file.getVirtualFile();
if (virtualFile != null) {
final Change change = ChangeListManager.getInstance(project).getChange(virtualFile);
if (change != null && change.getType() == Change.Type.NEW) {
return true;
}
}
final LineStatusTrackerManagerI manager = LineStatusTrackerManager.getInstance(project);
if (manager == null) {
return false;
}
final Document document = PsiDocumentManager.getInstance(project).getDocument(file);
if (document == null) {
return false;
}
final LineStatusTracker lineStatusTracker = manager.getLineStatusTracker(document);
if (lineStatusTracker == null) {
return false;
}
final List<Range> ranges = lineStatusTracker.getRanges();
if (ranges == null || ranges.isEmpty()) {
return false;
}
for (Range range : ranges) {
if (range.getType() != Range.DELETED) {
return true;
}
}
return false;
}
/**
* Allows to answer if any file below the given directory (any level of nesting) has changes in comparison with VCS.
*
* @param directory target directory to check
* @return <code>true</code> if any file below the given directory has changes in comparison with VCS;
* <code>false</code> otherwise
*/
public static boolean hasChanges(@NotNull PsiDirectory directory) {
return hasChanges(directory.getVirtualFile(), directory.getProject());
}
/**
* Allows to answer if given file or any file below the given directory (any level of nesting) has changes in comparison with VCS.
*
* @param file target directory to check
* @param project target project
* @return <code>true</code> if given file or any file below the given directory has changes in comparison with VCS;
* <code>false</code> otherwise
*/
public static boolean hasChanges(@NotNull VirtualFile file, @NotNull Project project) {
final Collection<Change> changes = ChangeListManager.getInstance(project).getChangesIn(file);
for (Change change : changes) {
if (change.getType() == Change.Type.NEW || change.getType() == Change.Type.MODIFICATION) {
return true;
}
}
return false;
}
/**
* Allows to answer if any file that belongs to the given module has changes in comparison with VCS.
*
* @param module target module to check
* @return <code>true</code> if any file that belongs to the given module has changes in comparison with VCS
* <code>false</code> otherwise
*/
public static boolean hasChanges(@NotNull Module module) {
final ModuleRootManager rootManager = ModuleRootManager.getInstance(module);
for (VirtualFile root : rootManager.getSourceRoots()) {
if (hasChanges(root, module.getProject())) {
return true;
}
}
return false;
}
/**
* Allows to answer if any file that belongs to the given project has changes in comparison with VCS.
*
* @param project target project to check
* @return <code>true</code> if any file that belongs to the given project has changes in comparison with VCS
* <code>false</code> otherwise
*/
public static boolean hasChanges(@NotNull final Project project) {
final ModifiableModuleModel moduleModel = new ReadAction<ModifiableModuleModel>() {
protected void run(Result<ModifiableModuleModel> result) throws Throwable {
result.setResult(ModuleManager.getInstance(project).getModifiableModel());
}
}.execute().getResultObject();
try {
for (Module module : moduleModel.getModules()) {
if (hasChanges(module)) {
return true;
}
}
return false;
}
finally {
moduleModel.dispose();
}
}
/**
* Allows to ask for the changed text of the given file (in comparison with VCS).
*
* @param file target file
* @return collection of changed regions for the given file
*/
@NotNull
public static Collection<TextRange> getChanges(@NotNull PsiFile file) {
final Set<TextRange> defaultResult = Collections.singleton(file.getTextRange());
final VirtualFile virtualFile = file.getVirtualFile();
if (virtualFile != null) {
final Change change = ChangeListManager.getInstance(file.getProject()).getChange(virtualFile);
if (change != null && change.getType() == Change.Type.NEW) {
return defaultResult;
}
}
final LineStatusTrackerManagerI manager = LineStatusTrackerManager.getInstance(file.getProject());
if (manager == null) {
return defaultResult;
}
final Document document = PsiDocumentManager.getInstance(file.getProject()).getDocument(file);
if (document == null) {
return defaultResult;
}
final LineStatusTracker lineStatusTracker = manager.getLineStatusTracker(document);
if (lineStatusTracker == null) {
return defaultResult;
}
final List<Range> ranges = lineStatusTracker.getRanges();
if (ranges == null || ranges.isEmpty()) {
return defaultResult;
}
List<TextRange> result = new ArrayList<TextRange>();
for (Range range : ranges) {
if (range.getType() != Range.DELETED) {
final RangeHighlighter highlighter = range.getHighlighter();
if (highlighter != null) {
result.add(new TextRange(highlighter.getStartOffset(), highlighter.getEndOffset()));
}
}
}
return result;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,22 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.openapi.editor.impl.event;
package com.intellij.codeInsight.actions;
import com.intellij.openapi.editor.markup.MarkupModel;
import com.intellij.openapi.editor.markup.RangeHighlighter;
import org.jetbrains.annotations.NonNls;
import java.util.EventObject;
/**
* @author Denis Zhdanov
* @since 12/16/11 6:10 PM
*/
public class LayoutCodeConstants {
public class MarkupModelEvent extends EventObject {
private final RangeHighlighter myHighlighter;
public MarkupModelEvent(MarkupModel source, RangeHighlighter segmentHighlighter) {
super(source);
myHighlighter = segmentHighlighter;
}
public RangeHighlighter getHighlighter() {
return myHighlighter;
public static final @NonNls String OPTIMIZE_IMPORTS_KEY = "LayoutCode.optimizeImports";
public static final @NonNls String PROCESS_CHANGED_TEXT_KEY = "LayoutCode.processChangedText";
private LayoutCodeConstants() {
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,7 +26,7 @@ import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiFile;
import com.intellij.util.ui.OptionsDialog;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -37,23 +37,23 @@ import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
public class LayoutCodeDialog extends DialogWrapper {
private final PsiFile myFile;
private final PsiFile myFile;
@Nullable private final PsiDirectory myDirectory;
private final Boolean myTextSelected;
private final Boolean myTextSelected;
private JRadioButton myRbFile;
private JRadioButton myRbSelectedText;
private JRadioButton myRbDirectory;
private JCheckBox myCbIncludeSubdirs;
private JCheckBox myCbOptimizeImports;
private JCheckBox myDoNotAskMeCheckBox;
private JCheckBox myCbIncludeSubdirs;
private JCheckBox myCbOptimizeImports;
private JCheckBox myCbOnlyVcsChangedRegions;
private JCheckBox myDoNotAskMeCheckBox;
public static final @NonNls String OPTIMIZE_IMPORTS_KEY = "LayoutCode.optimizeImports";
private final String myHelpId;
public LayoutCodeDialog(Project project,
String title,
PsiFile file,
public LayoutCodeDialog(@NotNull Project project,
@NotNull String title,
@Nullable PsiFile file,
@Nullable PsiDirectory directory,
Boolean isTextSelected,
final String helpId) {
@@ -84,7 +84,7 @@ public class LayoutCodeDialog extends DialogWrapper {
}
myCbIncludeSubdirs.setSelected(true);
myCbOptimizeImports.setSelected(isOptmizeImportsOptionOn());
myCbOptimizeImports.setSelected(PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, false));
ItemListener listener = new ItemListener() {
public void itemStateChanged(ItemEvent e) {
@@ -99,18 +99,17 @@ public class LayoutCodeDialog extends DialogWrapper {
updateState();
}
private static boolean isOptmizeImportsOptionOn() {
return Boolean.toString(true).equals(PropertiesComponent.getInstance().getValue(OPTIMIZE_IMPORTS_KEY));
}
private static void setOptimizeImportsOption(boolean state) {
PropertiesComponent.getInstance().setValue(OPTIMIZE_IMPORTS_KEY, Boolean.toString(state));
}
private void updateState() {
myCbIncludeSubdirs.setEnabled(myRbDirectory.isSelected());
myCbOptimizeImports.setEnabled(
!myRbSelectedText.isSelected() && !(myFile != null && LanguageImportStatements.INSTANCE.forFile(myFile) == null && myRbFile.isSelected()));
!myRbSelectedText.isSelected() &&
!(myFile != null && LanguageImportStatements.INSTANCE.forFile(myFile).isEmpty() && myRbFile.isSelected()));
final boolean canTargetVcsChanges = canTargetVcsRegions();
myCbOnlyVcsChangedRegions.setEnabled(canTargetVcsChanges);
myCbOnlyVcsChangedRegions.setSelected(
canTargetVcsChanges && PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, false)
);
myDoNotAskMeCheckBox.setEnabled(!myRbDirectory.isSelected());
myRbDirectory.setEnabled(!myDoNotAskMeCheckBox.isSelected());
@@ -163,6 +162,10 @@ public class LayoutCodeDialog extends DialogWrapper {
panel.add(myCbOptimizeImports, gbConstraints);
}
myCbOnlyVcsChangedRegions = new JCheckBox(CodeInsightBundle.message("reformat.option.vcs.changed.region"));
gbConstraints.gridy++;
panel.add(myCbOnlyVcsChangedRegions, gbConstraints);
ButtonGroup buttonGroup = new ButtonGroup();
buttonGroup.add(myRbFile);
buttonGroup.add(myRbSelectedText);
@@ -201,7 +204,7 @@ public class LayoutCodeDialog extends DialogWrapper {
public boolean isProcessWholeFile() {
return myRbFile.isSelected();
}
public boolean isProcessDirectory() {
return myRbDirectory.isSelected();
}
@@ -214,12 +217,35 @@ public class LayoutCodeDialog extends DialogWrapper {
return myCbOptimizeImports.isSelected();
}
public boolean isProcessOnlyChangedText() {
return myCbOnlyVcsChangedRegions.isEnabled() && myCbOnlyVcsChangedRegions.isSelected();
}
boolean isDoNotAskMe() {
return myDoNotAskMeCheckBox.isSelected();
return myDoNotAskMeCheckBox.isSelected();
}
protected void doOKAction() {
super.doOKAction();
setOptimizeImportsOption(isOptimizeImports());
PropertiesComponent.getInstance().setValue(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, Boolean.toString(isOptimizeImports()));
PropertiesComponent.getInstance().setValue(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, Boolean.toString(isProcessOnlyChangedText()));
}
private boolean canTargetVcsRegions() {
if (isProcessSelectedText()) {
return false;
}
if (isProcessWholeFile()) {
return FormatChangedTextUtil.hasChanges(myFile);
}
if (isProcessDirectory()) {
if (myDirectory == null) {
return false;
}
return FormatChangedTextUtil.hasChanges(myDirectory);
}
return false;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,9 +19,12 @@ package com.intellij.codeInsight.actions;
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.help.HelpManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
@@ -30,36 +33,51 @@ import java.awt.*;
* @author max
*/
public class LayoutProjectCodeDialog extends DialogWrapper {
private static @NonNls final String OPTIMIZE_IMPORTS_KEY = "LayoutCode.optimizeImports";
private static @NonNls final String HELP_ID = "editing.codeReformatting";
private final String myText;
private final boolean mySuggestOptmizeImports;
private final String myText;
private final boolean mySuggestOptimizeImports;
private final Project myProject;
private final Module myModule;
private JCheckBox myCbOptimizeImports;
private JCheckBox myCbOnlyVcsChangedRegions;
public LayoutProjectCodeDialog(Project project, String title, String text, boolean suggestOptmizeImports) {
public LayoutProjectCodeDialog(@NotNull Project project,
@Nullable Module module,
String title,
String text,
boolean suggestOptimizeImports)
{
super(project, false);
myText = text;
mySuggestOptmizeImports = suggestOptmizeImports;
mySuggestOptimizeImports = suggestOptimizeImports;
myProject = project;
myModule = module;
setOKButtonText(CodeInsightBundle.message("reformat.code.accept.button.text"));
setTitle(title);
init();
}
protected JComponent createCenterPanel() {
if (!mySuggestOptmizeImports) return new JLabel(myText);
JPanel panel = new JPanel(new GridLayout(2, 1));
if (!mySuggestOptimizeImports) return new JLabel(myText);
JPanel panel = new JPanel(new GridLayout(3, 1));
panel.add(new JLabel(myText));
myCbOptimizeImports = new JCheckBox(CodeInsightBundle.message("reformat.option.optimize.imports"));
panel.add(myCbOptimizeImports);
myCbOptimizeImports.setSelected(Boolean.toString(true).equals(PropertiesComponent.getInstance().getValue(OPTIMIZE_IMPORTS_KEY)));
myCbOptimizeImports.setSelected(PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, false));
myCbOnlyVcsChangedRegions = new JCheckBox(CodeInsightBundle.message("reformat.option.vcs.changed.region"));
panel.add(myCbOnlyVcsChangedRegions);
final boolean canTargetVcsRegions = canTargetVcsRegions();
myCbOnlyVcsChangedRegions.setEnabled(canTargetVcsRegions);
myCbOnlyVcsChangedRegions.setSelected(
canTargetVcsRegions && PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, false)
);
return panel;
}
private void setOptimizeImportsOption(boolean state) {
PropertiesComponent.getInstance().setValue(OPTIMIZE_IMPORTS_KEY, Boolean.toString(state));
}
protected Action[] createActions() {
return new Action[]{getOKAction(), getCancelAction(), getHelpAction()};
}
@@ -70,12 +88,24 @@ public class LayoutProjectCodeDialog extends DialogWrapper {
protected void doOKAction() {
super.doOKAction();
if (mySuggestOptmizeImports) {
setOptimizeImportsOption(isOptimizeImports());
if (mySuggestOptimizeImports) {
PropertiesComponent.getInstance().setValue(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, Boolean.toString(isOptimizeImports()));
}
}
public boolean isOptimizeImports() {
return myCbOptimizeImports.isSelected();
}
public boolean isProcessOnlyChangedText() {
return myCbOnlyVcsChangedRegions.isEnabled() && myCbOnlyVcsChangedRegions.isSelected();
}
private boolean canTargetVcsRegions() {
if (myModule != null) {
return FormatChangedTextUtil.hasChanges(myModule);
}
return FormatChangedTextUtil.hasChanges(myProject);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -54,7 +54,7 @@ public class OptimizeImportsAction extends AnAction {
if (file == null) return;
dir = file.getContainingDirectory();
}
else if (ReformatCodeAction.areFiles(files)) {
else if (files != null && ReformatCodeAction.areFiles(files)) {
final ReadonlyStatusHandler.OperationStatus operationStatus = ReadonlyStatusHandler.getInstance(project).ensureFilesWritable(files);
if (!operationStatus.hasReadonlyFiles()) {
new OptimizeImportsProcessor(project, ReformatCodeAction.convertToPsiFiles(files, project), null).run();
@@ -73,7 +73,8 @@ public class OptimizeImportsAction extends AnAction {
else {
text = CodeInsightBundle.message("process.scope.project", projectContext.getPresentableUrl());
}
LayoutProjectCodeDialog dialog = new LayoutProjectCodeDialog(project, CodeInsightBundle.message("process.optimize.imports"), text, false);
LayoutProjectCodeDialog dialog
= new LayoutProjectCodeDialog(project, null, CodeInsightBundle.message("process.optimize.imports"), text, false);
dialog.show();
if (!dialog.isOK()) return;
if (moduleContext != null) {
@@ -192,6 +193,6 @@ public class OptimizeImportsAction extends AnAction {
}
private static boolean isOptimizeImportsAvailable(final PsiFile file) {
return LanguageImportStatements.INSTANCE.forFile(file) != null;
return !LanguageImportStatements.INSTANCE.forFile(file).isEmpty();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,7 +17,6 @@
package com.intellij.codeInsight.actions;
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.lang.ImportOptimizer;
import com.intellij.lang.LanguageImportStatements;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
@@ -27,6 +26,7 @@ import com.intellij.psi.PsiFile;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.concurrent.FutureTask;
public class OptimizeImportsProcessor extends AbstractLayoutCodeProcessor {
@@ -34,19 +34,19 @@ public class OptimizeImportsProcessor extends AbstractLayoutCodeProcessor {
private static final String COMMAND_NAME = CodeInsightBundle.message("process.optimize.imports");
public OptimizeImportsProcessor(Project project) {
super(project, COMMAND_NAME, PROGRESS_TEXT);
super(project, COMMAND_NAME, PROGRESS_TEXT, false);
}
public OptimizeImportsProcessor(Project project, Module module) {
super(project, module, COMMAND_NAME, PROGRESS_TEXT);
super(project, module, COMMAND_NAME, PROGRESS_TEXT, false);
}
public OptimizeImportsProcessor(Project project, PsiDirectory directory, boolean includeSubdirs) {
super(project, directory, includeSubdirs, PROGRESS_TEXT, COMMAND_NAME);
super(project, directory, includeSubdirs, PROGRESS_TEXT, COMMAND_NAME, false);
}
public OptimizeImportsProcessor(Project project, PsiFile file) {
super(project, file, PROGRESS_TEXT, COMMAND_NAME);
super(project, file, PROGRESS_TEXT, COMMAND_NAME, false);
}
public OptimizeImportsProcessor(Project project, PsiFile[] files, Runnable postRunnable) {
@@ -54,13 +54,20 @@ public class OptimizeImportsProcessor extends AbstractLayoutCodeProcessor {
}
public OptimizeImportsProcessor(Project project, PsiFile[] files, String commandName, Runnable postRunnable) {
super(project, files, PROGRESS_TEXT, commandName, postRunnable);
super(project, files, PROGRESS_TEXT, commandName, postRunnable, false);
}
@NotNull
protected FutureTask<Boolean> preprocessFile(final PsiFile file) throws IncorrectOperationException {
final ImportOptimizer optimizer = LanguageImportStatements.INSTANCE.forFile(file);
Runnable runnable = optimizer != null ? optimizer.processFile(file) : EmptyRunnable.getInstance();
protected FutureTask<Boolean> preprocessFile(@NotNull final PsiFile file, boolean processChangedTextOnly) throws IncorrectOperationException {
final List<Runnable> optimizers = LanguageImportStatements.INSTANCE.forFile(file);
Runnable runnable = optimizers.isEmpty() ? EmptyRunnable.getInstance() : new Runnable() {
@Override
public void run() {
for (Runnable optimizer : optimizers) {
optimizer.run();
}
}
};
return new FutureTask<Boolean>(runnable, true);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -38,40 +38,44 @@ public class ReformatAndOptimizeImportsProcessor extends AbstractLayoutCodeProce
private final OptimizeImportsProcessor myOptimizeImportsProcessor;
private final ReformatCodeProcessor myReformatCodeProcessor;
public ReformatAndOptimizeImportsProcessor(Project project) {
super(project, COMMAND_NAME, PROGRESS_TEXT);
public ReformatAndOptimizeImportsProcessor(Project project, boolean processChangedTextOnly) {
super(project, COMMAND_NAME, PROGRESS_TEXT, processChangedTextOnly);
myOptimizeImportsProcessor = new OptimizeImportsProcessor(project);
myReformatCodeProcessor = new ReformatCodeProcessor(project);
myReformatCodeProcessor = new ReformatCodeProcessor(project, processChangedTextOnly);
}
public ReformatAndOptimizeImportsProcessor(Project project, Module module) {
super(project, module, COMMAND_NAME, PROGRESS_TEXT);
public ReformatAndOptimizeImportsProcessor(Project project, Module module, boolean processChangedTextOnly) {
super(project, module, COMMAND_NAME, PROGRESS_TEXT, processChangedTextOnly);
myOptimizeImportsProcessor = new OptimizeImportsProcessor(project, module);
myReformatCodeProcessor = new ReformatCodeProcessor(project, module);
myReformatCodeProcessor = new ReformatCodeProcessor(project, module, processChangedTextOnly);
}
public ReformatAndOptimizeImportsProcessor(Project project, PsiFile[] files) {
super(project, files, PROGRESS_TEXT, COMMAND_NAME, null);
public ReformatAndOptimizeImportsProcessor(Project project, PsiFile[] files, boolean processChangedTextOnly) {
super(project, files, PROGRESS_TEXT, COMMAND_NAME, null, processChangedTextOnly);
myOptimizeImportsProcessor = new OptimizeImportsProcessor(project);
myReformatCodeProcessor = new ReformatCodeProcessor(project);
myReformatCodeProcessor = new ReformatCodeProcessor(project, processChangedTextOnly);
}
public ReformatAndOptimizeImportsProcessor(Project project, PsiDirectory directory, boolean includeSubdirs) {
super(project, directory, includeSubdirs, PROGRESS_TEXT, COMMAND_NAME);
public ReformatAndOptimizeImportsProcessor(Project project,
PsiDirectory directory,
boolean includeSubdirs,
boolean processChangedTextOnly)
{
super(project, directory, includeSubdirs, PROGRESS_TEXT, COMMAND_NAME, processChangedTextOnly);
myOptimizeImportsProcessor = new OptimizeImportsProcessor(project, directory, includeSubdirs);
myReformatCodeProcessor = new ReformatCodeProcessor(project, directory, includeSubdirs);
myReformatCodeProcessor = new ReformatCodeProcessor(project, directory, includeSubdirs, processChangedTextOnly);
}
public ReformatAndOptimizeImportsProcessor(Project project, PsiFile file) {
super(project, file, PROGRESS_TEXT, COMMAND_NAME);
public ReformatAndOptimizeImportsProcessor(Project project, PsiFile file, boolean processChangedTextOnly) {
super(project, file, PROGRESS_TEXT, COMMAND_NAME, processChangedTextOnly);
myOptimizeImportsProcessor = new OptimizeImportsProcessor(project, file);
myReformatCodeProcessor = new ReformatCodeProcessor(project, file, null);
myReformatCodeProcessor = new ReformatCodeProcessor(project, file, null, processChangedTextOnly);
}
@NotNull
protected FutureTask<Boolean> preprocessFile(PsiFile file) throws IncorrectOperationException {
final FutureTask<Boolean> reformatTask = myReformatCodeProcessor.preprocessFile(file);
final FutureTask<Boolean> optimizeImportsTask = myOptimizeImportsProcessor.preprocessFile(file);
protected FutureTask<Boolean> preprocessFile(@NotNull PsiFile file, boolean processChangedTextOnly) throws IncorrectOperationException {
final FutureTask<Boolean> reformatTask = myReformatCodeProcessor.preprocessFile(file, processChangedTextOnly);
final FutureTask<Boolean> optimizeImportsTask = myOptimizeImportsProcessor.preprocessFile(file, false);
return new FutureTask<Boolean>(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -75,20 +75,22 @@ public class ReformatCodeAction extends AnAction implements DumbAware {
else if (areFiles(files)) {
final ReadonlyStatusHandler.OperationStatus operationStatus = ReadonlyStatusHandler.getInstance(project).ensureFilesWritable(files);
if (!operationStatus.hasReadonlyFiles()) {
final ReformatFilesDialog reformatFilesDialog = new ReformatFilesDialog(project);
final ReformatFilesDialog reformatFilesDialog = new ReformatFilesDialog(project, files);
reformatFilesDialog.show();
if (!reformatFilesDialog.isOK()) return;
if (reformatFilesDialog.optimizeImports() && !DumbService.getInstance(project).isDumb()) {
new ReformatAndOptimizeImportsProcessor(project, convertToPsiFiles(files, project)).run();
new ReformatAndOptimizeImportsProcessor(
project, convertToPsiFiles(files, project), reformatFilesDialog.isProcessOnlyChangedText()
).run();
}
else {
new ReformatCodeProcessor(project, convertToPsiFiles(files, project), null).run();
new ReformatCodeProcessor(project, convertToPsiFiles(files, project), null, reformatFilesDialog.isProcessOnlyChangedText()).run();
}
}
return;
}
else{
else {
Project projectContext = PlatformDataKeys.PROJECT_CONTEXT.getData(dataContext);
Module moduleContext = LangDataKeys.MODULE_CONTEXT.getData(dataContext);
@@ -98,26 +100,27 @@ public class ReformatCodeAction extends AnAction implements DumbAware {
text = CodeInsightBundle.message("process.scope.module", moduleContext.getModuleFilePath());
}
else {
text = CodeInsightBundle.message("process.scope.project", projectContext.getPresentableUrl());
text = CodeInsightBundle.message("process.scope.project", project.getPresentableUrl());
}
LayoutProjectCodeDialog dialog = new LayoutProjectCodeDialog(project, CodeInsightBundle.message("process.reformat.code"), text, true);
LayoutProjectCodeDialog dialog
= new LayoutProjectCodeDialog(project, moduleContext, CodeInsightBundle.message("process.reformat.code"), text, true);
dialog.show();
if (!dialog.isOK()) return;
if (dialog.isOptimizeImports() && !DumbService.getInstance(project).isDumb()) {
if (moduleContext != null) {
new ReformatAndOptimizeImportsProcessor(project, moduleContext).run();
new ReformatAndOptimizeImportsProcessor(project, moduleContext, dialog.isProcessOnlyChangedText()).run();
}
else {
new ReformatAndOptimizeImportsProcessor(projectContext).run();
new ReformatAndOptimizeImportsProcessor(project, dialog.isProcessOnlyChangedText()).run();
}
}
else {
if (moduleContext != null) {
new ReformatCodeProcessor(project, moduleContext).run();
new ReformatCodeProcessor(project, moduleContext, dialog.isProcessOnlyChangedText()).run();
}
else {
new ReformatCodeProcessor(projectContext).run();
new ReformatCodeProcessor(project, dialog.isProcessOnlyChangedText()).run();
}
}
return;
@@ -140,6 +143,7 @@ public class ReformatCodeAction extends AnAction implements DumbAware {
boolean optimizeImports = ReformatFilesDialog.isOptmizeImportsOptionOn();
boolean processWholeFile = false;
boolean processChangedTextOnly = false;
if (EditorSettingsExternalizable.getInstance().getOptions().SHOW_REFORMAT_DIALOG || (file == null && dir != null)) {
final LayoutCodeDialog dialog = new LayoutCodeDialog(project, CodeInsightBundle.message("process.reformat.code"), file, dir,
hasSelection ? Boolean.TRUE : Boolean.FALSE, HELP_ID);
@@ -149,12 +153,14 @@ public class ReformatCodeAction extends AnAction implements DumbAware {
updateShowDialogSetting(dialog, "\"Reformat Code\" dialog disabled");
optimizeImports = dialog.isOptimizeImports();
processWholeFile = dialog.isProcessWholeFile();
processChangedTextOnly = dialog.isProcessOnlyChangedText();
if (dialog.isProcessDirectory()){
if (optimizeImports) {
new ReformatAndOptimizeImportsProcessor(project, dir, dialog.isIncludeSubdirectories()).run();
new ReformatAndOptimizeImportsProcessor(project, dir, dialog.isIncludeSubdirectories(), processChangedTextOnly).run();
}
else {
new ReformatCodeProcessor(project, dir, dialog.isIncludeSubdirectories()).run();
new ReformatCodeProcessor(project, dir, dialog.isIncludeSubdirectories(), processChangedTextOnly).run();
}
return;
}
@@ -170,14 +176,14 @@ public class ReformatCodeAction extends AnAction implements DumbAware {
if (optimizeImports && range == null) {
if (file != null || dir == null) {
new ReformatAndOptimizeImportsProcessor(project, file).run();
new ReformatAndOptimizeImportsProcessor(project, file, processChangedTextOnly).run();
}
else {
new ReformatAndOptimizeImportsProcessor(project, dir, true).run();
new ReformatAndOptimizeImportsProcessor(project, dir, true, processChangedTextOnly).run();
}
}
else {
new ReformatCodeProcessor(project, file, range).run();
new ReformatCodeProcessor(project, file, range, processChangedTextOnly).run();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,7 +27,10 @@ import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
@@ -37,53 +40,66 @@ public class ReformatCodeProcessor extends AbstractLayoutCodeProcessor {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.actions.ReformatCodeProcessor");
private final TextRange myRange;
private final Collection<TextRange> myRanges = new ArrayList<TextRange>();
private static final String PROGRESS_TEXT = CodeInsightBundle.message("reformat.progress.common.text");
public ReformatCodeProcessor(Project project) {
super(project, COMMAND_NAME, PROGRESS_TEXT);
myRange = null;
public ReformatCodeProcessor(Project project, boolean processChangedTextOnly) {
super(project, COMMAND_NAME, PROGRESS_TEXT, processChangedTextOnly);
}
public ReformatCodeProcessor(Project project, Module module) {
super(project, module, COMMAND_NAME, PROGRESS_TEXT);
myRange = null;
public ReformatCodeProcessor(Project project, Module module, boolean processChangedTextOnly) {
super(project, module, COMMAND_NAME, PROGRESS_TEXT, processChangedTextOnly);
}
public ReformatCodeProcessor(Project project, PsiDirectory directory, boolean includeSubdirs) {
super(project, directory, includeSubdirs, PROGRESS_TEXT, COMMAND_NAME);
myRange = null;
public ReformatCodeProcessor(Project project, PsiDirectory directory, boolean includeSubdirs, boolean processChangedTextOnly) {
super(project, directory, includeSubdirs, PROGRESS_TEXT, COMMAND_NAME, processChangedTextOnly);
}
public ReformatCodeProcessor(Project project, PsiFile file, TextRange range) {
super(project, file, PROGRESS_TEXT, COMMAND_NAME);
myRange = range;
public ReformatCodeProcessor(Project project, PsiFile file, @Nullable TextRange range, boolean processChangedTextOnly) {
super(project, file, PROGRESS_TEXT, COMMAND_NAME, processChangedTextOnly);
if (range != null) {
myRanges.add(range);
}
}
public ReformatCodeProcessor(Project project, PsiFile[] files, Runnable postRunnable) {
this(project, files, COMMAND_NAME, postRunnable);
public ReformatCodeProcessor(Project project, PsiFile[] files, Runnable postRunnable, boolean processChangedTextOnly) {
this(project, files, COMMAND_NAME, postRunnable, processChangedTextOnly);
}
public ReformatCodeProcessor(Project project, PsiFile[] files, String commandName, Runnable postRunnable) {
super(project, files, PROGRESS_TEXT, commandName, postRunnable);
myRange = null;
public ReformatCodeProcessor(Project project,
PsiFile[] files,
String commandName,
Runnable postRunnable,
boolean processChangedTextOnly)
{
super(project, files, PROGRESS_TEXT, commandName, postRunnable, processChangedTextOnly);
}
@NotNull
protected FutureTask<Boolean> preprocessFile(final PsiFile file) throws IncorrectOperationException {
protected FutureTask<Boolean> preprocessFile(@NotNull final PsiFile file, final boolean processChangedTextOnly)
throws IncorrectOperationException
{
return new FutureTask<Boolean>(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
FormattingProgressTask.FORMATTING_CANCELLED_FLAG.set(false);
try {
TextRange range = myRange == null ? file.getTextRange() : myRange;
CodeStyleManager.getInstance(myProject).reformatText(file, range.getStartOffset(), range.getEndOffset());
if (myRanges.isEmpty() && processChangedTextOnly) {
myRanges.addAll(FormatChangedTextUtil.getChanges(file));
}
if (myRanges.isEmpty()) {
myRanges.add(file.getTextRange());
}
CodeStyleManager.getInstance(myProject).reformatText(file, myRanges);
return !FormattingProgressTask.FORMATTING_CANCELLED_FLAG.get();
}
catch (IncorrectOperationException e) {
LOG.error(e);
return false;
}
finally {
myRanges.clear();
}
}
});
}
@@ -1,27 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.codeInsight.actions.ReformatFilesDialog">
<grid id="59847" binding="myPanel" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="59847" binding="myPanel" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="4" bottom="0" right="0"/>
<constraints>
<xy x="30" y="17" width="179" height="94"/>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3"/>
<xy x="30" y="17" width="196" height="104"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<grid id="e83d0" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="e83d0" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="4" y="0" width="119" height="94"/>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3"/>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="cb57" class="javax.swing.JLabel">
<constraints>
<xy x="0" y="3" width="119" height="14"/>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0"/>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="messages/CodeInsightBundle" key="dialog.reformat.files.reformat.selected.files.label"/>
@@ -29,8 +26,7 @@
</component>
<component id="4c38e" class="javax.swing.JCheckBox" binding="myOptimizeImports">
<constraints>
<xy x="0" y="25" width="105" height="22"/>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0"/>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="messages/CodeInsightBundle" key="dialog.reformat.files.optimize.imports.checkbox"/>
@@ -38,16 +34,22 @@
</component>
<vspacer id="8d758">
<constraints>
<xy x="54" y="47" width="11" height="47"/>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2"/>
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<component id="a0a79" class="javax.swing.JCheckBox" binding="myOnlyChangedText">
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="messages/CodeInsightBundle" key="reformat.option.vcs.changed.region"/>
</properties>
</component>
</children>
</grid>
<hspacer id="c7098">
<constraints>
<xy x="123" y="41" width="56" height="11"/>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1"/>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</hspacer>
</children>
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,17 +20,34 @@ import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
public class ReformatFilesDialog extends DialogWrapper {
private JPanel myPanel;
private JCheckBox myOptimizeImports;
private JCheckBox myOnlyChangedText;
private final VirtualFile[] myFiles;
public ReformatFilesDialog(Project project) {
public ReformatFilesDialog(@NotNull Project project, @NotNull VirtualFile[] files) {
super(project, true);
myFiles = files;
setTitle(CodeInsightBundle.message("dialog.reformat.files.title"));
myOptimizeImports.setSelected(isOptmizeImportsOptionOn());
boolean canTargetVcsChanges = false;
for (VirtualFile file : files) {
if (FormatChangedTextUtil.hasChanges(file, project)) {
canTargetVcsChanges = true;
break;
}
}
myOnlyChangedText.setEnabled(canTargetVcsChanges);
myOnlyChangedText.setSelected(
canTargetVcsChanges && PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, false)
);
myOptimizeImports.setSelected(isOptmizeImportsOptionOn());
init();
}
@@ -42,13 +59,19 @@ public class ReformatFilesDialog extends DialogWrapper {
return myOptimizeImports.isSelected();
}
public boolean isProcessOnlyChangedText() {
return myOnlyChangedText.isEnabled() && myOnlyChangedText.isSelected();
}
protected void doOKAction() {
PropertiesComponent.getInstance().setValue(LayoutCodeDialog.OPTIMIZE_IMPORTS_KEY, Boolean.toString(myOptimizeImports.isSelected()));
super.doOKAction();
PropertiesComponent.getInstance().setValue(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, Boolean.toString(myOptimizeImports.isSelected()));
PropertiesComponent.getInstance().setValue(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY,
Boolean.toString(myOnlyChangedText.isSelected()));
}
static boolean isOptmizeImportsOptionOn() {
return Boolean.valueOf(PropertiesComponent.getInstance().getValue(LayoutCodeDialog.OPTIMIZE_IMPORTS_KEY));
return PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, false);
}
}
@@ -0,0 +1,48 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.completion;
import com.intellij.openapi.util.Ref;
import com.intellij.util.Consumer;
/**
* @author Dmitry Avdeev
* Date: 12/19/11
*/
public abstract class NoVariantsDelegator extends CompletionContributor {
@Override
public void fillCompletionVariants(final CompletionParameters parameters, final CompletionResultSet result) {
final Ref<Boolean> empty = Ref.create(true);
Consumer<CompletionResult> passResult = new Consumer<CompletionResult>() {
public void consume(final CompletionResult lookupElement) {
empty.set(false);
result.passResult(lookupElement);
}
};
result.runRemainingContributors(parameters, passResult);
if (!empty.get() && parameters.getInvocationCount() == 0) {
result.restartCompletionWhenNothingMatches();
}
if (empty.get()) {
delegate(parameters, result, passResult);
}
}
protected abstract void delegate(CompletionParameters parameters, CompletionResultSet result, Consumer<CompletionResult> passResult);
}
@@ -31,6 +31,7 @@ import com.intellij.ide.PowerSaveMode;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.components.ProjectComponent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
@@ -695,10 +696,16 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
// we'll restart when write action finish
return;
}
if (PsiDocumentManager.getInstance(myProject).hasUncommitedDocuments()) {
((PsiDocumentManagerImpl)PsiDocumentManager.getInstance(myProject)).cancelAndRunWhenAllCommitted(
"restart daemon when all committed", this);
return;
PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject);
if (documentManager.hasUncommitedDocuments()) {
if (ModalityState.current() == ModalityState.NON_MODAL) {
((PsiDocumentManagerImpl)documentManager).cancelAndRunWhenAllCommitted("restart daemon when all committed", this);
return;
}
else {
// when modal dialog is open, DocumentCommitThread is not able to commit in background, so force commit here
documentManager.commitAllDocuments();
}
}
Map<FileEditor, HighlightingPass[]> passes = new THashMap<FileEditor, HighlightingPass[]>(activeEditors.size());
@@ -297,7 +297,8 @@ public class DocumentationManager {
}
}, keyboardShortcut != null ? keyboardShortcut.getFirstKeyStroke() : null)); // Null keyStroke is ok here
final JBPopup hint = JBPopupFactory.getInstance().createComponentPopupBuilder(component, component)
boolean hasLookup = LookupManager.getActiveLookup(myEditor) != null;
final JBPopup hint = JBPopupFactory.getInstance().createComponentPopupBuilder(component, component)
.setRequestFocusCondition(project, NotLookupOrSearchCondition.INSTANCE)
.setProject(project)
.addListener(updateProcessor)
@@ -308,6 +309,7 @@ public class DocumentationManager {
.setResizable(true)
.setMovable(true)
.setRequestFocus(requestFocus)
.setCancelOnClickOutside(!hasLookup) // otherwise selecting lookup items by mouse would close the doc
.setTitle(getTitle(element, false))
.setCouldPin(pinCallback)
.setCancelCallback(new Computable<Boolean>() {
@@ -29,6 +29,7 @@ import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ex.util.EditorUtil;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
@@ -40,7 +41,9 @@ import java.util.Map;
public class ListTemplatesHandler implements CodeInsightActionHandler {
public void invoke(@NotNull final Project project, @NotNull final Editor editor, @NotNull PsiFile file) {
if (!file.isWritable()) return;
if (!FileDocumentManager.getInstance().requestWriting(editor.getDocument(), project)) {
return;
}
EditorUtil.fillVirtualSpaceUntilCaret(editor);
PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument());
@@ -22,6 +22,7 @@ import com.intellij.ide.projectView.impl.ProjectRootsUtil;
import com.intellij.ide.structureView.StructureView;
import com.intellij.ide.structureView.StructureViewBuilder;
import com.intellij.ide.structureView.StructureViewWrapper;
import com.intellij.ide.structureView.impl.StructureViewComposite;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ModalityState;
@@ -43,6 +44,9 @@ import com.intellij.openapi.wm.ToolWindowId;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.openapi.wm.ex.IdeFocusTraversalPolicy;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.ui.content.Content;
import com.intellij.ui.content.ContentFactory;
import com.intellij.ui.content.ContentManager;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.update.MergingUpdateQueue;
import com.intellij.util.ui.update.Update;
@@ -59,13 +63,14 @@ import java.awt.event.HierarchyListener;
*/
public class StructureViewWrapperImpl implements StructureViewWrapper, Disposable {
private final Project myProject;
private final ToolWindow myToolWindow;
private VirtualFile myFile;
private StructureView myStructureView;
private ModuleStructureComponent myModuleStructureComponent;
private final JPanel myPanel;
private JPanel[] myPanels = new JPanel[0];
private final MergingUpdateQueue myUpdateQueue;
private final String myKey = new String("DATA_SELECTOR");
@@ -75,17 +80,16 @@ public class StructureViewWrapperImpl implements StructureViewWrapper, Disposabl
private Runnable myPendingSelection;
public StructureViewWrapperImpl(Project project) {
public StructureViewWrapperImpl(Project project, ToolWindow toolWindow) {
myProject = project;
myPanel = new ContentPanel();
myPanel.setBackground(UIUtil.getTreeTextBackground());
myUpdateQueue = new MergingUpdateQueue("StructureView", Registry.intValue("structureView.coalesceTime"), false, myPanel, this, myPanel, true);
myToolWindow = toolWindow;
myUpdateQueue = new MergingUpdateQueue("StructureView", Registry.intValue("structureView.coalesceTime"), false, myToolWindow.getComponent(), this, myToolWindow.getComponent(), true);
myUpdateQueue.setRestartTimerOnAdd(true);
ActionManager.getInstance().addTimerListener(500, new TimerListener() {
public ModalityState getModalityState() {
return ModalityState.stateForComponent(myPanel);
return ModalityState.stateForComponent(myToolWindow.getComponent());
}
public void run() {
@@ -93,20 +97,21 @@ public class StructureViewWrapperImpl implements StructureViewWrapper, Disposabl
}
});
getComponent().addHierarchyListener(new HierarchyListener() {
myToolWindow.getComponent().addHierarchyListener(new HierarchyListener() {
public void hierarchyChanged(HierarchyEvent e) {
if ((e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0) {
scheduleRebuild();
}
}
});
Disposer.register(myToolWindow.getContentManager(), this);
}
private void checkUpdate() {
if (myProject.isDisposed()) return;
final Component owner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
if (SwingUtilities.isDescendingFrom(myPanel, owner) || JBPopupFactory.getInstance().isPopupActive()) return;
if (SwingUtilities.isDescendingFrom(myToolWindow.getComponent(), owner) || JBPopupFactory.getInstance().isPopupActive()) return;
final DataContext dataContext = DataManager.getInstance().getDataContext(owner);
if (dataContext.getData(myKey) == this) return;
@@ -133,10 +138,6 @@ public class StructureViewWrapperImpl implements StructureViewWrapper, Disposabl
// StructureView interface implementation
// -------------------------------------------------------------------------
public JComponent getComponent() {
return myPanel;
}
public void dispose() {
rebuild();
}
@@ -202,8 +203,8 @@ public class StructureViewWrapperImpl implements StructureViewWrapper, Disposabl
myModuleStructureComponent = null;
}
myPanel.removeAll();
final ContentManager contentManager = myToolWindow.getContentManager();
contentManager.removeAllContents(true);
if (!isStructureViewShowing()) {
return;
}
@@ -216,19 +217,16 @@ public class StructureViewWrapperImpl implements StructureViewWrapper, Disposabl
}
}
String[] names = new String[] {""};
JComponent focusedComponent = null;
if (file != null && file.isValid()) {
if (file.isDirectory()) {
if (ProjectRootsUtil.isModuleContentRoot(file, myProject)) {
Module module = ModuleUtil.findModuleForFile(file, myProject);
if (module != null) {
myModuleStructureComponent = new ModuleStructureComponent(module);
myPanel.add(myModuleStructureComponent, BorderLayout.CENTER);
if (hadFocus) {
JComponent focusedComponent = IdeFocusTraversalPolicy.getPreferredFocusedComponent(myModuleStructureComponent);
if (focusedComponent != null) {
IdeFocusManager.getInstance(myProject).requestFocus(focusedComponent, true);
}
}
focusedComponent = hadFocus ? IdeFocusTraversalPolicy.getPreferredFocusedComponent(myModuleStructureComponent) : null;
createSinglePanel(myModuleStructureComponent.getComponent());
}
}
}
@@ -246,13 +244,22 @@ public class StructureViewWrapperImpl implements StructureViewWrapper, Disposabl
if (myStructureView instanceof StructureView.Scrollable) {
((StructureView.Scrollable)myStructureView).setReferenceSizeWhileInitializing(referenceSize);
}
myPanel.add(myStructureView.getComponent(), BorderLayout.CENTER);
if (hadFocus) {
JComponent focusedComponent = IdeFocusTraversalPolicy.getPreferredFocusedComponent(myStructureView.getComponent());
if (focusedComponent != null) {
IdeFocusManager.getInstance(myProject).requestFocus(focusedComponent, true);
final StructureViewComposite.StructureViewDescriptor[] views;
if (myStructureView instanceof StructureViewComposite) {
final StructureViewComposite composite = (StructureViewComposite)myStructureView;
views = composite.getStructureViews();
myPanels = new JPanel[views.length];
names = new String[views.length];
for (int i = 0; i < myPanels.length; i++) {
myPanels[i] = createContentPanel(views[i].structureView.getComponent());
names[i] = views[i].title;
}
} else {
createSinglePanel(myStructureView.getComponent());
}
focusedComponent = hadFocus ? IdeFocusTraversalPolicy.getPreferredFocusedComponent(myStructureView.getComponent()) : null;
myStructureView.restoreState();
myStructureView.centerSelectedRow();
}
@@ -264,11 +271,19 @@ public class StructureViewWrapperImpl implements StructureViewWrapper, Disposabl
}
if (myModuleStructureComponent == null && myStructureView == null) {
myPanel.add(new JLabel(IdeBundle.message("message.nothing.to.show.in.structure.view"), SwingConstants.CENTER), BorderLayout.CENTER);
createSinglePanel(new JLabel(IdeBundle.message("message.nothing.to.show.in.structure.view"), SwingConstants.CENTER));
}
myPanel.validate();
myPanel.repaint();
for (int i = 0; i < myPanels.length; i++) {
final Content content = ContentFactory.SERVICE.getInstance().createContent(myPanels[i], names[i], false);
contentManager.addContent(content);
if (i == 0 && myStructureView != null) {
Disposer.register(content, myStructureView);
}
}
if (hadFocus && focusedComponent != null) {
IdeFocusManager.getInstance(myProject).requestFocus(focusedComponent, true);
}
if (myPendingSelection != null) {
Runnable selection = myPendingSelection;
@@ -277,6 +292,18 @@ public class StructureViewWrapperImpl implements StructureViewWrapper, Disposabl
}
}
private void createSinglePanel(final JComponent component) {
myPanels = new JPanel[1];
myPanels[0] = createContentPanel(component);
}
private ContentPanel createContentPanel(JComponent component) {
final ContentPanel panel = new ContentPanel();
panel.setBackground(UIUtil.getTreeTextBackground());
panel.add(component, BorderLayout.CENTER);
return panel;
}
@Nullable
private FileEditor createTempFileEditor(VirtualFile file) {
FileEditorProviderManager editorProviderManager = FileEditorProviderManager.getInstance();
@@ -20,12 +20,9 @@ import com.intellij.ide.structureView.StructureView;
import com.intellij.ide.structureView.StructureViewModel;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.util.Disposer;
import com.intellij.ui.TabbedPaneWrapper;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
/**
* @author cdr
@@ -33,8 +30,6 @@ import javax.swing.event.ChangeListener;
public class StructureViewComposite implements StructureView {
@NotNull private final StructureViewDescriptor[] myStructureViews;
@NotNull private StructureViewDescriptor mySelectedViewDescriptor;
@NotNull private final TabbedPaneWrapper myTabbedPaneWrapper;
public static class StructureViewDescriptor {
public final String title;
public final StructureView structureView;
@@ -53,17 +48,6 @@ public class StructureViewComposite implements StructureView {
Disposer.register(this, descriptor.structureView);
}
mySelectedViewDescriptor = views[0];
myTabbedPaneWrapper = new TabbedPaneWrapper(this);
for (StructureViewDescriptor descriptor : views) {
myTabbedPaneWrapper.addTab(descriptor.title, descriptor.icon, descriptor.structureView.getComponent(), null);
}
myTabbedPaneWrapper.setSelectedIndex(0);
myTabbedPaneWrapper.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
int index = myTabbedPaneWrapper.getSelectedIndex();
mySelectedViewDescriptor = myStructureViews[index];
}
});
}
public StructureView getSelectedStructureView() {
@@ -84,7 +68,7 @@ public class StructureViewComposite implements StructureView {
}
public JComponent getComponent() {
return myTabbedPaneWrapper.getComponent();
return mySelectedViewDescriptor.structureView.getComponent();
}
public void dispose() {
@@ -25,14 +25,11 @@ import com.intellij.openapi.components.Storage;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.MultiValuesMap;
import com.intellij.openapi.util.NotNullLazyValue;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.psi.PsiElement;
import com.intellij.ui.content.Content;
import com.intellij.ui.content.ContentFactory;
import com.intellij.util.ReflectionCache;
import org.jetbrains.annotations.NotNull;
@@ -96,11 +93,7 @@ public final class StructureViewFactoryImpl extends StructureViewFactoryEx imple
}
public void initToolWindow(ToolWindow toolWindow) {
myStructureViewWrapperImpl = new StructureViewWrapperImpl(myProject);
final Content content = ContentFactory.SERVICE.getInstance().createContent(myStructureViewWrapperImpl.getComponent(), "", false);
Disposer.register(content, myStructureViewWrapperImpl);
toolWindow.getContentManager().addContent(content);
myStructureViewWrapperImpl = new StructureViewWrapperImpl(myProject, toolWindow);
if (myRunWhenInitialized != null) {
myRunWhenInitialized.run();
myRunWhenInitialized = null;
@@ -18,13 +18,15 @@ package com.intellij.injected.editor;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.LogicalPosition;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.editor.event.DocumentListener;
import com.intellij.openapi.editor.ex.DocumentEx;
import com.intellij.openapi.editor.ex.EditReadOnlyListener;
import com.intellij.openapi.editor.ex.LineIterator;
import com.intellij.openapi.editor.ex.RangeMarkerEx;
import com.intellij.openapi.editor.impl.DocumentImpl;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.ProperTextRange;
import com.intellij.openapi.util.TextRange;
@@ -46,21 +48,24 @@ import java.util.List;
* @author Alexey
*/
public class DocumentWindowImpl extends UserDataHolderBase implements Disposable, DocumentWindow, DocumentEx {
private static final Logger LOG = Logger.getInstance("com.intellij.openapi.editor.impl.injected.DocumentRangee");
private static final Logger LOG = Logger.getInstance("#com.intellij.injected.editor.DocumentWindowImpl");
private final DocumentEx myDelegate;
private final boolean myOneLine;
private Place myShreds;
private Place myShreds; // guarded by myLock
private final int myPrefixLineCount;
private final int mySuffixLineCount;
private final Object myLock = new Object();
private CachedText myCachedText = null;
public DocumentWindowImpl(@NotNull DocumentEx delegate, boolean oneLine, Place shreds) {
myDelegate = delegate;
myOneLine = oneLine;
myShreds = shreds;
myPrefixLineCount = Math.max(1, 1 + StringUtil.countNewLines(myShreds.get(0).prefix));
mySuffixLineCount = Math.max(1, 1 + StringUtil.countNewLines(myShreds.get(shreds.size()- 1).suffix));
synchronized (myLock) {
myShreds = shreds;
}
myPrefixLineCount = Math.max(1, 1 + StringUtil.countNewLines(shreds.get(0).prefix));
mySuffixLineCount = Math.max(1, 1 + StringUtil.countNewLines(shreds.get(shreds.size()- 1).suffix));
}
@Nullable("null means we were unable to calculate")
@@ -70,20 +75,22 @@ public class DocumentWindowImpl extends UserDataHolderBase implements Disposable
int iLineStartOffset = hostToInjected(hLineStartOffset);
int iLine = getLineNumber(iLineStartOffset);
for (int i = myShreds.size() - 1; i >= 0; i--) {
PsiLanguageInjectionHost.Shred shred = myShreds.get(i);
if (!shred.isValid()) continue;
int hShredEndOffset = shred.getHostRangeMarker().getEndOffset();
int hShredStartOffset = shred.getHostRangeMarker().getStartOffset();
synchronized (myLock) {
for (int i = myShreds.size() - 1; i >= 0; i--) {
PsiLanguageInjectionHost.Shred shred = myShreds.get(i);
if (!shred.isValid()) continue;
int hShredEndOffset = shred.getHostRangeMarker().getEndOffset();
int hShredStartOffset = shred.getHostRangeMarker().getStartOffset();
int hShredStartLine = myDelegate.getLineNumber(hShredStartOffset);
int hShredEndLine = myDelegate.getLineNumber(hShredEndOffset);
int hShredStartLine = myDelegate.getLineNumber(hShredStartOffset);
int hShredEndLine = myDelegate.getLineNumber(hShredEndOffset);
if (hShredStartLine <= hPos.line && hPos.line <= hShredEndLine) {
int hColumnOfShredEnd = hShredEndOffset - hLineStartOffset;
int iColumnOfShredEnd = hostToInjected(hShredEndOffset) - iLineStartOffset;
int iColumn = iColumnOfShredEnd + hPos.column - hColumnOfShredEnd;
return new LogicalPosition(iLine, iColumn);
if (hShredStartLine <= hPos.line && hPos.line <= hShredEndLine) {
int hColumnOfShredEnd = hShredEndOffset - hLineStartOffset;
int iColumnOfShredEnd = hostToInjected(hShredEndOffset) - iLineStartOffset;
int iColumn = iColumnOfShredEnd + hPos.column - hColumnOfShredEnd;
return new LogicalPosition(iLine, iColumn);
}
}
}
@@ -117,13 +124,29 @@ public class DocumentWindowImpl extends UserDataHolderBase implements Disposable
@Override
public int getLineStartOffset(int line) {
//int oldso = oldso(line);
int newso = newStartOffset(line);
//if (newso != oldso) {
// int i = 0;
//}
LOG.assertTrue(line >= 0, line);
if (line == 0) return 0;
String hostText = myDelegate.getText();
return newso;
int[] pos = new int[2]; // pos[0] = curLine; pos[1] == offset;
synchronized (myLock) {
for (PsiLanguageInjectionHost.Shred shred : myShreds) {
RangeMarker hostRange = shred.getHostRangeMarker();
if (!hostRange.isValid()) continue;
int found = countNewLinesIn(shred.prefix, pos, line);
if (found != -1) return found;
String text = hostText.substring(hostRange.getStartOffset(), hostRange.getEndOffset());
found = countNewLinesIn(text, pos, line);
if (found != -1) return found;
found = countNewLinesIn(shred.suffix, pos, line);
if (found != -1) return found;
}
}
return pos[1];
}
// returns startOffset found, or -1 if need to continue searching
@@ -140,35 +163,6 @@ public class DocumentWindowImpl extends UserDataHolderBase implements Disposable
return -1;
}
private int newStartOffset(int line) {
LOG.assertTrue(line >= 0, line);
if (line == 0) return 0;
String hostText = myDelegate.getText();
int[] pos = new int[2]; // pos[0] = curLine; pos[1] == offset;
for (PsiLanguageInjectionHost.Shred shred : myShreds) {
RangeMarker hostRange = shred.getHostRangeMarker();
if (!hostRange.isValid()) continue;
int found = countNewLinesIn(shred.prefix, pos, line);
if (found != -1) return found;
String text = hostText.substring(hostRange.getStartOffset(), hostRange.getEndOffset());
found = countNewLinesIn(text, pos, line);
if (found != -1) return found;
found = countNewLinesIn(shred.suffix, pos, line);
if (found != -1) return found;
}
return pos[1];
}
private int oldso(int line) {
assert line >= 0 : line;
return new DocumentImpl(getText()).getLineStartOffset(line);
}
@Override
public int getLineEndOffset(int line) {
LOG.assertTrue(line >= 0, line);
@@ -191,12 +185,14 @@ public class DocumentWindowImpl extends UserDataHolderBase implements Disposable
private String calcText() {
StringBuilder text = new StringBuilder();
CharSequence hostText = myDelegate.getCharsSequence();
for (PsiLanguageInjectionHost.Shred shred : myShreds) {
RangeMarker hostRange = shred.getHostRangeMarker();
if (hostRange.isValid()) {
text.append(shred.prefix);
text.append(hostText, hostRange.getStartOffset(), hostRange.getEndOffset());
text.append(shred.suffix);
synchronized (myLock) {
for (PsiLanguageInjectionHost.Shred shred : myShreds) {
RangeMarker hostRange = shred.getHostRangeMarker();
if (hostRange.isValid()) {
text.append(shred.prefix);
text.append(hostText, hostRange.getStartOffset(), hostRange.getEndOffset());
text.append(shred.suffix);
}
}
}
return text.toString();
@@ -223,11 +219,13 @@ public class DocumentWindowImpl extends UserDataHolderBase implements Disposable
@Override
public int getTextLength() {
int length = 0;
for (PsiLanguageInjectionHost.Shred shred : myShreds) {
RangeMarker hostRange = shred.getHostRangeMarker();
length += shred.prefix.length();
length += hostRange.getEndOffset() - hostRange.getStartOffset();
length += shred.suffix.length();
synchronized (myLock) {
for (PsiLanguageInjectionHost.Shred shred : myShreds) {
RangeMarker hostRange = shred.getHostRangeMarker();
length += shred.prefix.length();
length += hostRange.getEndOffset() - hostRange.getStartOffset();
length += shred.suffix.length();
}
}
return length;
}
@@ -236,32 +234,34 @@ public class DocumentWindowImpl extends UserDataHolderBase implements Disposable
public int getLineNumber(int offset) {
int lineNumber = 0;
String hostText = myDelegate.getText();
for (PsiLanguageInjectionHost.Shred shred : myShreds) {
String prefix = shred.prefix;
String suffix = shred.suffix;
lineNumber += StringUtil.getLineBreakCount(prefix.substring(0, Math.min(offset, prefix.length())));
if (offset < prefix.length()) {
return lineNumber;
synchronized (myLock) {
for (PsiLanguageInjectionHost.Shred shred : myShreds) {
String prefix = shred.prefix;
String suffix = shred.suffix;
lineNumber += StringUtil.getLineBreakCount(prefix.substring(0, Math.min(offset, prefix.length())));
if (offset < prefix.length()) {
return lineNumber;
}
offset -= prefix.length();
RangeMarker currentRange = shred.getHostRangeMarker();
if (!currentRange.isValid()) continue;
int rangeLength = currentRange.getEndOffset() - currentRange.getStartOffset();
String rangeText = hostText.substring(currentRange.getStartOffset(), currentRange.getEndOffset());
lineNumber += StringUtil.getLineBreakCount(rangeText.substring(0, Math.min(offset, rangeLength)));
if (offset < rangeLength) {
return lineNumber;
}
offset -= rangeLength;
lineNumber += StringUtil.getLineBreakCount(suffix.substring(0, Math.min(offset, suffix.length())));
if (offset < suffix.length()) {
return lineNumber;
}
offset -= suffix.length();
}
offset -= prefix.length();
RangeMarker currentRange = shred.getHostRangeMarker();
if (!currentRange.isValid()) continue;
int rangeLength = currentRange.getEndOffset() - currentRange.getStartOffset();
String rangeText = hostText.substring(currentRange.getStartOffset(), currentRange.getEndOffset());
lineNumber += StringUtil.getLineBreakCount(rangeText.substring(0, Math.min(offset, rangeLength)));
if (offset < rangeLength) {
return lineNumber;
}
offset -= rangeLength;
lineNumber += StringUtil.getLineBreakCount(suffix.substring(0, Math.min(offset, suffix.length())));
if (offset < suffix.length()) {
return lineNumber;
}
offset -= suffix.length();
}
lineNumber = getLineCount() - 1;
return lineNumber < 0 ? 0 : lineNumber;
@@ -269,18 +269,22 @@ public class DocumentWindowImpl extends UserDataHolderBase implements Disposable
@Override
public TextRange getHostRange(int hostOffset) {
for (PsiLanguageInjectionHost.Shred shred : myShreds) {
RangeMarker currentRange = shred.getHostRangeMarker();
TextRange textRange = ProperTextRange.create(currentRange);
if (textRange.grown(1).contains(hostOffset)) return textRange;
}
synchronized (myLock) {
for (PsiLanguageInjectionHost.Shred shred : myShreds) {
RangeMarker currentRange = shred.getHostRangeMarker();
TextRange textRange = ProperTextRange.create(currentRange);
if (textRange.grown(1).contains(hostOffset)) return textRange;
}
}
return null;
}
@Override
public void insertString(final int offset, @NotNull CharSequence s) {
LOG.assertTrue(offset >= myShreds.get(0).prefix.length(), myShreds.get(0).prefix);
LOG.assertTrue(offset <= getTextLength() - myShreds.get(myShreds.size() - 1).suffix.length(), myShreds.get(myShreds.size() - 1).suffix);
synchronized (myLock) {
LOG.assertTrue(offset >= myShreds.get(0).prefix.length(), myShreds.get(0).prefix);
LOG.assertTrue(offset <= getTextLength() - myShreds.get(myShreds.size() - 1).suffix.length(), myShreds.get(myShreds.size() - 1).suffix);
}
if (isOneLine()) {
s = StringUtil.replace(s.toString(), "\n", "");
}
@@ -292,25 +296,28 @@ public class DocumentWindowImpl extends UserDataHolderBase implements Disposable
assert intersectWithEditable(new TextRange(startOffset, startOffset)) != null;
assert intersectWithEditable(new TextRange(endOffset, endOffset)) != null;
List<TextRange> hostRangesToDelete = new ArrayList<TextRange>(myShreds.size());
List<TextRange> hostRangesToDelete;
synchronized (myLock) {
hostRangesToDelete = new ArrayList<TextRange>(myShreds.size());
int offset = startOffset;
int curRangeStart = 0;
for (PsiLanguageInjectionHost.Shred shred : myShreds) {
curRangeStart += shred.prefix.length();
if (offset < curRangeStart) offset = curRangeStart;
if (offset >= endOffset) break;
RangeMarker hostRange = shred.getHostRangeMarker();
if (!hostRange.isValid()) continue;
int hostRangeLength = hostRange.getEndOffset() - hostRange.getStartOffset();
TextRange range = TextRange.from(curRangeStart, hostRangeLength);
if (range.contains(offset)) {
TextRange rangeToDelete = new TextRange(offset, Math.min(range.getEndOffset(), endOffset));
hostRangesToDelete.add(rangeToDelete.shiftRight(hostRange.getStartOffset() - curRangeStart));
offset = rangeToDelete.getEndOffset();
int offset = startOffset;
int curRangeStart = 0;
for (PsiLanguageInjectionHost.Shred shred : myShreds) {
curRangeStart += shred.prefix.length();
if (offset < curRangeStart) offset = curRangeStart;
if (offset >= endOffset) break;
RangeMarker hostRange = shred.getHostRangeMarker();
if (!hostRange.isValid()) continue;
int hostRangeLength = hostRange.getEndOffset() - hostRange.getStartOffset();
TextRange range = TextRange.from(curRangeStart, hostRangeLength);
if (range.contains(offset)) {
TextRange rangeToDelete = new TextRange(offset, Math.min(range.getEndOffset(), endOffset));
hostRangesToDelete.add(rangeToDelete.shiftRight(hostRange.getStartOffset() - curRangeStart));
offset = rangeToDelete.getEndOffset();
}
curRangeStart += hostRangeLength;
curRangeStart += shred.suffix.length();
}
curRangeStart += hostRangeLength;
curRangeStart += shred.suffix.length();
}
int delta = 0;
@@ -342,30 +349,33 @@ public class DocumentWindowImpl extends UserDataHolderBase implements Disposable
assert intersectWithEditable(new TextRange(startOffset, startOffset)) != null;
assert intersectWithEditable(new TextRange(endOffset, endOffset)) != null;
List<Pair<TextRange,CharSequence>> hostRangesToModify = new ArrayList<Pair<TextRange, CharSequence>>(myShreds.size());
List<Pair<TextRange,CharSequence>> hostRangesToModify;
synchronized (myLock) {
hostRangesToModify = new ArrayList<Pair<TextRange, CharSequence>>(myShreds.size());
int offset = startOffset;
int curRangeStart = 0;
for (int i = 0; i < myShreds.size(); i++) {
PsiLanguageInjectionHost.Shred shred = myShreds.get(i);
curRangeStart += shred.prefix.length();
if (offset < curRangeStart) offset = curRangeStart;
RangeMarker hostRange = shred.getHostRangeMarker();
if (!hostRange.isValid()) continue;
int hostRangeLength = hostRange.getEndOffset() - hostRange.getStartOffset();
TextRange range = TextRange.from(curRangeStart, hostRangeLength);
if (range.contains(offset) || range.getEndOffset() == offset/* in case of inserting at the end*/) {
TextRange rangeToModify = new TextRange(offset, Math.min(range.getEndOffset(), endOffset));
TextRange hostRangeToModify = rangeToModify.shiftRight(hostRange.getStartOffset() - curRangeStart);
CharSequence toReplace = i == myShreds.size() - 1 || range.getEndOffset() + shred.suffix.length() >= endOffset
? s : s.subSequence(0, Math.min(hostRangeToModify.getLength(), s.length()));
s = toReplace == s ? "" : s.subSequence(toReplace.length(), s.length());
hostRangesToModify.add(Pair.create(hostRangeToModify, toReplace));
offset = rangeToModify.getEndOffset();
int offset = startOffset;
int curRangeStart = 0;
for (int i = 0; i < myShreds.size(); i++) {
PsiLanguageInjectionHost.Shred shred = myShreds.get(i);
curRangeStart += shred.prefix.length();
if (offset < curRangeStart) offset = curRangeStart;
RangeMarker hostRange = shred.getHostRangeMarker();
if (!hostRange.isValid()) continue;
int hostRangeLength = hostRange.getEndOffset() - hostRange.getStartOffset();
TextRange range = TextRange.from(curRangeStart, hostRangeLength);
if (range.contains(offset) || range.getEndOffset() == offset/* in case of inserting at the end*/) {
TextRange rangeToModify = new TextRange(offset, Math.min(range.getEndOffset(), endOffset));
TextRange hostRangeToModify = rangeToModify.shiftRight(hostRange.getStartOffset() - curRangeStart);
CharSequence toReplace = i == myShreds.size() - 1 || range.getEndOffset() + shred.suffix.length() >= endOffset
? s : s.subSequence(0, Math.min(hostRangeToModify.getLength(), s.length()));
s = toReplace == s ? "" : s.subSequence(toReplace.length(), s.length());
hostRangesToModify.add(Pair.create(hostRangeToModify, toReplace));
offset = rangeToModify.getEndOffset();
}
curRangeStart += hostRangeLength;
curRangeStart += shred.suffix.length();
if (curRangeStart >= endOffset) break;
}
curRangeStart += hostRangeLength;
curRangeStart += shred.suffix.length();
if (curRangeStart >= endOffset) break;
}
int delta = 0;
@@ -484,18 +494,20 @@ public class DocumentWindowImpl extends UserDataHolderBase implements Disposable
@Override
public void setText(@NotNull CharSequence text) {
LOG.assertTrue(text.toString().startsWith(myShreds.get(0).prefix));
LOG.assertTrue(text.toString().endsWith(myShreds.get(myShreds.size() - 1).suffix));
if (isOneLine()) {
text = StringUtil.replace(text.toString(), "\n", "");
}
String[] changes = calculateMinEditSequence(text.toString());
assert changes.length == myShreds.size();
for (int i = 0; i < changes.length; i++) {
String change = changes[i];
if (change != null) {
RangeMarker hostRange = myShreds.get(i).getHostRangeMarker();
myDelegate.replaceString(hostRange.getStartOffset(), hostRange.getEndOffset(), change);
synchronized (myLock) {
LOG.assertTrue(text.toString().startsWith(myShreds.get(0).prefix));
LOG.assertTrue(text.toString().endsWith(myShreds.get(myShreds.size() - 1).suffix));
if (isOneLine()) {
text = StringUtil.replace(text.toString(), "\n", "");
}
String[] changes = calculateMinEditSequence(text.toString());
assert changes.length == myShreds.size();
for (int i = 0; i < changes.length; i++) {
String change = changes[i];
if (change != null) {
RangeMarker hostRange = myShreds.get(i).getHostRangeMarker();
myDelegate.replaceString(hostRange.getStartOffset(), hostRange.getEndOffset(), change);
}
}
}
}
@@ -503,12 +515,14 @@ public class DocumentWindowImpl extends UserDataHolderBase implements Disposable
@Override
@NotNull
public RangeMarker[] getHostRanges() {
RangeMarker[] markers = new RangeMarker[myShreds.size()];
for (int i = 0; i < myShreds.size(); i++) {
PsiLanguageInjectionHost.Shred shred = myShreds.get(i);
markers[i] = shred.getHostRangeMarker();
synchronized (myLock) {
RangeMarker[] markers = new RangeMarker[myShreds.size()];
for (int i = 0; i < myShreds.size(); i++) {
PsiLanguageInjectionHost.Shred shred = myShreds.get(i);
markers[i] = shred.getHostRangeMarker();
}
return markers;
}
return markers;
}
@Override
@@ -603,20 +617,22 @@ public class DocumentWindowImpl extends UserDataHolderBase implements Disposable
//todo use escaper?
@Override
public int hostToInjected(int hostOffset) {
if (hostOffset < myShreds.get(0).getHostRangeMarker().getStartOffset()) return myShreds.get(0).prefix.length();
int offset = 0;
for (int i = 0; i < myShreds.size(); i++) {
offset += myShreds.get(i).prefix.length();
RangeMarker currentRange = myShreds.get(i).getHostRangeMarker();
RangeMarker nextRange = i == myShreds.size() - 1 ? null : myShreds.get(i + 1).getHostRangeMarker();
if (nextRange == null || hostOffset < nextRange.getStartOffset()) {
if (hostOffset >= currentRange.getEndOffset()) hostOffset = currentRange.getEndOffset();
return offset + hostOffset - currentRange.getStartOffset();
synchronized (myLock) {
if (hostOffset < myShreds.get(0).getHostRangeMarker().getStartOffset()) return myShreds.get(0).prefix.length();
int offset = 0;
for (int i = 0; i < myShreds.size(); i++) {
offset += myShreds.get(i).prefix.length();
RangeMarker currentRange = myShreds.get(i).getHostRangeMarker();
RangeMarker nextRange = i == myShreds.size() - 1 ? null : myShreds.get(i + 1).getHostRangeMarker();
if (nextRange == null || hostOffset < nextRange.getStartOffset()) {
if (hostOffset >= currentRange.getEndOffset()) hostOffset = currentRange.getEndOffset();
return offset + hostOffset - currentRange.getStartOffset();
}
offset += currentRange.getEndOffset() - currentRange.getStartOffset();
offset += myShreds.get(i).suffix.length();
}
offset += currentRange.getEndOffset() - currentRange.getStartOffset();
offset += myShreds.get(i).suffix.length();
return getTextLength() - myShreds.get(myShreds.size() - 1).suffix.length();
}
return getTextLength() - myShreds.get(myShreds.size() - 1).suffix.length();
}
@Override
@@ -627,7 +643,9 @@ public class DocumentWindowImpl extends UserDataHolderBase implements Disposable
// heuristics: return offset closest to the caret
Editor[] editors = EditorFactory.getInstance().getEditors(getDelegate());
for (Editor editor : editors) {
Editor editor = editors.length == 0 ? null : editors[0];
if (editor != null)
{
if (editor instanceof EditorWindow) editor = ((EditorWindow)editor).getDelegate();
int caret = editor.getCaretModel().getOffset();
return Math.abs(caret - offsetInLeftFragment) < Math.abs(caret - offsetInRightFragment) ? offsetInLeftFragment : offsetInRightFragment;
@@ -636,26 +654,28 @@ public class DocumentWindowImpl extends UserDataHolderBase implements Disposable
}
private int injectedToHost(int offset, boolean preferLeftFragment) {
if (offset < myShreds.get(0).prefix.length()) return myShreds.get(0).getHostRangeMarker().getStartOffset();
int prevEnd = 0;
for (int i = 0; i < myShreds.size(); i++) {
RangeMarker currentRange = myShreds.get(i).getHostRangeMarker();
offset -= myShreds.get(i).prefix.length();
int length = currentRange.getEndOffset() - currentRange.getStartOffset();
if (offset < 0) {
return preferLeftFragment ? prevEnd : currentRange.getStartOffset() - 1;
synchronized (myLock) {
if (offset < myShreds.get(0).prefix.length()) return myShreds.get(0).getHostRangeMarker().getStartOffset();
int prevEnd = 0;
for (int i = 0; i < myShreds.size(); i++) {
RangeMarker currentRange = myShreds.get(i).getHostRangeMarker();
offset -= myShreds.get(i).prefix.length();
int length = currentRange.getEndOffset() - currentRange.getStartOffset();
if (offset < 0) {
return preferLeftFragment ? prevEnd : currentRange.getStartOffset() - 1;
}
if (offset == 0) {
return preferLeftFragment && i != 0 ? prevEnd : currentRange.getStartOffset();
}
if (offset < length || offset == length && preferLeftFragment) {
return currentRange.getStartOffset() + offset;
}
offset -= length;
offset -= myShreds.get(i).suffix.length();
prevEnd = currentRange.getEndOffset();
}
if (offset == 0) {
return preferLeftFragment && i != 0 ? prevEnd : currentRange.getStartOffset();
}
if (offset < length || offset == length && preferLeftFragment) {
return currentRange.getStartOffset() + offset;
}
offset -= length;
offset -= myShreds.get(i).suffix.length();
prevEnd = currentRange.getEndOffset();
return myShreds.get(myShreds.size() - 1).getHostRangeMarker().getEndOffset();
}
return myShreds.get(myShreds.size() - 1).getHostRangeMarker().getEndOffset();
}
@Override
@@ -673,7 +693,9 @@ public class DocumentWindowImpl extends UserDataHolderBase implements Disposable
@Override
public int injectedToHostLine(int line) {
if (line < myPrefixLineCount) {
return myDelegate.getLineNumber(myShreds.get(0).getHostRangeMarker().getStartOffset());
synchronized (myLock) {
return myDelegate.getLineNumber(myShreds.get(0).getHostRangeMarker().getStartOffset());
}
}
int lineCount = getLineCount();
if (line > lineCount - mySuffixLineCount) {
@@ -687,145 +709,140 @@ public class DocumentWindowImpl extends UserDataHolderBase implements Disposable
@Override
public boolean containsRange(int start, int end) {
if (end - start > myShreds.get(0).getHostRangeMarker().getEndOffset() - myShreds.get(0).getHostRangeMarker().getStartOffset()) return false;
for (PsiLanguageInjectionHost.Shred shred : myShreds) {
RangeMarker hostRange = shred.getHostRangeMarker();
if (!hostRange.isValid()) continue;
TextRange textRange = ProperTextRange.create(hostRange);
if (textRange.contains(new ProperTextRange(start, end))) return true;
synchronized (myLock) {
if (end - start > myShreds.get(0).getHostRangeMarker().getEndOffset() - myShreds.get(0).getHostRangeMarker().getStartOffset()) return false;
for (PsiLanguageInjectionHost.Shred shred : myShreds) {
RangeMarker hostRange = shred.getHostRangeMarker();
if (!hostRange.isValid()) continue;
TextRange textRange = ProperTextRange.create(hostRange);
if (textRange.contains(new ProperTextRange(start, end))) return true;
}
return false;
}
return false;
}
@Override
@Deprecated
@Nullable
public TextRange intersectWithEditable(@NotNull TextRange rangeToEdit) {
int offset = 0;
int startOffset = -1;
int endOffset = -1;
for (PsiLanguageInjectionHost.Shred shred : myShreds) {
RangeMarker hostRange = shred.getHostRangeMarker();
offset += shred.prefix.length();
int length = hostRange.getEndOffset() - hostRange.getStartOffset();
TextRange intersection = new ProperTextRange(offset, offset + length).intersection(rangeToEdit);
if (intersection != null) {
if (startOffset == -1) {
startOffset = intersection.getStartOffset();
synchronized (myLock) {
int offset = 0;
for (PsiLanguageInjectionHost.Shred shred : myShreds) {
RangeMarker hostRange = shred.getHostRangeMarker();
offset += shred.prefix.length();
int length = hostRange.getEndOffset() - hostRange.getStartOffset();
TextRange intersection = new ProperTextRange(offset, offset + length).intersection(rangeToEdit);
if (intersection != null) {
if (startOffset == -1) {
startOffset = intersection.getStartOffset();
}
endOffset = intersection.getEndOffset();
}
endOffset = intersection.getEndOffset();
offset += length;
offset += shred.suffix.length();
}
offset += length;
offset += shred.suffix.length();
}
if (startOffset == -1) return null;
return new ProperTextRange(startOffset, endOffset);
}
boolean intersects(DocumentWindowImpl documentWindow) {
int i = 0;
int j = 0;
while (i < myShreds.size() && j < documentWindow.myShreds.size()) {
RangeMarker range = myShreds.get(i).getHostRangeMarker();
RangeMarker otherRange = documentWindow.myShreds.get(j).getHostRangeMarker();
if (ProperTextRange.create(range).intersects(ProperTextRange.create(otherRange))) return true;
if (range.getEndOffset() > otherRange.getStartOffset()) i++;
else if (range.getStartOffset() < otherRange.getEndOffset()) j++;
else {
i++;
j++;
}
}
return false;
}
// minimum sequence of text replacement operations for each host range
// result[i] == null means no change
// result[i] == "" means delete
// result[i] == string means replace
public String[] calculateMinEditSequence(String newText) {
String[] result = new String[myShreds.size()];
String hostText = myDelegate.getText();
calculateMinEditSequence(hostText, newText, result, 0, result.length - 1);
for (int i = 0; i < result.length; i++) {
String change = result[i];
if (change == null) continue;
String prefix = myShreds.get(i).prefix;
String suffix = myShreds.get(i).suffix;
assert change.startsWith(prefix) : change + "/" + prefix;
assert change.endsWith(suffix) : change + "/" + suffix;
result[i] = StringUtil.trimEnd(StringUtil.trimStart(change, prefix), suffix);
synchronized (myLock) {
String[] result = new String[myShreds.size()];
String hostText = myDelegate.getText();
calculateMinEditSequence(hostText, newText, result, 0, result.length - 1);
for (int i = 0; i < result.length; i++) {
String change = result[i];
if (change == null) continue;
String prefix = myShreds.get(i).prefix;
String suffix = myShreds.get(i).suffix;
assert change.startsWith(prefix) : change + "/" + prefix;
assert change.endsWith(suffix) : change + "/" + suffix;
result[i] = StringUtil.trimEnd(StringUtil.trimStart(change, prefix), suffix);
}
return result;
}
return result;
}
private String getRangeText(String hostText, int hostNum) {
PsiLanguageInjectionHost.Shred shred = myShreds.get(hostNum);
return shred.prefix +
hostText.substring(shred.getHostRangeMarker().getStartOffset(), shred.getHostRangeMarker().getEndOffset()) +
shred.suffix;
synchronized (myLock) {
PsiLanguageInjectionHost.Shred shred = myShreds.get(hostNum);
return shred.prefix +
hostText.substring(shred.getHostRangeMarker().getStartOffset(), shred.getHostRangeMarker().getEndOffset()) +
shred.suffix;
}
}
private void calculateMinEditSequence(String hostText, String newText, String[] result, int i, int j) {
String rangeText1 = getRangeText(hostText, i);
if (i == j) {
result[i] = rangeText1.equals(newText) ? null : newText;
return;
}
if (StringUtil.startsWith(newText, rangeText1)) {
result[i] = null; //no change
calculateMinEditSequence(hostText, newText.substring(rangeText1.length()), result, i+1, j);
return;
}
String rangeText2 = getRangeText(hostText, j);
if (StringUtil.endsWith(newText, rangeText2)) {
result[j] = null; //no change
calculateMinEditSequence(hostText, newText.substring(0, newText.length() - rangeText2.length()), result, i, j-1);
return;
}
if (i+1 == j) {
String suffix = myShreds.get(i).suffix;
String prefix = myShreds.get(j).prefix;
String separator = suffix + prefix;
if (separator.length() != 0) {
int sep = newText.indexOf(separator);
assert sep != -1;
result[i] = newText.substring(0, sep + suffix.length());
result[j] = newText.substring(sep + suffix.length() + prefix.length(), newText.length());
synchronized (myLock) {
String rangeText1 = getRangeText(hostText, i);
if (i == j) {
result[i] = rangeText1.equals(newText) ? null : newText;
return;
}
String commonPrefix = StringUtil.commonPrefix(rangeText1, newText);
result[i] = commonPrefix;
result[j] = newText.substring(commonPrefix.length());
return;
if (StringUtil.startsWith(newText, rangeText1)) {
result[i] = null; //no change
calculateMinEditSequence(hostText, newText.substring(rangeText1.length()), result, i+1, j);
return;
}
String rangeText2 = getRangeText(hostText, j);
if (StringUtil.endsWith(newText, rangeText2)) {
result[j] = null; //no change
calculateMinEditSequence(hostText, newText.substring(0, newText.length() - rangeText2.length()), result, i, j-1);
return;
}
if (i+1 == j) {
String suffix = myShreds.get(i).suffix;
String prefix = myShreds.get(j).prefix;
String separator = suffix + prefix;
if (!separator.isEmpty()) {
int sep = newText.indexOf(separator);
assert sep != -1;
result[i] = newText.substring(0, sep + suffix.length());
result[j] = newText.substring(sep + suffix.length() + prefix.length(), newText.length());
return;
}
String commonPrefix = StringUtil.commonPrefix(rangeText1, newText);
result[i] = commonPrefix;
result[j] = newText.substring(commonPrefix.length());
return;
}
String middleText = getRangeText(hostText, i + 1);
int m = newText.indexOf(middleText);
if (m != -1) {
result[i] = newText.substring(0, m);
result[i+1] = null;
calculateMinEditSequence(hostText, newText.substring(m+middleText.length(), newText.length()), result, i+2, j);
return;
}
middleText = getRangeText(hostText, j - 1);
m = newText.lastIndexOf(middleText);
if (m != -1) {
result[j] = newText.substring(m+middleText.length());
result[j-1] = null;
calculateMinEditSequence(hostText, newText.substring(0, m), result, i, j-2);
return;
}
result[i] = "";
result[j] = "";
calculateMinEditSequence(hostText, newText, result, i+1, j-1);
}
String middleText = getRangeText(hostText, i + 1);
int m = newText.indexOf(middleText);
if (m != -1) {
result[i] = newText.substring(0, m);
result[i+1] = null;
calculateMinEditSequence(hostText, newText.substring(m+middleText.length(), newText.length()), result, i+2, j);
return;
}
middleText = getRangeText(hostText, j - 1);
m = newText.lastIndexOf(middleText);
if (m != -1) {
result[j] = newText.substring(m+middleText.length());
result[j-1] = null;
calculateMinEditSequence(hostText, newText.substring(0, m), result, i, j-2);
return;
}
result[i] = "";
result[j] = "";
calculateMinEditSequence(hostText, newText, result, i+1, j-1);
}
@Override
public boolean areRangesEqual(@NotNull DocumentWindow otherd) {
DocumentWindowImpl window = (DocumentWindowImpl)otherd;
if (myShreds.size() != window.myShreds.size()) return false;
for (int i = 0; i < myShreds.size(); i++) {
PsiLanguageInjectionHost.Shred shred = myShreds.get(i);
PsiLanguageInjectionHost.Shred otherShred = window.myShreds.get(i);
Place shreds = getShreds();
Place otherShreds = window.getShreds();
if (shreds.size() != otherShreds.size()) return false;
for (int i = 0; i < shreds.size(); i++) {
PsiLanguageInjectionHost.Shred shred = shreds.get(i);
PsiLanguageInjectionHost.Shred otherShred = otherShreds.get(i);
if (!shred.prefix.equals(otherShred.prefix)) return false;
if (!shred.suffix.equals(otherShred.suffix)) return false;
@@ -839,7 +856,9 @@ public class DocumentWindowImpl extends UserDataHolderBase implements Disposable
@Override
public boolean isValid() {
return myShreds.isValid();
synchronized (myLock) {
return myShreds.isValid();
}
}
public boolean equals(Object o) {
@@ -849,7 +868,9 @@ public class DocumentWindowImpl extends UserDataHolderBase implements Disposable
}
public int hashCode() {
return myShreds.get(0).getHostRangeMarker().getStartOffset();
synchronized (myLock) {
return myShreds.get(0).getHostRangeMarker().getStartOffset();
}
}
public boolean isOneLine() {
@@ -858,14 +879,27 @@ public class DocumentWindowImpl extends UserDataHolderBase implements Disposable
@Override
public void dispose() {
for (PsiLanguageInjectionHost.Shred shred : myShreds) {
RangeMarker rangeMarker = shred.getHostRangeMarker();
rangeMarker.dispose();
synchronized (myLock) {
for (PsiLanguageInjectionHost.Shred shred : myShreds) {
RangeMarker rangeMarker = shred.getHostRangeMarker();
rangeMarker.dispose();
}
}
}
public void setShreds(Place shreds) {
myShreds = shreds;
public void setShreds(@NotNull Place shreds) {
synchronized (myLock) {
if (myShreds != shreds) {
myShreds.dispose();
myShreds = shreds;
}
}
}
public Place getShreds() {
synchronized (myLock) {
return myShreds;
}
}
@Override
@@ -39,6 +39,7 @@ import com.intellij.openapi.editor.impl.softwrap.SoftWrapAppliancePlaces;
import com.intellij.openapi.editor.markup.MarkupModel;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
@@ -109,7 +110,7 @@ public class EditorWindow extends UserDataHolderBase implements EditorEx {
Iterator<EditorWindow> iterator = allEditors.iterator();
while (iterator.hasNext()) {
EditorWindow editorWindow = iterator.next();
if (!editorWindow.isValid()/* || myDocumentWindow.intersects(editorWindow.myDocumentWindow)*/) {
if (!editorWindow.isValid()) {
editorWindow.dispose();
InjectedLanguageUtil.clearCaches(editorWindow.myInjectedFile, editorWindow.getDocument());
@@ -185,6 +186,7 @@ public class EditorWindow extends UserDataHolderBase implements EditorEx {
myEditorMouseMotionListeners.clear();
myDisposed = true;
Disposer.dispose(myDocumentWindow);
}
@Override
@@ -84,7 +84,9 @@ public class ReformatBeforeCheckinHandler extends CheckinHandler implements Chec
};
if (reformat(configuration, true)) {
new ReformatCodeProcessor(myProject, BeforeCheckinHandlerUtil.getPsiFiles(myProject, files), COMMAND_NAME, performCheckoutAction).run();
new ReformatCodeProcessor(
myProject, BeforeCheckinHandlerUtil.getPsiFiles(myProject, files), COMMAND_NAME, performCheckoutAction, false
).run();
}
else {
performCheckoutAction.run();
@@ -37,8 +37,12 @@ public class CompositeWhiteSpaceFormattingStrategy implements WhiteSpaceFormatti
private final List<WhiteSpaceFormattingStrategy> myStrategies = new ArrayList<WhiteSpaceFormattingStrategy>();
private boolean myReplaceDefaultStrategy;
public CompositeWhiteSpaceFormattingStrategy(@NotNull Collection<WhiteSpaceFormattingStrategy> strategies) {
myStrategies.addAll(strategies);
public CompositeWhiteSpaceFormattingStrategy(@NotNull Collection<WhiteSpaceFormattingStrategy> strategies)
throws IllegalArgumentException
{
for (WhiteSpaceFormattingStrategy strategy : strategies) {
addStrategy(strategy);
}
}
@Override
@@ -64,9 +68,9 @@ public class CompositeWhiteSpaceFormattingStrategy implements WhiteSpaceFormatti
return myReplaceDefaultStrategy;
}
public void addStrategy(@NotNull WhiteSpaceFormattingStrategy strategy) throws IllegalStateException {
public void addStrategy(@NotNull WhiteSpaceFormattingStrategy strategy) throws IllegalArgumentException {
if (myReplaceDefaultStrategy && strategy.replaceDefaultStrategy()) {
throw new IllegalStateException(String.format(
throw new IllegalArgumentException(String.format(
"Can't combine strategy '%s' with already registered strategies (%s). Reason: given strategy is marked to replace "
+ "all existing strategies but strategy with such characteristics is already registered", strategy, myStrategies
));
@@ -1,122 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.impl.cache.impl;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileFilter;
import com.intellij.psi.PsiBundle;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class VfsIndexer {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.cache.impl.VfsIndexer");
public static VirtualFile[] writeFileIndex(
OutputStream stream,
VirtualFile root,
VirtualFileFilter filter) throws IOException {
List<VirtualFile> result = new ArrayList<VirtualFile>();
ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
if (progress != null){
progress.setText2(PsiBundle.message("psi.scanning.files.in.folder.progress", root.getPresentableUrl()));
}
DataOutputStream out = stream == null ? null : new DataOutputStream(stream);
_writeFileIndex(out, root, filter, result);
if (out != null){
out.flush();
}
return VfsUtil.toVirtualFileArray(result);
}
private static void _writeFileIndex(DataOutputStream out, VirtualFile file, VirtualFileFilter filter, List<VirtualFile> result) throws IOException {
ProgressManager.checkCanceled();
result.add(file);
if (out != null){
out.writeUTF(file.getName());
}
VirtualFile[] children = file.getChildren();
if (children == null) {
if (out != null){
out.writeInt(0);
}
return;
}
int childrenCount = 0;
for (VirtualFile child : children) {
if (filter.accept(child)) childrenCount++;
}
if (out != null){
out.writeInt(childrenCount);
}
for (VirtualFile child : children) {
if (filter.accept(child)) {
_writeFileIndex(out, child, filter, result);
}
}
}
public static VirtualFile[] readFileIndex(
InputStream stream,
VirtualFile root,
VirtualFileFilter filter
) throws IOException {
List<VirtualFile> result = new ArrayList<VirtualFile>();
DataInputStream in = new DataInputStream(stream);
String rootName = in.readUTF();
LOG.assertTrue(root.getName().equals(rootName));
_readFileIndex(in, root, filter, result);
return VfsUtil.toVirtualFileArray(result);
}
private static void _readFileIndex(DataInputStream in, VirtualFile file, VirtualFileFilter filter, List<VirtualFile> result) throws IOException {
ProgressManager.checkCanceled();
result.add(file);
int childrenCount = in.readInt();
if (childrenCount == 0) return;
for (int i = 0; i < childrenCount; i++) {
String name = in.readUTF();
VirtualFile child = file != null ? file.findChild(name) : null;
if (child != null && !filter.accept(child)){
child = null;
}
_readFileIndex(in, child, filter, result);
}
}
}
@@ -319,7 +319,7 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
}
});
}
if (progress != null) {
if (progress != null && progress.isRunning()) {
double fraction = (double)counter.incrementAndGet() / size;
progress.setFraction(fraction);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -48,6 +48,10 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class CodeStyleManagerImpl extends CodeStyleManager {
@@ -137,6 +141,14 @@ public class CodeStyleManagerImpl extends CodeStyleManager {
@Override
public void reformatText(@NotNull PsiFile file, int startOffset, int endOffset) throws IncorrectOperationException {
reformatText(file, Collections.singleton(new TextRange(startOffset, endOffset)));
}
@Override
public void reformatText(@NotNull PsiFile file, @NotNull Collection<TextRange> ranges) throws IncorrectOperationException {
if (ranges.isEmpty()) {
return;
}
ApplicationManager.getApplication().assertWriteAccessAllowed();
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
@@ -150,17 +162,9 @@ public class CodeStyleManagerImpl extends CodeStyleManager {
final CodeFormatterFacade codeFormatter = new CodeFormatterFacade(getSettings());
LOG.assertTrue(file.isValid());
final PsiElement start = findElementInTreeWithFormatterEnabled(file, startOffset);
final PsiElement end = findElementInTreeWithFormatterEnabled(file, endOffset);
if (start != null && !start.isValid()) {
LOG.error("start=" + start + "; file=" + file);
}
if (end != null && !end.isValid()) {
LOG.error("end=" + start + "; end=" + file);
}
Editor editor = PsiUtilBase.findEditor(file);
// There is a possible case that cursor is located at the end of the line that contains only white spaces. For example:
// public void foo() {
// <caret>
@@ -168,7 +172,7 @@ public class CodeStyleManagerImpl extends CodeStyleManager {
// Formatter removes such white spaces, i.e. keeps only line feed symbol. But we want to preserve caret position then.
// So, we check if it should be preserved and restore it after formatting if necessary
int visualColumnToRestore = -1;
if (editor != null) {
Document document = editor.getDocument();
int caretOffset = editor.getCaretModel().getOffset();
@@ -189,23 +193,40 @@ public class CodeStyleManagerImpl extends CodeStyleManager {
visualColumnToRestore = editor.getCaretModel().getVisualPosition().column;
}
}
boolean formatFromStart = startOffset == 0;
boolean formatToEnd = endOffset == file.getTextLength();
final SmartPointerManager smartPointerManager = SmartPointerManager.getInstance(getProject());
final SmartPsiElementPointer startPointer = start == null ? null : smartPointerManager.createSmartPsiElementPointer(start);
final SmartPsiElementPointer endPointer = end == null ? null : smartPointerManager.createSmartPsiElementPointer(end);
codeFormatter.processText(file, new FormatTextRanges(new TextRange(startOffset, endOffset), true), true);
final PsiElement startElement = startPointer == null ? null : startPointer.getElement();
final PsiElement endElement = endPointer == null ? null : endPointer.getElement();
if ((startElement != null || formatFromStart) && (endElement != null || formatToEnd)) {
postProcessText(file, new TextRange(formatFromStart ? 0 : startElement.getTextRange().getStartOffset(),
formatToEnd ? file.getTextLength() : endElement.getTextRange().getEndOffset()));
List<RangeFormatInfo> infos = new ArrayList<RangeFormatInfo>();
for (TextRange range : ranges) {
final PsiElement start = findElementInTreeWithFormatterEnabled(file, range.getStartOffset());
final PsiElement end = findElementInTreeWithFormatterEnabled(file, range.getEndOffset());
if (start != null && !start.isValid()) {
LOG.error("start=" + start + "; file=" + file);
}
if (end != null && !end.isValid()) {
LOG.error("end=" + start + "; end=" + file);
}
boolean formatFromStart = range.getStartOffset() == 0;
boolean formatToEnd = range.getEndOffset() == file.getTextLength();
infos.add(new RangeFormatInfo(
start == null ? null : smartPointerManager.createSmartPsiElementPointer(start),
end == null ? null : smartPointerManager.createSmartPsiElementPointer(end),
formatFromStart,
formatToEnd
));
}
FormatTextRanges formatRanges = new FormatTextRanges();
for (TextRange range : ranges) {
formatRanges.add(range, true);
}
codeFormatter.processText(file, formatRanges, true);
for (RangeFormatInfo info : infos) {
final PsiElement startElement = info.startPointer == null ? null : info.startPointer.getElement();
final PsiElement endElement = info.endPointer == null ? null : info.endPointer.getElement();
if ((startElement != null || info.fromStart) && (endElement != null || info.toEnd)) {
postProcessText(file, new TextRange(info.fromStart ? 0 : startElement.getTextRange().getStartOffset(),
info.toEnd ? file.getTextLength() : endElement.getTextRange().getEndOffset()));
}
}
if (visualColumnToRestore < 0) {
@@ -758,5 +779,23 @@ public class CodeStyleManagerImpl extends CodeStyleManager {
}
});
}
private static class RangeFormatInfo{
public final SmartPsiElementPointer startPointer;
public final SmartPsiElementPointer endPointer;
public final boolean fromStart;
public final boolean toEnd;
RangeFormatInfo(@Nullable SmartPsiElementPointer startPointer,
@Nullable SmartPsiElementPointer endPointer,
boolean fromStart,
boolean toEnd)
{
this.startPointer = startPointer;
this.endPointer = endPointer;
this.fromStart = fromStart;
this.toEnd = toEnd;
}
}
}
@@ -38,10 +38,9 @@ import java.util.List;
* @author cdr
*/
public class InjectedFileViewProvider extends SingleRootFileViewProvider implements FreeThreadedFileViewProvider {
private Place myShreds;
private Project myProject;
private final Object myLock = new Object();
private final DocumentWindow myDocumentWindow;
private final DocumentWindowImpl myDocumentWindow;
private static final ThreadLocal<Boolean> disabledTemporarily = new ThreadLocal<Boolean>(){
@Override
protected Boolean initialValue() {
@@ -52,15 +51,11 @@ public class InjectedFileViewProvider extends SingleRootFileViewProvider impleme
InjectedFileViewProvider(@NotNull PsiManager psiManager,
@NotNull VirtualFileWindow virtualFile,
@NotNull Place shreds,
@NotNull DocumentWindow documentWindow,
@NotNull DocumentWindowImpl documentWindow,
@NotNull Language language) {
super(psiManager, (VirtualFile)virtualFile, true, language);
myDocumentWindow = documentWindow;
synchronized (myLock) {
myShreds = shreds;
myProject = myShreds.get(0).host.getProject();
}
myProject = documentWindow.getShreds().get(0).host.getProject();
}
@Override
@@ -69,11 +64,8 @@ public class InjectedFileViewProvider extends SingleRootFileViewProvider impleme
if (!isPhysical()) return; // injected PSI change happened inside reparse; ignore
if (myPatchingLeaves) return;
List<PsiLanguageInjectionHost.Shred> shreds;
synchronized (myLock) {
shreds = myShreds;
}
DocumentWindowImpl documentWindow = (DocumentWindowImpl)myDocumentWindow;
DocumentWindowImpl documentWindow = myDocumentWindow;
List<PsiLanguageInjectionHost.Shred> shreds = documentWindow.getShreds();
assert documentWindow.getHostRanges().length == shreds.size();
String[] changes = documentWindow.calculateMinEditSequence(psiFile.getNode().getText());
assert changes.length == shreds.size();
@@ -122,11 +114,10 @@ public class InjectedFileViewProvider extends SingleRootFileViewProvider impleme
return file;
}
void setShreds(Place shreds) {
void setShreds(@NotNull Place shreds) {
synchronized (myLock) {
myShreds = new Place(shreds);
myProject = shreds.get(0).host.getProject();
((DocumentWindowImpl)myDocumentWindow).setShreds(myShreds);
myDocumentWindow.setShreds(shreds);
}
}
@@ -141,12 +132,11 @@ public class InjectedFileViewProvider extends SingleRootFileViewProvider impleme
}
Place getShreds() {
synchronized (myLock) {
return myShreds;
}
return myDocumentWindow.getShreds();
}
@Override
@NotNull
public DocumentWindow getDocument() {
return myDocumentWindow;
}
@@ -21,7 +21,6 @@ import com.intellij.lang.Language;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.editor.impl.EditorImpl;
import com.intellij.openapi.fileEditor.FileEditorManager;
@@ -31,7 +30,6 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.*;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiDocumentManagerImpl;
import com.intellij.psi.impl.PsiManagerEx;
import com.intellij.psi.impl.PsiParameterizedCachedValue;
import com.intellij.psi.impl.source.DummyHolder;
@@ -108,7 +106,7 @@ public class InjectedLanguageUtil {
public static Place getShreds(@NotNull FileViewProvider viewProvider) {
if (!(viewProvider instanceof InjectedFileViewProvider)) return null;
InjectedFileViewProvider myFileViewProvider = (InjectedFileViewProvider)viewProvider;
return myFileViewProvider.getShreds();
return ((DocumentWindowImpl)myFileViewProvider.getDocument()).getShreds();
}
public static void enumerate(@NotNull PsiElement host, @NotNull PsiLanguageInjectionHost.InjectedPsiVisitor visitor) {
@@ -330,44 +328,6 @@ public class InjectedLanguageUtil {
file.putUserData(INJECTED_DOCS_KEY, null);
}
public static void commitAllInjectedDocuments(Document hostDocument, Project project) {
PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
PsiFile hostPsiFile = documentManager.getPsiFile(hostDocument);
if (hostPsiFile == null) return;
List<DocumentWindow> injected = getCachedInjectedDocuments(hostPsiFile);
if (injected.isEmpty()) return;
for (int i = injected.size() - 1; i >= 0; i--) {
DocumentWindow documentWindow = injected.get(i);
ProgressManager.checkCanceled();
RangeMarker rangeMarker = documentWindow.getHostRanges()[0];
PsiElement element = rangeMarker.isValid() ? hostPsiFile.findElementAt(rangeMarker.getStartOffset()) : null;
if (element == null) {
injected.remove(i);
continue;
}
final DocumentWindow[] stillInjectedDocument = {null};
// it is here where the reparse happens and old file contents replaced
enumerate(element, hostPsiFile, true, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
@Override
public void visit(@NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) {
stillInjectedDocument[0] = (DocumentWindow)injectedPsi.getViewProvider().getDocument();
PsiDocumentManagerImpl.checkConsistency(injectedPsi, stillInjectedDocument[0]);
}
});
if (stillInjectedDocument[0] == null) {
injected.remove(i);
}
else if (stillInjectedDocument[0] != documentWindow) {
injected.set(i,stillInjectedDocument[0]);
}
}
EditorWindow.disposeInvalidEditors(); // in write action
PsiDocumentManagerImpl.checkConsistency(hostPsiFile, hostDocument);
}
public static void clearCaches(@NotNull PsiFile injected, @NotNull DocumentWindowImpl documentWindow) {
VirtualFileWindowImpl virtualFile = (VirtualFileWindowImpl)injected.getVirtualFile();
PsiManagerEx psiManagerEx = (PsiManagerEx)injected.getManager();
@@ -220,7 +220,7 @@ public class MultiHostRegistrarImpl implements MultiHostRegistrar {
}
FileDocumentManagerImpl.registerDocument(decodedDocument, virtualFile);
InjectedFileViewProvider viewProvider = new InjectedFileViewProvider(myPsiManager, virtualFile, place, documentWindow, myLanguage);
InjectedFileViewProvider viewProvider = new InjectedFileViewProvider(myPsiManager, virtualFile, documentWindow, myLanguage);
ParserDefinition parserDefinition = LanguageParserDefinitions.INSTANCE.forLanguage(myLanguage);
assert parserDefinition != null : "Parser definition for language "+myLanguage+" is null";
PsiFile psiFile = parserDefinition.createFile(viewProvider);
@@ -295,11 +295,11 @@ public class MultiHostRegistrarImpl implements MultiHostRegistrar {
}
}
private static void cacheEverything(Place place,
DocumentWindowImpl documentWindow,
InjectedFileViewProvider viewProvider,
PsiFile psiFile,
SmartPsiElementPointer<PsiLanguageInjectionHost> pointer) {
private static void cacheEverything(@NotNull Place place,
@NotNull DocumentWindowImpl documentWindow,
@NotNull InjectedFileViewProvider viewProvider,
@NotNull PsiFile psiFile,
@NotNull SmartPsiElementPointer<PsiLanguageInjectionHost> pointer) {
FileDocumentManagerImpl.registerDocument(documentWindow, viewProvider.getVirtualFile());
viewProvider.forceCachedPsi(psiFile);
@@ -357,6 +357,7 @@ public class MultiHostRegistrarImpl implements MultiHostRegistrar {
result.add(Pair.create(place, psiFile));
}
@NotNull
private static <T extends PsiLanguageInjectionHost> SmartPsiElementPointer<T> createHostSmartPointer(@NotNull T host, @NotNull PsiFile hostPsiFile) {
return hostPsiFile.isPhysical()
? SmartPointerManager.getInstance(host.getProject()).createSmartPsiElementPointer(host, hostPsiFile)
@@ -38,4 +38,10 @@ public class Place extends SmartList<PsiLanguageInjectionHost.Shred> {
}
return true;
}
public void dispose() {
for (PsiLanguageInjectionHost.Shred shred : this) {
shred.getHostRangeMarker().dispose();
}
}
}
@@ -65,10 +65,8 @@ import javax.swing.table.TableCellEditor;
import java.awt.*;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.*;
import java.util.List;
import java.util.Set;
/**
* @author Konstantin Bulenkov
@@ -370,16 +368,30 @@ public abstract class ChangeSignatureDialogBase<P extends ParameterInfo, M exten
protected JPanel createParametersPanel(boolean hasTabsInDialog) {
myParametersTable = new TableView<ParameterTableModelItemBase<P>>(myParametersTableModel) {
public void removeEditor() {
clearEditorListeners();
super.removeEditor();
}
@Override
public void editingStopped(ChangeEvent e) {
super.editingStopped(e);
repaint(); // to update disabled cells background
}
@Nullable
@Override
public TableCellEditor getCellEditor(final int row, final int column) {
final TableCellEditor editor = super.getCellEditor(row, column);
private void clearEditorListeners() {
final TableCellEditor editor = getCellEditor();
if (editor instanceof StringTableCellEditor) {
final StringTableCellEditor ed = (StringTableCellEditor)editor;
ed.clearListeners();
}
else if (editor instanceof CodeFragmentTableCellEditorBase) {
((CodeFragmentTableCellEditorBase)editor).clearListeners();
}
}
public Component prepareEditor(final TableCellEditor editor, final int row, final int column) {
final DocumentAdapter listener = new DocumentAdapter() {
@Override
public void documentChanged(DocumentEvent e) {
@@ -400,7 +412,7 @@ public abstract class ChangeSignatureDialogBase<P extends ParameterInfo, M exten
else if (editor instanceof CodeFragmentTableCellEditorBase) {
((CodeFragmentTableCellEditorBase)editor).addDocumentListener(listener);
}
return editor;
return super.prepareEditor(editor, row, column);
}
};
@@ -73,11 +73,22 @@ public class CopyFilesOrDirectoriesHandler extends CopyHandlerDelegateBase {
}
public static void copyAsFiles(PsiElement[] elements, PsiDirectory defaultTargetDirectory, Project project) {
CopyFilesOrDirectoriesDialog dialog = new CopyFilesOrDirectoriesDialog(elements, defaultTargetDirectory, project, false);
dialog.show();
if (dialog.isOK()) {
final String newName = elements.length == 1 ? dialog.getNewName() : null;
final PsiDirectory targetDirectory = dialog.getTargetDirectory();
PsiDirectory targetDirectory = null;
String newName = null;
if (ApplicationManager.getApplication().isUnitTestMode()) {
targetDirectory = defaultTargetDirectory;
}
else {
CopyFilesOrDirectoriesDialog dialog = new CopyFilesOrDirectoriesDialog(elements, defaultTargetDirectory, project, false);
dialog.show();
if (dialog.isOK()) {
newName = elements.length == 1 ? dialog.getNewName() : null;
targetDirectory = dialog.getTargetDirectory();
}
}
if (targetDirectory != null) {
try {
for (PsiElement element : elements) {
PsiFileSystemItem psiElement = (PsiFileSystemItem)element;
@@ -155,7 +166,10 @@ public class CopyFilesOrDirectoriesHandler extends CopyHandlerDelegateBase {
* @param newName can be not null only if elements.length == 1
* @param targetDirectory
*/
private static void copyImpl(final PsiElement[] elements, final String newName, final PsiDirectory targetDirectory, final boolean doClone) {
private static void copyImpl(@NotNull final PsiElement[] elements,
@Nullable final String newName,
@NotNull final PsiDirectory targetDirectory,
final boolean doClone) {
if (doClone && elements.length != 1) {
throw new IllegalArgumentException("invalid number of elements to clone:" + elements.length);
}

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