mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote branch 'origin/master'
This commit is contained in:
@@ -128,12 +128,17 @@ public class CompileServerManager implements ApplicationComponent{
|
||||
@Override
|
||||
public void run() {
|
||||
if (!myAutoMakeInProgress.getAndSet(true)) {
|
||||
try {
|
||||
runAutoMake();
|
||||
}
|
||||
finally {
|
||||
myAutoMakeInProgress.set(false);
|
||||
}
|
||||
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
runAutoMake();
|
||||
}
|
||||
finally {
|
||||
myAutoMakeInProgress.set(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
scheduleMake(this);
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.intellij.openapi.compiler.CompilerBundle;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
@@ -155,7 +156,7 @@ public class CompilerUtil {
|
||||
|
||||
public static void addSourceCommandLineSwitch(final Sdk jdk, LanguageLevel chunkLanguageLevel, @NonNls final List<String> commandLine) {
|
||||
final String versionString = jdk.getVersionString();
|
||||
if (versionString == null || "".equals(versionString)) {
|
||||
if (StringUtil.isEmpty(versionString)) {
|
||||
throw new IllegalArgumentException(CompilerBundle.message("javac.error.unknown.jdk.version", jdk.getName()));
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -113,7 +113,7 @@ public class JavaCompletionContributor extends CompletionContributor {
|
||||
return new AndFilter(ElementClassFilter.CLASS, new NotFilter(new AssignableFromContextFilter()));
|
||||
}
|
||||
|
||||
if (JavaCompletionData.DECLARATION_START.isAcceptable(position, position) ||
|
||||
if (JavaCompletionData.DECLARATION_START.accepts(position) ||
|
||||
JavaCompletionData.INSIDE_PARAMETER_LIST.accepts(position)) {
|
||||
return new OrFilter(ElementClassFilter.CLASS, ElementClassFilter.PACKAGE_FILTER);
|
||||
}
|
||||
|
||||
@@ -166,16 +166,18 @@ public class JavaCompletionData extends JavaAwareCompletionData{
|
||||
defineScopeEquivalence(PsiMethod.class, JavaCodeFragment.class);
|
||||
}
|
||||
|
||||
public static final AndFilter DECLARATION_START = new AndFilter(
|
||||
CLASS_BODY,
|
||||
new OrFilter(
|
||||
END_OF_BLOCK,
|
||||
new LeftNeighbour(new OrFilter(
|
||||
new SuperParentFilter(new ClassFilter(PsiModifierList.class)),
|
||||
new AndFilter (new TokenTypeFilter(JavaTokenType.GT),
|
||||
new SuperParentFilter(new ClassFilter(PsiTypeParameterList.class)))))
|
||||
),
|
||||
new PatternFilter(not(psiElement().afterLeaf("@", "."))));
|
||||
public static final ElementPattern<PsiElement> DECLARATION_START = psiElement().andNot(psiElement().afterLeaf("@", ".")).
|
||||
andOr(
|
||||
psiElement().and(new FilterPattern(CLASS_BODY)).
|
||||
andOr(
|
||||
new FilterPattern(END_OF_BLOCK),
|
||||
psiElement().afterLeaf(or(
|
||||
psiElement().inside(PsiModifierList.class),
|
||||
psiElement().withElementType(JavaTokenType.GT).inside(PsiTypeParameterList.class)
|
||||
))),
|
||||
psiElement().withParents(PsiJavaCodeReferenceElement.class, PsiTypeElement.class, PsiMember.class),
|
||||
psiElement().withParents(PsiJavaCodeReferenceElement.class, PsiTypeElement.class, PsiClassLevelDeclarationStatement.class)
|
||||
);
|
||||
|
||||
private void declareCompletionSpaces() {
|
||||
declareFinalScope(PsiFile.class);
|
||||
@@ -578,9 +580,7 @@ public class JavaCompletionData extends JavaAwareCompletionData{
|
||||
.afterLeaf(psiElement().withText("(").withParent(psiElement(PsiParenthesizedExpression.class, PsiTypeCastExpression.class)))
|
||||
.accepts(position);
|
||||
|
||||
boolean declaration = DECLARATION_START.isAcceptable(position, position) ||
|
||||
psiElement().withParents(PsiJavaCodeReferenceElement.class, PsiTypeElement.class, PsiMember.class).accepts(position) ||
|
||||
psiElement().withParents(PsiJavaCodeReferenceElement.class, PsiTypeElement.class, PsiClassLevelDeclarationStatement.class).accepts(position);
|
||||
boolean declaration = DECLARATION_START.accepts(position);
|
||||
if (START_FOR.accepts(position) ||
|
||||
INSIDE_PARAMETER_LIST.accepts(position) && !AFTER_DOT.accepts(position) ||
|
||||
VARIABLE_AFTER_FINAL.accepts(position) ||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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.daemon.impl;
|
||||
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiMember;
|
||||
import com.intellij.psi.PsiNamedElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public abstract class GlobalUsageHelper {
|
||||
final Map<PsiClass,Boolean> unusedClassCache = new HashMap<PsiClass, Boolean>();
|
||||
|
||||
public abstract boolean shouldCheckUsages(@NotNull PsiMember member);
|
||||
public abstract boolean isLocallyUsed(@NotNull PsiNamedElement member);
|
||||
public abstract boolean shouldIgnoreUsagesInCurrentFile();
|
||||
}
|
||||
@@ -82,7 +82,6 @@ import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.refactoring.changeSignature.ChangeSignatureGestureDetector;
|
||||
import com.intellij.util.Processor;
|
||||
import gnu.trove.THashSet;
|
||||
import gnu.trove.TObjectIntHashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.PropertyKey;
|
||||
@@ -102,7 +101,7 @@ public class PostHighlightingPass extends TextEditorHighlightingPass {
|
||||
private final JavaCodeStyleManager myStyleManager;
|
||||
private int myCurrentEntryIndex;
|
||||
private boolean myHasMissortedImports;
|
||||
private final ImplicitUsageProvider[] myImplicitUsageProviders;
|
||||
private static final ImplicitUsageProvider[] ourImplicitUsageProviders = Extensions.getExtensions(ImplicitUsageProvider.EP_NAME);
|
||||
private UnusedDeclarationInspection myDeadCodeInspection;
|
||||
private UnusedSymbolLocalInspection myUnusedSymbolInspection;
|
||||
private HighlightDisplayKey myUnusedSymbolKey;
|
||||
@@ -124,8 +123,6 @@ public class PostHighlightingPass extends TextEditorHighlightingPass {
|
||||
|
||||
myStyleManager = JavaCodeStyleManager.getInstance(myProject);
|
||||
myCurrentEntryIndex = -1;
|
||||
|
||||
myImplicitUsageProviders = Extensions.getExtensions(ImplicitUsageProvider.EP_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -254,13 +251,33 @@ public class PostHighlightingPass extends TextEditorHighlightingPass {
|
||||
|
||||
myDeadCodeInfoType = myDeadCodeKey == null ? null : new HighlightInfoType.HighlightInfoTypeImpl(profile.getErrorLevel(myDeadCodeKey, myFile).getSeverity(), HighlightInfoType.UNUSED_SYMBOL.getAttributesKey());
|
||||
|
||||
GlobalUsageHelper helper = new GlobalUsageHelper() {
|
||||
@Override
|
||||
public boolean shouldCheckUsages(@NotNull PsiMember member) {
|
||||
if (myInLibrary) return false;
|
||||
if (!myDeadCodeEnabled) return false;
|
||||
if (myDeadCodeInspection.isEntryPoint(member)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldIgnoreUsagesInCurrentFile() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLocallyUsed(@NotNull PsiNamedElement member) {
|
||||
return myRefCountHolder.isReferenced(member);
|
||||
}
|
||||
};
|
||||
|
||||
boolean errorFound = false;
|
||||
if (unusedSymbolEnabled) {
|
||||
for (PsiElement element : elements) {
|
||||
progress.checkCanceled();
|
||||
if (element instanceof PsiIdentifier) {
|
||||
PsiIdentifier identifier = (PsiIdentifier)element;
|
||||
HighlightInfo info = processIdentifier(identifier, progress);
|
||||
HighlightInfo info = processIdentifier(identifier, progress, helper);
|
||||
if (info != null) {
|
||||
errorFound |= info.getSeverity() == HighlightSeverity.ERROR;
|
||||
result.add(info);
|
||||
@@ -287,7 +304,7 @@ public class PostHighlightingPass extends TextEditorHighlightingPass {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private HighlightInfo processIdentifier(PsiIdentifier identifier, ProgressIndicator progress) {
|
||||
private HighlightInfo processIdentifier(PsiIdentifier identifier, ProgressIndicator progress, GlobalUsageHelper helper) {
|
||||
if (InspectionManagerEx.inspectionResultSuppressed(identifier, myUnusedSymbolInspection)) return null;
|
||||
PsiElement parent = identifier.getParent();
|
||||
if (PsiUtilCore.hasErrorElementChild(parent)) return null;
|
||||
@@ -296,17 +313,17 @@ public class PostHighlightingPass extends TextEditorHighlightingPass {
|
||||
return processLocalVariable((PsiLocalVariable)parent, progress);
|
||||
}
|
||||
if (parent instanceof PsiField && myUnusedSymbolInspection.FIELD) {
|
||||
return processField((PsiField)parent, identifier, progress);
|
||||
return processField((PsiField)parent, identifier, progress, helper);
|
||||
}
|
||||
if (parent instanceof PsiParameter && myUnusedSymbolInspection.PARAMETER) {
|
||||
if (InspectionManagerEx.isSuppressed(identifier, UnusedParametersInspection.SHORT_NAME)) return null;
|
||||
return processParameter((PsiParameter)parent, progress);
|
||||
}
|
||||
if (parent instanceof PsiMethod && myUnusedSymbolInspection.METHOD) {
|
||||
return processMethod((PsiMethod)parent, progress);
|
||||
return processMethod((PsiMethod)parent, progress, helper);
|
||||
}
|
||||
if (parent instanceof PsiClass && myUnusedSymbolInspection.CLASS) {
|
||||
return processClass((PsiClass)parent, progress);
|
||||
return processClass((PsiClass)parent, progress, helper);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -346,9 +363,9 @@ public class PostHighlightingPass extends TextEditorHighlightingPass {
|
||||
}
|
||||
|
||||
|
||||
private boolean isImplicitUsage(final PsiModifierListOwner element, ProgressIndicator progress) {
|
||||
public static boolean isImplicitUsage(final PsiModifierListOwner element, ProgressIndicator progress) {
|
||||
if (UnusedSymbolLocalInspection.isInjected(element)) return true;
|
||||
for (ImplicitUsageProvider provider : myImplicitUsageProviders) {
|
||||
for (ImplicitUsageProvider provider : ourImplicitUsageProviders) {
|
||||
progress.checkCanceled();
|
||||
if (provider.isImplicitUsage(element)) {
|
||||
return true;
|
||||
@@ -358,8 +375,8 @@ public class PostHighlightingPass extends TextEditorHighlightingPass {
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isImplicitRead(final PsiVariable element, ProgressIndicator progress) {
|
||||
for(ImplicitUsageProvider provider: myImplicitUsageProviders) {
|
||||
private static boolean isImplicitRead(final PsiVariable element, ProgressIndicator progress) {
|
||||
for(ImplicitUsageProvider provider: ourImplicitUsageProviders) {
|
||||
progress.checkCanceled();
|
||||
if (provider.isImplicitRead(element)) {
|
||||
return true;
|
||||
@@ -368,8 +385,8 @@ public class PostHighlightingPass extends TextEditorHighlightingPass {
|
||||
return UnusedSymbolLocalInspection.isInjected(element);
|
||||
}
|
||||
|
||||
private boolean isImplicitWrite(final PsiVariable element, ProgressIndicator progress) {
|
||||
for(ImplicitUsageProvider provider: myImplicitUsageProviders) {
|
||||
private static boolean isImplicitWrite(final PsiVariable element, ProgressIndicator progress) {
|
||||
for(ImplicitUsageProvider provider: ourImplicitUsageProviders) {
|
||||
progress.checkCanceled();
|
||||
if (provider.isImplicitWrite(element)) {
|
||||
return true;
|
||||
@@ -378,7 +395,7 @@ public class PostHighlightingPass extends TextEditorHighlightingPass {
|
||||
return UnusedSymbolLocalInspection.isInjected(element);
|
||||
}
|
||||
|
||||
private static HighlightInfo createUnusedSymbolInfo(PsiElement element, String message, final HighlightInfoType highlightInfoType) {
|
||||
public static HighlightInfo createUnusedSymbolInfo(@NotNull PsiElement element, @Nullable String message, @NotNull final HighlightInfoType highlightInfoType) {
|
||||
HighlightInfo info = HighlightInfo.createHighlightInfo(highlightInfoType, element, message);
|
||||
UnusedDeclarationFixProvider[] fixProviders = Extensions.getExtensions(UnusedDeclarationFixProvider.EP_NAME);
|
||||
for (UnusedDeclarationFixProvider provider : fixProviders) {
|
||||
@@ -391,7 +408,7 @@ public class PostHighlightingPass extends TextEditorHighlightingPass {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private HighlightInfo processField(final PsiField field, final PsiIdentifier identifier, ProgressIndicator progress) {
|
||||
private HighlightInfo processField(final PsiField field, final PsiIdentifier identifier, ProgressIndicator progress, GlobalUsageHelper helper) {
|
||||
if (field.hasModifierProperty(PsiModifier.PRIVATE)) {
|
||||
if (!myRefCountHolder.isReferenced(field) && !isImplicitUsage(field, progress)) {
|
||||
if (HighlightUtil.isSerializationImplicitlyUsedField(field)) {
|
||||
@@ -435,12 +452,22 @@ public class PostHighlightingPass extends TextEditorHighlightingPass {
|
||||
else if (isImplicitUsage(field, progress)) {
|
||||
return null;
|
||||
}
|
||||
else if (!myRefCountHolder.isReferenced(field) && weAreSureThereAreNoUsages(field, progress)) {
|
||||
else if (isFieldUnused(field, progress, helper)) {
|
||||
return formatUnusedSymbolHighlightInfo("field.is.not.used", field, "fields", myDeadCodeKey, myDeadCodeInfoType);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean isFieldUnused(PsiField field, ProgressIndicator progress, GlobalUsageHelper helper) {
|
||||
if (helper.isLocallyUsed(field) || !weAreSureThereAreNoUsages(field, progress, helper)) {
|
||||
return false;
|
||||
}
|
||||
if (field instanceof PsiEnumConstant && isEnumValuesMethodUsed(field, progress, helper)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private HighlightInfo suggestionsToMakeFieldUsed(final PsiField field, final PsiIdentifier identifier, final String message) {
|
||||
HighlightInfo highlightInfo = createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL);
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, new RemoveUnusedVariableFix(field), myUnusedSymbolKey);
|
||||
@@ -508,14 +535,12 @@ public class PostHighlightingPass extends TextEditorHighlightingPass {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private HighlightInfo processMethod(final PsiMethod method, ProgressIndicator progress) {
|
||||
boolean isPrivate = method.hasModifierProperty(PsiModifier.PRIVATE);
|
||||
PsiClass containingClass = method.getContainingClass();
|
||||
if (isMethodReferenced(method, progress, isPrivate, containingClass)) return null;
|
||||
private HighlightInfo processMethod(final PsiMethod method, ProgressIndicator progress, GlobalUsageHelper helper) {
|
||||
if (isMethodReferenced(method, progress, helper)) return null;
|
||||
HighlightInfoType highlightInfoType;
|
||||
HighlightDisplayKey highlightDisplayKey;
|
||||
String key;
|
||||
if (isPrivate) {
|
||||
if (method.hasModifierProperty(PsiModifier.PRIVATE)) {
|
||||
highlightInfoType = HighlightInfoType.UNUSED_SYMBOL;
|
||||
highlightDisplayKey = myUnusedSymbolKey;
|
||||
key = method.isConstructor() ? "private.constructor.is.not.used" : "private.method.is.not.used";
|
||||
@@ -537,6 +562,7 @@ public class PostHighlightingPass extends TextEditorHighlightingPass {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
PsiClass containingClass = method.getContainingClass();
|
||||
if (method.getReturnType() != null || containingClass != null && Comparing.strEqual(containingClass.getName(), method.getName())) {
|
||||
//ignore methods with deleted return types as they are always marked as unused without any reason
|
||||
ChangeSignatureGestureDetector.getInstance(myProject).dismissForElement(method);
|
||||
@@ -544,9 +570,13 @@ public class PostHighlightingPass extends TextEditorHighlightingPass {
|
||||
return highlightInfo;
|
||||
}
|
||||
|
||||
private boolean isMethodReferenced(PsiMethod method, ProgressIndicator progress, boolean aPrivate, PsiClass containingClass) {
|
||||
if (myRefCountHolder.isReferenced(method)) return true;
|
||||
public static boolean isMethodReferenced(PsiMethod method,
|
||||
ProgressIndicator progress,
|
||||
GlobalUsageHelper helper) {
|
||||
if (helper.isLocallyUsed(method)) return true;
|
||||
|
||||
boolean aPrivate = method.hasModifierProperty(PsiModifier.PRIVATE);
|
||||
PsiClass containingClass = method.getContainingClass();
|
||||
if (HighlightMethodUtil.isSerializationRelatedMethod(method, containingClass)) return true;
|
||||
if (aPrivate) {
|
||||
if (isIntentionalPrivateConstructor(method, containingClass)) {
|
||||
@@ -555,12 +585,15 @@ public class PostHighlightingPass extends TextEditorHighlightingPass {
|
||||
if (isImplicitUsage(method, progress)) {
|
||||
return true;
|
||||
}
|
||||
if (!helper.shouldIgnoreUsagesInCurrentFile()) {
|
||||
return !weAreSureThereAreNoUsages(method, progress, helper);
|
||||
}
|
||||
}
|
||||
else {
|
||||
//class maybe used in some weird way, e.g. from XML, therefore the only constructor is used too
|
||||
if (containingClass != null && method.isConstructor()
|
||||
&& containingClass.getConstructors().length == 1
|
||||
&& isClassUnused(containingClass, progress) == USED) {
|
||||
&& isClassUsed(containingClass, progress, helper)) {
|
||||
return true;
|
||||
}
|
||||
if (isImplicitUsage(method, progress)) return true;
|
||||
@@ -568,70 +601,49 @@ public class PostHighlightingPass extends TextEditorHighlightingPass {
|
||||
if (method.findSuperMethods().length != 0) {
|
||||
return true;
|
||||
}
|
||||
if (!weAreSureThereAreNoUsages(method, progress)) {
|
||||
if (!weAreSureThereAreNoUsages(method, progress, helper)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean weAreSureThereAreNoUsages(PsiMember member, ProgressIndicator progress) {
|
||||
if (myInLibrary) return false;
|
||||
if (!myDeadCodeEnabled) return false;
|
||||
if (myDeadCodeInspection.isEntryPoint(member)) return false;
|
||||
private static boolean weAreSureThereAreNoUsages(PsiMember member, ProgressIndicator progress, GlobalUsageHelper helper) {
|
||||
if (!helper.shouldCheckUsages(member)) return false;
|
||||
|
||||
String name = member.getName();
|
||||
if (name == null) return false;
|
||||
SearchScope useScope = member.getUseScope();
|
||||
if (!(useScope instanceof GlobalSearchScope)) return false;
|
||||
GlobalSearchScope scope = (GlobalSearchScope)useScope;
|
||||
// some classes may have references from within XML outside dependent modules, e.g. our actions
|
||||
if (member instanceof PsiClass) scope = GlobalSearchScope.projectScope(myProject).uniteWith(scope);
|
||||
Project project = member.getProject();
|
||||
if (useScope instanceof GlobalSearchScope) {
|
||||
GlobalSearchScope scope = (GlobalSearchScope)useScope;
|
||||
// some classes may have references from within XML outside dependent modules, e.g. our actions
|
||||
if (member instanceof PsiClass) scope = GlobalSearchScope.projectScope(project).uniteWith(scope);
|
||||
|
||||
PsiSearchHelper.SearchCostResult cheapEnough = PsiSearchHelper.SERVICE.getInstance(myFile.getProject())
|
||||
.isCheapEnoughToSearch(name, scope, myFile, progress);
|
||||
if (cheapEnough == PsiSearchHelper.SearchCostResult.TOO_MANY_OCCURRENCES) return false;
|
||||
PsiSearchHelper.SearchCostResult cheapEnough = PsiSearchHelper.SERVICE.getInstance(project).isCheapEnoughToSearch(name, scope,
|
||||
helper.shouldIgnoreUsagesInCurrentFile() ? member.getContainingFile() : null,
|
||||
progress);
|
||||
if (cheapEnough == PsiSearchHelper.SearchCostResult.TOO_MANY_OCCURRENCES) return false;
|
||||
|
||||
//search usages if it cheap
|
||||
//if count is 0 there is no usages since we've called myRefCountHolder.isReferenced() before
|
||||
if (cheapEnough == PsiSearchHelper.SearchCostResult.ZERO_OCCURRENCES) {
|
||||
if (member instanceof PsiEnumConstant) {
|
||||
return !isEnumValuesMethodUsed(member, progress);
|
||||
//search usages if it cheap
|
||||
//if count is 0 there is no usages since we've called myRefCountHolder.isReferenced() before
|
||||
if (cheapEnough == PsiSearchHelper.SearchCostResult.ZERO_OCCURRENCES) {
|
||||
if (!canBeReferencedViaWeirdNames(member)) return true;
|
||||
}
|
||||
if (!canBeReferencedViaWeirdNames(member)) return true;
|
||||
}
|
||||
FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(myProject)).getFindUsagesManager();
|
||||
FindUsagesOptions findUsagesOptions;
|
||||
if (member instanceof PsiClass) {
|
||||
findUsagesOptions = new JavaClassFindUsagesOptions(myProject);
|
||||
}
|
||||
else if (member instanceof PsiMethod) {
|
||||
findUsagesOptions = new JavaMethodFindUsagesOptions(myProject);
|
||||
}
|
||||
else if (member instanceof PsiField) {
|
||||
findUsagesOptions = new JavaVariableFindUsagesOptions(myProject);
|
||||
}
|
||||
else {
|
||||
LOG.error("unknown member: " + member);
|
||||
return false;
|
||||
}
|
||||
findUsagesOptions.searchScope = scope;
|
||||
|
||||
boolean used = findUsagesManager.isUsed(member, findUsagesOptions);
|
||||
|
||||
if (!used && member instanceof PsiEnumConstant) {
|
||||
return !isEnumValuesMethodUsed(member, progress);
|
||||
}
|
||||
return !used;
|
||||
FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(project)).getFindUsagesManager();
|
||||
FindUsagesHandler handler = new JavaFindUsagesHandler(member, new JavaFindUsagesHandlerFactory(project));
|
||||
FindUsagesOptions findUsagesOptions = handler.getFindUsagesOptions();
|
||||
findUsagesOptions.searchScope = useScope;
|
||||
return !findUsagesManager.isUsed(member, findUsagesOptions);
|
||||
}
|
||||
|
||||
private boolean isEnumValuesMethodUsed(PsiMember member, ProgressIndicator progress) {
|
||||
private static boolean isEnumValuesMethodUsed(PsiMember member, ProgressIndicator progress, GlobalUsageHelper helper) {
|
||||
final PsiClassImpl containingClass = (PsiClassImpl)member.getContainingClass();
|
||||
if (containingClass == null) return true;
|
||||
final PsiMethod valuesMethod = containingClass.getValuesMethod();
|
||||
if (valuesMethod == null) return true;
|
||||
boolean isPrivate = valuesMethod.hasModifierProperty(PsiModifier.PRIVATE);
|
||||
return isMethodReferenced(valuesMethod, progress, isPrivate, containingClass);
|
||||
return isMethodReferenced(valuesMethod, progress, helper);
|
||||
}
|
||||
|
||||
private static boolean canBeReferencedViaWeirdNames(PsiMember member) {
|
||||
@@ -646,9 +658,8 @@ public class PostHighlightingPass extends TextEditorHighlightingPass {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private HighlightInfo processClass(PsiClass aClass, ProgressIndicator progress) {
|
||||
int usage = isClassUnused(aClass, progress);
|
||||
if (usage == USED) return null;
|
||||
private HighlightInfo processClass(PsiClass aClass, ProgressIndicator progress, GlobalUsageHelper helper) {
|
||||
if (isClassUsed(aClass, progress, helper)) return null;
|
||||
|
||||
String pattern;
|
||||
HighlightDisplayKey highlightDisplayKey;
|
||||
@@ -678,27 +689,22 @@ public class PostHighlightingPass extends TextEditorHighlightingPass {
|
||||
return formatUnusedSymbolHighlightInfo(pattern, aClass, "classes", highlightDisplayKey, highlightInfoType);
|
||||
}
|
||||
|
||||
private static final int USED = 1;
|
||||
private static final int UNUSED_LOCALLY = 2;
|
||||
private static final int UNUSED_GLOBALLY = 3;
|
||||
private final TObjectIntHashMap<PsiClass> unusedClassCache = new TObjectIntHashMap<PsiClass>();
|
||||
private int isClassUnused(PsiClass aClass, ProgressIndicator progress) {
|
||||
if (aClass == null) return USED;
|
||||
int result = unusedClassCache.get(aClass);
|
||||
if (result == 0) {
|
||||
result = isReallyUnused(aClass, progress);
|
||||
unusedClassCache.put(aClass, result);
|
||||
public static boolean isClassUsed(PsiClass aClass, ProgressIndicator progress, GlobalUsageHelper helper) {
|
||||
if (aClass == null) return true;
|
||||
Boolean result = helper.unusedClassCache.get(aClass);
|
||||
if (result == null) {
|
||||
result = isReallyUsed(aClass, progress, helper);
|
||||
helper.unusedClassCache.put(aClass, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private int isReallyUnused(PsiClass aClass, ProgressIndicator progress) {
|
||||
if (isImplicitUsage(aClass, progress) || myRefCountHolder.isReferenced(aClass)) return USED;
|
||||
private static boolean isReallyUsed(PsiClass aClass, ProgressIndicator progress, GlobalUsageHelper helper) {
|
||||
if (isImplicitUsage(aClass, progress) || helper.isLocallyUsed(aClass)) return true;
|
||||
if (aClass.getContainingClass() != null && aClass.hasModifierProperty(PsiModifier.PRIVATE) ||
|
||||
aClass.getParent() instanceof PsiDeclarationStatement ||
|
||||
aClass instanceof PsiTypeParameter) return UNUSED_LOCALLY;
|
||||
if (weAreSureThereAreNoUsages(aClass, progress)) return UNUSED_GLOBALLY;
|
||||
return USED;
|
||||
aClass instanceof PsiTypeParameter) return false;
|
||||
return !weAreSureThereAreNoUsages(aClass, progress, helper);
|
||||
}
|
||||
|
||||
private static HighlightInfo formatUnusedSymbolHighlightInfo(@PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) String pattern,
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.intellij.lang.StdLanguages;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.ScrollType;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
@@ -40,9 +41,7 @@ import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
public class GenerateMembersUtil {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.generation.GenerateMembersUtil");
|
||||
@@ -279,7 +278,9 @@ public class GenerateMembersUtil {
|
||||
|
||||
PsiParameter newParameter = factory.createParameter(paramName, substituted);
|
||||
if (parameter.getLanguage() == StdLanguages.JAVA) {
|
||||
newParameter.getModifierList().replace(parameter.getModifierList());
|
||||
PsiModifierList modifierList = newParameter.getModifierList();
|
||||
modifierList = (PsiModifierList)modifierList.replace(parameter.getModifierList());
|
||||
processAnnotations(project, modifierList);
|
||||
}
|
||||
newMethod.getParameterList().add(newParameter);
|
||||
}
|
||||
@@ -312,6 +313,23 @@ public class GenerateMembersUtil {
|
||||
}
|
||||
}
|
||||
|
||||
private static void processAnnotations(Project project, PsiModifierList modifierList) {
|
||||
final Set<String> toRemove = new HashSet<String>();
|
||||
for (PsiAnnotation annotation : modifierList.getAnnotations()) {
|
||||
final String qualifiedName = annotation.getQualifiedName();
|
||||
for (OverrideImplementsAnnotationsHandler handler : Extensions.getExtensions(OverrideImplementsAnnotationsHandler.EP_NAME)) {
|
||||
final String[] annotations2Remove = handler.annotationsToRemove(project, qualifiedName);
|
||||
Collections.addAll(toRemove, annotations2Remove);
|
||||
}
|
||||
}
|
||||
for (String fqn : toRemove) {
|
||||
final PsiAnnotation psiAnnotation = modifierList.findAnnotation(fqn);
|
||||
if (psiAnnotation != null) {
|
||||
psiAnnotation.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static PsiType substituteType(final PsiSubstitutor substitutor, final PsiType type) {
|
||||
final PsiType psiType = substitutor.substitute(type);
|
||||
if (psiType != null) return psiType;
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.codeInspection.canBeFinal;
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.psi.PsiMember;
|
||||
|
||||
/**
|
||||
* User: anna
|
||||
* Date: 1/31/12
|
||||
*/
|
||||
public abstract class CanBeFinalHandler {
|
||||
public static final ExtensionPointName<CanBeFinalHandler> EP_NAME = ExtensionPointName.create("com.intellij.canBeFinal");
|
||||
|
||||
public abstract boolean canBeFinal(PsiMember member);
|
||||
|
||||
public static boolean allowToBeFinal(PsiMember member) {
|
||||
for (CanBeFinalHandler handler : Extensions.getExtensions(EP_NAME)) {
|
||||
if (!handler.canBeFinal(member)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -139,6 +139,9 @@ public class CanBeFinalInspection extends GlobalJavaInspectionTool {
|
||||
if (refElement.isFinal()) return null;
|
||||
if (!((RefElementImpl)refElement).checkFlag(CanBeFinalAnnotator.CAN_BE_FINAL_MASK)) return null;
|
||||
|
||||
final PsiMember psiMember = (PsiMember)refElement.getElement();
|
||||
if (!CanBeFinalHandler.allowToBeFinal(psiMember)) return null;
|
||||
|
||||
PsiIdentifier psiIdentifier = null;
|
||||
if (refElement instanceof RefClass) {
|
||||
RefClass refClass = (RefClass)refElement;
|
||||
|
||||
+5
-3
@@ -13,13 +13,15 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.refactoring.rename;
|
||||
package com.intellij.refactoring.actions;
|
||||
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiClassOwner;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.refactoring.rename.PsiElementRenameHandler;
|
||||
|
||||
/**
|
||||
* @author ven
|
||||
@@ -34,13 +36,13 @@ public class RenameFileAction extends AnAction implements DumbAware {
|
||||
assert virtualFile != null;
|
||||
final Project project = e.getData(PlatformDataKeys.PROJECT);
|
||||
assert project != null;
|
||||
new RenameDialog(project, file, file, null).show();
|
||||
PsiElementRenameHandler.invoke(file, project, file, null);
|
||||
}
|
||||
|
||||
public void update(AnActionEvent e) {
|
||||
PsiFile file = e.getData(LangDataKeys.PSI_FILE);
|
||||
Presentation presentation = e.getPresentation();
|
||||
boolean enabled = file != null && e.getPlace() != ActionPlaces.EDITOR_POPUP && e.getData(PlatformDataKeys.PROJECT) != null;
|
||||
boolean enabled = file instanceof PsiClassOwner && e.getPlace() != ActionPlaces.EDITOR_POPUP && e.getData(PlatformDataKeys.PROJECT) != null;
|
||||
presentation.setEnabled(enabled);
|
||||
presentation.setVisible(enabled);
|
||||
if (enabled) {
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.core;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.roots.PackageIndex;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
@@ -39,6 +40,8 @@ import java.util.List;
|
||||
* @author yole
|
||||
*/
|
||||
public class CoreJavaFileManager extends PackageIndex implements JavaFileManager {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.core.CoreJavaFileManager");
|
||||
|
||||
private final CoreLocalFileSystem myLocalFileSystem;
|
||||
private final CoreJarFileSystem myJarFileSystem;
|
||||
private final List<File> myClasspath = new ArrayList<File>();
|
||||
@@ -85,11 +88,17 @@ public class CoreJavaFileManager extends PackageIndex implements JavaFileManager
|
||||
|
||||
@Nullable
|
||||
private VirtualFile findUnderClasspathEntry(File classpathEntry, String relativeName) {
|
||||
VirtualFile root = findRootInClassPathEntry(classpathEntry);
|
||||
return root != null ? root.findFileByRelativePath(relativeName) : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private VirtualFile findRootInClassPathEntry(File classpathEntry) {
|
||||
if (classpathEntry.isFile()) {
|
||||
return myJarFileSystem.findFileByPath(classpathEntry.getPath() + "!/" + relativeName);
|
||||
return myJarFileSystem.findFileByPath(classpathEntry.getPath() + "!/");
|
||||
}
|
||||
else {
|
||||
return myLocalFileSystem.findFileByPath(new File(classpathEntry, relativeName).getPath());
|
||||
return myLocalFileSystem.findFileByPath(classpathEntry.getPath());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,25 +124,77 @@ public class CoreJavaFileManager extends PackageIndex implements JavaFileManager
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private PsiClass findClassInClasspathEntry(String qName, File file) {
|
||||
// TODO handle inner classes correctly
|
||||
String fileName = qName.replace(".", "/") + ".java";
|
||||
VirtualFile classFile = findUnderClasspathEntry(file, fileName);
|
||||
if (classFile == null) {
|
||||
fileName = qName.replace(".", "/") + ".class";
|
||||
classFile = findUnderClasspathEntry(file, fileName);
|
||||
private PsiClass findClassInClasspathEntry(String qName, File rootEntry) {
|
||||
VirtualFile root = findRootInClassPathEntry(rootEntry);
|
||||
if (root == null) return null;
|
||||
|
||||
return findClassInClasspathRoot(qName, root, myPsiManager);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiClass findClassInClasspathRoot(String qName, VirtualFile root, PsiManager psiManager) {
|
||||
String pathRest = qName;
|
||||
VirtualFile cur = root;
|
||||
|
||||
while (true) {
|
||||
int dot = pathRest.indexOf('.');
|
||||
if (dot < 0) break;
|
||||
|
||||
String pathComponent = pathRest.substring(0, dot);
|
||||
VirtualFile child = cur.findChild(pathComponent);
|
||||
|
||||
if (child == null) break;
|
||||
pathRest = pathRest.substring(dot + 1);
|
||||
cur = child;
|
||||
}
|
||||
|
||||
if (classFile != null) {
|
||||
PsiFile psiFile = myPsiManager.findFile(classFile);
|
||||
if (!(psiFile instanceof PsiJavaFile)) {
|
||||
throw new UnsupportedOperationException("no java file for " + fileName);
|
||||
String className = pathRest.replace('.', '$');
|
||||
int bucks = className.indexOf('$');
|
||||
|
||||
String rootClassName;
|
||||
if (bucks < 0) {
|
||||
rootClassName = className;
|
||||
}
|
||||
else {
|
||||
rootClassName = className.substring(0, bucks);
|
||||
className = className.substring(bucks + 1);
|
||||
}
|
||||
|
||||
VirtualFile vFile = cur.findChild(rootClassName + ".class");
|
||||
if (vFile == null) vFile = cur.findChild(rootClassName + ".java");
|
||||
|
||||
if (vFile != null) {
|
||||
if (!vFile.isValid()) {
|
||||
LOG.error("Invalid child of valid parent: " + vFile.getPath() + "; " + root.isValid() + " path=" + root.getPath());
|
||||
return null;
|
||||
}
|
||||
final PsiClass[] classes = ((PsiJavaFile)psiFile).getClasses();
|
||||
if (classes.length == 1) {
|
||||
return classes[0];
|
||||
|
||||
final PsiFile file = psiManager.findFile(vFile);
|
||||
if (file instanceof PsiClassOwner) {
|
||||
final PsiClass[] classes = ((PsiClassOwner)file).getClasses();
|
||||
if (classes.length == 1) {
|
||||
PsiClass curClass = classes[0];
|
||||
|
||||
if (bucks > 0) {
|
||||
while (true) {
|
||||
int b = className.indexOf("$");
|
||||
|
||||
String component = b < 0 ? className : className.substring(0, b);
|
||||
PsiClass inner = curClass.findInnerClassByName(component, false);
|
||||
|
||||
if (inner == null) return null;
|
||||
curClass = inner;
|
||||
className = className.substring(b + 1);
|
||||
if (b < 0) break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return curClass;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+3
@@ -775,6 +775,9 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
break;
|
||||
case CLASS_NAME_KIND:
|
||||
addClassFilter(filter);
|
||||
if (isQualified()) {
|
||||
filter.addFilter(ElementClassFilter.PACKAGE_FILTER);
|
||||
}
|
||||
break;
|
||||
case PACKAGE_NAME_KIND:
|
||||
filter.addFilter(ElementClassFilter.PACKAGE_FILTER);
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
class Foo {
|
||||
java.l<caret>
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
class Foo {
|
||||
java.lang.<caret>
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
class Anonymous {
|
||||
int num1;
|
||||
int num2;
|
||||
Object o = new Object(){<caret>};
|
||||
|
||||
Anonymous() {}
|
||||
void foo() {}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
-Anonymous.java
|
||||
-Anonymous
|
||||
Anonymous()
|
||||
foo():void
|
||||
num1:int
|
||||
num2:int
|
||||
-[o:Object = new Object() {...}]
|
||||
$1
|
||||
@@ -0,0 +1,15 @@
|
||||
class AnonymousInAnonymous {
|
||||
int num1;
|
||||
int num2;
|
||||
|
||||
AnonymousInAnonymous() {}
|
||||
void foo() {
|
||||
new Object() {
|
||||
public String toString() {
|
||||
return new Object(){
|
||||
void method() {<caret>}
|
||||
}.toString();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
-AnonymousInAnonymous.java
|
||||
-AnonymousInAnonymous
|
||||
AnonymousInAnonymous()
|
||||
-foo():void
|
||||
-$1
|
||||
-toString():String
|
||||
-Anonymous
|
||||
[method():void]
|
||||
num1:int
|
||||
num2:int
|
||||
@@ -0,0 +1,10 @@
|
||||
class Anonymous {
|
||||
int num1;
|
||||
int num2;
|
||||
Object o = new Object(){
|
||||
int num = 1;
|
||||
};
|
||||
|
||||
Anonymous() {}
|
||||
void foo() {}
|
||||
}
|
||||
+4
-10
@@ -1258,16 +1258,10 @@ public class ListUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public void testNoGenericsWhenChoosingWithParen() {
|
||||
configure()
|
||||
myFixture.type 'Ma('
|
||||
checkResult()
|
||||
}
|
||||
public void testNoGenericsWhenChoosingWithParen() { doTest('Ma(') }
|
||||
|
||||
public void testNoClosingWhenChoosingWithParenBeforeIdentifier() {
|
||||
configure()
|
||||
myFixture.type '('
|
||||
checkResult()
|
||||
}
|
||||
public void testNoClosingWhenChoosingWithParenBeforeIdentifier() { doTest '(' }
|
||||
|
||||
public void testPackageInMemberType() { doTest() }
|
||||
|
||||
}
|
||||
|
||||
+6
-4
@@ -24,8 +24,10 @@ public class JavaFileStructureSelectionTest extends JavaFileStructureTestCase {
|
||||
return "selection";
|
||||
}
|
||||
|
||||
public void testField() throws Exception {checkTree();}
|
||||
public void testMethod() throws Exception {checkTree();}
|
||||
public void testConstructor() throws Exception {checkTree();}
|
||||
public void testInsideClass() throws Exception {checkTree();}
|
||||
public void testField() throws Exception {checkTree();}
|
||||
public void testMethod() throws Exception {checkTree();}
|
||||
public void testConstructor() throws Exception {checkTree();}
|
||||
public void testInsideClass() throws Exception {checkTree();}
|
||||
public void testAnonymous() throws Exception {checkTree();}
|
||||
public void testAnonymousInAnonymous() throws Exception {checkTree();}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,9 @@ public abstract class JavaFileStructureTestCase extends FileStructureTestBase {
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
myShowAnonymousByDefault = PropertiesComponent.getInstance().getBoolean(getAnonymousPropertyName(), false);
|
||||
if (getTestName(false).contains("Anonymous")) {
|
||||
setShowAnonymous(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -40,6 +43,11 @@ public abstract class JavaFileStructureTestCase extends FileStructureTestBase {
|
||||
return "java";
|
||||
}
|
||||
|
||||
public void setShowAnonymous(boolean show) throws Exception {
|
||||
myPopup.setTreeActionState(JavaAnonymousClassesNodeProvider.class, show);
|
||||
update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tearDown() throws Exception {
|
||||
PropertiesComponent.getInstance().setValue(getAnonymousPropertyName(), Boolean.toString(myShowAnonymousByDefault));
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/testSrc" isTestSource="true" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
|
||||
@@ -32,11 +32,14 @@ public class CoreJarVirtualFile extends VirtualFile {
|
||||
private final CoreJarFileSystem myFileSystem;
|
||||
private final CoreJarHandler myHandler;
|
||||
private final String myPathInJar;
|
||||
private final VirtualFile myParent;
|
||||
private VirtualFile[] myChildren;
|
||||
|
||||
public CoreJarVirtualFile(CoreJarFileSystem fileSystem, CoreJarHandler handler, String pathInJar) {
|
||||
myFileSystem = fileSystem;
|
||||
myHandler = handler;
|
||||
myPathInJar = pathInJar;
|
||||
myParent = calcParent();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -77,6 +80,10 @@ public class CoreJarVirtualFile extends VirtualFile {
|
||||
|
||||
@Override
|
||||
public VirtualFile getParent() {
|
||||
return myParent;
|
||||
}
|
||||
|
||||
private VirtualFile calcParent() {
|
||||
if (myPathInJar.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
@@ -89,6 +96,15 @@ public class CoreJarVirtualFile extends VirtualFile {
|
||||
|
||||
@Override
|
||||
public VirtualFile[] getChildren() {
|
||||
VirtualFile[] answer = myChildren;
|
||||
if (answer == null) {
|
||||
answer = calcChildren();
|
||||
myChildren = answer;
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
private VirtualFile[] calcChildren() {
|
||||
List<VirtualFile> result = new ArrayList<VirtualFile>();
|
||||
final String[] children = myHandler.list(this);
|
||||
for (String child : children) {
|
||||
|
||||
@@ -107,6 +107,7 @@ public class FileStructurePopup implements Disposable {
|
||||
private int myPreferredWidth;
|
||||
private final FilteringTreeStructure myFilteringStructure;
|
||||
private PsiElement myInitialPsiElement;
|
||||
private Map<Class, JCheckBox> myCheckBoxes = new HashMap<Class, JCheckBox>();
|
||||
|
||||
public FileStructurePopup(StructureViewModel structureViewModel,
|
||||
@Nullable Editor editor,
|
||||
@@ -128,7 +129,7 @@ public class FileStructurePopup implements Disposable {
|
||||
|
||||
myTreeStructure = new SmartTreeStructure(project, myTreeModel){
|
||||
public void rebuildTree() {
|
||||
if (!myPopup.isDisposed()) {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode() || !myPopup.isDisposed()) {
|
||||
super.rebuildTree();
|
||||
}
|
||||
}
|
||||
@@ -503,7 +504,7 @@ public class FileStructurePopup implements Disposable {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected JComponent createCenterPanel() {
|
||||
public JComponent createCenterPanel() {
|
||||
List<FileStructureFilter> fileStructureFilters = new ArrayList<FileStructureFilter>();
|
||||
List<FileStructureNodeProvider> fileStructureNodeProviders = new ArrayList<FileStructureNodeProvider>();
|
||||
if (myTreeActionsOwner != null) {
|
||||
@@ -704,6 +705,7 @@ public class FileStructurePopup implements Disposable {
|
||||
}
|
||||
chkFilter.setText(text);
|
||||
panel.add(chkFilter);
|
||||
myCheckBoxes.put(action.getClass(), chkFilter);
|
||||
}
|
||||
|
||||
private static boolean getDefaultValue(TreeAction action) {
|
||||
@@ -742,6 +744,16 @@ public class FileStructurePopup implements Disposable {
|
||||
return myAbstractTreeBuilder;
|
||||
}
|
||||
|
||||
public void setTreeActionState(Class<? extends TreeAction> action, boolean state) {
|
||||
final JCheckBox checkBox = myCheckBoxes.get(action);
|
||||
if (checkBox != null) {
|
||||
checkBox.setSelected(state);
|
||||
for (ActionListener listener : checkBox.getActionListeners()) {
|
||||
listener.actionPerformed(new ActionEvent(this, 1, ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class FileStructurePopupFilter implements ElementFilter {
|
||||
private String myLastFilter = null;
|
||||
private HashSet<Object> myVisibleParents = new HashSet<Object>();
|
||||
|
||||
@@ -254,7 +254,6 @@
|
||||
class = "com.intellij.refactoring.actions.RefactoringQuickListPopupAction"
|
||||
text = "Refactor This..." description="Context aware popup with list of refactoring actions"/>
|
||||
<action id="RenameElement" class="com.intellij.refactoring.actions.RenameElementAction"/>
|
||||
<action id="RenameFile" class="com.intellij.refactoring.rename.RenameFileAction"/>
|
||||
<action id="ChangeSignature" class="com.intellij.refactoring.actions.ChangeSignatureAction"/>
|
||||
<separator/>
|
||||
<action id="Move" class="com.intellij.refactoring.actions.MoveAction"/>
|
||||
@@ -572,9 +571,6 @@
|
||||
<separator/>
|
||||
<reference ref="AddToFavorites"/>
|
||||
<reference ref="AddAllToFavorites"/>
|
||||
<separator/>
|
||||
<reference ref="RenameFile"/>
|
||||
<separator/>
|
||||
<reference ref="MoveToChangeList"/>
|
||||
<separator/>
|
||||
<reference ref="RunContextPopupGroup"/>
|
||||
|
||||
@@ -36,7 +36,7 @@ import java.io.File;
|
||||
* @author Konstantin Bulenkov
|
||||
*/
|
||||
public abstract class FileStructureTestBase extends CodeInsightFixtureTestCase {
|
||||
FileStructurePopup myPopup;
|
||||
protected FileStructurePopup myPopup;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
@@ -46,6 +46,9 @@ public abstract class FileStructureTestBase extends CodeInsightFixtureTestCase {
|
||||
myFixture.getProject(),
|
||||
null,
|
||||
TextEditorProvider.getInstance().getTextEditor(myFixture.getEditor()));
|
||||
assert myPopup != null;
|
||||
myPopup.createCenterPanel();
|
||||
getBuilder().getUi().getUpdater().setPassThroughMode(true);
|
||||
update();
|
||||
}
|
||||
|
||||
@@ -71,15 +74,17 @@ public abstract class FileStructureTestBase extends CodeInsightFixtureTestCase {
|
||||
}
|
||||
|
||||
|
||||
private void update() throws InterruptedException {
|
||||
public void update() throws InterruptedException {
|
||||
myPopup.getTreeBuilder().refilter().doWhenProcessed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
getStructure().rebuild();
|
||||
updateTree();
|
||||
getBuilder().updateFromRoot();
|
||||
TreeUtil.expandAll(getTree());
|
||||
final FilteringTreeStructure.FilteringNode node = myPopup.selectPsiElement(myPopup.getCurrentElement(getFile()));
|
||||
getTree().getSelectionModel().setSelectionPath(getTree().getPath(node));
|
||||
getBuilder().getUi().select(node, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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.testFramework;
|
||||
|
||||
import com.intellij.ide.util.treeView.AbstractTreeBuilder;
|
||||
import com.intellij.ide.util.treeView.AbstractTreeUpdater;
|
||||
|
||||
/**
|
||||
* @author Konstantin Bulenkov
|
||||
*/
|
||||
public class TestTreeUpdater extends AbstractTreeUpdater {
|
||||
public TestTreeUpdater(AbstractTreeBuilder treeBuilder) {
|
||||
super(treeBuilder);
|
||||
}
|
||||
}
|
||||
@@ -100,17 +100,20 @@ public class RollbackAction extends AnAction implements DumbAware {
|
||||
FileDocumentManager.getInstance().saveAllDocuments();
|
||||
|
||||
List<FilePath> missingFiles = e.getData(ChangesListView.MISSING_FILES_DATA_KEY);
|
||||
boolean hasChanges = false;
|
||||
if (missingFiles != null && !missingFiles.isEmpty()) {
|
||||
hasChanges = true;
|
||||
new RollbackDeletionAction().actionPerformed(e);
|
||||
}
|
||||
|
||||
List<VirtualFile> modifiedWithoutEditing = getModifiedWithoutEditing(e);
|
||||
if (modifiedWithoutEditing != null && !modifiedWithoutEditing.isEmpty()) {
|
||||
hasChanges = true;
|
||||
rollbackModifiedWithoutEditing(project, modifiedWithoutEditing);
|
||||
}
|
||||
|
||||
Change[] changes = getChanges(project, e);
|
||||
if (changes != null) {
|
||||
if (changes != null && (changes.length > 0 || !hasChanges)) {
|
||||
RollbackChangesDialog.rollbackChanges(project, Arrays.asList(changes));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -460,7 +460,7 @@ large.array.allocation.no.outofmemoryerror.problem.descriptor=Large array alloca
|
||||
large.array.allocation.no.outofmemoryerror.maximum.number.of.elements.option=Maximum number of elements:
|
||||
connection.opened.not.safely.closed.display.name=Connection opened but not safely closed
|
||||
field.repeatedly.accessed.in.method.display.name=Field repeatedly accessed in method
|
||||
field.repeatedly.accessed.in.method.problem.descriptor=Field ''{0}'' accessed repeatedly in method <code>#ref(0</code> #loc
|
||||
field.repeatedly.accessed.in.method.problem.descriptor=Field ''{0}'' accessed repeatedly in method <code>#ref()</code> #loc
|
||||
field.repeatedly.accessed.in.method.ignore.option=Ignore final fields
|
||||
interface.one.inheritor.display.name=Interface which has only one direct inheritor
|
||||
interface.one.inheritor.problem.descriptor=Interface <code>#ref</code> has only one direct inheritor #loc
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.siyeh.ig.style;
|
||||
|
||||
import com.intellij.codeInspection.canBeFinal.CanBeFinalHandler;
|
||||
import com.intellij.psi.PsiField;
|
||||
import com.intellij.psi.PsiModifier;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
@@ -65,6 +66,7 @@ public class FieldMayBeFinalInspection extends BaseInspection {
|
||||
!field.hasModifierProperty(PsiModifier.PRIVATE)) {
|
||||
return;
|
||||
}
|
||||
if (!CanBeFinalHandler.allowToBeFinal(field)) return;
|
||||
if (!FinalUtils.canBeFinal(field)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
|
||||
* Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -24,7 +24,7 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.siyeh.IntentionPowerPackBundle;
|
||||
import com.siyeh.ipp.psiutils.BoolUtils;
|
||||
@@ -46,8 +46,7 @@ public abstract class Intention extends PsiElementBaseIntentionAction {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(Project project, Editor editor, PsiElement element)
|
||||
throws IncorrectOperationException {
|
||||
public void invoke(Project project, Editor editor, PsiElement element) throws IncorrectOperationException {
|
||||
if (!isWritable(project, element)) {
|
||||
return;
|
||||
}
|
||||
@@ -58,33 +57,25 @@ public abstract class Intention extends PsiElementBaseIntentionAction {
|
||||
processIntention(matchingElement);
|
||||
}
|
||||
|
||||
protected abstract void processIntention(@NotNull PsiElement element)
|
||||
throws IncorrectOperationException;
|
||||
protected abstract void processIntention(@NotNull PsiElement element) throws IncorrectOperationException;
|
||||
|
||||
@NotNull
|
||||
protected abstract PsiElementPredicate getElementPredicate();
|
||||
|
||||
protected static void replaceExpression(@NotNull String newExpression,
|
||||
@NotNull PsiExpression expression)
|
||||
protected static void replaceExpression(@NotNull String newExpression, @NotNull PsiExpression expression)
|
||||
throws IncorrectOperationException {
|
||||
final Project project = expression.getProject();
|
||||
final PsiElementFactory factory =
|
||||
JavaPsiFacade.getElementFactory(project);
|
||||
final PsiExpression newCall =
|
||||
factory.createExpressionFromText(newExpression, expression);
|
||||
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
|
||||
final PsiExpression newCall = factory.createExpressionFromText(newExpression, expression);
|
||||
final PsiElement insertedElement = expression.replace(newCall);
|
||||
final CodeStyleManager codeStyleManager =
|
||||
CodeStyleManager.getInstance(project);
|
||||
final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project);
|
||||
codeStyleManager.reformat(insertedElement);
|
||||
}
|
||||
|
||||
protected static void replaceExpressionWithNegatedExpression(
|
||||
@NotNull PsiExpression newExpression,
|
||||
@NotNull PsiExpression expression)
|
||||
protected static void replaceExpressionWithNegatedExpression(@NotNull PsiExpression newExpression, @NotNull PsiExpression expression)
|
||||
throws IncorrectOperationException {
|
||||
final Project project = expression.getProject();
|
||||
final PsiElementFactory factory =
|
||||
JavaPsiFacade.getElementFactory(project);
|
||||
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
|
||||
PsiExpression expressionToReplace = expression;
|
||||
final String newExpressionText = newExpression.getText();
|
||||
final String expString;
|
||||
@@ -93,36 +84,29 @@ public abstract class Intention extends PsiElementBaseIntentionAction {
|
||||
expString = newExpressionText;
|
||||
}
|
||||
else if (ComparisonUtils.isComparison(newExpression)) {
|
||||
final PsiBinaryExpression binaryExpression =
|
||||
(PsiBinaryExpression)newExpression;
|
||||
final String negatedComparison =
|
||||
ComparisonUtils.getNegatedComparison(binaryExpression.getOperationTokenType());
|
||||
final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)newExpression;
|
||||
final String negatedComparison = ComparisonUtils.getNegatedComparison(binaryExpression.getOperationTokenType());
|
||||
final PsiExpression lhs = binaryExpression.getLOperand();
|
||||
final PsiExpression rhs = binaryExpression.getROperand();
|
||||
assert rhs != null;
|
||||
expString = lhs.getText() + negatedComparison + rhs.getText();
|
||||
}
|
||||
else {
|
||||
if (ParenthesesUtils.getPrecedence(newExpression) >
|
||||
ParenthesesUtils.PREFIX_PRECEDENCE) {
|
||||
if (ParenthesesUtils.getPrecedence(newExpression) > ParenthesesUtils.PREFIX_PRECEDENCE) {
|
||||
expString = "!(" + newExpressionText + ')';
|
||||
}
|
||||
else {
|
||||
expString = '!' + newExpressionText;
|
||||
}
|
||||
}
|
||||
final PsiExpression newCall =
|
||||
factory.createExpressionFromText(expString, expression);
|
||||
final PsiExpression newCall = factory.createExpressionFromText(expString, expression);
|
||||
assert expressionToReplace != null;
|
||||
final PsiElement insertedElement = expressionToReplace.replace(newCall);
|
||||
final CodeStyleManager codeStyleManager =
|
||||
CodeStyleManager.getInstance(project);
|
||||
final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project);
|
||||
codeStyleManager.reformat(insertedElement);
|
||||
}
|
||||
|
||||
protected static void replaceExpressionWithNegatedExpressionString(
|
||||
@NotNull String newExpression,
|
||||
@NotNull PsiExpression expression)
|
||||
protected static void replaceExpressionWithNegatedExpressionString(@NotNull String newExpression, @NotNull PsiExpression expression)
|
||||
throws IncorrectOperationException {
|
||||
final Project project = expression.getProject();
|
||||
final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
|
||||
@@ -130,52 +114,44 @@ public abstract class Intention extends PsiElementBaseIntentionAction {
|
||||
PsiExpression expressionToReplace = expression;
|
||||
final String expString;
|
||||
if (BoolUtils.isNegated(expression)) {
|
||||
expressionToReplace = BoolUtils.findNegation(expression);
|
||||
expressionToReplace = BoolUtils.findNegation(expressionToReplace);
|
||||
expString = newExpression;
|
||||
}
|
||||
else {
|
||||
PsiElement parent = expressionToReplace.getParent();
|
||||
while (parent instanceof PsiParenthesizedExpression) {
|
||||
expressionToReplace = (PsiExpression)parent;
|
||||
parent = parent.getParent();
|
||||
}
|
||||
expString = "!(" + newExpression + ')';
|
||||
}
|
||||
final PsiExpression newCall =
|
||||
factory.createExpressionFromText(expString, expression);
|
||||
final PsiExpression newCall = factory.createExpressionFromText(expString, expression);
|
||||
assert expressionToReplace != null;
|
||||
final PsiElement insertedElement = expressionToReplace.replace(newCall);
|
||||
final CodeStyleManager codeStyleManager =
|
||||
CodeStyleManager.getInstance(project);
|
||||
final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project);
|
||||
codeStyleManager.reformat(insertedElement);
|
||||
}
|
||||
|
||||
protected static void replaceStatement(
|
||||
@NonNls @NotNull String newStatementText,
|
||||
@NonNls @NotNull PsiStatement statement)
|
||||
protected static void replaceStatement(@NonNls @NotNull String newStatementText, @NonNls @NotNull PsiStatement statement)
|
||||
throws IncorrectOperationException {
|
||||
final Project project = statement.getProject();
|
||||
final PsiElementFactory factory =
|
||||
JavaPsiFacade.getElementFactory(project);
|
||||
final PsiStatement newStatement =
|
||||
factory.createStatementFromText(newStatementText, statement);
|
||||
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
|
||||
final PsiStatement newStatement = factory.createStatementFromText(newStatementText, statement);
|
||||
final PsiElement insertedElement = statement.replace(newStatement);
|
||||
final CodeStyleManager codeStyleManager =
|
||||
CodeStyleManager.getInstance(project);
|
||||
final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project);
|
||||
codeStyleManager.reformat(insertedElement);
|
||||
}
|
||||
|
||||
protected static void replaceStatementAndShorten(
|
||||
@NonNls @NotNull String newStatementText,
|
||||
@NonNls @NotNull PsiStatement statement)
|
||||
protected static void replaceStatementAndShorten(@NonNls @NotNull String newStatementText, @NonNls @NotNull PsiStatement statement)
|
||||
throws IncorrectOperationException {
|
||||
final Project project = statement.getProject();
|
||||
final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
|
||||
final PsiElementFactory factory = psiFacade.getElementFactory();
|
||||
final PsiStatement newStatement =
|
||||
factory.createStatementFromText(newStatementText, statement);
|
||||
final PsiStatement newStatement = factory.createStatementFromText(newStatementText, statement);
|
||||
final PsiElement insertedElement = statement.replace(newStatement);
|
||||
final JavaCodeStyleManager javaCodeStyleManager =
|
||||
JavaCodeStyleManager.getInstance(project);
|
||||
final PsiElement shortenedElement =
|
||||
javaCodeStyleManager.shortenClassReferences(insertedElement);
|
||||
final CodeStyleManager codeStyleManager =
|
||||
CodeStyleManager.getInstance(project);
|
||||
final JavaCodeStyleManager javaCodeStyleManager = JavaCodeStyleManager.getInstance(project);
|
||||
final PsiElement shortenedElement = javaCodeStyleManager.shortenClassReferences(insertedElement);
|
||||
final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project);
|
||||
codeStyleManager.reformat(shortenedElement);
|
||||
}
|
||||
|
||||
@@ -202,8 +178,7 @@ public abstract class Intention extends PsiElementBaseIntentionAction {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull Project project, Editor editor,
|
||||
@NotNull PsiElement element) {
|
||||
public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) {
|
||||
return findMatchingElement(element, editor) != null;
|
||||
}
|
||||
|
||||
@@ -213,14 +188,12 @@ public abstract class Intention extends PsiElementBaseIntentionAction {
|
||||
}
|
||||
|
||||
private static boolean isWritable(Project project, PsiElement element) {
|
||||
final VirtualFile virtualFile = PsiUtil.getVirtualFile(element);
|
||||
final VirtualFile virtualFile = PsiUtilCore.getVirtualFile(element);
|
||||
if (virtualFile == null) {
|
||||
return true;
|
||||
}
|
||||
final ReadonlyStatusHandler readonlyStatusHandler =
|
||||
ReadonlyStatusHandler.getInstance(project);
|
||||
final ReadonlyStatusHandler.OperationStatus operationStatus =
|
||||
readonlyStatusHandler.ensureFilesWritable(virtualFile);
|
||||
final ReadonlyStatusHandler readonlyStatusHandler = ReadonlyStatusHandler.getInstance(project);
|
||||
final ReadonlyStatusHandler.OperationStatus operationStatus = readonlyStatusHandler.ensureFilesWritable(virtualFile);
|
||||
return !operationStatus.hasReadonlyFiles();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2006 Dave Griffith, Bas Leijdekkers
|
||||
* Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -29,8 +29,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
public class DemorgansIntention extends MutablyNamedIntention {
|
||||
|
||||
protected String getTextForElement(PsiElement element) {
|
||||
final PsiPolyadicExpression binaryExpression =
|
||||
(PsiPolyadicExpression)element;
|
||||
final PsiPolyadicExpression binaryExpression = (PsiPolyadicExpression)element;
|
||||
final IElementType tokenType = binaryExpression.getOperationTokenType();
|
||||
if (tokenType.equals(JavaTokenType.ANDAND)) {
|
||||
return IntentionPowerPackBundle.message("demorgans.intention.name1");
|
||||
@@ -45,84 +44,55 @@ public class DemorgansIntention extends MutablyNamedIntention {
|
||||
return new ConjunctionPredicate();
|
||||
}
|
||||
|
||||
public void processIntention(@NotNull PsiElement element)
|
||||
throws IncorrectOperationException {
|
||||
PsiPolyadicExpression exp =
|
||||
(PsiPolyadicExpression)element;
|
||||
final IElementType tokenType = exp.getOperationTokenType();
|
||||
PsiElement parent = exp.getParent();
|
||||
while (isConjunctionExpression(parent, tokenType)) {
|
||||
exp = (PsiPolyadicExpression)parent;
|
||||
assert exp != null;
|
||||
parent = exp.getParent();
|
||||
}
|
||||
final String newExpression =
|
||||
convertConjunctionExpression(exp, tokenType);
|
||||
replaceExpressionWithNegatedExpressionString(newExpression,
|
||||
exp);
|
||||
public void processIntention(@NotNull PsiElement element) throws IncorrectOperationException {
|
||||
final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)element;
|
||||
final String newExpression = convertConjunctionExpression(polyadicExpression);
|
||||
replaceExpressionWithNegatedExpressionString(newExpression, polyadicExpression);
|
||||
}
|
||||
|
||||
private static String convertConjunctionExpression(PsiPolyadicExpression exp,
|
||||
IElementType tokenType) {
|
||||
private static String convertConjunctionExpression(PsiPolyadicExpression polyadicExpression) {
|
||||
final IElementType tokenType = polyadicExpression.getOperationTokenType();
|
||||
final String flippedConjunction;
|
||||
if (tokenType.equals(JavaTokenType.ANDAND)) {
|
||||
flippedConjunction = "||";
|
||||
final boolean tokenTypeAndAnd = tokenType.equals(JavaTokenType.ANDAND);
|
||||
flippedConjunction = tokenTypeAndAnd ? "||" : "&&";
|
||||
final StringBuilder result = new StringBuilder();
|
||||
for (PsiExpression operand : polyadicExpression.getOperands()) {
|
||||
if (result.length() != 0) {
|
||||
result.append(flippedConjunction);
|
||||
}
|
||||
result.append(convertLeafExpression(operand, tokenTypeAndAnd));
|
||||
}
|
||||
else {
|
||||
flippedConjunction = "&&";
|
||||
}
|
||||
String result = null;
|
||||
for (PsiExpression expression : exp.getOperands()) {
|
||||
String lhsText = convertLeafExpression(expression);
|
||||
result = result == null ? lhsText : result + flippedConjunction + lhsText;
|
||||
}
|
||||
return result;
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private static String convertLeafExpression(PsiExpression condition) {
|
||||
if (BoolUtils.isNegation(condition)) {
|
||||
final PsiExpression negated = BoolUtils.getNegated(condition);
|
||||
if (negated == null) {
|
||||
private static String convertLeafExpression(PsiExpression expression, boolean tokenTypeAndAnd) {
|
||||
if (BoolUtils.isNegation(expression)) {
|
||||
final PsiExpression negatedExpression = BoolUtils.getNegated(expression);
|
||||
if (negatedExpression == null) {
|
||||
return "";
|
||||
}
|
||||
if (ParenthesesUtils.getPrecedence(negated) >
|
||||
ParenthesesUtils.OR_PRECEDENCE) {
|
||||
return '(' + negated.getText() + ')';
|
||||
if (tokenTypeAndAnd) {
|
||||
if (ParenthesesUtils.getPrecedence(negatedExpression) > ParenthesesUtils.OR_PRECEDENCE) {
|
||||
return '(' + negatedExpression.getText() + ')';
|
||||
}
|
||||
} else if (ParenthesesUtils.getPrecedence(negatedExpression) > ParenthesesUtils.AND_PRECEDENCE) {
|
||||
return '(' + negatedExpression.getText() + ')';
|
||||
}
|
||||
final PsiElement conditionParent = condition.getParent();
|
||||
if (conditionParent instanceof PsiExpression &&
|
||||
ParenthesesUtils.getPrecedence(negated) > ParenthesesUtils.AND_PRECEDENCE &&
|
||||
ParenthesesUtils.getPrecedence((PsiExpression)conditionParent) > ParenthesesUtils.AND_PRECEDENCE) {
|
||||
return '(' + negated.getText() + ')';
|
||||
}
|
||||
return negated.getText();
|
||||
return negatedExpression.getText();
|
||||
}
|
||||
else if (ComparisonUtils.isComparison(condition)) {
|
||||
final PsiBinaryExpression binaryExpression =
|
||||
(PsiBinaryExpression)condition;
|
||||
final String negatedComparison =
|
||||
ComparisonUtils.getNegatedComparison(binaryExpression.getOperationTokenType());
|
||||
else if (ComparisonUtils.isComparison(expression)) {
|
||||
final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)expression;
|
||||
final String negatedComparison = ComparisonUtils.getNegatedComparison(binaryExpression.getOperationTokenType());
|
||||
final PsiExpression lhs = binaryExpression.getLOperand();
|
||||
final PsiExpression rhs = binaryExpression.getROperand();
|
||||
assert rhs != null;
|
||||
return lhs.getText() + negatedComparison + rhs.getText();
|
||||
}
|
||||
else if (ParenthesesUtils.getPrecedence(condition) >
|
||||
ParenthesesUtils.PREFIX_PRECEDENCE) {
|
||||
return "!(" + condition.getText() + ')';
|
||||
else if (ParenthesesUtils.getPrecedence(expression) > ParenthesesUtils.PREFIX_PRECEDENCE) {
|
||||
return "!(" + expression.getText() + ')';
|
||||
}
|
||||
else {
|
||||
return '!' + condition.getText();
|
||||
return '!' + expression.getText();
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isConjunctionExpression(PsiElement exp,
|
||||
IElementType conjunctionType) {
|
||||
if (!(exp instanceof PsiPolyadicExpression)) {
|
||||
return false;
|
||||
}
|
||||
final PsiPolyadicExpression binExp = (PsiPolyadicExpression)exp;
|
||||
final IElementType tokenType = binExp.getOperationTokenType();
|
||||
return tokenType.equals(conjunctionType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
|
||||
* Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,17 +22,17 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class BoolUtils {
|
||||
|
||||
private BoolUtils() {
|
||||
}
|
||||
private BoolUtils() {}
|
||||
|
||||
public static boolean isNegated(PsiExpression exp) {
|
||||
PsiExpression ancestor = exp;
|
||||
while (ancestor.getParent() instanceof PsiParenthesizedExpression) {
|
||||
ancestor = (PsiExpression)ancestor.getParent();
|
||||
PsiElement parent = ancestor.getParent();
|
||||
while (parent instanceof PsiParenthesizedExpression) {
|
||||
ancestor = (PsiExpression)parent;
|
||||
parent = ancestor.getParent();
|
||||
}
|
||||
if (ancestor.getParent() instanceof PsiPrefixExpression) {
|
||||
final PsiPrefixExpression prefixAncestor =
|
||||
(PsiPrefixExpression)ancestor.getParent();
|
||||
if (parent instanceof PsiPrefixExpression) {
|
||||
final PsiPrefixExpression prefixAncestor = (PsiPrefixExpression)parent;
|
||||
final IElementType tokenType = prefixAncestor.getOperationTokenType();
|
||||
if (tokenType.equals(JavaTokenType.EXCL)) {
|
||||
return true;
|
||||
@@ -42,14 +42,15 @@ public class BoolUtils {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiExpression findNegation(PsiExpression exp) {
|
||||
PsiExpression ancestor = exp;
|
||||
while (ancestor.getParent() instanceof PsiParenthesizedExpression) {
|
||||
ancestor = (PsiExpression)ancestor.getParent();
|
||||
public static PsiExpression findNegation(PsiExpression expression) {
|
||||
PsiExpression ancestor = expression;
|
||||
PsiElement parent = ancestor.getParent();
|
||||
while (parent instanceof PsiParenthesizedExpression) {
|
||||
ancestor = (PsiExpression)parent;
|
||||
parent = ancestor.getParent();
|
||||
}
|
||||
if (ancestor.getParent() instanceof PsiPrefixExpression) {
|
||||
final PsiPrefixExpression prefixAncestor =
|
||||
(PsiPrefixExpression)ancestor.getParent();
|
||||
if (parent instanceof PsiPrefixExpression) {
|
||||
final PsiPrefixExpression prefixAncestor = (PsiPrefixExpression)parent;
|
||||
if (JavaTokenType.EXCL.equals(prefixAncestor.getOperationTokenType())) {
|
||||
return prefixAncestor;
|
||||
}
|
||||
@@ -67,12 +68,16 @@ public class BoolUtils {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiExpression getNegated(PsiExpression exp) {
|
||||
final PsiPrefixExpression prefixExp = (PsiPrefixExpression)exp;
|
||||
final PsiExpression operand = prefixExp.getOperand();
|
||||
if (operand == null) {
|
||||
public static PsiExpression getNegated(PsiExpression expression) {
|
||||
if (!(expression instanceof PsiPrefixExpression)) {
|
||||
return null;
|
||||
}
|
||||
final PsiPrefixExpression prefixExpression = (PsiPrefixExpression)expression;
|
||||
final IElementType tokenType = prefixExpression.getOperationTokenType();
|
||||
if (!JavaTokenType.EXCL.equals(tokenType)) {
|
||||
return null;
|
||||
}
|
||||
final PsiExpression operand = prefixExpression.getOperand();
|
||||
return ParenthesesUtils.stripParentheses(operand);
|
||||
}
|
||||
|
||||
@@ -80,23 +85,18 @@ public class BoolUtils {
|
||||
if (!(expression instanceof PsiLiteralExpression)) {
|
||||
return false;
|
||||
}
|
||||
final PsiLiteralExpression literalExpression =
|
||||
(PsiLiteralExpression)expression;
|
||||
final PsiLiteralExpression literalExpression = (PsiLiteralExpression)expression;
|
||||
@NonNls final String text = literalExpression.getText();
|
||||
return PsiKeyword.TRUE.equals(text) ||
|
||||
PsiKeyword.FALSE.equals(text);
|
||||
return PsiKeyword.TRUE.equals(text) || PsiKeyword.FALSE.equals(text);
|
||||
}
|
||||
|
||||
public static String getNegatedExpressionText(
|
||||
@Nullable PsiExpression condition) {
|
||||
public static String getNegatedExpressionText(@Nullable PsiExpression condition) {
|
||||
if (condition == null) {
|
||||
return "";
|
||||
}
|
||||
if (condition instanceof PsiParenthesizedExpression) {
|
||||
final PsiParenthesizedExpression parenthesizedExpression =
|
||||
(PsiParenthesizedExpression)condition;
|
||||
final PsiExpression expression =
|
||||
parenthesizedExpression.getExpression();
|
||||
final PsiParenthesizedExpression parenthesizedExpression = (PsiParenthesizedExpression)condition;
|
||||
final PsiExpression expression = parenthesizedExpression.getExpression();
|
||||
return '(' + getNegatedExpressionText(expression) + ')';
|
||||
}
|
||||
else if (isNegation(condition)) {
|
||||
@@ -107,10 +107,8 @@ public class BoolUtils {
|
||||
return negated.getText();
|
||||
}
|
||||
else if (ComparisonUtils.isComparison(condition)) {
|
||||
final PsiBinaryExpression binaryExpression =
|
||||
(PsiBinaryExpression)condition;
|
||||
final String negatedComparison =
|
||||
ComparisonUtils.getNegatedComparison(binaryExpression.getOperationTokenType());
|
||||
final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)condition;
|
||||
final String negatedComparison = ComparisonUtils.getNegatedComparison(binaryExpression.getOperationTokenType());
|
||||
final PsiExpression lhs = binaryExpression.getLOperand();
|
||||
final PsiExpression rhs = binaryExpression.getROperand();
|
||||
if (rhs == null) {
|
||||
@@ -118,8 +116,7 @@ public class BoolUtils {
|
||||
}
|
||||
return lhs.getText() + negatedComparison + rhs.getText();
|
||||
}
|
||||
else if (ParenthesesUtils.getPrecedence(condition) >
|
||||
ParenthesesUtils.PREFIX_PRECEDENCE) {
|
||||
else if (ParenthesesUtils.getPrecedence(condition) > ParenthesesUtils.PREFIX_PRECEDENCE) {
|
||||
return "!(" + condition.getText() + ')';
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.siyeh.ipp.bool.demorgans;
|
||||
|
||||
class NeedsMoreParentheses {
|
||||
void foo(boolean a, boolean b, boolean c, boolean d) {
|
||||
boolean f = !(!(a || b) |<caret>| !(c || d));
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package com.siyeh.ipp.bool.demorgans;
|
||||
|
||||
class NeedsMoreParentheses {
|
||||
void foo(boolean a, boolean b, boolean c, boolean d) {
|
||||
boolean f = (a || b) && (c || d);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.siyeh.ipp.bool.demorgans;
|
||||
|
||||
class NeedsParentheses {
|
||||
|
||||
void foo(boolean a, boolean b) {
|
||||
if (!(!a || !b) <caret>|| !(a || b)){}
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package com.siyeh.ipp.bool.demorgans;
|
||||
|
||||
class NeedsParentheses {
|
||||
|
||||
void foo(boolean a, boolean b) {
|
||||
if (!((!a || !b) && (a || b))){}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.siyeh.ipp.bool.demorgans;
|
||||
|
||||
class NotTooManyParentheses {
|
||||
void foo(boolean a, boolean b, boolean c) {
|
||||
if (a && (b ||<caret> c)) {}
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package com.siyeh.ipp.bool.demorgans;
|
||||
|
||||
class NotTooManyParentheses {
|
||||
void foo(boolean a, boolean b, boolean c) {
|
||||
if (a && !(!b && !c)) {}
|
||||
}
|
||||
}
|
||||
@@ -28,8 +28,12 @@ public abstract class IPPTestCase extends LightCodeInsightFixtureTestCase {
|
||||
protected abstract String getRelativePath();
|
||||
|
||||
protected void doTest() {
|
||||
doTest(getIntentionName());
|
||||
}
|
||||
|
||||
protected void doTest(String intentionName) {
|
||||
final String testName = getTestName(false);
|
||||
CodeInsightTestUtil.doIntentionTest(myFixture, getIntentionName(), testName + ".java", testName + "_after.java");
|
||||
CodeInsightTestUtil.doIntentionTest(myFixture, intentionName, testName + ".java", testName + "_after.java");
|
||||
}
|
||||
|
||||
protected void assertIntentionNotAvailable() {
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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.siyeh.ipp.bool;
|
||||
|
||||
import com.siyeh.IntentionPowerPackBundle;
|
||||
import com.siyeh.ipp.IPPTestCase;
|
||||
|
||||
public class DemorgansIntentionTest extends IPPTestCase {
|
||||
public void testNeedsParentheses() { doTest(); }
|
||||
public void testNeedsMoreParentheses() { doTest(); }
|
||||
public void testNotTooManyParentheses() { doTest(); }
|
||||
|
||||
@Override
|
||||
protected String getIntentionName() {
|
||||
return IntentionPowerPackBundle.message("demorgans.intention.name2");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getRelativePath() {
|
||||
return "bool/demorgans";
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,13 @@ package org.jetbrains.plugins.gradle.action;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.Presentation;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.gradle.config.GradleSettings;
|
||||
import org.jetbrains.plugins.gradle.util.GradleBundle;
|
||||
@@ -19,6 +24,8 @@ import org.jetbrains.plugins.gradle.util.GradleBundle;
|
||||
*/
|
||||
public class GradleOpenScriptAction extends AbstractGradleLinkedProjectAction implements DumbAware {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance("#" + GradleOpenScriptAction.class.getName());
|
||||
|
||||
public GradleOpenScriptAction() {
|
||||
getTemplatePresentation().setText(GradleBundle.message("gradle.action.open.script.text"));
|
||||
getTemplatePresentation().setDescription(GradleBundle.message("gradle.action.open.script.description"));
|
||||
@@ -30,6 +37,12 @@ public class GradleOpenScriptAction extends AbstractGradleLinkedProjectAction im
|
||||
|
||||
@Override
|
||||
protected void doActionPerformed(@NotNull Project project, @NotNull String linkedProjectPath) {
|
||||
// TODO den implement
|
||||
final VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByPath(linkedProjectPath);
|
||||
if (virtualFile == null) {
|
||||
LOG.warn(String.format("Can't obtain virtual file for the target file path: '%s'", linkedProjectPath));
|
||||
return;
|
||||
}
|
||||
OpenFileDescriptor descriptor = new OpenFileDescriptor(project, virtualFile);
|
||||
FileEditorManager.getInstance(project).openTextEditor(descriptor, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,6 +382,10 @@
|
||||
<copyPastePreProcessor implementation="org.jetbrains.plugins.groovy.lang.editor.GroovyLiteralCopyPasteProcessor"/>
|
||||
<copyPastePostProcessor implementation="org.jetbrains.plugins.groovy.lang.editor.GroovyReferenceCopyPasteProcessor"/>
|
||||
|
||||
<specialTool shortName="GroovyUnusedDeclaration" displayName="Unused declaration"
|
||||
groupName="Declaration Redundancy" enabledByDefault="true" level="WARNING"
|
||||
implementationClass="org.jetbrains.plugins.groovy.codeInspection.GroovyUnusedDeclarationInspection"/>
|
||||
|
||||
<localInspection language="Groovy" groupPath="Groovy" shortName="SecondUnsafeCall" bundle="org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle"
|
||||
key="second.unsafe.call" groupName="Probable bugs" enabledByDefault="true" level="WARNING"
|
||||
implementationClass="org.jetbrains.plugins.groovy.codeInspection.secondUnsafeCall.SecondUnsafeCallInspection"/>
|
||||
@@ -713,6 +717,8 @@
|
||||
groupName="Annotations verifying" enabledByDefault="true" level="WARNING"
|
||||
implementationClass="org.jetbrains.plugins.groovy.annotator.inspections.GroovySingletonAnnotationInspection"/>
|
||||
|
||||
<implicitUsageProvider implementation="org.jetbrains.plugins.groovy.gpp.GppImplicitUsageProvider"/>
|
||||
|
||||
<!-- control flow -->
|
||||
<intentionAction>
|
||||
<bundleName>org.jetbrains.plugins.groovy.intentions.GroovyIntentionsBundle</bundleName>
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.codeInspection;
|
||||
|
||||
import com.intellij.analysis.AnalysisScope;
|
||||
import com.intellij.codeInspection.GlobalInspectionContext;
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.codeInspection.ex.DescriptorProviderInspection;
|
||||
import com.intellij.codeInspection.ex.JobDescriptor;
|
||||
import com.intellij.codeInspection.ex.UnfairLocalInspectionTool;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class GroovyUnusedDeclarationInspection extends DescriptorProviderInspection implements UnfairLocalInspectionTool {
|
||||
public static final String SHORT_NAME = "GroovyUnusedDeclaration";
|
||||
|
||||
@Override
|
||||
public void runInspection(@NotNull AnalysisScope scope, @NotNull InspectionManager manager) {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JobDescriptor[] getJobDescriptors(GlobalInspectionContext globalInspectionContext) {
|
||||
return JobDescriptor.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
}
|
||||
+65
-9
@@ -19,33 +19,41 @@ package org.jetbrains.plugins.groovy.codeInspection.local;
|
||||
import com.intellij.codeHighlighting.TextEditorHighlightingPass;
|
||||
import com.intellij.codeInsight.CodeInsightSettings;
|
||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
|
||||
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
|
||||
import com.intellij.codeInsight.daemon.impl.*;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.codeInspection.InspectionProfile;
|
||||
import com.intellij.codeInspection.ProblemHighlightType;
|
||||
import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection;
|
||||
import com.intellij.lang.annotation.Annotation;
|
||||
import com.intellij.lang.annotation.AnnotationHolder;
|
||||
import com.intellij.lang.annotation.AnnotationSession;
|
||||
import com.intellij.lang.annotation.HighlightSeverity;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiRecursiveElementWalkingVisitor;
|
||||
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.util.Processor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.GroovyUnusedDeclarationInspection;
|
||||
import org.jetbrains.plugins.groovy.lang.editor.GroovyImportOptimizer;
|
||||
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GrNamedElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -56,20 +64,44 @@ import java.util.Set;
|
||||
/**
|
||||
* @author ilyas
|
||||
*/
|
||||
public class GroovyUnusedImportPass extends TextEditorHighlightingPass {
|
||||
public class GroovyPostHighlightingPass extends TextEditorHighlightingPass {
|
||||
private final GroovyFile myFile;
|
||||
private final Editor myEditor;
|
||||
public static final Logger LOG = Logger.getInstance("org.jetbrains.plugins.groovy.codeInspection.local.GroovyUnusedImportsPass");
|
||||
private volatile Set<GrImportStatement> myUnusedImports;
|
||||
private volatile Runnable myOptimizeRunnable;
|
||||
private volatile List<HighlightInfo> myUnusedDeclarations;
|
||||
|
||||
public GroovyUnusedImportPass(GroovyFile file, Editor editor) {
|
||||
public GroovyPostHighlightingPass(GroovyFile file, Editor editor) {
|
||||
super(file.getProject(), editor.getDocument(), true);
|
||||
myFile = file;
|
||||
myEditor = editor;
|
||||
}
|
||||
|
||||
public void doCollectInformation(ProgressIndicator progress) {
|
||||
public void doCollectInformation(final ProgressIndicator progress) {
|
||||
final InspectionProfile profile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile();
|
||||
final boolean deadCodeEnabled = profile.isToolEnabled(HighlightDisplayKey.find(GroovyUnusedDeclarationInspection.SHORT_NAME), myFile);
|
||||
ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
|
||||
VirtualFile virtualFile = myFile.getViewProvider().getVirtualFile();
|
||||
if (!fileIndex.isInContent(virtualFile)) {
|
||||
return;
|
||||
}
|
||||
final UnusedDeclarationInspection deadCodeInspection = (UnusedDeclarationInspection)profile.getInspectionTool(UnusedDeclarationInspection.SHORT_NAME, myFile);
|
||||
final GlobalUsageHelper usageHelper = new GlobalUsageHelper() {
|
||||
public boolean shouldIgnoreUsagesInCurrentFile() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isLocallyUsed(@NotNull PsiNamedElement member) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldCheckUsages(@NotNull PsiMember member) {
|
||||
return deadCodeInspection == null || !deadCodeInspection.isEntryPoint(member);
|
||||
}
|
||||
};
|
||||
|
||||
final List<HighlightInfo> unusedDeclarations = new ArrayList<HighlightInfo>();
|
||||
final Set<GrImportStatement> unusedImports = new HashSet<GrImportStatement>(GroovyImportOptimizer.getValidImportStatements(myFile));
|
||||
myFile.accept(new PsiRecursiveElementWalkingVisitor() {
|
||||
@Override
|
||||
@@ -83,10 +115,34 @@ public class GroovyUnusedImportPass extends TextEditorHighlightingPass {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (deadCodeEnabled && element instanceof GrNamedElement && !PostHighlightingPass.isImplicitUsage((GrNamedElement)element, progress)) {
|
||||
PsiElement nameId = ((GrNamedElement)element).getNameIdentifierGroovy();
|
||||
if (nameId.getNode().getElementType() == GroovyTokenTypes.mIDENT) {
|
||||
String name = ((GrNamedElement)element).getName();
|
||||
if (element instanceof GrTypeDefinition && !PostHighlightingPass.isClassUsed((GrTypeDefinition)element, progress, usageHelper)) {
|
||||
unusedDeclarations.add(
|
||||
PostHighlightingPass.createUnusedSymbolInfo(nameId, "Class " + name + " is unused", HighlightInfoType.UNUSED_SYMBOL));
|
||||
}
|
||||
else if (element instanceof GrMethod) {
|
||||
GrMethod method = (GrMethod)element;
|
||||
if (!PostHighlightingPass.isMethodReferenced(method, progress, usageHelper)) {
|
||||
unusedDeclarations.add(
|
||||
PostHighlightingPass.createUnusedSymbolInfo(nameId, (method.isConstructor() ? "Constructor" : "Method") +" " + name + " is unused", HighlightInfoType.UNUSED_SYMBOL));
|
||||
}
|
||||
}
|
||||
else if (element instanceof GrField && PostHighlightingPass.isFieldUnused((GrField)element, progress, usageHelper)) {
|
||||
unusedDeclarations.add(
|
||||
PostHighlightingPass.createUnusedSymbolInfo(nameId, "Property " + name + " is unused", HighlightInfoType.UNUSED_SYMBOL));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
super.visitElement(element);
|
||||
}
|
||||
});
|
||||
myUnusedImports = unusedImports;
|
||||
myUnusedDeclarations = unusedDeclarations;
|
||||
if (!unusedImports.isEmpty() && CodeInsightSettings.getInstance().OPTIMIZE_IMPORTS_ON_THE_FLY) {
|
||||
final VirtualFile vfile = myFile.getVirtualFile();
|
||||
if (vfile != null && ProjectRootManager.getInstance(myFile.getProject()).getFileIndex().isInSource(vfile)) {
|
||||
@@ -143,7 +199,7 @@ public class GroovyUnusedImportPass extends TextEditorHighlightingPass {
|
||||
|
||||
public void doApplyInformationToEditor() {
|
||||
AnnotationHolder annotationHolder = new AnnotationHolderImpl(new AnnotationSession(myFile));
|
||||
List<HighlightInfo> infos = new ArrayList<HighlightInfo>(myUnusedImports.size());
|
||||
List<HighlightInfo> infos = new ArrayList<HighlightInfo>(myUnusedDeclarations);
|
||||
for (GrImportStatement unusedImport : myUnusedImports) {
|
||||
Annotation annotation = annotationHolder.createWarningAnnotation(unusedImport, GroovyInspectionBundle.message("unused.import"));
|
||||
annotation.setHighlightType(ProblemHighlightType.LIKE_UNUSED_SYMBOL);
|
||||
+1
-1
@@ -42,7 +42,7 @@ public class GroovyUnusedImportsPassFactory extends AbstractProjectComponent imp
|
||||
@Nullable
|
||||
public TextEditorHighlightingPass createHighlightingPass(@NotNull PsiFile file, @NotNull Editor editor) {
|
||||
if (!(file instanceof GroovyFile)) return null;
|
||||
return new GroovyUnusedImportPass((GroovyFile)file, editor);
|
||||
return new GroovyPostHighlightingPass((GroovyFile)file, editor);
|
||||
}
|
||||
|
||||
@NonNls
|
||||
|
||||
+68
-3
@@ -16,19 +16,24 @@
|
||||
|
||||
package org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiPackage;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.util.containers.CollectionFactory;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.annotator.GroovyAnnotator;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.BaseInspection;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
|
||||
import org.jetbrains.plugins.groovy.gpp.GppTypeConverter;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.plugins.groovy.annotator.GroovyAnnotator.isDeclarationAssignment;
|
||||
|
||||
/**
|
||||
@@ -72,10 +77,70 @@ public class GroovyUnresolvedAccessInspection extends BaseInspection {
|
||||
if (!(parent instanceof GrCall) && ResolveUtil.isKeyOfMap(refExpr)) return; // It's a key of map.
|
||||
|
||||
if (!GroovyAnnotator.shouldHighlightAsUnresolved(refExpr)) return;
|
||||
|
||||
if (qualifier != null && isBuilderInvocation(refExpr)) return;
|
||||
|
||||
PsiElement refNameElement = refExpr.getReferenceNameElement();
|
||||
registerError(refNameElement == null ? refExpr : refNameElement);
|
||||
}
|
||||
|
||||
}
|
||||
private static boolean isBuilderInvocation(@NotNull GrReferenceExpression refExpr) {
|
||||
GrExpression qualifier = refExpr.getQualifier();
|
||||
PsiType type = qualifier == null ? null : qualifier.getType();
|
||||
if (type instanceof PsiClassType) {
|
||||
PsiClass target = ((PsiClassType)type).resolve();
|
||||
if (target != null) {
|
||||
for (PsiMethod method : findBuilderMetaMethods(refExpr, target)) {
|
||||
PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass != null &&
|
||||
method.getParameterList().getParameters()[0].getType().equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
|
||||
String qname = containingClass.getQualifiedName();
|
||||
if (!GroovyCommonClassNames.GROOVY_OBJECT.equals(qname) && !GroovyCommonClassNames.GROOVY_OBJECT_SUPPORT.equals(qname)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static List<PsiMethod> findBuilderMetaMethods(GrReferenceExpression refExpr, PsiClass target) {
|
||||
boolean gpp = GppTypeConverter.hasTypedContext(target) && GppTypeConverter.hasTypedContext(refExpr);
|
||||
if (refExpr.getParent() instanceof GrCall) {
|
||||
List<PsiMethod> toSearch =
|
||||
CollectionFactory.arrayList(target.findMethodsByName(gpp ? "invokeUnresolvedMethod" : "invokeMethod", true));
|
||||
for (Iterator<PsiMethod> iterator = toSearch.iterator(); iterator.hasNext(); ) {
|
||||
PsiMethod method = iterator.next();
|
||||
if (!gpp &&
|
||||
(method.getParameterList().getParametersCount() != 2 || method.getParameterList().getParameters()[1].getType()
|
||||
.equalsToText(CommonClassNames.JAVA_LANG_OBJECT + "[]"))) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
return toSearch;
|
||||
}
|
||||
|
||||
if (PsiUtil.isLValue(refExpr)) {
|
||||
List<PsiMethod> toSearch = CollectionFactory.arrayList(target.findMethodsByName(gpp ? "setUnresolvedProperty" : "setProperty", true));
|
||||
for (Iterator<PsiMethod> iterator = toSearch.iterator(); iterator.hasNext(); ) {
|
||||
PsiMethod method = iterator.next();
|
||||
if (method.getParameterList().getParametersCount() != 2 || (!gpp && !method.getParameterList().getParameters()[1].getType()
|
||||
.equalsToText(CommonClassNames.JAVA_LANG_OBJECT))) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
return toSearch;
|
||||
}
|
||||
|
||||
List<PsiMethod> toSearch = CollectionFactory.arrayList(target.findMethodsByName(gpp ? "getUnresolvedProperty" : "getProperty", true));
|
||||
for (Iterator<PsiMethod> iterator = toSearch.iterator(); iterator.hasNext(); ) {
|
||||
if (iterator.next().getParameterList().getParametersCount() != 1) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
return toSearch;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.gpp;
|
||||
|
||||
import com.intellij.codeInsight.daemon.ImplicitUsageProvider;
|
||||
import com.intellij.psi.*;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class GppImplicitUsageProvider implements ImplicitUsageProvider {
|
||||
|
||||
private static boolean isGppMetaMethod(PsiMethod method) {
|
||||
PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
if (parameters.length == 0 || !parameters[0].getType().equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ("invokeUnresolvedMethod".equals(method.getName())) {
|
||||
return true;
|
||||
}
|
||||
if ("getUnresolvedProperty".equals(method.getName())) {
|
||||
return parameters.length == 1;
|
||||
}
|
||||
if ("setUnresolvedProperty".equals(method.getName())) {
|
||||
return parameters.length == 2;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isImplicitUsage(PsiElement element) {
|
||||
return element instanceof PsiMethod && isGppMetaMethod((PsiMethod)element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isImplicitRead(PsiElement element) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isImplicitWrite(PsiElement element) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.plugins.groovy.lang.psi;
|
||||
|
||||
import com.intellij.psi.PsiModifierListOwner;
|
||||
import com.intellij.psi.PsiNamedElement;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -23,7 +24,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
/**
|
||||
* @author ven
|
||||
*/
|
||||
public interface GrNamedElement extends PsiNamedElement, GroovyPsiElement {
|
||||
public interface GrNamedElement extends PsiNamedElement, GroovyPsiElement, PsiModifierListOwner {
|
||||
@NotNull
|
||||
PsiElement getNameIdentifierGroovy();
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefini
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod
|
||||
import org.jetbrains.plugins.groovy.util.TestUtils
|
||||
import com.intellij.psi.*
|
||||
import org.jetbrains.plugins.groovy.codeInspection.GroovyUnusedDeclarationInspection
|
||||
import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
@@ -581,6 +583,22 @@ def bar() {
|
||||
myFixture.checkHighlighting(true, false, false)
|
||||
}
|
||||
|
||||
public void testUsedInterceptors() {
|
||||
configureGppScript '''
|
||||
class Bar {
|
||||
Object getUnresolvedProperty(String name) {}
|
||||
Object <warning descr="Method getUnresolvedProperty is unused">getUnresolvedProperty</warning>(int name) {}
|
||||
void setUnresolvedProperty(String name, String value) {}
|
||||
int invokeUnresolvedMethod(String name, String arg1, boolean arg2, Object... args) {}
|
||||
int invokeUnresolvedMethod(String name, Object... args) {}
|
||||
int <warning descr="Method invokeUnresolvedMethod is unused">invokeUnresolvedMethod</warning>(Object... args) {}
|
||||
}
|
||||
println new Bar().zzz
|
||||
'''
|
||||
myFixture.enableInspections(new GroovyUnusedDeclarationInspection(), new UnusedDeclarationInspection())
|
||||
myFixture.checkHighlighting(true, false, false)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class GppProjectDescriptor extends DefaultLightProjectDescriptor {
|
||||
|
||||
+13
-3
@@ -16,7 +16,7 @@
|
||||
package org.jetbrains.plugins.groovy.lang;
|
||||
|
||||
|
||||
import com.intellij.codeInspection.LocalInspectionTool
|
||||
import com.intellij.codeInspection.InspectionProfileEntry
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.roots.ContentEntry
|
||||
import com.intellij.openapi.roots.ModifiableRootModel
|
||||
@@ -31,6 +31,7 @@ import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
|
||||
import com.siyeh.ig.junit.JUnitAbstractTestClassNamingConventionInspection
|
||||
import com.siyeh.ig.junit.JUnitTestClassNamingConventionInspection
|
||||
import org.jetbrains.annotations.NotNull
|
||||
import org.jetbrains.plugins.groovy.codeInspection.GroovyUnusedDeclarationInspection
|
||||
import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection
|
||||
import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyResultOfAssignmentUsedInspection
|
||||
import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyUncheckedAssignmentOfMemberOfRawTypeInspection
|
||||
@@ -48,6 +49,7 @@ import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.Groov
|
||||
import org.jetbrains.plugins.groovy.codeInspection.unusedDef.UnusedDefInspection
|
||||
import org.jetbrains.plugins.groovy.util.TestUtils
|
||||
import org.jetbrains.plugins.groovy.codeInspection.bugs.*
|
||||
import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
@@ -83,7 +85,7 @@ public class GroovyHighlightingTest extends LightCodeInsightFixtureTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest(LocalInspectionTool... tools) {
|
||||
private void doTest(InspectionProfileEntry... tools) {
|
||||
myFixture.enableInspections(tools);
|
||||
myFixture.testHighlighting(true, false, false, getTestName(false) + ".groovy");
|
||||
}
|
||||
@@ -415,7 +417,7 @@ public class GroovyHighlightingTest extends LightCodeInsightFixtureTestCase {
|
||||
doTest(new GroovyAssignabilityCheckInspection());
|
||||
}
|
||||
|
||||
public void _testInnerClassConstructorThis() {
|
||||
public void testInnerClassConstructorThis() {
|
||||
myFixture.enableInspections(new GroovyResultOfAssignmentUsedInspection());
|
||||
myFixture.testHighlighting(true, true, true, getTestName(false) + ".groovy");
|
||||
}
|
||||
@@ -452,6 +454,10 @@ public class GroovyHighlightingTest extends LightCodeInsightFixtureTestCase {
|
||||
doTest(new GroovyAssignabilityCheckInspection(), new GroovyUnresolvedAccessInspection());
|
||||
}
|
||||
|
||||
public void testBuilderMembersAreNotUnresolved() throws Exception {
|
||||
doTest(new GroovyUnresolvedAccessInspection());
|
||||
}
|
||||
|
||||
public void testUnknownVarInArgList() {
|
||||
doTest(new GroovyAssignabilityCheckInspection());
|
||||
}
|
||||
@@ -655,4 +661,8 @@ List<?> list2
|
||||
''')
|
||||
myFixture.testHighlighting(true, false, false)
|
||||
}
|
||||
|
||||
public void testGloballyUnusedSymbols() {
|
||||
doTest(new GroovyUnusedDeclarationInspection(), new UnusedDeclarationInspection())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
class MyBuilder {
|
||||
@Override
|
||||
Object getProperty(String property) {
|
||||
return super.getProperty(property)
|
||||
}
|
||||
|
||||
@Override
|
||||
Object invokeMethod(String name, Object args) {
|
||||
return super.invokeMethod(name, args)
|
||||
}
|
||||
|
||||
@Override
|
||||
void setProperty(String property, Object newValue) {
|
||||
super.setProperty(property, newValue)
|
||||
}
|
||||
}
|
||||
|
||||
def b = new MyBuilder()
|
||||
println b.foo
|
||||
println new Object().<warning descr="Can not resolve symbol 'foo'">foo</warning>
|
||||
b.foo = 2
|
||||
b.bar()
|
||||
@@ -0,0 +1,5 @@
|
||||
@Typed package foo;
|
||||
class Bar {
|
||||
|
||||
}
|
||||
println new Bar().zzz
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
class <warning descr="Class UnusedClass is unused">UnusedClass</warning> {}
|
||||
class Bar {
|
||||
int <warning descr="Property unusedProperty is unused">unusedProperty</warning> = 2
|
||||
int usedProperty = 39
|
||||
int usedProperty2 = 39
|
||||
int usedProperty3 = 39
|
||||
def <warning descr="Method unusedMethod is unused">unusedMethod</warning>() {}
|
||||
Bar usedMethod() { this }
|
||||
|
||||
Bar getUsedPropertyGetter() {}
|
||||
|
||||
public static void main(String[] args) { usedPrivately() }
|
||||
|
||||
private static void usedPrivately() {}
|
||||
private void <warning descr="Method unusedPrivately is unused">unusedPrivately</warning>() {}
|
||||
|
||||
}
|
||||
println new Bar().usedMethod().usedProperty
|
||||
new Bar().setUsedProperty2 42
|
||||
println new Bar().getUsedProperty3()
|
||||
println new Bar().usedPropertyGetter
|
||||
@@ -65,6 +65,8 @@
|
||||
<extensionPoint name="unusedDeclarationFixProvider"
|
||||
interface="com.intellij.codeInspection.reference.UnusedDeclarationFixProvider"/>
|
||||
|
||||
<extensionPoint name="canBeFinal"
|
||||
interface="com.intellij.codeInspection.canBeFinal.CanBeFinalHandler"/>
|
||||
<!-- PsiMember -->
|
||||
<extensionPoint name="javaDocNotNecessary"
|
||||
interface="com.intellij.openapi.util.Condition"/>
|
||||
|
||||
@@ -73,6 +73,11 @@
|
||||
<add-to-group group-id="IntroduceActionsGroup" anchor="after" relative-to-action="IntroduceParameter"/>
|
||||
</action>
|
||||
|
||||
<action id="RenameFile" class="com.intellij.refactoring.actions.RenameFileAction">
|
||||
<add-to-group group-id="RefactoringMenu" anchor="after" relative-to-action="RenameElement"/>
|
||||
<add-to-group group-id="EditorTabPopupMenuEx" anchor="after" relative-to-action="AddAllToFavorites"/>
|
||||
</action>
|
||||
|
||||
<group id="RefactoringMenu4">
|
||||
<action id="TurnRefsToSuper" class="com.intellij.refactoring.actions.TurnRefsToSuperAction"/>
|
||||
<action id="InheritanceToDelegation" class="com.intellij.refactoring.actions.InheritanceToDelegationAction"/>
|
||||
|
||||
Reference in New Issue
Block a user