mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'master' of git@git.labs.intellij.net:idea/community
This commit is contained in:
@@ -225,7 +225,7 @@ public class PositionHighlighter {
|
||||
}
|
||||
|
||||
if (breakpoint instanceof BreakpointWithHighlighter) {
|
||||
if (((BreakpointWithHighlighter)breakpoint).isVisible()) {
|
||||
if (((BreakpointWithHighlighter)breakpoint).isVisible() && breakpoint.isValid()) {
|
||||
breakpoint.reload();
|
||||
final SourcePosition sourcePosition = ((BreakpointWithHighlighter)breakpoint).getSourcePosition();
|
||||
if (sourcePosition == null || sourcePosition.getLine() != lineIndex) {
|
||||
|
||||
+2
-2
@@ -42,7 +42,7 @@ class CollectionsUtilityMethodsProvider {
|
||||
final PsiType type = parameters.getExpectedType();
|
||||
final PsiType defaultType = parameters.getDefaultType();
|
||||
final PsiElement pparent = parent.getParent();
|
||||
if (parameters.getInvocationCount() > 1 ||
|
||||
if (parameters.getParameters().getInvocationCount() > 1 ||
|
||||
pparent instanceof PsiReturnStatement ||
|
||||
pparent instanceof PsiConditionalExpression && pparent.getParent() instanceof PsiReturnStatement) {
|
||||
addCollectionMethod(result, type, defaultType, JAVA_UTIL_LIST, "emptyList", collectionsClass);
|
||||
@@ -50,7 +50,7 @@ class CollectionsUtilityMethodsProvider {
|
||||
addCollectionMethod(result, type, defaultType, JAVA_UTIL_MAP, "emptyMap", collectionsClass);
|
||||
}
|
||||
|
||||
if (parameters.getInvocationCount() > 1) {
|
||||
if (parameters.getParameters().getInvocationCount() > 1) {
|
||||
addCollectionMethod(result, type, defaultType, JAVA_UTIL_LIST, "singletonList", collectionsClass);
|
||||
addCollectionMethod(result, type, defaultType, JAVA_UTIL_SET, "singleton", collectionsClass);
|
||||
addCollectionMethod(result, type, defaultType, JAVA_UTIL_MAP, "singletonMap", collectionsClass);
|
||||
|
||||
+51
-20
@@ -7,6 +7,7 @@ import com.intellij.codeInsight.generation.PsiMethodMember;
|
||||
import com.intellij.codeInsight.lookup.Lookup;
|
||||
import com.intellij.codeInsight.lookup.LookupElementDecorator;
|
||||
import com.intellij.codeInsight.lookup.LookupItem;
|
||||
import com.intellij.codeInsight.lookup.PsiTypeLookupItem;
|
||||
import com.intellij.featureStatistics.FeatureUsageTracker;
|
||||
import com.intellij.ide.util.MemberChooser;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
@@ -16,6 +17,7 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.ScrollType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
|
||||
@@ -63,38 +65,67 @@ class ConstructorInsertHandler implements InsertHandler<LookupElementDecorator<L
|
||||
}
|
||||
}
|
||||
|
||||
OffsetKey insideRef = context.trackOffset(context.getTailOffset(), false);
|
||||
|
||||
insertParentheses(context, delegate, delegate.getObject(), withTail && isAbstract);
|
||||
|
||||
DefaultInsertHandler.addImportForItem(context, delegate);
|
||||
|
||||
|
||||
if (withTail) {
|
||||
if (isAbstract) {
|
||||
if (mySmart) {
|
||||
FeatureUsageTracker.getInstance().triggerFeatureUsed(JavaCompletionFeatures.AFTER_NEW_ANONYMOUS);
|
||||
}
|
||||
if (!withTail) {
|
||||
return;
|
||||
}
|
||||
|
||||
PostprocessReformattingAspect.getInstance(context.getProject()).doPostponedFormatting(context.getFile().getViewProvider());
|
||||
|
||||
final Editor editor = context.getEditor();
|
||||
final int offset = context.getTailOffset();
|
||||
editor.getDocument().insertString(offset, " {}");
|
||||
editor.getCaretModel().moveToOffset(offset + 2);
|
||||
context.setLaterRunnable(generateAnonymousBody(editor, context.getFile()));
|
||||
if (isAbstract) {
|
||||
if (mySmart) {
|
||||
FeatureUsageTracker.getInstance().triggerFeatureUsed(JavaCompletionFeatures.AFTER_NEW_ANONYMOUS);
|
||||
}
|
||||
else {
|
||||
final PsiNewExpression newExpression =
|
||||
PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getStartOffset(), PsiNewExpression.class, false);
|
||||
if (newExpression != null) {
|
||||
final PsiJavaCodeReferenceElement classReference = newExpression.getClassOrAnonymousClassReference();
|
||||
if (classReference != null) {
|
||||
CodeStyleManager.getInstance(context.getProject()).reformat(classReference);
|
||||
|
||||
PostprocessReformattingAspect.getInstance(context.getProject()).doPostponedFormatting(context.getFile().getViewProvider());
|
||||
|
||||
final Editor editor = context.getEditor();
|
||||
final int offset = context.getTailOffset();
|
||||
editor.getDocument().insertString(offset, " {}");
|
||||
editor.getCaretModel().moveToOffset(offset + 2);
|
||||
|
||||
if (delegate instanceof PsiTypeLookupItem) {
|
||||
PsiType type = JavaCompletionUtil.getLookupElementType(delegate);
|
||||
if (type instanceof PsiClassType) {
|
||||
PsiClassType.ClassResolveResult result = ((PsiClassType)type).resolveGenerics();
|
||||
PsiClass psiClass = result.getElement();
|
||||
if (psiClass != null) {
|
||||
for (PsiTypeParameter parameter : psiClass.getTypeParameters()) {
|
||||
PsiType substitution = result.getSubstitutor().substitute(parameter);
|
||||
if (substitution instanceof PsiClassType && parameter.equals(((PsiClassType)substitution).resolve())) {
|
||||
PsiReferenceParameterList paramList = PsiTreeUtil
|
||||
.findElementOfClassAtOffset(context.getFile(), context.getOffset(insideRef) - 1, PsiReferenceParameterList.class, false);
|
||||
if (paramList != null && paramList.getTextLength() > 0) {
|
||||
TextRange range = paramList.getTextRange();
|
||||
context.getDocument().replaceString(range.getStartOffset(), range.getEndOffset(), "<>");
|
||||
editor.getCaretModel().moveToOffset(range.getStartOffset() + 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mySmart) {
|
||||
FeatureUsageTracker.getInstance().triggerFeatureUsed(JavaCompletionFeatures.AFTER_NEW);
|
||||
}
|
||||
|
||||
context.setLaterRunnable(generateAnonymousBody(editor, context.getFile()));
|
||||
}
|
||||
else {
|
||||
final PsiNewExpression newExpression =
|
||||
PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getStartOffset(), PsiNewExpression.class, false);
|
||||
if (newExpression != null) {
|
||||
final PsiJavaCodeReferenceElement classReference = newExpression.getClassOrAnonymousClassReference();
|
||||
if (classReference != null) {
|
||||
CodeStyleManager.getInstance(context.getProject()).reformat(classReference);
|
||||
}
|
||||
}
|
||||
if (mySmart) {
|
||||
FeatureUsageTracker.getInstance().triggerFeatureUsed(JavaCompletionFeatures.AFTER_NEW);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -220,15 +220,14 @@ public class JavaCompletionContributor extends CompletionContributor {
|
||||
|
||||
addKeywords(parameters, result);
|
||||
|
||||
addAllClasses(parameters, result, position, inheritors);
|
||||
addAllClasses(parameters, result, inheritors);
|
||||
result.stopHere();
|
||||
}
|
||||
|
||||
public static void addAllClasses(CompletionParameters parameters,
|
||||
final CompletionResultSet result,
|
||||
PsiElement position,
|
||||
final InheritorsHolder inheritors) {
|
||||
if (shouldRunClassNameCompletion(result, position)) {
|
||||
if (shouldRunClassNameCompletion(result, parameters)) {
|
||||
JavaClassNameCompletionContributor.addAllClasses(parameters, result, new Consumer<LookupElement>() {
|
||||
@Override
|
||||
public void consume(LookupElement element) {
|
||||
@@ -314,7 +313,8 @@ public class JavaCompletionContributor extends CompletionContributor {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean shouldRunClassNameCompletion(CompletionResultSet result, PsiElement position) {
|
||||
private static boolean shouldRunClassNameCompletion(CompletionResultSet result, CompletionParameters parameters) {
|
||||
PsiElement position = parameters.getPosition();
|
||||
final PsiElement parent = position.getParent();
|
||||
if (!(parent instanceof PsiJavaCodeReferenceElement)) return false;
|
||||
if (((PsiJavaCodeReferenceElement)parent).getQualifier() != null) return false;
|
||||
@@ -331,7 +331,7 @@ public class JavaCompletionContributor extends CompletionContributor {
|
||||
return false;
|
||||
}
|
||||
|
||||
return StringUtil.isNotEmpty(result.getPrefixMatcher().getPrefix());
|
||||
return StringUtil.isCapitalized(result.getPrefixMatcher().getPrefix()) || parameters.relaxMatching();
|
||||
}
|
||||
|
||||
private static void completeAnnotationAttributeName(CompletionResultSet result, PsiElement insertedElement,
|
||||
|
||||
+1
-1
@@ -103,7 +103,7 @@ public class JavaDocCompletionContributor extends CompletionContributor {
|
||||
result.addElement(item);
|
||||
}
|
||||
|
||||
JavaCompletionContributor.addAllClasses(parameters, result, position, new InheritorsHolder(position, result));
|
||||
JavaCompletionContributor.addAllClasses(parameters, result, new InheritorsHolder(position, result));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
+12
-2
@@ -15,17 +15,19 @@
|
||||
*/
|
||||
package com.intellij.codeInsight.completion;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.codeInsight.ExpectedTypeInfo;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class JavaSmartCompletionParameters extends CompletionParameters{
|
||||
public class JavaSmartCompletionParameters {
|
||||
private final CompletionParameters myParameters;
|
||||
private final ExpectedTypeInfo myExpectedType;
|
||||
|
||||
public JavaSmartCompletionParameters(CompletionParameters parameters, final ExpectedTypeInfo expectedType) {
|
||||
super(parameters.getPosition(), parameters.getOriginalFile(), parameters.getCompletionType(), parameters.getOffset(), parameters.getInvocationCount());
|
||||
myParameters = parameters;
|
||||
myExpectedType = expectedType;
|
||||
}
|
||||
|
||||
@@ -36,4 +38,12 @@ public class JavaSmartCompletionParameters extends CompletionParameters{
|
||||
public PsiType getDefaultType() {
|
||||
return myExpectedType.getDefaultType();
|
||||
}
|
||||
|
||||
public PsiElement getPosition() {
|
||||
return myParameters.getPosition();
|
||||
}
|
||||
|
||||
public CompletionParameters getParameters() {
|
||||
return myParameters;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -110,7 +110,7 @@ public class ReferenceExpressionCompletionContributor {
|
||||
final PsiElement element = parameters.getPosition();
|
||||
if (JavaSmartCompletionContributor.INSIDE_TYPECAST_EXPRESSION.accepts(element)) return;
|
||||
|
||||
final int offset = parameters.getOffset();
|
||||
final int offset = parameters.getParameters().getOffset();
|
||||
final PsiReference reference = element.getContainingFile().findReferenceAt(offset);
|
||||
if (reference != null) {
|
||||
final ElementFilter filter = getReferenceFilter(element, false);
|
||||
@@ -118,9 +118,9 @@ public class ReferenceExpressionCompletionContributor {
|
||||
result.consume(item);
|
||||
}
|
||||
|
||||
final boolean secondTime = parameters.getInvocationCount() >= 2;
|
||||
final boolean secondTime = parameters.getParameters().getInvocationCount() >= 2;
|
||||
|
||||
for (final LookupElement item : JavaSmartCompletionContributor.completeReference(element, reference, filter, false, parameters)) {
|
||||
for (final LookupElement item : JavaSmartCompletionContributor.completeReference(element, reference, filter, false, parameters.getParameters())) {
|
||||
addSingleArrayElementAccess(element, item, parameters, result);
|
||||
|
||||
if (secondTime) {
|
||||
@@ -164,7 +164,7 @@ public class ReferenceExpressionCompletionContributor {
|
||||
public boolean isClassAcceptable(Class hintClass) {
|
||||
return true;
|
||||
}
|
||||
}), false, parameters);
|
||||
}), false, parameters.getParameters());
|
||||
for (LookupElement lookupElement : elements) {
|
||||
if (lookupElement.getObject() instanceof PsiMethod) {
|
||||
final JavaMethodCallElement item = lookupElement.as(JavaMethodCallElement.CLASS_CONDITION_KEY);
|
||||
|
||||
@@ -188,9 +188,10 @@ public class PostHighlightingPass extends TextEditorHighlightingPass {
|
||||
}
|
||||
|
||||
public static void invokeOnTheFlyImportOptimizer(@NotNull final Runnable runnable, @NotNull final PsiFile file, @NotNull final Editor editor) {
|
||||
final long stamp = editor.getDocument().getModificationStamp();
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
if (file.getProject().isDisposed() || editor.isDisposed()) return;
|
||||
if (file.getProject().isDisposed() || editor.isDisposed() || editor.getDocument().getModificationStamp() != stamp) return;
|
||||
PsiDocumentManager.getInstance(file.getProject()).commitAllDocuments();
|
||||
String beforeText = file.getText();
|
||||
CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
|
||||
|
||||
+3
@@ -37,6 +37,7 @@ import com.intellij.find.impl.FindManagerImpl;
|
||||
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;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -68,6 +69,7 @@ public class ChangeMethodSignatureFromUsageFix implements IntentionAction {
|
||||
private final boolean myChangeAllUsages;
|
||||
private final int myMinUsagesNumberToShowDialog;
|
||||
private ParameterInfoImpl[] myNewParametersInfo;
|
||||
private static final Logger LOG = Logger.getInstance("#" + ChangeMethodSignatureFromUsageFix.class.getName());
|
||||
|
||||
ChangeMethodSignatureFromUsageFix(@NotNull PsiMethod targetMethod,
|
||||
@NotNull PsiExpression[] expressions,
|
||||
@@ -99,6 +101,7 @@ public class ChangeMethodSignatureFromUsageFix implements IntentionAction {
|
||||
if (result.length() != 0) {
|
||||
result += ", ";
|
||||
}
|
||||
LOG.assertTrue(type != null, "old idx: " + info.getOldIndex() + "; " + info.getClass().getName());
|
||||
result += type.getPresentableText();
|
||||
}
|
||||
}
|
||||
|
||||
+4
-1
@@ -139,7 +139,10 @@ public class CreateConstructorParameterFromFieldFix implements IntentionAction {
|
||||
|
||||
// do not introduce assignment in chanined constructor
|
||||
if (HighlightControlFlowUtil.getChainedConstructors(constructor) == null) {
|
||||
AssignFieldFromParameterAction.addFieldAssignmentStatement(project, getField(), parameter, editor);
|
||||
PsiField field = getField();
|
||||
if (field != null) {
|
||||
AssignFieldFromParameterAction.addFieldAssignmentStatement(project, field, parameter, editor);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
+3
-2
@@ -20,7 +20,7 @@ import com.intellij.codeInsight.intention.AddAnnotationFix;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
@@ -72,7 +72,8 @@ public class AddOverrideAnnotationAction implements IntentionAction {
|
||||
//Not available in method's body
|
||||
PsiCodeBlock body = res.getBody();
|
||||
if (body == null) return null;
|
||||
if (body.getTextRange().getStartOffset() <= offset) return null;
|
||||
TextRange textRange = body.getTextRange();
|
||||
if (textRange == null || textRange.getStartOffset() <= offset) return null;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
+5
-5
@@ -80,17 +80,17 @@ public class AssignFieldFromParameterAction extends BaseIntentionAction {
|
||||
IdeDocumentHistory.getInstance(project).includeCurrentPlaceAsChangePlace();
|
||||
try {
|
||||
PsiField field = findFieldToAssign(myParameter);
|
||||
addFieldAssignmentStatement(project, field, myParameter, editor);
|
||||
if (field != null) addFieldAssignmentStatement(project, field, myParameter, editor);
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addFieldAssignmentStatement(final Project project,
|
||||
final PsiField field,
|
||||
final PsiParameter parameter,
|
||||
final Editor editor) throws IncorrectOperationException {
|
||||
public static void addFieldAssignmentStatement(@NotNull Project project,
|
||||
@NotNull PsiField field,
|
||||
@NotNull PsiParameter parameter,
|
||||
@NotNull Editor editor) throws IncorrectOperationException {
|
||||
final PsiMethod method = (PsiMethod)parameter.getDeclarationScope();
|
||||
PsiCodeBlock methodBody = method.getBody();
|
||||
if (methodBody == null) return;
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.intellij.codeInsight.unwrap;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightBundle;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.tree.java.PsiWhileStatementImpl;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
|
||||
public class JavaWhileUnwrapper extends JavaUnwrapper {
|
||||
@@ -25,7 +26,9 @@ public class JavaWhileUnwrapper extends JavaUnwrapper {
|
||||
}
|
||||
|
||||
public boolean isApplicableTo(PsiElement e) {
|
||||
return e instanceof PsiWhileStatement || e instanceof PsiDoWhileStatement;
|
||||
return e instanceof PsiWhileStatementImpl // Don't use "e instanceof PsiWhileStatement" because JspWhileStatement intanceof PsiWhileStatement,
|
||||
// but we doesn't support unwrap JspWhileStatement.
|
||||
|| e instanceof PsiDoWhileStatement;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -218,6 +218,7 @@ public class GlobalJavaInspectionContextImpl extends GlobalJavaInspectionContext
|
||||
));
|
||||
|
||||
final List<DerivedClassesProcessor> processors = myDerivedClassesRequests.get(sortedID);
|
||||
LOG.assertTrue(processors != null, psiClass.getClass().getName());
|
||||
ClassInheritorsSearch.search(psiClass, searchScope, false)
|
||||
.forEach(createMembersProcessor(processors, scope));
|
||||
}
|
||||
@@ -229,12 +230,14 @@ public class GlobalJavaInspectionContextImpl extends GlobalJavaInspectionContext
|
||||
final List<SmartPsiElementPointer> sortedIDs = getSortedIDs(myDerivedMethodsRequests);
|
||||
for (SmartPsiElementPointer sortedID : sortedIDs) {
|
||||
final PsiMethod psiMethod = (PsiMethod)sortedID.getElement();
|
||||
if (psiMethod == null) continue;
|
||||
final RefMethod refMethod = (RefMethod)refManager.getReference(psiMethod);
|
||||
|
||||
context
|
||||
.incrementJobDoneAmount(GlobalInspectionContextImpl.FIND_EXTERNAL_USAGES, refManager.getQualifiedName(refMethod));
|
||||
|
||||
final List<DerivedMethodsProcessor> processors = myDerivedMethodsRequests.get(sortedID);
|
||||
LOG.assertTrue(processors != null, psiMethod.getClass().getName());
|
||||
OverridingMethodsSearch.search(psiMethod, searchScope, true)
|
||||
.forEach(createMembersProcessor(processors, scope));
|
||||
}
|
||||
@@ -249,6 +252,7 @@ public class GlobalJavaInspectionContextImpl extends GlobalJavaInspectionContext
|
||||
if (psiField == null) continue;
|
||||
final List<UsagesProcessor> processors = myFieldUsagesRequests.get(sortedID);
|
||||
|
||||
LOG.assertTrue(processors != null, psiField.getClass().getName());
|
||||
context
|
||||
.incrementJobDoneAmount(GlobalInspectionContextImpl.FIND_EXTERNAL_USAGES,
|
||||
refManager.getQualifiedName(refManager.getReference(psiField)));
|
||||
@@ -267,6 +271,7 @@ public class GlobalJavaInspectionContextImpl extends GlobalJavaInspectionContext
|
||||
if (psiClass == null) continue;
|
||||
final List<UsagesProcessor> processors = myClassUsagesRequests.get(sortedID);
|
||||
|
||||
LOG.assertTrue(processors != null, psiClass.getClass().getName());
|
||||
context.incrementJobDoneAmount(GlobalInspectionContextImpl.FIND_EXTERNAL_USAGES, ApplicationManager.getApplication().runReadAction(
|
||||
new Computable<String>() {
|
||||
public String compute() {
|
||||
@@ -289,6 +294,7 @@ public class GlobalJavaInspectionContextImpl extends GlobalJavaInspectionContext
|
||||
if (psiMethod == null) continue;
|
||||
final List<UsagesProcessor> processors = myMethodUsagesRequests.get(sortedID);
|
||||
|
||||
LOG.assertTrue(processors != null, psiMethod.getClass().getName());
|
||||
context
|
||||
.incrementJobDoneAmount(GlobalInspectionContextImpl.FIND_EXTERNAL_USAGES,
|
||||
refManager.getQualifiedName(refManager.getReference(psiMethod)));
|
||||
|
||||
@@ -13,10 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package com.intellij.psi.impl;
|
||||
|
||||
import com.intellij.ProjectTopics;
|
||||
@@ -55,7 +51,6 @@ import com.intellij.psi.javadoc.JavadocManager;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.PsiShortNamesCache;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.xml.XmlFile;
|
||||
import com.intellij.util.ConcurrencyUtil;
|
||||
import com.intellij.util.Processor;
|
||||
@@ -65,10 +60,14 @@ import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.messages.MessageBus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public class JavaPsiFacadeImpl extends JavaPsiFacadeEx implements Disposable {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.JavaPsiFacadeImpl");
|
||||
|
||||
@@ -90,9 +89,7 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx implements Disposable {
|
||||
PsiManagerImpl psiManager,
|
||||
final ProjectRootManagerEx projectRootManagerEx,
|
||||
StartupManager startupManager,
|
||||
MessageBus bus
|
||||
|
||||
) {
|
||||
MessageBus bus) {
|
||||
myProject = project;
|
||||
myResolveHelper = new PsiResolveHelperImpl(PsiManager.getInstance(project));
|
||||
myJavadocManager = new JavadocManagerImpl(project);
|
||||
@@ -270,7 +267,7 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx implements Disposable {
|
||||
|
||||
@NotNull
|
||||
public PsiJavaParserFacade getParserFacade() {
|
||||
return getElementFactory(); // TODO: ligter implementation which doesn't mark all the elements as generated.
|
||||
return getElementFactory(); // TODO: lighter implementation which doesn't mark all the elements as generated.
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -370,6 +367,7 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx implements Disposable {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private PsiPackage findPackageDefault(String qualifiedName) {
|
||||
final PsiPackage aPackage = myFileManager.findPackage(qualifiedName);
|
||||
if (aPackage == null && myCurrentMigration != null) {
|
||||
@@ -416,9 +414,9 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx implements Disposable {
|
||||
final Map<String, PsiPackage> packagesMap = new HashMap<String, PsiPackage>();
|
||||
final String qualifiedName = psiPackage.getQualifiedName();
|
||||
for (PsiDirectory dir : psiPackage.getDirectories(scope)) {
|
||||
PsiDirectory[] subdirs = dir.getSubdirectories();
|
||||
for (PsiDirectory subdir : subdirs) {
|
||||
final PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage(subdir);
|
||||
PsiDirectory[] subDirs = dir.getSubdirectories();
|
||||
for (PsiDirectory subDir : subDirs) {
|
||||
final PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage(subDir);
|
||||
if (aPackage != null) {
|
||||
final String subQualifiedName = aPackage.getQualifiedName();
|
||||
if (subQualifiedName.startsWith(qualifiedName) && !packagesMap.containsKey(subQualifiedName)) {
|
||||
@@ -578,16 +576,7 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx implements Disposable {
|
||||
case BEFORE_CHILD_MOVEMENT:
|
||||
case BEFORE_CHILD_REPLACEMENT:
|
||||
case BEFORE_CHILD_ADDITION:
|
||||
break;
|
||||
case BEFORE_CHILD_REMOVAL:
|
||||
checkAnnotation(event.getChild());
|
||||
checkModifierListOwner(event.getChild());
|
||||
if (event.getChild() instanceof PsiClassOwner) {
|
||||
PsiClass[] classes = ((PsiClassOwner)event.getChild()).getClasses();
|
||||
for (PsiClass psiClass : classes) {
|
||||
checkModifierListOwner(psiClass);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CHILD_ADDED:
|
||||
@@ -611,15 +600,6 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx implements Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
private void checkModifierListOwner(PsiElement child) {
|
||||
if (child instanceof PsiClass || child instanceof PsiMethod) {
|
||||
PsiModifierList modifierList = ((PsiModifierListOwner)child).getModifierList();
|
||||
if (modifierList != null && modifierList.getAnnotations().length > 0) {
|
||||
myModificationTracker.incAnnotationModificationCounter();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processChange(final PsiElement parent, final PsiElement child1, final PsiElement child2) {
|
||||
try {
|
||||
if (!isInsideCodeBlock(parent)) {
|
||||
@@ -629,8 +609,6 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx implements Disposable {
|
||||
else {
|
||||
myModificationTracker.incOutOfCodeBlockModificationCounter();
|
||||
}
|
||||
checkAnnotation(parent);
|
||||
checkModifierListOwner(parent);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -643,12 +621,6 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx implements Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
private void checkAnnotation(PsiElement parent) {
|
||||
if (PsiTreeUtil.getParentOfType(parent, PsiAnnotation.class, false) != null) {
|
||||
myModificationTracker.incAnnotationModificationCounter();
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isClassOwner(final PsiElement element) {
|
||||
return element instanceof PsiClassOwner && !(element instanceof XmlFile) || element instanceof JspDirective;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.DummyHolder;
|
||||
@@ -34,6 +35,7 @@ import com.intellij.psi.impl.source.SourceTreeToPsiMap;
|
||||
import com.intellij.psi.impl.source.tree.TreeElement;
|
||||
import com.intellij.psi.javadoc.PsiDocComment;
|
||||
import com.intellij.psi.javadoc.PsiDocTag;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -41,8 +43,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import static com.intellij.openapi.util.text.StringUtil.join;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
@@ -79,6 +79,13 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
|
||||
};
|
||||
|
||||
public static final JavaParserUtil.ParserWrapper REFERENCE = new JavaParserUtil.ParserWrapper() {
|
||||
@Override
|
||||
public void parse(final PsiBuilder builder) {
|
||||
ReferenceParser.parseJavaCodeReference(builder, false, true, false, false, false);
|
||||
}
|
||||
};
|
||||
|
||||
public static final JavaParserUtil.ParserWrapper DIAMOND_REF = new JavaParserUtil.ParserWrapper() {
|
||||
@Override
|
||||
public void parse(final PsiBuilder builder) {
|
||||
ReferenceParser.parseJavaCodeReference(builder, false, true, false, false, true);
|
||||
@@ -174,7 +181,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiDocTag createDocTagFromText(@NotNull final String text) throws IncorrectOperationException {
|
||||
return createDocCommentFromText(join("/**\n", text, "\n */")).getTags()[0];
|
||||
return createDocCommentFromText(StringUtil.join("/**\n", text, "\n */")).getTags()[0];
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -186,7 +193,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiDocComment createDocCommentFromText(@NotNull final String text) throws IncorrectOperationException {
|
||||
final PsiMethod method = createMethodFromText(join(text, "void m();"), null);
|
||||
final PsiMethod method = createMethodFromText(StringUtil.join(text, "void m();"), null);
|
||||
final PsiDocComment comment = method.getDocComment();
|
||||
assert comment != null : text;
|
||||
return comment;
|
||||
@@ -201,7 +208,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiClass createClassFromText(@NotNull final String body, final PsiElement context) throws IncorrectOperationException {
|
||||
final PsiJavaFile aFile = createDummyJavaFile(join("class _Dummy_ { ", body, " }"));
|
||||
final PsiJavaFile aFile = createDummyJavaFile(StringUtil.join("class _Dummy_ { ", body, " }"));
|
||||
final PsiClass[] classes = aFile.getClasses();
|
||||
if (classes.length != 1) {
|
||||
throw new IncorrectOperationException("Incorrect class \"" + body + "\".");
|
||||
@@ -293,7 +300,9 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
|
||||
public PsiJavaCodeReferenceElement createReferenceFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
|
||||
final boolean isStaticImport = context instanceof PsiImportStaticStatement &&
|
||||
!((PsiImportStaticStatement)context).isOnDemand();
|
||||
final JavaParserUtil.ParserWrapper wrapper = isStaticImport ? STATIC_IMPORT_REF : REFERENCE;
|
||||
final boolean mayHaveDiamonds = context instanceof PsiNewExpression &&
|
||||
PsiUtil.getLanguageLevel(context).isAtLeast(LanguageLevel.JDK_1_7);
|
||||
final JavaParserUtil.ParserWrapper wrapper = isStaticImport ? STATIC_IMPORT_REF : mayHaveDiamonds ? DIAMOND_REF : REFERENCE;
|
||||
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, wrapper, false), context);
|
||||
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
|
||||
if (!(element instanceof PsiJavaCodeReferenceElement)) {
|
||||
@@ -385,11 +394,12 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
|
||||
@Override
|
||||
public PsiCatchSection createCatchSection(@NotNull final PsiClassType exceptionType, @NotNull final String exceptionName,
|
||||
final PsiElement context) throws IncorrectOperationException {
|
||||
final String text = join("catch (", exceptionType.getCanonicalText(), " ", exceptionName, ") {}");
|
||||
final String text = StringUtil
|
||||
.join("catch (", exceptionType.getCanonicalText(), " ", exceptionName, ") {}");
|
||||
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, CATCH_SECTION, false), context);
|
||||
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
|
||||
if (!(element instanceof PsiCatchSection)) {
|
||||
throw new IncorrectOperationException("Incorrect catch section \"" + text + "\".");
|
||||
throw new IncorrectOperationException("Incorrect catch section '" + text + "'. Parsed element: "+element);
|
||||
}
|
||||
setupCatchBlock(exceptionName, context, (PsiCatchSection)element);
|
||||
return (PsiCatchSection)myManager.getCodeStyleManager().reformat(element);
|
||||
|
||||
+3
-3
@@ -524,7 +524,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
throw new IncorrectOperationException(aClass.toString());
|
||||
}
|
||||
final PsiJavaParserFacade parserFacade = JavaPsiFacade.getInstance(getProject()).getParserFacade();
|
||||
final PsiJavaCodeReferenceElement ref = parserFacade.createReferenceFromText(name, null);
|
||||
final PsiJavaCodeReferenceElement ref = parserFacade.createReferenceFromText(name, getParent());
|
||||
getTreeParent().replaceChildInternal(this, (TreeElement)ref.getNode());
|
||||
return ref;
|
||||
}
|
||||
@@ -562,7 +562,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
final PsiManager manager = aClass.getManager();
|
||||
final PsiReferenceParameterList parameterList = getParameterList();
|
||||
String text = (parameterList != null ? qName + parameterList.getText() : qName);
|
||||
PsiJavaCodeReferenceElement ref = facade.getParserFacade().createReferenceFromText(text, null);
|
||||
PsiJavaCodeReferenceElement ref = facade.getParserFacade().createReferenceFromText(text, getParent());
|
||||
getTreeParent().replaceChildInternal(this, (TreeElement)ref.getNode());
|
||||
if (!preserveQualification /*&& (TreeUtil.findParent(ref, ElementType.DOC_COMMENT) == null)*/) {
|
||||
final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(aClass.getProject());
|
||||
@@ -605,7 +605,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
throw new IncorrectOperationException("Cannot bind to default package: "+aPackage);
|
||||
}
|
||||
final PsiJavaParserFacade parserFacade = JavaPsiFacade.getInstance(getProject()).getParserFacade();
|
||||
final PsiJavaCodeReferenceElement ref = parserFacade.createReferenceFromText(qName, null);
|
||||
final PsiJavaCodeReferenceElement ref = parserFacade.createReferenceFromText(qName, getParent());
|
||||
getTreeParent().replaceChildInternal(this, (TreeElement)ref.getNode());
|
||||
return ref;
|
||||
}
|
||||
|
||||
+7
-1
@@ -259,7 +259,13 @@ public class PsiReferenceExpressionImpl extends ExpressionPsiElement implements
|
||||
@NotNull
|
||||
public String getCanonicalText() {
|
||||
PsiElement element = resolve();
|
||||
if (element instanceof PsiClass) return ((PsiClass)element).getQualifiedName();
|
||||
if (element instanceof PsiClass) {
|
||||
String fqn = ((PsiClass)element).getQualifiedName();
|
||||
if (fqn == null) {
|
||||
LOG.error("FQN is null. reference:" + getElement().getText()+"; resolves to "+element);
|
||||
}
|
||||
return fqn;
|
||||
}
|
||||
return getCachedTextSkipWhiteSpaceAndComments();
|
||||
}
|
||||
|
||||
|
||||
+16
-3
@@ -678,9 +678,8 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr
|
||||
PsiParameter[] parameters = list.getParameters();
|
||||
|
||||
final JavaParameterInfo[] parameterInfos = changeInfo.getNewParameters();
|
||||
PsiParameter[] newParms = new PsiParameter[parameterInfos.length -
|
||||
(baseMethod != null ? baseMethod.getParameterList().getParametersCount() -
|
||||
method.getParameterList().getParametersCount() : 0)];
|
||||
final int delta = baseMethod != null ? baseMethod.getParameterList().getParametersCount() - method.getParameterList().getParametersCount() : 0;
|
||||
PsiParameter[] newParms = new PsiParameter[Math.max(parameterInfos.length - delta, 0)];
|
||||
final String[] oldParameterNames = changeInfo.getOldParameterNames();
|
||||
final String[] oldParameterTypes = changeInfo.getOldParameterTypes();
|
||||
for (int i = 0; i < newParms.length; i++) {
|
||||
@@ -865,6 +864,20 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr
|
||||
}
|
||||
}
|
||||
|
||||
for (UsageInfo usageInfo : usagesSet) {
|
||||
if (usageInfo instanceof OverriderUsageInfo) {
|
||||
final PsiMethod method = (PsiMethod)usageInfo.getElement();
|
||||
final PsiMethod baseMethod = ((OverriderUsageInfo)usageInfo).getBaseMethod();
|
||||
final int delta = baseMethod.getParameterList().getParametersCount() - method.getParameterList().getParametersCount();
|
||||
if (delta > 0) {
|
||||
final boolean[] toRemove = myChangeInfo.toRemoveParm();
|
||||
if (toRemove[toRemove.length - 1]) { //todo check if implicit parameter is not the last one
|
||||
conflictDescriptions.putValue(baseMethod, "Implicit last parameter should not be deleted");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return conflictDescriptions;
|
||||
}
|
||||
|
||||
|
||||
+10
-6
@@ -89,7 +89,7 @@ class InplaceIntroduceParameterPopup extends IntroduceParameterSettingsUI {
|
||||
myMethodToSearchFor = methodToSearchFor;
|
||||
myOccurrences = occurrences;
|
||||
myMustBeFinal = mustBeFinal;
|
||||
myExprMarker = expr != null ? myEditor.getDocument().createRangeMarker(expr.getTextRange()) : null;
|
||||
myExprMarker = expr != null && expr.isPhysical() ? myEditor.getDocument().createRangeMarker(expr.getTextRange()) : null;
|
||||
myExprText = myExpr != null ? myExpr.getText() : null;
|
||||
|
||||
myWholePanel = new JPanel(new GridBagLayout());
|
||||
@@ -187,7 +187,9 @@ class InplaceIntroduceParameterPopup extends IntroduceParameterSettingsUI {
|
||||
|
||||
final JPanel wrapper = new JPanel(new BorderLayout());
|
||||
wrapper.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
|
||||
wrapper.add(myCanBeFinal, BorderLayout.NORTH);
|
||||
if (myCanBeFinal != null) {
|
||||
wrapper.add(myCanBeFinal, BorderLayout.NORTH);
|
||||
}
|
||||
panel.add(wrapper, BorderLayout.SOUTH);
|
||||
|
||||
return panel;
|
||||
@@ -200,7 +202,7 @@ class InplaceIntroduceParameterPopup extends IntroduceParameterSettingsUI {
|
||||
|
||||
@Override
|
||||
protected PsiExpression getExpr() {
|
||||
return myExpr;
|
||||
return myExpr != null && myExpr.isValid() && myExpr.isPhysical() ? myExpr : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -299,9 +301,11 @@ class InplaceIntroduceParameterPopup extends IntroduceParameterSettingsUI {
|
||||
public void run() {
|
||||
final PsiFile containingFile = myMethod.getContainingFile();
|
||||
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(myProject);
|
||||
myExpr = restoreExpression(containingFile, psiParameter, elementFactory, myExprMarker, myExprText);
|
||||
if (myExpr != null) {
|
||||
myExprMarker = myEditor.getDocument().createRangeMarker(myExpr.getTextRange());
|
||||
if (myExprMarker != null) {
|
||||
myExpr = restoreExpression(containingFile, psiParameter, elementFactory, myExprMarker, myExprText);
|
||||
if (myExpr != null) {
|
||||
myExprMarker = myEditor.getDocument().createRangeMarker(myExpr.getTextRange());
|
||||
}
|
||||
}
|
||||
final List<RangeMarker> occurrenceMarkers = getOccurrenceMarkers();
|
||||
for (int i = 0, occurrenceMarkersSize = occurrenceMarkers.size(); i < occurrenceMarkersSize; i++) {
|
||||
|
||||
+5
-4
@@ -164,8 +164,9 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase implements R
|
||||
final Introducer introducer = new Introducer(project, expr, localVar, editor);
|
||||
final boolean unitTestMode = ApplicationManager.getApplication().isUnitTestMode();
|
||||
if (validEnclosingMethods.size() == 1 || unitTestMode) {
|
||||
if (validEnclosingMethods.get(0).findDeepestSuperMethod() == null || unitTestMode) {
|
||||
introducer.introduceParameter(method, method);
|
||||
final PsiMethod methodToIntroduceParameterTo = validEnclosingMethods.get(0);
|
||||
if (methodToIntroduceParameterTo.findDeepestSuperMethod() == null || unitTestMode) {
|
||||
introducer.introduceParameter(methodToIntroduceParameterTo, methodToIntroduceParameterTo);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -176,8 +177,8 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase implements R
|
||||
}
|
||||
|
||||
private void chooseMethodToIntroduceParameter(final Editor editor,
|
||||
final List<PsiMethod> validEnclosingMethods,
|
||||
final Introducer introducer) {
|
||||
final List<PsiMethod> validEnclosingMethods,
|
||||
final Introducer introducer) {
|
||||
final JPanel panel = new JPanel(new BorderLayout());
|
||||
final JCheckBox superMethod = new JCheckBox("Use super method of", true);
|
||||
superMethod.setMnemonic('U');
|
||||
|
||||
+1
@@ -478,6 +478,7 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme
|
||||
final VariableInplaceRenamer renamer =
|
||||
new VariableInplaceIntroducer(project, expression, editor, elementToRename, cantChangeFinalModifier,
|
||||
typeSelectorManager.getTypesForAll().length > 1, exprMarker, occurrenceMarkers);
|
||||
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument());
|
||||
renamer.performInplaceRename(false, new LinkedHashSet<String>(Arrays.asList(suggestedName.names)));
|
||||
}
|
||||
}
|
||||
|
||||
+3
-1
@@ -235,7 +235,9 @@ public class VariableInplaceIntroducer extends VariableInplaceRenamer {
|
||||
titlePanel.setText(IntroduceVariableBase.REFACTORING_NAME);
|
||||
panel.add(titlePanel, new GridBagConstraints(0, 0, 1, 1, 1, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
|
||||
|
||||
panel.add(myCanBeFinal, new GridBagConstraints(0, 1, 1, 1, 1, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0));
|
||||
if (myCanBeFinal != null) {
|
||||
panel.add(myCanBeFinal, new GridBagConstraints(0, 1, 1, 1, 1, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0));
|
||||
}
|
||||
|
||||
panel.add(Box.createVerticalBox(), new GridBagConstraints(0, 2, 1, 1, 1, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(0,0,0,0), 0,0));
|
||||
|
||||
|
||||
+3
-1
@@ -40,9 +40,11 @@ public class LocalHidesRenamedLocalUsageInfo extends UnresolvableCollisionUsageI
|
||||
|
||||
public String getDescription() {
|
||||
|
||||
PsiElement element = getElement();
|
||||
String type = element == null ? "element" : UsageViewUtil.getType(element);
|
||||
final String descr = RefactoringBundle.message("there.is.already.a.0.it.will.conflict.with.the.renamed.1",
|
||||
RefactoringUIUtil.getDescription(myConflictingElement, true),
|
||||
UsageViewUtil.getType(getElement()));
|
||||
type);
|
||||
return CommonRefactoringUtil.capitalize(descr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@@ -38,6 +39,7 @@ public class CanonicalTypes {
|
||||
private CanonicalTypes() { }
|
||||
|
||||
public abstract static class Type {
|
||||
@NotNull
|
||||
public abstract PsiType getType(PsiElement context, final PsiManager manager) throws IncorrectOperationException;
|
||||
|
||||
@NonNls
|
||||
@@ -53,6 +55,7 @@ public class CanonicalTypes {
|
||||
myType = type;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiType getType(PsiElement context, final PsiManager manager) {
|
||||
return myType;
|
||||
}
|
||||
@@ -71,6 +74,7 @@ public class CanonicalTypes {
|
||||
myComponentType = componentType;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiType getType(PsiElement context, final PsiManager manager) throws IncorrectOperationException {
|
||||
return myComponentType.getType(context, manager).createArrayType();
|
||||
}
|
||||
@@ -91,6 +95,7 @@ public class CanonicalTypes {
|
||||
myComponentType = componentType;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiType getType(PsiElement context, final PsiManager manager) throws IncorrectOperationException {
|
||||
return new PsiEllipsisType(myComponentType.getType(context, manager));
|
||||
}
|
||||
@@ -113,6 +118,7 @@ public class CanonicalTypes {
|
||||
myBound = bound;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiType getType(PsiElement context, final PsiManager manager) throws IncorrectOperationException {
|
||||
if(myBound == null) return PsiWildcardType.createUnbounded(context.getManager());
|
||||
if (myIsExtending) {
|
||||
@@ -140,6 +146,7 @@ public class CanonicalTypes {
|
||||
myText = text;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiType getType(PsiElement context, final PsiManager manager) throws IncorrectOperationException {
|
||||
return JavaPsiFacade.getInstance(context.getProject()).getElementFactory().createTypeFromText(myText, context);
|
||||
}
|
||||
@@ -162,6 +169,7 @@ public class CanonicalTypes {
|
||||
mySubstitutor = substitutor;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiType getType(PsiElement context, final PsiManager manager) throws IncorrectOperationException {
|
||||
final JavaPsiFacade facade = JavaPsiFacade.getInstance(manager.getProject());
|
||||
final PsiElementFactory factory = facade.getElementFactory();
|
||||
@@ -205,6 +213,7 @@ public class CanonicalTypes {
|
||||
myTypes = types;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiType getType(final PsiElement context, final PsiManager manager) throws IncorrectOperationException {
|
||||
final List<PsiType> types = ContainerUtil.map(myTypes, new Function<Type, PsiType>() {
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
interface Foo {}
|
||||
interface FooEx<T> extends Foo {
|
||||
T foo();
|
||||
}
|
||||
|
||||
class Bar {
|
||||
{
|
||||
Foo f = new FooEx<<caret>>() {};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
interface Foo {}
|
||||
interface FooEx<T> extends Foo {
|
||||
T foo();
|
||||
}
|
||||
|
||||
class Bar {
|
||||
{
|
||||
Foo f = new FE<caret>
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import java.util.Map;
|
||||
|
||||
// "Import Class" "true"
|
||||
public class Foo {
|
||||
void foo() {
|
||||
Ma<caret>p<> l;
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// "Import Class" "true"
|
||||
public class Foo {
|
||||
void foo() {
|
||||
Ma<caret>p<> l;
|
||||
}
|
||||
}
|
||||
+2
@@ -861,6 +861,8 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testUnboundTypeArgs() throws Exception { doTest(); }
|
||||
|
||||
public void testIDEADEV2668() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.intention;
|
||||
|
||||
import com.intellij.codeInsight.daemon.LightIntentionActionTestCase;
|
||||
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
|
||||
public class AddImportActionTest extends LightIntentionActionTestCase {
|
||||
|
||||
public void test() throws Exception {
|
||||
final LanguageLevelProjectExtension extension = LanguageLevelProjectExtension.getInstance(getProject());
|
||||
|
||||
extension.setLanguageLevel(LanguageLevel.JDK_1_5);
|
||||
doAllTests();
|
||||
|
||||
extension.setLanguageLevel(LanguageLevel.HIGHEST);
|
||||
doAllTests();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return "/codeInsight/daemonCodeAnalyzer/quickFix/addImport";
|
||||
}
|
||||
}
|
||||
+13
-3
@@ -29,9 +29,10 @@ public class CompletionParameters {
|
||||
private final CompletionType myCompletionType;
|
||||
private final int myOffset;
|
||||
private final int myInvocationCount;
|
||||
private final boolean myRelaxedMatching;
|
||||
|
||||
protected CompletionParameters(@NotNull final PsiElement position, @NotNull final PsiFile originalFile,
|
||||
final CompletionType completionType, int offset, final int invocationCount) {
|
||||
final CompletionType completionType, int offset, final int invocationCount, final boolean relaxedMatching) {
|
||||
assert offset >= position.getTextRange().getStartOffset();
|
||||
myPosition = position;
|
||||
assert position.isValid();
|
||||
@@ -39,14 +40,19 @@ public class CompletionParameters {
|
||||
myCompletionType = completionType;
|
||||
myOffset = offset;
|
||||
myInvocationCount = invocationCount;
|
||||
myRelaxedMatching = relaxedMatching;
|
||||
}
|
||||
|
||||
public CompletionParameters withType(CompletionType type) {
|
||||
return new CompletionParameters(myPosition, myOriginalFile, type, myOffset, myInvocationCount);
|
||||
return new CompletionParameters(myPosition, myOriginalFile, type, myOffset, myInvocationCount, myRelaxedMatching);
|
||||
}
|
||||
|
||||
public CompletionParameters withInvocationCount(int newCount) {
|
||||
return new CompletionParameters(myPosition, myOriginalFile, myCompletionType, myOffset, newCount);
|
||||
return new CompletionParameters(myPosition, myOriginalFile, myCompletionType, myOffset, newCount, myRelaxedMatching);
|
||||
}
|
||||
|
||||
public CompletionParameters withRelaxedMatching() {
|
||||
return new CompletionParameters(myPosition, myOriginalFile, myCompletionType, myOffset, myInvocationCount, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -82,4 +88,8 @@ public class CompletionParameters {
|
||||
public int getInvocationCount() {
|
||||
return myInvocationCount;
|
||||
}
|
||||
|
||||
public boolean relaxMatching() {
|
||||
return myRelaxedMatching;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ public class FindModel extends UserDataHolderBase implements Cloneable {
|
||||
void findModelChanged(FindModel findModel);
|
||||
}
|
||||
|
||||
private CopyOnWriteArrayList<FindModelObserver> myObservers = new CopyOnWriteArrayList<FindModelObserver>();
|
||||
private final CopyOnWriteArrayList<FindModelObserver> myObservers = new CopyOnWriteArrayList<FindModelObserver>();
|
||||
|
||||
public void addObserver(FindModelObserver observer) {
|
||||
myObservers.add(observer);
|
||||
@@ -712,7 +712,7 @@ public class FindModel extends UserDataHolderBase implements Cloneable {
|
||||
}
|
||||
|
||||
public void setCustomScope(final SearchScope customScope) {
|
||||
boolean changed = this.customScope != null ? this.customScope.equals(customScope) : (customScope != null);
|
||||
boolean changed = this.customScope != null ? this.customScope.equals(customScope) : customScope != null;
|
||||
this.customScope = customScope;
|
||||
if (changed) {
|
||||
notifyObservers();
|
||||
@@ -766,7 +766,7 @@ public class FindModel extends UserDataHolderBase implements Cloneable {
|
||||
myPattern = pattern = Pattern.compile(toFind, isCaseSensitive() ? Pattern.MULTILINE : Pattern.MULTILINE | Pattern.CASE_INSENSITIVE);
|
||||
}
|
||||
catch(PatternSyntaxException e){
|
||||
LOG.error(e);
|
||||
LOG.error("Regexp:'"+toFind+"'", e);
|
||||
myPattern = null;
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.ModificationTracker;
|
||||
|
||||
public interface PsiModificationTracker extends ModificationTracker {
|
||||
|
||||
/**
|
||||
* This key can be passed as a dependency in a {@link com.intellij.psi.util.CachedValueProvider}.
|
||||
* @see #getModificationCount()
|
||||
@@ -48,12 +47,6 @@ public interface PsiModificationTracker extends ModificationTracker {
|
||||
|
||||
long getJavaStructureModificationCount();
|
||||
|
||||
/**
|
||||
* Tracks modifications in Java annotations and annotated classes and methods.
|
||||
* @return current counter value.
|
||||
*/
|
||||
long getAnnotationModificationCount();
|
||||
|
||||
interface Listener {
|
||||
void modificationCountChanged();
|
||||
}
|
||||
|
||||
@@ -25,10 +25,11 @@ import org.jetbrains.annotations.NotNull;
|
||||
/**
|
||||
* RefactoringActionHandler is an implementation of IDEA refactoring,
|
||||
* with dialogs, UI and all.
|
||||
* It is what gets invoked when user choses an item from 'Refactoring' menu.<br>
|
||||
* It is what gets invoked when user chooses an item from 'Refactoring' menu.<br>
|
||||
*
|
||||
* <code>RefactoringActionHandler</code> is a "one-shot" object: you should not
|
||||
* invoke it twice.
|
||||
*
|
||||
* @see RefactoringActionHandlerFactory
|
||||
*/
|
||||
public interface RefactoringActionHandler {
|
||||
@@ -36,8 +37,9 @@ public interface RefactoringActionHandler {
|
||||
* Invokes refactoring action from editor. The refactoring obtains
|
||||
* all data from editor selection.
|
||||
*
|
||||
* @param editor editor that refactoring is invoked in
|
||||
* @param file file should correspond to <code>editor</code>
|
||||
* @param project the project in which the refactoring is invoked.
|
||||
* @param editor editor that refactoring is invoked in
|
||||
* @param file file should correspond to <code>editor</code>
|
||||
* @param dataContext can be null for some but not all of refactoring action handlers
|
||||
* (it is recommended to pass DataManager.getDataContext() instead of null)
|
||||
*/
|
||||
@@ -47,8 +49,8 @@ public interface RefactoringActionHandler {
|
||||
* Invokes refactoring action from elsewhere (not from editor). Some refactorings
|
||||
* do not implement this method.
|
||||
*
|
||||
* @param project the project in which the refactoring is invoked.
|
||||
* @param elements list of elements that refactoring should work on. Refactoring-dependent.
|
||||
* @param project the project in which the refactoring is invoked.
|
||||
* @param elements list of elements that refactoring should work on. Refactoring-dependent.
|
||||
* @param dataContext can be null for some but not all of refactoring action handlers
|
||||
* (it is recommended to pass DataManager.getDataContext() instead of null)
|
||||
*/
|
||||
|
||||
+2
-1
@@ -88,7 +88,8 @@ public abstract class TextEditorHighlightingPass implements HighlightingPass {
|
||||
public final void applyInformationToEditor() {
|
||||
if (!isValid()) return; // Document has changed.
|
||||
if (DumbService.getInstance(myProject).isDumb() && !(this instanceof DumbAware)) {
|
||||
PsiFile file = PsiDocumentManager.getInstance(myProject).getPsiFile(getDocument());
|
||||
Document document = getDocument();
|
||||
PsiFile file = document == null ? null : PsiDocumentManager.getInstance(myProject).getPsiFile(document);
|
||||
if (file != null) {
|
||||
((DaemonCodeAnalyzerImpl)DaemonCodeAnalyzer.getInstance(myProject)).getFileStatusMap().markFileUpToDate(getDocument(), file, getId());
|
||||
}
|
||||
|
||||
+13
-3
@@ -53,6 +53,7 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.codeStyle.NameUtil;
|
||||
import com.intellij.psi.impl.PsiFileEx;
|
||||
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
|
||||
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
|
||||
@@ -291,11 +292,20 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
|
||||
indicator.duringCompletion(initContext);
|
||||
ProgressManager.checkCanceled();
|
||||
|
||||
data.set(CompletionService.getCompletionService().performCompletion(parameters, new Consumer<LookupElement>() {
|
||||
Consumer<LookupElement> consumer = new Consumer<LookupElement>() {
|
||||
public void consume(final LookupElement lookupElement) {
|
||||
indicator.addItem(lookupElement);
|
||||
}
|
||||
}));
|
||||
};
|
||||
LookupElement[] result = CompletionService.getCompletionService().performCompletion(parameters, consumer);
|
||||
if (NameUtil.isUseMinusculeHumpMatcher() && parameters.getInvocationCount() == 0) {
|
||||
if (result.length == 0) {
|
||||
result = CompletionService.getCompletionService().performCompletion(parameters.withRelaxedMatching(), consumer);
|
||||
} else {
|
||||
indicator.restartOnEmpty = true;
|
||||
}
|
||||
}
|
||||
data.set(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -347,7 +357,7 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
|
||||
LOG.error("wrong text: copy='" + fileCopy.getText() + "'; element='" + insertedElement.getText() + "'; range=" + range);
|
||||
}
|
||||
|
||||
return new CompletionParameters(insertedElement, fileCopy.getOriginalFile(), myCompletionType, offset, invocationCount);
|
||||
return new CompletionParameters(insertedElement, fileCopy.getOriginalFile(), myCompletionType, offset, invocationCount, invocationCount >= 2);
|
||||
}
|
||||
|
||||
private AutoCompletionDecision shouldAutoComplete(
|
||||
|
||||
+7
-2
@@ -18,6 +18,7 @@ package com.intellij.codeInsight.completion;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightSettings;
|
||||
import com.intellij.codeInsight.completion.impl.CompletionServiceImpl;
|
||||
import com.intellij.codeInsight.editorActions.CompletionAutoPopupHandler;
|
||||
import com.intellij.codeInsight.hint.EditorHintListener;
|
||||
import com.intellij.codeInsight.hint.HintManager;
|
||||
import com.intellij.codeInsight.lookup.*;
|
||||
@@ -399,7 +400,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
Disposer.dispose(myQueue);
|
||||
|
||||
CompletionProgressIndicator currentCompletion = CompletionServiceImpl.getCompletionService().getCurrentCompletion();
|
||||
assert currentCompletion == this : currentCompletion + "!=" + this;
|
||||
LOG.assertTrue(currentCompletion == this, currentCompletion + "!=" + this);
|
||||
CompletionServiceImpl.getCompletionService().setCurrentCompletion(null);
|
||||
|
||||
CompletionServiceImpl.assertPhase(CompletionPhase.BgCalculation.class, CompletionPhase.ItemsCalculated.class, CompletionPhase.Synchronous.class, CompletionPhase.Restarted.class);
|
||||
@@ -573,6 +574,8 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
}
|
||||
}
|
||||
|
||||
public boolean restartOnEmpty = false;
|
||||
|
||||
public void prefixUpdated() {
|
||||
final CharSequence text = myEditor.getDocument().getCharsSequence();
|
||||
final int caretOffset = myEditor.getCaretModel().getOffset();
|
||||
@@ -585,7 +588,9 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
}
|
||||
}
|
||||
|
||||
hideAutopopupIfMeaningless();
|
||||
if (hideAutopopupIfMeaningless() && restartOnEmpty) {
|
||||
CompletionAutoPopupHandler.scheduleAutoPopup(getProject(), myEditor, getParameters().getOriginalFile());
|
||||
}
|
||||
updateFocus();
|
||||
}
|
||||
|
||||
|
||||
+16
-5
@@ -28,13 +28,15 @@ public class CamelHumpMatcher extends PrefixMatcher {
|
||||
private NameUtil.Matcher myMatcher;
|
||||
private final boolean myCaseSensitive;
|
||||
private final int currentSetting;
|
||||
private final boolean myRelaxedMatching;
|
||||
|
||||
public CamelHumpMatcher(@NotNull final String prefix) {
|
||||
this(prefix, true);
|
||||
this(prefix, true, false);
|
||||
}
|
||||
|
||||
public CamelHumpMatcher(String prefix, boolean caseSensitive) {
|
||||
public CamelHumpMatcher(String prefix, boolean caseSensitive, boolean relaxedMatching) {
|
||||
super(prefix);
|
||||
myRelaxedMatching = relaxedMatching;
|
||||
currentSetting = CodeInsightSettings.getInstance().COMPLETION_CASE_SENSITIVE;
|
||||
myCaseSensitive = caseSensitive;
|
||||
}
|
||||
@@ -47,10 +49,11 @@ public class CamelHumpMatcher extends PrefixMatcher {
|
||||
ourLastCompletionCaseSetting = currentSetting;
|
||||
}
|
||||
|
||||
NameUtil.Matcher pattern = ourPatternCache.get(myPrefix);
|
||||
String key = myRelaxedMatching + myPrefix;
|
||||
NameUtil.Matcher pattern = ourPatternCache.get(key);
|
||||
if (pattern == null) {
|
||||
pattern = createCamelHumpsMatcher();
|
||||
ourPatternCache.put(myPrefix, pattern);
|
||||
ourPatternCache.put(key, pattern);
|
||||
}
|
||||
myMatcher = pattern;
|
||||
}
|
||||
@@ -81,7 +84,7 @@ public class CamelHumpMatcher extends PrefixMatcher {
|
||||
|
||||
@NotNull
|
||||
public PrefixMatcher cloneWithPrefix(@NotNull final String prefix) {
|
||||
return new CamelHumpMatcher(prefix);
|
||||
return new CamelHumpMatcher(prefix, myCaseSensitive, myRelaxedMatching);
|
||||
}
|
||||
|
||||
private NameUtil.Matcher createCamelHumpsMatcher() {
|
||||
@@ -89,6 +92,10 @@ public class CamelHumpMatcher extends PrefixMatcher {
|
||||
return NameUtil.buildCompletionMatcher(myPrefix, 0, true, true);
|
||||
}
|
||||
|
||||
if (myRelaxedMatching) {
|
||||
return NameUtil.buildCompletionMatcher(myPrefix, 0, true, true);
|
||||
}
|
||||
|
||||
switch (CodeInsightSettings.getInstance().COMPLETION_CASE_SENSITIVE) {
|
||||
case CodeInsightSettings.NONE:
|
||||
return NameUtil.buildCompletionMatcher(myPrefix, 0, true, true);
|
||||
@@ -106,4 +113,8 @@ public class CamelHumpMatcher extends PrefixMatcher {
|
||||
public String toString() {
|
||||
return myPrefix;
|
||||
}
|
||||
|
||||
public boolean isRelaxedMatching() {
|
||||
return myRelaxedMatching;
|
||||
}
|
||||
}
|
||||
|
||||
+5
-3
@@ -82,7 +82,7 @@ public class CompletionServiceImpl extends CompletionService{
|
||||
final PsiElement position = parameters.getPosition();
|
||||
final String prefix = CompletionData.findPrefixStatic(position, parameters.getOffset());
|
||||
final String textBeforePosition = parameters.getPosition().getContainingFile().getText().substring(0, parameters.getOffset());
|
||||
return new CompletionResultSetImpl(consumer, textBeforePosition, new CamelHumpMatcher(prefix), contributor, defaultSorter(parameters), null);
|
||||
return new CompletionResultSetImpl(consumer, textBeforePosition, new CamelHumpMatcher(prefix, true, parameters.relaxMatching()), contributor, defaultSorter(parameters), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -148,7 +148,8 @@ public class CompletionServiceImpl extends CompletionService{
|
||||
|
||||
@NotNull
|
||||
public CompletionResultSet withPrefixMatcher(@NotNull final String prefix) {
|
||||
return withPrefixMatcher(new CamelHumpMatcher(prefix));
|
||||
boolean relaxed = getPrefixMatcher() instanceof CamelHumpMatcher && ((CamelHumpMatcher)getPrefixMatcher()).isRelaxedMatching();
|
||||
return withPrefixMatcher(new CamelHumpMatcher(prefix, true, relaxed));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -160,7 +161,8 @@ public class CompletionServiceImpl extends CompletionService{
|
||||
@NotNull
|
||||
@Override
|
||||
public CompletionResultSet caseInsensitive() {
|
||||
return withPrefixMatcher(new CamelHumpMatcher(getPrefixMatcher().getPrefix(), false));
|
||||
boolean relaxed = getPrefixMatcher() instanceof CamelHumpMatcher && ((CamelHumpMatcher)getPrefixMatcher()).isRelaxedMatching();
|
||||
return withPrefixMatcher(new CamelHumpMatcher(getPrefixMatcher().getPrefix(), false, relaxed));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -423,10 +423,12 @@ public class HighlightInfo implements Segment {
|
||||
}
|
||||
|
||||
public int getActualStartOffset() {
|
||||
return highlighter == null || !highlighter.isValid() ? startOffset : highlighter.getStartOffset();
|
||||
RangeHighlighterEx h = highlighter;
|
||||
return h == null || !h.isValid() ? startOffset : h.getStartOffset();
|
||||
}
|
||||
public int getActualEndOffset() {
|
||||
return highlighter == null || !highlighter.isValid() ? endOffset : highlighter.getEndOffset();
|
||||
RangeHighlighterEx h = highlighter;
|
||||
return h == null || !h.isValid() ? endOffset : h.getEndOffset();
|
||||
}
|
||||
|
||||
//public void setCustomColorScheme(@Nullable final EditorColorsScheme customColorScheme) {
|
||||
|
||||
+5
-1
@@ -76,6 +76,11 @@ public class CompletionAutoPopupHandler extends TypedHandlerDelegate {
|
||||
return Result.CONTINUE;
|
||||
}
|
||||
|
||||
scheduleAutoPopup(project, editor, file);
|
||||
return Result.STOP;
|
||||
}
|
||||
|
||||
public static void scheduleAutoPopup(final Project project, final Editor editor, final PsiFile file) {
|
||||
final boolean isMainEditor = FileEditorManager.getInstance(project).getSelectedTextEditor() == editor;
|
||||
|
||||
final CompletionPhase.AutoPopupAlarm phase = new CompletionPhase.AutoPopupAlarm();
|
||||
@@ -95,7 +100,6 @@ public class CompletionAutoPopupHandler extends TypedHandlerDelegate {
|
||||
}
|
||||
};
|
||||
AutoPopupController.getInstance(project).invokeAutoPopupRunnable(request, CodeInsightSettings.getInstance().AUTO_LOOKUP_DELAY);
|
||||
return Result.STOP;
|
||||
}
|
||||
|
||||
public static void invokeAutoPopupCompletion(Project project, final Editor editor) {
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -102,9 +103,12 @@ public class SelectWordUtil {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static TextRange getWordSelectionRange(CharSequence editorText, int cursorOffset) {
|
||||
if (editorText.length() == 0) return null;
|
||||
if (cursorOffset > 0 && !Character.isJavaIdentifierPart(editorText.charAt(cursorOffset)) &&
|
||||
@Nullable
|
||||
public static TextRange getWordSelectionRange(@NotNull CharSequence editorText, int cursorOffset) {
|
||||
int length = editorText.length();
|
||||
if (length == 0) return null;
|
||||
if (cursorOffset == length ||
|
||||
cursorOffset > 0 && !Character.isJavaIdentifierPart(editorText.charAt(cursorOffset)) &&
|
||||
Character.isJavaIdentifierPart(editorText.charAt(cursorOffset - 1))) {
|
||||
cursorOffset--;
|
||||
}
|
||||
@@ -117,7 +121,7 @@ public class SelectWordUtil {
|
||||
start--;
|
||||
}
|
||||
|
||||
while (end < editorText.length() && Character.isJavaIdentifierPart(editorText.charAt(end))) {
|
||||
while (end < length && Character.isJavaIdentifierPart(editorText.charAt(end))) {
|
||||
end++;
|
||||
}
|
||||
|
||||
|
||||
@@ -87,12 +87,12 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable {
|
||||
private final Project myProject;
|
||||
private final Editor myEditor;
|
||||
|
||||
private int myMinPrefixLength;
|
||||
private int myPreferredItemsCount;
|
||||
private String myInitialPrefix;
|
||||
private LookupArranger myCustomArranger;
|
||||
|
||||
private RangeMarker myLookupStartMarker;
|
||||
private boolean myStableStart;
|
||||
@NotNull private RangeMarker myLookupStartMarker;
|
||||
private final JList myList = new JBList(new DefaultListModel());
|
||||
private final LookupCellRenderer myCellRenderer;
|
||||
private Boolean myPositionedAbove = null;
|
||||
@@ -154,6 +154,8 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable {
|
||||
myIconPanel.setBackground(Color.LIGHT_GRAY);
|
||||
myIconPanel.add(myProcessIcon);
|
||||
|
||||
updateLookupStart(0);
|
||||
|
||||
final ListModel model = myList.getModel();
|
||||
addEmptyItem((DefaultListModel)model);
|
||||
updateListHeight(model);
|
||||
@@ -270,10 +272,6 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable {
|
||||
return myModel.getActionsFor(element);
|
||||
}
|
||||
|
||||
public int getMinPrefixLength() {
|
||||
return myMinPrefixLength;
|
||||
}
|
||||
|
||||
public JList getList() {
|
||||
return myList;
|
||||
}
|
||||
@@ -421,15 +419,17 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable {
|
||||
}
|
||||
|
||||
private void checkMinPrefixLengthChanges(Collection<LookupElement> items) {
|
||||
if (myStableStart) return;
|
||||
if (!myCalculating && !items.isEmpty()) {
|
||||
myStableStart = true;
|
||||
}
|
||||
|
||||
int minPrefixLength = items.isEmpty() ? 0 : Integer.MAX_VALUE;
|
||||
for (final LookupElement item : items) {
|
||||
minPrefixLength = Math.min(item.getPrefixMatcher().getPrefix().length(), minPrefixLength);
|
||||
}
|
||||
|
||||
if (myMinPrefixLength != minPrefixLength) {
|
||||
myLookupStartMarker = null;
|
||||
}
|
||||
myMinPrefixLength = minPrefixLength;
|
||||
updateLookupStart(minPrefixLength);
|
||||
}
|
||||
|
||||
private void restoreSelection(@Nullable LookupElement oldSelected, boolean choosePreselectedItem, @Nullable String oldInvariant) {
|
||||
@@ -568,7 +568,7 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable {
|
||||
Dimension dim = component.getPreferredSize();
|
||||
int lookupStart = getLookupStart();
|
||||
if (lookupStart < 0) {
|
||||
LOG.error(lookupStart + "; minprefix=" + myMinPrefixLength + "; offset=" + myEditor.getCaretModel().getOffset() + "; element=" +
|
||||
LOG.error(lookupStart + "; offset=" + myEditor.getCaretModel().getOffset() + "; element=" +
|
||||
getPsiElement());
|
||||
}
|
||||
|
||||
@@ -656,12 +656,6 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable {
|
||||
}
|
||||
|
||||
public int getLookupStart() {
|
||||
if (myLookupStartMarker == null) {
|
||||
final int start = calcLookupStart();
|
||||
myLookupStartMarker = myEditor.getDocument().createRangeMarker(start, start);
|
||||
myLookupStartMarker.setGreedyToLeft(true);
|
||||
}
|
||||
|
||||
return myLookupStartMarker.getStartOffset();
|
||||
}
|
||||
|
||||
@@ -675,6 +669,9 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable {
|
||||
finally {
|
||||
myChangeGuard = false;
|
||||
}
|
||||
if (isVisible()) {
|
||||
updateLookupBounds();
|
||||
}
|
||||
LOG.assertTrue(!myDisposed, disposeTrace);
|
||||
}
|
||||
|
||||
@@ -816,11 +813,14 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
private int calcLookupStart() {
|
||||
private int updateLookupStart(int myMinPrefixLength) {
|
||||
int offset = myEditor.getSelectionModel().hasSelection()
|
||||
? myEditor.getSelectionModel().getSelectionStart()
|
||||
: myEditor.getCaretModel().getOffset();
|
||||
return Math.max(offset - myMinPrefixLength - myAdditionalPrefix.length(), 0);
|
||||
int start = Math.max(offset - myMinPrefixLength - myAdditionalPrefix.length(), 0);
|
||||
myLookupStartMarker = myEditor.getDocument().createRangeMarker(start, start);
|
||||
myLookupStartMarker.setGreedyToLeft(true);
|
||||
return start;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -1138,8 +1138,7 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable {
|
||||
}
|
||||
|
||||
updateScrollbarVisibility();
|
||||
HintManagerImpl.adjustEditorHintPosition(this, myEditor, calculatePosition(getComponent()));
|
||||
layoutStatusIcons();
|
||||
updateLookupBounds();
|
||||
|
||||
if (reused) {
|
||||
ensureSelectionVisible();
|
||||
@@ -1147,6 +1146,11 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
private void updateLookupBounds() {
|
||||
HintManagerImpl.adjustEditorHintPosition(this, myEditor, calculatePosition(getComponent()));
|
||||
layoutStatusIcons();
|
||||
}
|
||||
|
||||
private void layoutStatusIcons() {
|
||||
final JLayeredPane layeredPane = getComponent().getRootPane().getLayeredPane();
|
||||
|
||||
|
||||
@@ -126,8 +126,11 @@ public class TypedHandler implements TypedActionHandler {
|
||||
|
||||
@Nullable
|
||||
private static CharFilter.Result getFiltersDecision(char charTyped, LookupImpl lookup) {
|
||||
LookupElement item = lookup.getCurrentItem();
|
||||
int prefixLength = (item == null ? 0 : item.getPrefixMatcher().getPrefix().length()) + lookup.getAdditionalPrefix().length();
|
||||
|
||||
for (final CharFilter extension : getFilters()) {
|
||||
final CharFilter.Result result = extension.acceptChar(charTyped, lookup.getMinPrefixLength() + lookup.getAdditionalPrefix().length(), lookup);
|
||||
final CharFilter.Result result = extension.acceptChar(charTyped, prefixLength, lookup);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ import com.intellij.openapi.fileEditor.ex.IdeDocumentHistory;
|
||||
import com.intellij.openapi.keymap.KeymapUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.JDOMUtil;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
@@ -699,7 +700,7 @@ public class FindUtil {
|
||||
};
|
||||
editor.getCaretModel().addCaretListener(listener);
|
||||
}
|
||||
JComponent component = HintUtil.createInformationLabel(message);
|
||||
JComponent component = HintUtil.createInformationLabel(JDOMUtil.escapeText(message, false, false));
|
||||
final LightweightHint hint = new LightweightHint(component);
|
||||
HintManagerImpl.getInstanceImpl().showEditorHint(hint, editor, HintManager.UNDER,
|
||||
HintManager.HIDE_BY_ANY_KEY | HintManager.HIDE_BY_TEXT_CHANGE | HintManager.HIDE_BY_SCROLLING,
|
||||
|
||||
+3
-2
@@ -133,10 +133,11 @@ public class LivePreviewControllerBase implements LivePreview.Delegate, FindUtil
|
||||
myUserActivityDelay = userActivityDelay;
|
||||
}
|
||||
|
||||
public void updateInBackground(final FindModel findModel, final boolean allowedToChangedEditorSelection) {
|
||||
public void updateInBackground(FindModel findModel, final boolean allowedToChangedEditorSelection) {
|
||||
myLivePreviewAlarm.cancelAllRequests();
|
||||
if (findModel == null) return;
|
||||
final boolean unitTestMode = ApplicationManager.getApplication().isUnitTestMode();
|
||||
final FindModel copy = (FindModel)findModel.clone();
|
||||
Runnable request = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -151,7 +152,7 @@ public class LivePreviewControllerBase implements LivePreview.Delegate, FindUtil
|
||||
} else {
|
||||
ApplicationManager.getApplication().invokeAndWait(denyReplace, ModalityState.NON_MODAL);
|
||||
}
|
||||
mySearchResults.updateThreadSafe(findModel, allowedToChangedEditorSelection, null);
|
||||
mySearchResults.updateThreadSafe(copy, allowedToChangedEditorSelection, null);
|
||||
}
|
||||
};
|
||||
if (unitTestMode) {
|
||||
|
||||
@@ -13,30 +13,26 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: mike
|
||||
* Date: Jul 18, 2002
|
||||
* Time: 5:57:57 PM
|
||||
* To change template for new class use
|
||||
* Code Style | Class Templates options (Tools | IDE Options).
|
||||
*/
|
||||
package com.intellij.psi.impl;
|
||||
|
||||
import com.intellij.ProjectTopics;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.util.messages.MessageBus;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* @author mike
|
||||
* Date: Jul 18, 2002
|
||||
*/
|
||||
public class PsiModificationTrackerImpl implements PsiModificationTracker, PsiTreeChangePreprocessor {
|
||||
private volatile long myModificationCount = 0;
|
||||
private volatile long myOutOfCodeBlockModificationCount = 0;
|
||||
private volatile long myJavaStructureModificationCount = 0;
|
||||
private volatile long myAnnotationModificationCount = 0;
|
||||
private final AtomicLong myModificationCount = new AtomicLong(0);
|
||||
private final AtomicLong myOutOfCodeBlockModificationCount = new AtomicLong(0);
|
||||
private final AtomicLong myJavaStructureModificationCount = new AtomicLong(0);
|
||||
private final Listener myPublisher;
|
||||
|
||||
public PsiModificationTrackerImpl(Project project) {
|
||||
@@ -58,23 +54,19 @@ public class PsiModificationTrackerImpl implements PsiModificationTracker, PsiTr
|
||||
});
|
||||
}
|
||||
|
||||
public void incCounter(){
|
||||
myModificationCount++;
|
||||
myJavaStructureModificationCount++;
|
||||
public void incCounter() {
|
||||
myModificationCount.getAndIncrement();
|
||||
myJavaStructureModificationCount.getAndIncrement();
|
||||
incOutOfCodeBlockModificationCounter();
|
||||
}
|
||||
|
||||
public void incOutOfCodeBlockModificationCounter() {
|
||||
myOutOfCodeBlockModificationCount++;
|
||||
myOutOfCodeBlockModificationCount.getAndIncrement();
|
||||
myPublisher.modificationCountChanged();
|
||||
}
|
||||
|
||||
public void incAnnotationModificationCounter() {
|
||||
myAnnotationModificationCount++;
|
||||
}
|
||||
|
||||
public void treeChanged(PsiTreeChangeEventImpl event) {
|
||||
myModificationCount++;
|
||||
myModificationCount.getAndIncrement();
|
||||
if (event.getParent() instanceof PsiDirectory) {
|
||||
incOutOfCodeBlockModificationCounter();
|
||||
}
|
||||
@@ -83,18 +75,14 @@ public class PsiModificationTrackerImpl implements PsiModificationTracker, PsiTr
|
||||
}
|
||||
|
||||
public long getModificationCount() {
|
||||
return myModificationCount;
|
||||
return myModificationCount.get();
|
||||
}
|
||||
|
||||
public long getOutOfCodeBlockModificationCount() {
|
||||
return myOutOfCodeBlockModificationCount;
|
||||
return myOutOfCodeBlockModificationCount.get();
|
||||
}
|
||||
|
||||
public long getJavaStructureModificationCount() {
|
||||
return myJavaStructureModificationCount;
|
||||
}
|
||||
|
||||
public long getAnnotationModificationCount() {
|
||||
return myAnnotationModificationCount;
|
||||
return myJavaStructureModificationCount.get();
|
||||
}
|
||||
}
|
||||
|
||||
+3
-4
@@ -81,8 +81,8 @@ public class IndexCacheManagerImpl implements CacheManager{
|
||||
return processor.getResults().isEmpty() ? PsiFile.EMPTY_ARRAY : processor.toArray(PsiFile.EMPTY_ARRAY);
|
||||
}
|
||||
|
||||
public static boolean shouldBeFound(VirtualFile virtualFile, ProjectFileIndex index) {
|
||||
return (index.isInContent(virtualFile) || index.isInLibrarySource(virtualFile)) && !virtualFile.getFileType().isBinary();
|
||||
public static boolean shouldBeFound(GlobalSearchScope scope, VirtualFile virtualFile, ProjectFileIndex index) {
|
||||
return (scope.isSearchOutsideRootModel() || index.isInContent(virtualFile) || index.isInLibrarySource(virtualFile)) && !virtualFile.getFileType().isBinary();
|
||||
}
|
||||
|
||||
public boolean processFilesWithWord(@NotNull final Processor<PsiFile> psiFileProcessor, @NotNull final String word, final short occurrenceMask, @NotNull final GlobalSearchScope scope, final boolean caseSensitively) {
|
||||
@@ -111,13 +111,12 @@ public class IndexCacheManagerImpl implements CacheManager{
|
||||
if (vFiles.isEmpty()) return true;
|
||||
|
||||
final ProjectFileIndex index = ProjectRootManager.getInstance(myProject).getFileIndex();
|
||||
final boolean globalScope = scope.isSearchOutsideRootModel();
|
||||
|
||||
final Processor<VirtualFile> virtualFileProcessor = new ReadActionProcessor<VirtualFile>() {
|
||||
@Override
|
||||
public boolean processInReadAction(VirtualFile virtualFile) {
|
||||
LOG.assertTrue(virtualFile.isValid());
|
||||
if (virtualFile.isValid() && scope.contains(virtualFile) && (globalScope || shouldBeFound(virtualFile, index))) {
|
||||
if (virtualFile.isValid() && scope.contains(virtualFile) && shouldBeFound(scope, virtualFile, index)) {
|
||||
final PsiFile psiFile = myPsiManager.findFile(virtualFile);
|
||||
return psiFile == null || psiFileProcessor.process(psiFile);
|
||||
}
|
||||
|
||||
@@ -674,21 +674,20 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
|
||||
final GlobalSearchScope commonScope,
|
||||
final ProgressIndicator progress) {
|
||||
final MultiMap<VirtualFile, RequestWithProcessor> local = createMultiMap();
|
||||
final boolean inRootsOnly = !commonScope.isSearchOutsideRootModel();
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
if (progress != null) progress.checkCanceled();
|
||||
FileBasedIndex.getInstance().processValues(IdIndex.NAME, entry, null, new FileBasedIndex.ValueProcessor<Integer>() {
|
||||
public boolean process(VirtualFile file, Integer value) {
|
||||
if (progress != null) progress.checkCanceled();
|
||||
if (inRootsOnly && !IndexCacheManagerImpl.shouldBeFound(file, index)) {
|
||||
return true;
|
||||
}
|
||||
int mask = value.intValue();
|
||||
for (RequestWithProcessor single : data) {
|
||||
final PsiSearchRequest request = single.request;
|
||||
if ((mask & request.searchContext) != 0 && ((GlobalSearchScope)request.searchScope).contains(file)) {
|
||||
local.putValue(file, single);
|
||||
|
||||
if (IndexCacheManagerImpl.shouldBeFound(commonScope, file, index)) {
|
||||
int mask = value.intValue();
|
||||
for (RequestWithProcessor single : data) {
|
||||
final PsiSearchRequest request = single.request;
|
||||
if ((mask & request.searchContext) != 0 && ((GlobalSearchScope)request.searchScope).contains(file)) {
|
||||
local.putValue(file, single);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
+5
@@ -166,4 +166,9 @@ public class InjectedFileViewProvider extends SingleRootFileViewProvider {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Injected file '"+getVirtualFile().getName()+"' " + (isValid() ? "" : " invalid") + (physical ? "" : " nonphysical");
|
||||
}
|
||||
}
|
||||
|
||||
+9
-3
@@ -102,10 +102,16 @@ public abstract class ParameterTableModelBase<P extends ParameterInfo> extends L
|
||||
if (!table.isCellEditable(row, table.convertColumnIndexToModel(column))) {
|
||||
Color bg = table.getBackground().darker();
|
||||
component.setBackground(new Color(bg.getRed(), bg.getGreen(), bg.getBlue(), 230));
|
||||
if (component instanceof EditorTextField) {
|
||||
((EditorTextField)component).setCenterByHeight(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (component instanceof EditorTextField) {
|
||||
((EditorTextField)component).setCenterByHeight(false);
|
||||
}
|
||||
|
||||
if (component instanceof SimpleColoredComponent) {
|
||||
((SimpleColoredComponent)component).setIpad(new Insets(0, 0, 0, 0));
|
||||
}
|
||||
|
||||
return component;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -63,6 +63,12 @@ public class CodeFragmentTableCellRenderer implements TableCellRenderer {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (!table.isShowing()) {
|
||||
editorTextField.ensureWillComputePreferredSize();
|
||||
}
|
||||
|
||||
editorTextField.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
|
||||
editorTextField.setBorder(hasFocus ? BorderFactory.createLineBorder(table.getForeground()): new EmptyBorder(1, 1, 1, 1));
|
||||
return editorTextField;
|
||||
}
|
||||
|
||||
@@ -3338,11 +3338,6 @@ public class AbstractTreeUi {
|
||||
notified = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!notified) {
|
||||
myTreeModel.nodeChanged(node);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public DefaultTreeModel getTreeModel() {
|
||||
|
||||
@@ -43,15 +43,17 @@ public class DataKey<T> {
|
||||
}
|
||||
|
||||
public static <T> DataKey<T> create(@NotNull @NonNls String name) {
|
||||
if (ourDataKeyIndex.containsKey(name)) {
|
||||
//noinspection unchecked
|
||||
return ourDataKeyIndex.get(name);
|
||||
//noinspection unchecked
|
||||
DataKey<T> key = ourDataKeyIndex.get(name);
|
||||
if (key != null) {
|
||||
return key;
|
||||
}
|
||||
DataKey<T> key = new DataKey<T>(name);
|
||||
key = new DataKey<T>(name);
|
||||
ourDataKeyIndex.put(name, key);
|
||||
return key;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return myName;
|
||||
}
|
||||
@@ -74,7 +76,7 @@ public class DataKey<T> {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public T getData(DataProvider dataProvider) {
|
||||
public T getData(@NotNull DataProvider dataProvider) {
|
||||
//noinspection unchecked
|
||||
return (T) dataProvider.getData(myName);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,9 @@ public class BooleanTableCellRenderer extends JCheckBox implements TableCellRend
|
||||
|
||||
public BooleanTableCellRenderer() {
|
||||
super();
|
||||
setHorizontalAlignment(JLabel.CENTER);
|
||||
setHorizontalAlignment(CENTER);
|
||||
setVerticalAlignment(CENTER);
|
||||
setBorder(null);
|
||||
}
|
||||
|
||||
public Component getTableCellRendererComponent(JTable table, Object value,
|
||||
|
||||
@@ -49,6 +49,11 @@ public class JBViewport extends JViewport {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
return super.getPreferredSize(); //To change body of overridden methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
super.paint(g);
|
||||
|
||||
@@ -48,7 +48,7 @@ public class HintUtil {
|
||||
HintHint hintHint = new HintHint().setTextBg(INFORMATION_COLOR).setTextFg(Color.black).setFont(getBoldFont()).setAwtTooltip(true);
|
||||
|
||||
HintLabel label = new HintLabel();
|
||||
label.setText(JDOMUtil.escapeText(text, false, false), hintHint);
|
||||
label.setText(text, hintHint);
|
||||
label.setIcon(INFORMATION_ICON);
|
||||
|
||||
if (!hintHint.isAwtTooltip()) {
|
||||
|
||||
+2
-1
@@ -379,7 +379,7 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements
|
||||
return myDisposed || temporarilyDisposed;
|
||||
}
|
||||
|
||||
private volatile boolean temporarilyDisposed = false;
|
||||
protected volatile boolean temporarilyDisposed = false;
|
||||
@TestOnly
|
||||
public void setTemporarilyDisposed(boolean disposed) {
|
||||
temporarilyDisposed = disposed;
|
||||
@@ -725,6 +725,7 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements
|
||||
return super.hashCode();
|
||||
}
|
||||
|
||||
@SuppressWarnings({"EqualsWhichDoesntCheckParameterClass"})
|
||||
public final boolean equals(Object obj) {
|
||||
return super.equals(obj);
|
||||
}
|
||||
|
||||
@@ -81,11 +81,13 @@ public class RangeMarkerImpl extends UserDataHolderBase implements RangeMarkerEx
|
||||
}
|
||||
|
||||
public int getStartOffset() {
|
||||
return intervalStart() + (myNode == null ? 0 : myNode.computeDeltaUpToRoot());
|
||||
RangeMarkerTree.RMNode node = myNode;
|
||||
return intervalStart() + (node == null ? 0 : node.computeDeltaUpToRoot());
|
||||
}
|
||||
|
||||
public int getEndOffset() {
|
||||
return intervalEnd() + (myNode == null ? 0 : myNode.computeDeltaUpToRoot());
|
||||
RangeMarkerTree.RMNode node = myNode;
|
||||
return intervalEnd() + (node == null ? 0 : node.computeDeltaUpToRoot());
|
||||
}
|
||||
|
||||
public void invalidate() {
|
||||
|
||||
@@ -144,7 +144,7 @@ public abstract class RedBlackTree<K> {
|
||||
|
||||
Node<K> e = n;
|
||||
while (e.getParent() != null) e = e.getParent();
|
||||
assert e == root; // assert the node belongs to our tree
|
||||
assert e == root : e; // assert the node belongs to our tree
|
||||
|
||||
if (n.getLeft() != null && n.getRight() != null) {
|
||||
// Copy key/value from predecessor and then delete it instead
|
||||
|
||||
+2
-2
@@ -1568,14 +1568,14 @@ private final class MyVirtualFileListener extends VirtualFileAdapter {
|
||||
// already open
|
||||
if (eachWindow.findFileIndex(newFile) != -1) continue;
|
||||
|
||||
closeFile(eachFile, eachWindow);
|
||||
try {
|
||||
newFile.putUserData(EditorWindow.INITIAL_INDEX_KEY, i);
|
||||
openFile(newFile, eachFile == selected);
|
||||
openFileImpl2(eachWindow, newFile, eachFile == selected);
|
||||
}
|
||||
finally {
|
||||
newFile.putUserData(EditorWindow.INITIAL_INDEX_KEY, null);
|
||||
}
|
||||
closeFile(eachFile, eachWindow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -454,7 +454,8 @@ public class ProjectImpl extends ComponentManagerImpl implements ProjectEx {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Project"
|
||||
+ (isDisposed() ? " (Disposed)" : isDefault() ? "" : " '" + getLocation()+"'")
|
||||
+ (isDisposed() ? " (Disposed" + (temporarilyDisposed ? " temporarily" : "") + ")"
|
||||
:isDefault() ? "" : " '" + getLocation()+"'")
|
||||
+ (isDefault() ? " (Default)" : "")
|
||||
+ " " + myName
|
||||
;
|
||||
|
||||
+4
-7
@@ -170,7 +170,9 @@ public class IdeStatusBarImpl extends JComponent implements StatusBarEx {
|
||||
Disposer.register(Disposer.get("ui"), this);
|
||||
}
|
||||
|
||||
addWidget(new ToolWindowsWidget(), Position.LEFT);
|
||||
if (master == null) {
|
||||
addWidget(new ToolWindowsWidget(), Position.LEFT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -762,7 +764,7 @@ public class IdeStatusBarImpl extends JComponent implements StatusBarEx {
|
||||
return myFrame;
|
||||
}
|
||||
|
||||
private static class ToolWindowsWidget extends JLabel implements CustomStatusBarWidget, StatusBarWidget.Multiframe, Disposable,
|
||||
private static class ToolWindowsWidget extends JLabel implements CustomStatusBarWidget, StatusBarWidget, Disposable,
|
||||
UISettingsListener, PropertyChangeListener {
|
||||
|
||||
private static final Icon HIDDEN = IconLoader.getIcon("/general/tbShown.png");
|
||||
@@ -841,11 +843,6 @@ public class IdeStatusBarImpl extends JComponent implements StatusBarEx {
|
||||
return myStatusBar != null && myStatusBar.getFrame() != null && myStatusBar.getFrame().getProject() != null && Registry.is("ide.windowSystem.showTooWindowButtonsSwitcher");
|
||||
}
|
||||
|
||||
@Override
|
||||
public StatusBarWidget copy() {
|
||||
return new ToolWindowsWidget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getComponent() {
|
||||
return this;
|
||||
|
||||
@@ -74,6 +74,8 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener,
|
||||
private Color myEnforcedBgColor = null;
|
||||
private boolean myOneLineMode; // use getter to access this field! It is allowed to override getter and change initial behaviour
|
||||
private boolean myCenterByHeight = true;
|
||||
private boolean myEnsureWillComputePreferredSize;
|
||||
private Dimension myPassivePreferredSize;
|
||||
|
||||
public EditorTextField() {
|
||||
this("");
|
||||
@@ -307,9 +309,7 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener,
|
||||
|
||||
boolean isFocused = isFocusOwner();
|
||||
|
||||
myEditor = createEditor();
|
||||
final JComponent component = myEditor.getComponent();
|
||||
add(component);
|
||||
initEditor();
|
||||
|
||||
super.addNotify();
|
||||
|
||||
@@ -323,6 +323,12 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener,
|
||||
}
|
||||
}
|
||||
|
||||
private void initEditor() {
|
||||
myEditor = createEditor();
|
||||
final JComponent component = myEditor.getComponent();
|
||||
add(component);
|
||||
}
|
||||
|
||||
public void removeNotify() {
|
||||
super.removeNotify();
|
||||
releaseEditor();
|
||||
@@ -555,7 +561,7 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener,
|
||||
int prefHeight = c.getPreferredSize().height;
|
||||
if (myOneLineMode && getSize().height > prefHeight && myCenterByHeight) {
|
||||
int y = insets.top + getSize().height / 2 - prefHeight / 2;
|
||||
c.setBounds(insets.left, y - 1, getSize().width - insets.left - insets.right, prefHeight);
|
||||
c.setBounds(insets.left, y, getSize().width - insets.left - insets.right, prefHeight + 1);
|
||||
} else {
|
||||
c.setBounds(insets.left, insets.top, getSize().width - insets.left - insets.right, getSize().height - insets.top - insets.bottom);
|
||||
}
|
||||
@@ -565,6 +571,16 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener,
|
||||
if (super.isPreferredSizeSet()) {
|
||||
return super.getPreferredSize();
|
||||
}
|
||||
|
||||
boolean toReleaseEditor = false;
|
||||
if (myEditor == null && myEnsureWillComputePreferredSize) {
|
||||
myEnsureWillComputePreferredSize = false;
|
||||
initEditor();
|
||||
toReleaseEditor = true;
|
||||
}
|
||||
|
||||
|
||||
Dimension size = new Dimension(100, 20);
|
||||
if (myEditor != null) {
|
||||
final Dimension preferredSize = new Dimension(myEditor.getComponent().getPreferredSize());
|
||||
final Insets insets = getInsets();
|
||||
@@ -574,10 +590,17 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener,
|
||||
preferredSize.height += insets.top;
|
||||
preferredSize.height += insets.bottom;
|
||||
}
|
||||
|
||||
return preferredSize;
|
||||
size = preferredSize;
|
||||
} else if (myPassivePreferredSize != null) {
|
||||
size = myPassivePreferredSize;
|
||||
}
|
||||
return new Dimension(100, 20);
|
||||
|
||||
if (toReleaseEditor) {
|
||||
releaseEditor();
|
||||
myPassivePreferredSize = size;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
public Component getNextFocusableComponent() {
|
||||
@@ -653,6 +676,10 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener,
|
||||
myCenterByHeight = centerByHeight;
|
||||
}
|
||||
|
||||
public void ensureWillComputePreferredSize() {
|
||||
myEnsureWillComputePreferredSize = true;
|
||||
}
|
||||
|
||||
private static class DelegatingToRootTraversalPolicy extends FocusTraversalPolicy {
|
||||
@Override
|
||||
public Component getComponentAfter(final Container aContainer, final Component aComponent) {
|
||||
|
||||
+4
-1
@@ -15,13 +15,16 @@
|
||||
*/
|
||||
package com.intellij.execution.testframework.sm;
|
||||
|
||||
import com.intellij.execution.testframework.TestConsoleProperties;
|
||||
import com.intellij.execution.testframework.sm.runner.OutputToGeneralTestEventsConverter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author gregsh
|
||||
*/
|
||||
public interface SMCustomMessagesParsing {
|
||||
|
||||
OutputToGeneralTestEventsConverter createTestEventsConverter(final String testFrameworkName);
|
||||
OutputToGeneralTestEventsConverter createTestEventsConverter(@NotNull final String testFrameworkName,
|
||||
@NotNull final TestConsoleProperties consoleProperties);
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -179,8 +179,8 @@ public class SMTestRunnerConnectionUtil {
|
||||
@NotNull final String testFrameworkName) {
|
||||
//build messages consumer
|
||||
final OutputToGeneralTestEventsConverter outputConsumer = consoleProperties instanceof SMCustomMessagesParsing
|
||||
? ((SMCustomMessagesParsing)consoleProperties).createTestEventsConverter(testFrameworkName)
|
||||
: new OutputToGeneralTestEventsConverter(testFrameworkName);
|
||||
? ((SMCustomMessagesParsing)consoleProperties).createTestEventsConverter(testFrameworkName, consoleProperties)
|
||||
: new OutputToGeneralTestEventsConverter(testFrameworkName, consoleProperties);
|
||||
|
||||
//events processor
|
||||
final GeneralToSMTRunnerEventsConvertor eventsProcessor = new GeneralToSMTRunnerEventsConvertor(resultsViewer.getTestsRootNode(),
|
||||
|
||||
+27
-2
@@ -16,6 +16,7 @@
|
||||
package com.intellij.execution.testframework.sm.runner;
|
||||
|
||||
import com.intellij.execution.process.ProcessOutputTypes;
|
||||
import com.intellij.execution.testframework.TestConsoleProperties;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
@@ -41,10 +42,13 @@ import static com.intellij.execution.testframework.sm.runner.GeneralToSMTRunnerE
|
||||
*/
|
||||
public class OutputToGeneralTestEventsConverter implements ProcessOutputConsumer {
|
||||
private static final Logger LOG = Logger.getInstance(OutputToGeneralTestEventsConverter.class.getName());
|
||||
|
||||
|
||||
private static final String TEAMCITY_SERVICE_MESSAGE_PREFIX = "##teamcity[";
|
||||
|
||||
private GeneralTestEventsProcessor myProcessor;
|
||||
private final MyServiceMessageVisitor myServiceMessageVisitor;
|
||||
private final String myTestFrameworkName;
|
||||
private boolean myStdinSupportEnabled;
|
||||
|
||||
private static class OutputChunk {
|
||||
private final Key myKey;
|
||||
@@ -70,10 +74,12 @@ public class OutputToGeneralTestEventsConverter implements ProcessOutputConsumer
|
||||
|
||||
private final List<OutputChunk> myOutputChunks;
|
||||
|
||||
public OutputToGeneralTestEventsConverter(@NotNull final String testFrameworkName) {
|
||||
public OutputToGeneralTestEventsConverter(@NotNull final String testFrameworkName,
|
||||
@NotNull final TestConsoleProperties consoleProperties) {
|
||||
myTestFrameworkName = testFrameworkName;
|
||||
myServiceMessageVisitor = new MyServiceMessageVisitor();
|
||||
myOutputChunks = new ArrayList<OutputChunk>();
|
||||
myStdinSupportEnabled = consoleProperties.isEditable();
|
||||
}
|
||||
|
||||
public void setProcessor(final GeneralTestEventsProcessor processor) {
|
||||
@@ -145,9 +151,28 @@ public class OutputToGeneralTestEventsConverter implements ProcessOutputConsumer
|
||||
if (lastChar == '\n' || lastChar == '\r') {
|
||||
// buffer contains consistent string
|
||||
flushStdOutputBuffer();
|
||||
} else {
|
||||
// test framework may show some promt and ask user for smth. Question may not
|
||||
// finish with \n or \r thus buffer wont be flushed and user will have to input smth
|
||||
// before question. And question will became visible with next portion of text.
|
||||
// Such behaviour is confusing. So
|
||||
// 1. Let's assume that sevice messages starts with \n if console is editable
|
||||
// 2. Then we can suggest that each service message will start from new line and buffer should
|
||||
// be flushed before every service message. Thus if chunks list is empty and output doesn't end
|
||||
// with \n or \r but starts with ##teamcity then it is a service message and should be buffered otherwise
|
||||
// we can safely flush buffer.
|
||||
|
||||
// TODO if editable:
|
||||
if (myStdinSupportEnabled && !isMostLikelyServiceMessagePart(text)) {
|
||||
flushStdOutputBuffer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isMostLikelyServiceMessagePart(@NotNull final String text) {
|
||||
return text.startsWith(TEAMCITY_SERVICE_MESSAGE_PREFIX);
|
||||
}
|
||||
|
||||
private void processConsistentText(final String text, final Key outputType, boolean tcLikeFakeOutput) {
|
||||
try {
|
||||
final ServiceMessage serviceMessage = parseServiceMessage(text, outputType);
|
||||
|
||||
+6
-4
@@ -20,6 +20,7 @@ import com.intellij.execution.configurations.RuntimeConfiguration;
|
||||
import com.intellij.execution.testframework.TestConsoleProperties;
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.util.config.Storage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author: Roman Chernyatchik
|
||||
@@ -32,11 +33,12 @@ public class SMTRunnerConsoleProperties extends TestConsoleProperties {
|
||||
* @param testFrameworkName Prefix for storage which keeps runner settings. E.g. "RubyTestUnit"
|
||||
* @param executor
|
||||
*/
|
||||
public SMTRunnerConsoleProperties(final RuntimeConfiguration config,
|
||||
final String testFrameworkName,
|
||||
Executor executor)
|
||||
public SMTRunnerConsoleProperties(@NotNull final RuntimeConfiguration config,
|
||||
@NotNull final String testFrameworkName,
|
||||
@NotNull final Executor executor)
|
||||
{
|
||||
super(new Storage.PropertiesComponentStorage(testFrameworkName + "Support.", PropertiesComponent.getInstance()), config.getProject(),
|
||||
super(new Storage.PropertiesComponentStorage(testFrameworkName + "Support.", PropertiesComponent.getInstance()),
|
||||
config.getProject(),
|
||||
executor);
|
||||
myConfiguration = config;
|
||||
}
|
||||
|
||||
+5
-1
@@ -136,10 +136,14 @@ public abstract class TestConsoleProperties extends StoringPropertyContainer imp
|
||||
* Allows to make console editable and disable/enable input sending in process stdin stream.
|
||||
* Normally tests shouldn't ask anything in stdin so console is view only by default.
|
||||
*
|
||||
* NB: Process input support feature isn't fully implemented. Input text will be lost after
|
||||
* NB1: Process input support feature isn't fully implemented. Input text will be lost after
|
||||
* switching to any other test/suite in tests results view. It's highly not recommended to change
|
||||
* default behaviour. Please do it only in critical cases and only if you are sure that you need this feature.
|
||||
*
|
||||
*
|
||||
* NB2: If you are using Service Messages based test runner please ensure that before each service message
|
||||
* (e.g. #teamcity[...]) you always send "\n" to the output stream.
|
||||
*
|
||||
* @return False for view-only mode and true for stdin support.
|
||||
*/
|
||||
public boolean isEditable() {
|
||||
|
||||
@@ -93,7 +93,7 @@ public class ChunkExtractor {
|
||||
}
|
||||
};
|
||||
|
||||
public static TextChunk[] extractChunks(PsiFile file, UsageInfo2UsageAdapter usageAdapter) {
|
||||
public static TextChunk[] extractChunks(@NotNull PsiFile file, UsageInfo2UsageAdapter usageAdapter) {
|
||||
return ourExtractors.get().getValue().get(file).extractChunks(usageAdapter);
|
||||
}
|
||||
|
||||
|
||||
@@ -120,7 +120,8 @@ public class UsageInfo2UsageAdapter implements UsageInModule,
|
||||
}
|
||||
|
||||
private TextChunk[] initChunks() {
|
||||
TextChunk[] chunks = ChunkExtractor.extractChunks(getPsiFile(), this);
|
||||
PsiFile file = getPsiFile();
|
||||
TextChunk[] chunks = file == null ? TextChunk.EMPTY_ARRAY : ChunkExtractor.extractChunks(file, this);
|
||||
myTextChunks = new SoftReference<TextChunk[]>(chunks);
|
||||
return chunks;
|
||||
}
|
||||
@@ -328,7 +329,10 @@ public class UsageInfo2UsageAdapter implements UsageInModule,
|
||||
if (containingFile == null && oContainingFile == null || !Comparing.equal(containingFile, oContainingFile)) {
|
||||
return 0;
|
||||
}
|
||||
return getFirstSegment().getStartOffset() - o.getFirstSegment().getStartOffset();
|
||||
Segment s1 = getFirstSegment();
|
||||
Segment s2 = o.getFirstSegment();
|
||||
if (s1 == null || s2 == null) return 0;
|
||||
return s1.getStartOffset() - s2.getStartOffset();
|
||||
}
|
||||
|
||||
public void rename(String newName) throws IncorrectOperationException {
|
||||
|
||||
@@ -50,8 +50,9 @@ public class FileGroupingRule implements UsageGroupingRule {
|
||||
}
|
||||
|
||||
public UsageGroup groupUsage(Usage usage) {
|
||||
if (usage instanceof UsageInFile) {
|
||||
return new FileUsageGroup(myProject, ((UsageInFile)usage).getFile());
|
||||
VirtualFile virtualFile;
|
||||
if (usage instanceof UsageInFile && (virtualFile = ((UsageInFile)usage).getFile()) != null) {
|
||||
return new FileUsageGroup(myProject, virtualFile);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -62,7 +63,7 @@ public class FileGroupingRule implements UsageGroupingRule {
|
||||
private String myPresentableName;
|
||||
private ComputableIcon myIcon;
|
||||
|
||||
public FileUsageGroup(Project project, VirtualFile file) {
|
||||
public FileUsageGroup(@NotNull Project project, @NotNull VirtualFile file) {
|
||||
myProject = project;
|
||||
myFile = file instanceof VirtualFileWindow ? ((VirtualFileWindow)file).getDelegate() : file;
|
||||
myPresentableName = myFile.getName();
|
||||
@@ -91,13 +92,11 @@ public class FileGroupingRule implements UsageGroupingRule {
|
||||
|
||||
final FileUsageGroup fileUsageGroup = (FileUsageGroup)o;
|
||||
|
||||
if (myFile != null ? !myFile.equals(fileUsageGroup.myFile) : fileUsageGroup.myFile != null) return false;
|
||||
|
||||
return true;
|
||||
return myFile.equals(fileUsageGroup.myFile);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return myFile != null ? myFile.hashCode() : 0;
|
||||
return myFile.hashCode();
|
||||
}
|
||||
|
||||
public Icon getIcon(boolean isOpen) {
|
||||
@@ -145,7 +144,7 @@ public class FileGroupingRule implements UsageGroupingRule {
|
||||
|
||||
@Nullable
|
||||
public PsiFile getPsiFile() {
|
||||
return myFile != null && myFile.isValid() ? PsiManager.getInstance(myProject).findFile(myFile) : null;
|
||||
return myFile.isValid() ? PsiManager.getInstance(myProject).findFile(myFile) : null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package com.intellij.util.containers;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class IntArrayList implements Cloneable {
|
||||
private int[] myData;
|
||||
private int mySize;
|
||||
@@ -163,4 +165,9 @@ public class IntArrayList implements Cloneable {
|
||||
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + mySize);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Arrays.toString(toArray());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,7 +279,8 @@ class BeanBinding implements Binding {
|
||||
return new AccessorBindingWrapper(accessor, binding);
|
||||
}
|
||||
|
||||
return new OptionTagBinding(accessor, xmlSerializer);
|
||||
OptionTag optionTag = XmlSerializerImpl.findAnnotation(accessor.getAnnotations(), OptionTag.class);
|
||||
return new OptionTagBinding(accessor, xmlSerializer, optionTag);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,42 +19,57 @@ package com.intellij.util.xmlb;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.JDOMUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.xmlb.annotations.OptionTag;
|
||||
import org.jdom.Attribute;
|
||||
import org.jdom.Content;
|
||||
import org.jdom.Element;
|
||||
import org.jdom.Text;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
//todo: use TagBinding
|
||||
class OptionTagBinding implements Binding {
|
||||
|
||||
private final static Logger LOG = Logger.getInstance("#" + OptionTagBinding.class.getName());
|
||||
|
||||
private final Accessor accessor;
|
||||
private final String myName;
|
||||
private final Binding myBinding;
|
||||
private final String myTagName;
|
||||
private final String myNameAttribute;
|
||||
private final String myValueAttribute;
|
||||
|
||||
public OptionTagBinding(Accessor accessor, XmlSerializerImpl xmlSerializer) {
|
||||
public OptionTagBinding(Accessor accessor, XmlSerializerImpl xmlSerializer, @Nullable OptionTag optionTag) {
|
||||
this.accessor = accessor;
|
||||
myName = accessor.getName();
|
||||
myBinding = xmlSerializer.getBinding(accessor);
|
||||
if (optionTag != null) {
|
||||
String name = optionTag.value();
|
||||
myName = name.isEmpty() ? accessor.getName() : name;
|
||||
myTagName = optionTag.tag();
|
||||
myNameAttribute = optionTag.nameAttribute();
|
||||
myValueAttribute = optionTag.valueAttribute();
|
||||
}
|
||||
else {
|
||||
myName = accessor.getName();
|
||||
myTagName = Constants.OPTION;
|
||||
myNameAttribute = Constants.NAME;
|
||||
myValueAttribute = Constants.VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
public Object serialize(Object o, Object context) {
|
||||
Element targetElement = new Element(Constants.OPTION);
|
||||
Element targetElement = new Element(myTagName);
|
||||
Object value = accessor.read(o);
|
||||
|
||||
targetElement.setAttribute(Constants.NAME, myName);
|
||||
targetElement.setAttribute(myNameAttribute, myName);
|
||||
|
||||
if (value == null) return targetElement;
|
||||
|
||||
Object node = myBinding.serialize(value, targetElement);
|
||||
if (node instanceof Text) {
|
||||
Text text = (Text)node;
|
||||
targetElement.setAttribute(Constants.VALUE, text.getText());
|
||||
targetElement.setAttribute(myValueAttribute, text.getText());
|
||||
}
|
||||
else {
|
||||
if (targetElement != node) {
|
||||
@@ -72,7 +87,7 @@ class OptionTagBinding implements Binding {
|
||||
assert nodes.length != 0 : "Empty nodes passed to: " + this;
|
||||
|
||||
Element element = ((Element)nodes[0]);
|
||||
Attribute valueAttr = element.getAttribute(Constants.VALUE);
|
||||
Attribute valueAttr = element.getAttribute(myValueAttribute);
|
||||
|
||||
if (valueAttr != null) {
|
||||
Object value = myBinding.deserialize(o, valueAttr);
|
||||
@@ -102,8 +117,8 @@ class OptionTagBinding implements Binding {
|
||||
public boolean isBoundTo(Object node) {
|
||||
if (!(node instanceof Element)) return false;
|
||||
Element e = (Element)node;
|
||||
if (!e.getName().equals(Constants.OPTION)) return false;
|
||||
String name = e.getAttributeValue(Constants.NAME);
|
||||
if (!e.getName().equals(myTagName)) return false;
|
||||
String name = e.getAttributeValue(myNameAttribute);
|
||||
return name != null && name.equals(myName);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.util.xmlb.annotations;
|
||||
|
||||
import com.intellij.util.xmlb.Constants;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Store value in tag like <option name="optionName" value="optionValue"/>
|
||||
*
|
||||
* @author nik
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.FIELD, ElementType.METHOD})
|
||||
public @interface OptionTag {
|
||||
String value() default "";
|
||||
String tag() default Constants.OPTION;
|
||||
String nameAttribute() default Constants.NAME;
|
||||
String valueAttribute() default Constants.VALUE;
|
||||
}
|
||||
@@ -21,9 +21,6 @@ import com.intellij.util.xmlb.annotations.*;
|
||||
import junit.framework.TestCase;
|
||||
import org.jdom.Element;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.Collection;
|
||||
|
||||
@@ -36,7 +33,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
public static class EmptyBean {
|
||||
}
|
||||
|
||||
public void testEmptyBeanSerialization() throws Exception {
|
||||
public void testEmptyBeanSerialization() {
|
||||
doSerializerTest("<EmptyBean />", new EmptyBean());
|
||||
}
|
||||
|
||||
@@ -44,7 +41,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
public static class EmptyBeanWithCustomName {
|
||||
}
|
||||
|
||||
public void testEmptyBeanSerializationWithCustomName() throws Exception {
|
||||
public void testEmptyBeanSerializationWithCustomName() {
|
||||
doSerializerTest("<Bean />", new EmptyBeanWithCustomName());
|
||||
}
|
||||
|
||||
@@ -67,7 +64,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testPublicFieldSerialization() throws Exception {
|
||||
public void testPublicFieldSerialization() {
|
||||
BeanWithPublicFields bean = new BeanWithPublicFields();
|
||||
|
||||
doSerializerTest(
|
||||
@@ -91,7 +88,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
public String NEW_S = "foo";
|
||||
}
|
||||
|
||||
public void testPublicFieldSerializationWithInheritance() throws Exception {
|
||||
public void testPublicFieldSerializationWithInheritance() {
|
||||
BeanWithPublicFieldsDescendant bean = new BeanWithPublicFieldsDescendant();
|
||||
|
||||
doSerializerTest(
|
||||
@@ -120,7 +117,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
public BeanWithPublicFields BEAN2 = new BeanWithPublicFields();
|
||||
}
|
||||
|
||||
public void testSubBeanSerialization() throws Exception {
|
||||
public void testSubBeanSerialization() {
|
||||
BeanWithSubBean bean = new BeanWithSubBean();
|
||||
doSerializerTest(
|
||||
"<BeanWithSubBean>\n" +
|
||||
@@ -153,7 +150,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
bean);
|
||||
}
|
||||
|
||||
public void testNullFieldValue() throws Exception {
|
||||
public void testNullFieldValue() {
|
||||
BeanWithPublicFields bean1 = new BeanWithPublicFields();
|
||||
|
||||
doSerializerTest(
|
||||
@@ -187,7 +184,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
public List<String> VALUES = new ArrayList<String>(Arrays.asList("a", "b", "c"));
|
||||
}
|
||||
|
||||
public void testListSerialization() throws Exception {
|
||||
public void testListSerialization() {
|
||||
BeanWithList bean = new BeanWithList();
|
||||
|
||||
doSerializerTest(
|
||||
@@ -221,7 +218,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
public Set<String> VALUES = new LinkedHashSet<String>(Arrays.asList("a", "b", "w"));
|
||||
}
|
||||
|
||||
public void testSetSerialization() throws Exception {
|
||||
public void testSetSerialization() {
|
||||
BeanWithSet bean = new BeanWithSet();
|
||||
doSerializerTest(
|
||||
"<BeanWithSet>\n" +
|
||||
@@ -259,7 +256,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testMapSerialization() throws Exception {
|
||||
public void testMapSerialization() {
|
||||
BeanWithMap bean = new BeanWithMap();
|
||||
doSerializerTest(
|
||||
"<BeanWithMap>\n" +
|
||||
@@ -307,7 +304,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testMapSerializationWithAnnotations() throws Exception {
|
||||
public void testMapSerializationWithAnnotations() {
|
||||
BeanWithMapWithAnnotations bean = new BeanWithMapWithAnnotations();
|
||||
doSerializerTest(
|
||||
"<BeanWithMapWithAnnotations>\n" +
|
||||
@@ -335,7 +332,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
public Map<String, BeanWithProperty> VALUES = new HashMap<String, BeanWithProperty>();
|
||||
|
||||
}
|
||||
public void testMapWithBeanValue() throws Exception {
|
||||
public void testMapWithBeanValue() {
|
||||
BeanWithMapWithBeanValue bean = new BeanWithMapWithBeanValue();
|
||||
|
||||
bean.VALUES.put("a", new BeanWithProperty("James"));
|
||||
@@ -372,6 +369,33 @@ public class XmlSerializerTest extends TestCase {
|
||||
"</BeanWithMapWithBeanValue>",
|
||||
bean);
|
||||
}
|
||||
|
||||
public static class BeanWithOption {
|
||||
@OptionTag("path")
|
||||
public String PATH;
|
||||
}
|
||||
|
||||
public void testOptionTag() {
|
||||
BeanWithOption bean = new BeanWithOption();
|
||||
bean.PATH = "123";
|
||||
doSerializerTest("<BeanWithOption>\n" +
|
||||
" <option name=\"path\" value=\"123\" />\n" +
|
||||
"</BeanWithOption>", bean);
|
||||
}
|
||||
|
||||
public static class BeanWithCustomizedOption {
|
||||
@OptionTag(tag = "setting", nameAttribute = "key", valueAttribute = "saved")
|
||||
public String PATH;
|
||||
}
|
||||
|
||||
public void testCustomizedOptionTag() {
|
||||
BeanWithCustomizedOption bean = new BeanWithCustomizedOption();
|
||||
bean.PATH = "123";
|
||||
doSerializerTest("<BeanWithCustomizedOption>\n" +
|
||||
" <setting key=\"PATH\" saved=\"123\" />\n" +
|
||||
"</BeanWithCustomizedOption>", bean);
|
||||
}
|
||||
|
||||
public static class BeanWithProperty {
|
||||
private String name = "James";
|
||||
|
||||
@@ -392,7 +416,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testPropertySerialization() throws Exception {
|
||||
public void testPropertySerialization() {
|
||||
BeanWithProperty bean = new BeanWithProperty();
|
||||
|
||||
doSerializerTest(
|
||||
@@ -414,7 +438,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
public String STRING_V = "hello";
|
||||
}
|
||||
|
||||
public void testFieldWithTagAnnotation() throws Exception {
|
||||
public void testFieldWithTagAnnotation() {
|
||||
BeanWithFieldWithTagAnnotation bean = new BeanWithFieldWithTagAnnotation();
|
||||
|
||||
doSerializerTest(
|
||||
@@ -431,7 +455,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
"</BeanWithFieldWithTagAnnotation>", bean);
|
||||
}
|
||||
|
||||
public void testShuffledDeserialize() throws Exception {
|
||||
public void testShuffledDeserialize() {
|
||||
BeanWithPublicFields bean = new BeanWithPublicFields();
|
||||
bean.INT_V = 987;
|
||||
bean.STRING_V = "1234";
|
||||
@@ -448,7 +472,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
assertEquals("1234", bean.STRING_V);
|
||||
}
|
||||
|
||||
public void testFilterSerializer() throws Exception {
|
||||
public void testFilterSerializer() {
|
||||
BeanWithPublicFields bean = new BeanWithPublicFields();
|
||||
assertSerializer(bean,
|
||||
"<BeanWithPublicFields>\n" +
|
||||
@@ -465,7 +489,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
public static class BeanWithArray {
|
||||
public String[] ARRAY_V = new String[] {"a", "b"};
|
||||
}
|
||||
public void testArray() throws Exception {
|
||||
public void testArray() {
|
||||
final BeanWithArray bean = new BeanWithArray();
|
||||
doSerializerTest(
|
||||
"<BeanWithArray>\n" +
|
||||
@@ -498,7 +522,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
return "foo";
|
||||
}
|
||||
}
|
||||
public void testTransient() throws Exception {
|
||||
public void testTransient() {
|
||||
final BeanWithTransient bean = new BeanWithTransient();
|
||||
doSerializerTest("<BeanWithTransient />", bean);
|
||||
}
|
||||
@@ -507,7 +531,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
@com.intellij.util.xmlb.annotations.AbstractCollection(surroundWithTag = false)
|
||||
public String[] V = new String[]{"a"};
|
||||
}
|
||||
public void testArrayAnnotationWithoutTagNAmeGivesError() throws Exception {
|
||||
public void testArrayAnnotationWithoutTagNAmeGivesError() {
|
||||
final BeanWithArrayWithoutTagName bean = new BeanWithArrayWithoutTagName();
|
||||
|
||||
try {
|
||||
@@ -524,7 +548,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
@com.intellij.util.xmlb.annotations.AbstractCollection(elementTag = "vvalue", elementValueAttribute = "v")
|
||||
public String[] V = new String[]{"a", "b"};
|
||||
}
|
||||
public void testArrayAnnotationWithElementTag() throws Exception {
|
||||
public void testArrayAnnotationWithElementTag() {
|
||||
final BeanWithArrayWithElementTagName bean = new BeanWithArrayWithElementTagName();
|
||||
|
||||
doSerializerTest(
|
||||
@@ -557,7 +581,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
public String[] V = new String[]{"a", "b"};
|
||||
public int INT_V = 1;
|
||||
}
|
||||
public void testArrayWithoutTag() throws Exception {
|
||||
public void testArrayWithoutTag() {
|
||||
final BeanWithArrayWithoutTag bean = new BeanWithArrayWithoutTag();
|
||||
|
||||
doSerializerTest(
|
||||
@@ -587,7 +611,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
@Property(surroundWithTag = false)
|
||||
public int INT_V = 1;
|
||||
}
|
||||
public void testPropertyWithoutTagWithPrimitiveType() throws Exception {
|
||||
public void testPropertyWithoutTagWithPrimitiveType() {
|
||||
final BeanWithPropertyWithoutTagOnPrimitiveValue bean = new BeanWithPropertyWithoutTagOnPrimitiveValue();
|
||||
|
||||
try {
|
||||
@@ -605,7 +629,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
public BeanWithPublicFields BEAN1 = new BeanWithPublicFields();
|
||||
public int INT_V = 1;
|
||||
}
|
||||
public void testPropertyWithoutTag() throws Exception {
|
||||
public void testPropertyWithoutTag() {
|
||||
final BeanWithPropertyWithoutTag bean = new BeanWithPropertyWithoutTag();
|
||||
|
||||
doSerializerTest(
|
||||
@@ -638,7 +662,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
public String[] V = new String[]{"a", "b"};
|
||||
public int INT_V = 1;
|
||||
}
|
||||
public void testArrayWithoutAllTags() throws Exception {
|
||||
public void testArrayWithoutAllTags() {
|
||||
final BeanWithArrayWithoutAllsTag bean = new BeanWithArrayWithoutAllsTag();
|
||||
|
||||
doSerializerTest(
|
||||
@@ -666,7 +690,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
public String[] V = new String[]{"a", "b"};
|
||||
public int INT_V = 1;
|
||||
}
|
||||
public void testArrayWithoutAllTags2() throws Exception {
|
||||
public void testArrayWithoutAllTags2() {
|
||||
final BeanWithArrayWithoutAllsTag2 bean = new BeanWithArrayWithoutAllsTag2();
|
||||
|
||||
doSerializerTest(
|
||||
@@ -706,7 +730,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
public BeanWithPublicFields[] V = new BeanWithPublicFields[] {};
|
||||
}
|
||||
|
||||
public void testPolymorphicArray() throws Exception {
|
||||
public void testPolymorphicArray() {
|
||||
final BeanWithPolymorphicArray bean = new BeanWithPolymorphicArray();
|
||||
|
||||
doSerializerTest(
|
||||
@@ -747,7 +771,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
@Attribute("name")
|
||||
public String name = "James";
|
||||
}
|
||||
public void testBeanWithPrimitivePropertyBoundToAttribute() throws Exception {
|
||||
public void testBeanWithPrimitivePropertyBoundToAttribute() {
|
||||
final BeanWithPropertiesBoundToAttribute bean = new BeanWithPropertiesBoundToAttribute();
|
||||
|
||||
doSerializerTest("<BeanWithPropertiesBoundToAttribute count=\"3\" name=\"James\" />", bean);
|
||||
@@ -771,7 +795,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
return !accessor.read(bean).equals("skip");
|
||||
}
|
||||
}
|
||||
public void testPropertyFilter() throws Exception {
|
||||
public void testPropertyFilter() {
|
||||
BeanWithPropertyFilter bean = new BeanWithPropertyFilter();
|
||||
|
||||
doSerializerTest(
|
||||
@@ -797,7 +821,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
public org.jdom.Element actions;
|
||||
}
|
||||
|
||||
public void testSerializeJDOMElementField() throws Exception {
|
||||
public void testSerializeJDOMElementField() {
|
||||
BeanWithJDOMElement element = new BeanWithJDOMElement();
|
||||
element.STRING_V = "a";
|
||||
element.actions = new Element("x").addContent(new Element("a")).addContent(new Element("b"));
|
||||
@@ -881,7 +905,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testTextAnnotation() throws Exception {
|
||||
public void testTextAnnotation() {
|
||||
BeanWithTextAnnotation bean = new BeanWithTextAnnotation();
|
||||
|
||||
doSerializerTest(
|
||||
@@ -911,7 +935,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
public TestEnum FLD = TestEnum.VALUE_1;
|
||||
}
|
||||
|
||||
public void testEnums() throws Exception {
|
||||
public void testEnums() {
|
||||
BeanWithEnum bean = new BeanWithEnum();
|
||||
|
||||
doSerializerTest(
|
||||
@@ -927,7 +951,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
public Map<Collection<String>, String> myMap = new HashMap<Collection<String>, String>();
|
||||
}
|
||||
|
||||
public void testSetKeysInMap() throws Exception {
|
||||
public void testSetKeysInMap() {
|
||||
final BeanWithSetKeysInMap bean = new BeanWithSetKeysInMap();
|
||||
bean.myMap.put(new HashSet<String>(Arrays.asList("1", "2", "3")), "numbers");
|
||||
bean.myMap.put(new HashSet<String>(Arrays.asList("a", "b", "c")), "letters");
|
||||
@@ -982,7 +1006,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
public Map<BeanWithPublicFields, BeanWithTextAnnotation> MAP = new HashMap<BeanWithPublicFields, BeanWithTextAnnotation>();
|
||||
}
|
||||
|
||||
public void testMapWithNotSurroundingKeyAndValue() throws Exception {
|
||||
public void testMapWithNotSurroundingKeyAndValue() {
|
||||
BeanWithMapWithoutSurround bean = new BeanWithMapWithoutSurround();
|
||||
|
||||
bean.MAP.put(new BeanWithPublicFields(1, "a"), new BeanWithTextAnnotation(2, "b"));
|
||||
@@ -1028,24 +1052,29 @@ public class XmlSerializerTest extends TestCase {
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
private void assertSerializer(Object bean, String expected, SerializationFilter filter)
|
||||
throws TransformerException, ParserConfigurationException, IOException {
|
||||
private static void assertSerializer(Object bean, String expected, SerializationFilter filter) {
|
||||
assertSerializer(bean, expected, "Serialization failure", filter);
|
||||
}
|
||||
|
||||
private Object doSerializerTest(String expectedText, Object bean)
|
||||
throws ParserConfigurationException, TransformerException, XmlSerializationException, IOException {
|
||||
Element element = assertSerializer(bean, expectedText, "Serialization failure", null);
|
||||
private static Object doSerializerTest(String expectedText, Object bean) {
|
||||
try {
|
||||
Element element = assertSerializer(bean, expectedText, "Serialization failure", null);
|
||||
|
||||
//test deserializer
|
||||
//test deserializer
|
||||
|
||||
Object o = XmlSerializer.deserialize(element, bean.getClass());
|
||||
assertSerializer(o, expectedText, "Deserialization failure", null);
|
||||
return o;
|
||||
Object o = XmlSerializer.deserialize(element, bean.getClass());
|
||||
assertSerializer(o, expectedText, "Deserialization failure", null);
|
||||
return o;
|
||||
}
|
||||
catch (XmlSerializationException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private Element assertSerializer(Object bean, String expectedText, String message, SerializationFilter filter)
|
||||
throws ParserConfigurationException, XmlSerializationException, TransformerException, IOException {
|
||||
private static Element assertSerializer(Object bean, String expectedText, String message, SerializationFilter filter) throws XmlSerializationException {
|
||||
Element element = serialize(bean, filter);
|
||||
|
||||
|
||||
@@ -1060,7 +1089,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
return element;
|
||||
}
|
||||
|
||||
private Element serialize(Object bean, SerializationFilter filter) throws ParserConfigurationException {
|
||||
private static Element serialize(Object bean, SerializationFilter filter) {
|
||||
return XmlSerializer.serialize(bean, filter);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,14 +56,8 @@ public class VcsUtil {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.vcsUtil.VcsUtil");
|
||||
|
||||
|
||||
/**
|
||||
* Call "fileDirty" in the read action.
|
||||
*/
|
||||
public static void markFileAsDirty(final Project project, final VirtualFile file) {
|
||||
final VcsDirtyScopeManager mgr = VcsDirtyScopeManager.getInstance(project);
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() { mgr.fileDirty(file); }
|
||||
});
|
||||
VcsDirtyScopeManager.getInstance(project).fileDirty(file);
|
||||
}
|
||||
|
||||
public static void markFileAsDirty(final Project project, final FilePath path) {
|
||||
|
||||
+8
-3
@@ -45,7 +45,7 @@ public class ScheduleForAdditionAction extends AnAction implements DumbAware {
|
||||
}
|
||||
|
||||
public void update(AnActionEvent e) {
|
||||
final boolean enabled = e.getData(PlatformDataKeys.PROJECT) != null && (getUnversionedFiles(e) != null);
|
||||
final boolean enabled = e.getData(PlatformDataKeys.PROJECT) != null && (thereAreUnversionedFiles(e));
|
||||
e.getPresentation().setEnabled(enabled);
|
||||
final String place = e.getPlace();
|
||||
if (ActionPlaces.ACTION_PLACE_VCS_QUICK_LIST_POPUP_ACTION.equals(place) || ActionPlaces.CHANGES_VIEW_POPUP.equals(place) ) {
|
||||
@@ -62,8 +62,13 @@ public class ScheduleForAdditionAction extends AnAction implements DumbAware {
|
||||
changeListManager.addUnversionedFiles(changeListManager.getDefaultChangeList(), unversionedFiles);
|
||||
}
|
||||
|
||||
protected boolean thereAreUnversionedFiles(final AnActionEvent e) {
|
||||
final List<VirtualFile> unversionedFiles = getUnversionedFiles(e);
|
||||
return unversionedFiles != null && !(unversionedFiles.isEmpty());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static List<VirtualFile> getUnversionedFiles(final AnActionEvent e) {
|
||||
protected List<VirtualFile> getUnversionedFiles(final AnActionEvent e) {
|
||||
// first get from the ChangeListView
|
||||
List<VirtualFile> unversionedFiles = e.getData(ChangesListView.UNVERSIONED_FILES_DATA_KEY);
|
||||
if (unversionedFiles != null && !unversionedFiles.isEmpty()) {
|
||||
@@ -88,4 +93,4 @@ public class ScheduleForAdditionAction extends AnAction implements DumbAware {
|
||||
return unversionedFiles.isEmpty() ? null : unversionedFiles;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+27
-18
@@ -86,8 +86,12 @@ public class TryFinallyCanBeTryWithResourcesInspection extends BaseInspection {
|
||||
return;
|
||||
}
|
||||
final PsiElement[] tryBlockChildren = tryBlock.getChildren();
|
||||
final Set<PsiLocalVariable> variables =
|
||||
collectVariables(tryStatement);
|
||||
final Set<PsiLocalVariable> variables = new HashSet();
|
||||
for (PsiLocalVariable variable : collectVariables(tryStatement)) {
|
||||
if (!isVariableUsedOutsideContext(variable, tryStatement)) {
|
||||
variables.add(variable);
|
||||
}
|
||||
}
|
||||
final PsiElementFactory factory =
|
||||
JavaPsiFacade.getElementFactory(project);
|
||||
@NonNls final StringBuilder newTryStatementText =
|
||||
@@ -315,7 +319,7 @@ public class TryFinallyCanBeTryWithResourcesInspection extends BaseInspection {
|
||||
if (resourceList != null) {
|
||||
return;
|
||||
}
|
||||
final Set<PsiLocalVariable> variables =
|
||||
final List<PsiLocalVariable> variables =
|
||||
collectVariables(tryStatement);
|
||||
if (variables.isEmpty()) {
|
||||
return;
|
||||
@@ -338,17 +342,7 @@ public class TryFinallyCanBeTryWithResourcesInspection extends BaseInspection {
|
||||
final int index = findInitialization(tryBlockStatements,
|
||||
variable, hasInitializer);
|
||||
if (index >= 0 ^ hasInitializer) {
|
||||
final VariableUsedOutsideContextVisitor visitor =
|
||||
new VariableUsedOutsideContextVisitor(variable,
|
||||
tryStatement);
|
||||
final PsiElement context =
|
||||
PsiTreeUtil.getParentOfType(variable,
|
||||
PsiCodeBlock.class);
|
||||
if (context == null) {
|
||||
continue;
|
||||
}
|
||||
context.accept(visitor);
|
||||
if (visitor.variableIsUsed()) {
|
||||
if (isVariableUsedOutsideContext(variable, tryStatement)) {
|
||||
continue;
|
||||
}
|
||||
found = true;
|
||||
@@ -362,17 +356,32 @@ public class TryFinallyCanBeTryWithResourcesInspection extends BaseInspection {
|
||||
}
|
||||
}
|
||||
|
||||
static Set<PsiLocalVariable> collectVariables(
|
||||
static boolean isVariableUsedOutsideContext(
|
||||
PsiVariable variable, PsiElement context) {
|
||||
final VariableUsedOutsideContextVisitor visitor =
|
||||
new VariableUsedOutsideContextVisitor(variable,
|
||||
context);
|
||||
final PsiElement declarationScope =
|
||||
PsiTreeUtil.getParentOfType(variable,
|
||||
PsiCodeBlock.class);
|
||||
if (declarationScope == null) {
|
||||
return true;
|
||||
}
|
||||
declarationScope.accept(visitor);
|
||||
return visitor.variableIsUsed();
|
||||
}
|
||||
|
||||
static List<PsiLocalVariable> collectVariables(
|
||||
PsiTryStatement tryStatement) {
|
||||
final PsiCodeBlock finallyBlock = tryStatement.getFinallyBlock();
|
||||
if (finallyBlock == null) {
|
||||
return Collections.EMPTY_SET;
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
final PsiStatement[] statements = finallyBlock.getStatements();
|
||||
if (statements.length == 0) {
|
||||
return Collections.EMPTY_SET;
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
final Set<PsiLocalVariable> variables = new LinkedHashSet();
|
||||
final List<PsiLocalVariable> variables = new ArrayList();
|
||||
for (PsiStatement statement : statements) {
|
||||
final PsiLocalVariable variable =
|
||||
findAutoCloseableVariable(statement);
|
||||
|
||||
+4
-2
@@ -17,6 +17,7 @@
|
||||
package com.maddyhome.idea.copyright.options;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.JDOMUtil;
|
||||
import com.maddyhome.idea.copyright.CopyrightProfile;
|
||||
import org.jdom.Document;
|
||||
@@ -54,10 +55,11 @@ public class ExternalOptionHelper {
|
||||
}
|
||||
}
|
||||
}
|
||||
return profiles.isEmpty() ? null : profiles;
|
||||
return profiles;
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.error(e);
|
||||
logger.info(e);
|
||||
Messages.showErrorDialog(e.getMessage(), "Import Failure");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,7 +201,8 @@ public class CopyrightProfilesPanel extends MasterDetailsComponent implements Se
|
||||
if (files.length != 1) return;
|
||||
|
||||
final List<CopyrightProfile> copyrightProfiles = ExternalOptionHelper.loadOptions(VfsUtil.virtualToIoFile(files[0]));
|
||||
if (copyrightProfiles != null) {
|
||||
if (copyrightProfiles == null) return;
|
||||
if (!copyrightProfiles.isEmpty()) {
|
||||
if (copyrightProfiles.size() == 1) {
|
||||
importProfile(copyrightProfiles.get(0));
|
||||
} else {
|
||||
@@ -224,7 +225,7 @@ public class CopyrightProfilesPanel extends MasterDetailsComponent implements Se
|
||||
}
|
||||
}
|
||||
else {
|
||||
Messages.showWarningDialog(myProject, "The selected file did not contain any copyright settings.", "Import Failure");
|
||||
Messages.showWarningDialog(myProject, "The selected file does not contain any copyright settings.", "Import Failure");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -68,14 +68,20 @@ public class GithubCheckoutProvider implements CheckoutProvider {
|
||||
|
||||
// All the preliminary work is already done, go and clone the selected repository!
|
||||
final RepositoryInfo selectedRepository = checkoutDialog.getSelectedRepository();
|
||||
final boolean writeAccessAllowed = GithubUtil.isWriteAccessAllowed(project, selectedRepository);
|
||||
if (!writeAccessAllowed){
|
||||
Messages.showErrorDialog(project, "It seems that you have only read access to the selected repository.\n" +
|
||||
"GitHub supports only https protocol for readonly access, which is not supported yet.\n" +
|
||||
"More details are available here: http://youtrack.jetbrains.net/issue/IDEA-55298", "Cannot clone this repository");
|
||||
return;
|
||||
}
|
||||
final String host = writeAccessAllowed ? "git@" + settings.getHost() + ":" : "https://github.com" + settings.getHost() + "/";
|
||||
final String selectedPath = checkoutDialog.getSelectedPath();
|
||||
final VirtualFile selectedPathFile = LocalFileSystem.getInstance().findFileByPath(selectedPath);
|
||||
final String projectName = checkoutDialog.getProjectName();
|
||||
final String repositoryName = selectedRepository.getName();
|
||||
final String repositoryOwner = selectedRepository.getOwner();
|
||||
final String checkoutUrl = settings.getLogin().equals(repositoryOwner)
|
||||
? "git@github.com:" + repositoryOwner + "/" + repositoryName + ".git"
|
||||
: "https://github.com/" + repositoryOwner + "/" + repositoryName + ".git";
|
||||
final String checkoutUrl = host + repositoryOwner + "/" + repositoryName + ".git";
|
||||
GitCheckoutProvider.checkout(project, listener, selectedPathFile, checkoutUrl, projectName, "origin", selectedPath);
|
||||
}
|
||||
|
||||
|
||||
@@ -139,6 +139,29 @@ public class GithubUtil {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public static boolean isPushableRepo(final String url, final String login, final String password, final RepositoryInfo repositoryInfo) {
|
||||
try {
|
||||
final HttpMethod method = doREST(url, login, password, "/repos/pushable", false);
|
||||
final InputStream stream = method.getResponseBodyAsStream();
|
||||
final Element element = new SAXBuilder(false).build(stream).getRootElement();
|
||||
if ("error".equals(element.getName())){
|
||||
LOG.warn("Got error element by request: " + "/repos/pushable");
|
||||
return false;
|
||||
}
|
||||
final List repositories = element.getChildren();
|
||||
for (int i = 0; i < repositories.size(); i++) {
|
||||
final Element repo = (Element)repositories.get(i);
|
||||
if (repositoryInfo.equals(new RepositoryInfo(repo))){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static RepositoryInfo getDetailedRepoInfo(final String url, final String login, final String password, final String name) {
|
||||
try {
|
||||
@@ -325,4 +348,15 @@ public class GithubUtil {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean isWriteAccessAllowed(final Project project, final RepositoryInfo repo) {
|
||||
final GithubSettings settings = GithubSettings.getInstance();
|
||||
return accessToGithubWithModalProgress(project, new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
ProgressManager.getInstance().getProgressIndicator().setText("Extracting info about pushable repositories");
|
||||
return isPushableRepo(settings.getHost(), settings.getLogin(), settings.getPassword(), repo);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.jetbrains.plugins.github;
|
||||
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import org.jdom.Element;
|
||||
|
||||
/**
|
||||
@@ -28,4 +29,14 @@ public class RepositoryInfo {
|
||||
public String getParent() {
|
||||
return myRepository.getChildText("parent");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof RepositoryInfo)){
|
||||
return false;
|
||||
}
|
||||
final RepositoryInfo repositoryInfo = (RepositoryInfo)obj;
|
||||
return Comparing.equal(getName(), repositoryInfo.getName()) &&
|
||||
Comparing.equal(getOwner(), repositoryInfo.getOwner());
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -453,7 +453,7 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
}
|
||||
});
|
||||
|
||||
if (StringUtil.isNotEmpty(result.getPrefixMatcher().getPrefix())) {
|
||||
if (StringUtil.isCapitalized(result.getPrefixMatcher().getPrefix()) || parameters.relaxMatching()) {
|
||||
addAllClasses(parameters, result, inheritors);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,6 +243,7 @@ readonly
|
||||
refactor
|
||||
refactored
|
||||
refactoring
|
||||
refactorings
|
||||
reifiable
|
||||
reification
|
||||
reifications
|
||||
|
||||
@@ -691,7 +691,7 @@ public class TaskManagerImpl extends TaskManager implements ProjectComponent, Pe
|
||||
notification.expire();
|
||||
}
|
||||
}
|
||||
}));
|
||||
}), myProject);
|
||||
}
|
||||
}
|
||||
return issues;
|
||||
|
||||
+5
@@ -24,6 +24,7 @@ import com.intellij.lang.ASTNode;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.lang.annotation.HighlightSeverity;
|
||||
import com.intellij.lang.xml.XMLLanguage;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.colors.ColorKey;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsManager;
|
||||
@@ -72,6 +73,10 @@ public class HtmlTagTreeHighlightingPass extends TextEditorHighlightingPass {
|
||||
|
||||
@Override
|
||||
public void doCollectInformation(ProgressIndicator progress) {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!WebEditorOptions.getInstance().isTagTreeHighlightingEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
+5
@@ -20,6 +20,7 @@ import com.intellij.codeHighlighting.Pass;
|
||||
import com.intellij.codeHighlighting.TextEditorHighlightingPass;
|
||||
import com.intellij.codeHighlighting.TextEditorHighlightingPassFactory;
|
||||
import com.intellij.codeHighlighting.TextEditorHighlightingPassRegistrar;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.AbstractProjectComponent;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -39,6 +40,10 @@ public class HtmlTagTreeHighlightingPassFactory extends AbstractProjectComponent
|
||||
}
|
||||
|
||||
public TextEditorHighlightingPass createHighlightingPass(@NotNull final PsiFile file, @NotNull final Editor editor) {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (editor.isOneLineMode()) return null;
|
||||
|
||||
if (!(file instanceof XmlFile) || !HtmlUtil.hasHtml(file)) {
|
||||
|
||||
@@ -22,37 +22,59 @@ import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.FileViewProvider;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.xml.XmlChildRole;
|
||||
import com.intellij.psi.xml.XmlTag;
|
||||
import com.intellij.util.SmartList;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class XmlUnwrapDescriptor implements UnwrapDescriptor {
|
||||
public List<Pair<PsiElement, Unwrapper>> collectUnwrappers(Project project, Editor editor, PsiFile file) {
|
||||
List<Pair<PsiElement, Unwrapper>> result = new SmartList<Pair<PsiElement, Unwrapper>>();
|
||||
|
||||
int offset = editor.getCaretModel().getOffset();
|
||||
|
||||
PsiElement e1 = file.findElementAt(offset);
|
||||
if (e1 != null) {
|
||||
Language language = e1.getParent().getLanguage();
|
||||
if (language != file.getLanguage()) {
|
||||
UnwrapDescriptor unwrapDescriptor = LanguageUnwrappers.INSTANCE.forLanguage(language);
|
||||
if (unwrapDescriptor != null && !(unwrapDescriptor instanceof XmlUnwrapDescriptor)) {
|
||||
result.addAll(unwrapDescriptor.collectUnwrappers(project, editor, file));
|
||||
return unwrapDescriptor.collectUnwrappers(project, editor, file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PsiElement tag = PsiTreeUtil.getParentOfType(e1, XmlTag.class);
|
||||
while (tag != null) {
|
||||
result.add(new Pair<PsiElement, Unwrapper>(tag, new XmlEnclosingTagUnwrapper()));
|
||||
tag = PsiTreeUtil.getParentOfType(tag, XmlTag.class);
|
||||
List<Pair<PsiElement, Unwrapper>> result = new ArrayList<Pair<PsiElement, Unwrapper>>();
|
||||
|
||||
FileViewProvider viewProvider = file.getViewProvider();
|
||||
|
||||
for (Language language : viewProvider.getLanguages()) {
|
||||
UnwrapDescriptor unwrapDescriptor = LanguageUnwrappers.INSTANCE.forLanguage(language);
|
||||
if (unwrapDescriptor instanceof XmlUnwrapDescriptor) {
|
||||
PsiElement e = viewProvider.findElementAt(offset, language);
|
||||
|
||||
PsiElement tag = PsiTreeUtil.getParentOfType(e, XmlTag.class);
|
||||
while (tag != null) {
|
||||
if (XmlChildRole.START_TAG_END_FINDER.findChild(tag.getNode()) != null) { // Exclude implicit tags suck as 'jsp:root'
|
||||
result.add(new Pair<PsiElement, Unwrapper>(tag, new XmlEnclosingTagUnwrapper()));
|
||||
}
|
||||
tag = PsiTreeUtil.getParentOfType(tag, XmlTag.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Collections.sort(result, new Comparator<Pair<PsiElement, Unwrapper>>() {
|
||||
@Override
|
||||
public int compare(Pair<PsiElement, Unwrapper> o1, Pair<PsiElement, Unwrapper> o2) {
|
||||
return o2.first.getTextOffset() - o1.first.getTextOffset();
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user