Merge remote-tracking branch 'origin/master'

This commit is contained in:
Ekaterina Tuzova
2014-02-10 12:41:41 +04:00
158 changed files with 2210 additions and 1845 deletions
@@ -60,7 +60,7 @@ public class GetJPDADialog extends DialogWrapper {
new DoubleClickListener() {
@Override
protected boolean onDoubleClick(MouseEvent e) {
BrowserUtil.launchBrowser(JPDA_URL);
BrowserUtil.browse(JPDA_URL);
return true;
}
}.installOn(label2);
@@ -117,7 +117,7 @@ public class FacetLibrariesValidatorImpl extends FacetLibrariesValidator {
private CustomLibraryDescription myDescription;
public LibrariesQuickFix(CustomLibraryDescription description) {
super(IdeBundle.message("missing.libraries.fix.button"));
super(IdeBundle.message("button.fix"));
myDescription = description;
}
@@ -73,7 +73,7 @@ public class FrameworkLibraryValidatorImpl extends FrameworkLibraryValidator {
private CustomLibraryDescription myDescription;
public LibrariesQuickFix(CustomLibraryDescription description) {
super(IdeBundle.message("missing.libraries.fix.button"));
super(IdeBundle.message("button.fix"));
myDescription = description;
}
@@ -16,6 +16,7 @@
package com.intellij.openapi.roots.ui.configuration.artifacts;
import com.intellij.icons.AllIcons;
import com.intellij.ide.IdeBundle;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ConfigurationErrorQuickFix;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.PopupStep;
@@ -96,7 +97,7 @@ public class ArtifactErrorPanel {
myCurrentQuickFixes = quickFixes;
myFixButton.setVisible(!quickFixes.isEmpty());
if (!quickFixes.isEmpty()) {
myFixButton.setText(quickFixes.size() == 1 ? ContainerUtil.getFirstItem(quickFixes, null).getActionName() : "Fix...");
myFixButton.setText(quickFixes.size() == 1 ? ContainerUtil.getFirstItem(quickFixes, null).getActionName() : IdeBundle.message("button.fix"));
}
}
@@ -35,10 +35,10 @@ public class DevelopPluginsAction extends AnAction implements DumbAware {
public void actionPerformed(final AnActionEvent e) {
try {
if (new File(PLUGIN_URL).isFile()) {
BrowserUtil.launchBrowser(PLUGIN_URL);
BrowserUtil.browse(PLUGIN_URL);
}
else {
BrowserUtil.launchBrowser(PLUGIN_WEBSITE);
BrowserUtil.browse(PLUGIN_WEBSITE);
}
}
catch(IllegalStateException ex) {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@ import com.intellij.codeInsight.daemon.QuickFixActionRegistrar;
import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement;
import com.intellij.codeInspection.LocalQuickFixOnPsiElement;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
@@ -222,6 +223,26 @@ public abstract class QuickFixFactory {
public abstract void registerPullAsAbstractUpFixes(@NotNull PsiMethod method, @NotNull QuickFixActionRegistrar registrar);
public abstract IntentionAction createCreateAnnotationMethodFromUsageFix(PsiNameValuePair pair);
@NotNull
public abstract IntentionAction createCreateAnnotationMethodFromUsageFix(@NotNull PsiNameValuePair pair);
@NotNull
public abstract IntentionAction createOptimizeImportsFix();
public abstract void registerFixesForUnusedParameter(@NotNull PsiParameter parameter, @NotNull Object highlightInfo);
@NotNull
public abstract IntentionAction createAddToDependencyInjectionAnnotationsFix(@NotNull Project project, @NotNull String qualifiedName, @NotNull String element);
@NotNull
public abstract IntentionAction createCreateGetterOrSetterFix(boolean createGetter, boolean createSetter, @NotNull PsiField field);
@NotNull
public abstract IntentionAction createRenameToIgnoredFix(@NotNull PsiNamedElement namedElement);
@NotNull
public abstract IntentionAction createEnableOptimizeImportsOnTheFlyFix();
@NotNull
public abstract IntentionAction createSafeDeleteFix(@NotNull PsiElement element);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,32 +16,27 @@
package com.intellij.codeInsight.daemon.impl;
import com.intellij.codeHighlighting.Pass;
import com.intellij.codeInsight.CodeInsightSettings;
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
import com.intellij.codeInsight.daemon.ImplicitUsageProvider;
import com.intellij.codeInsight.daemon.JavaErrorMessages;
import com.intellij.codeInsight.daemon.ProblemHighlightFilter;
import com.intellij.codeInsight.daemon.impl.analysis.*;
import com.intellij.codeInsight.daemon.impl.quickfix.*;
import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction;
import com.intellij.codeInsight.intention.EmptyIntentionAction;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.IntentionManager;
import com.intellij.codeInspection.*;
import com.intellij.codeInsight.intention.QuickFixFactory;
import com.intellij.codeInspection.InspectionProfile;
import com.intellij.codeInspection.InspectionsBundle;
import com.intellij.codeInspection.SuppressionUtil;
import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection;
import com.intellij.codeInspection.ex.EntryPointsManagerBase;
import com.intellij.codeInspection.reference.UnusedDeclarationFixProvider;
import com.intellij.codeInspection.unusedImport.UnusedImportLocalInspection;
import com.intellij.codeInspection.unusedParameters.UnusedParametersInspection;
import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection;
import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspectionBase;
import com.intellij.codeInspection.util.SpecialAnnotationsUtilBase;
import com.intellij.diagnostic.AttachmentFactory;
import com.intellij.diagnostic.LogMessageEx;
import com.intellij.find.FindManager;
import com.intellij.find.findUsages.*;
import com.intellij.find.impl.FindManagerImpl;
import com.intellij.lang.Language;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.undo.UndoManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
@@ -51,8 +46,7 @@ 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.Comparing;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.PomNamedTarget;
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
@@ -60,34 +54,37 @@ import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.impl.PsiClassImplUtil;
import com.intellij.psi.impl.source.PsiClassImpl;
import com.intellij.psi.impl.source.jsp.jspJava.JspxImportStatement;
import com.intellij.psi.jsp.JspFile;
import com.intellij.psi.jsp.JspSpiUtil;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiNonJavaFileReferenceProcessor;
import com.intellij.psi.search.PsiSearchHelper;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.search.searches.OverridingMethodsSearch;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.search.searches.SuperMethodsSearch;
import com.intellij.psi.util.PropertyUtil;
import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.refactoring.changeSignature.ChangeSignatureGestureDetector;
import com.intellij.util.Processor;
import com.intellij.util.containers.Predicate;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.PropertyKey;
import java.util.*;
import static com.intellij.psi.search.PsiSearchHelper.SearchCostResult.TOO_MANY_OCCURRENCES;
import static com.intellij.psi.search.PsiSearchHelper.SearchCostResult.ZERO_OCCURRENCES;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.PostHighlightingPass");
private static final Key<Long> LAST_POST_PASS_TIMESTAMP = Key.create("LAST_POST_PASS_TIMESTAMP");
private RefCountHolder myRefCountHolder;
private final PsiFile myFile;
@Nullable private final Editor myEditor;
private final boolean myUnusedImportEnabled;
@NotNull private final Predicate<PsiElement> myIsEntryPointPredicate;
private final int myStartOffset;
private final int myEndOffset;
@@ -97,23 +94,24 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
private int myCurrentEntryIndex;
private boolean myHasMissortedImports;
private static final ImplicitUsageProvider[] ourImplicitUsageProviders = Extensions.getExtensions(ImplicitUsageProvider.EP_NAME);
private UnusedDeclarationInspection myDeadCodeInspection;
private UnusedSymbolLocalInspection myUnusedSymbolInspection;
private UnusedSymbolLocalInspectionBase myUnusedSymbolInspection;
private HighlightDisplayKey myUnusedSymbolKey;
private boolean myDeadCodeEnabled;
private boolean myInLibrary;
private HighlightDisplayKey myDeadCodeKey;
private HighlightInfoType myDeadCodeInfoType;
private UnusedParametersInspection myUnusedParametersInspection;
PostHighlightingPass(@NotNull Project project,
@NotNull PsiFile file,
@Nullable Editor editor,
@NotNull Document document,
@NotNull HighlightInfoProcessor highlightInfoProcessor) {
public PostHighlightingPass(@NotNull Project project,
@NotNull PsiFile file,
@Nullable Editor editor,
@NotNull Document document,
@NotNull HighlightInfoProcessor highlightInfoProcessor,
boolean unusedImportEnabled,
@NotNull Predicate<PsiElement> isEntryPoint) {
super(project, document, "Unused symbols", file, editor, file.getTextRange(), true, highlightInfoProcessor);
myFile = file;
myEditor = editor;
myUnusedImportEnabled = unusedImportEnabled;
myIsEntryPointPredicate = isEntryPoint;
myStartOffset = 0;
myEndOffset = file.getTextLength();
@@ -121,6 +119,21 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
myCurrentEntryIndex = -1;
}
static boolean isUpToDate(@NotNull PsiFile file) {
Long lastStamp = file.getUserData(LAST_POST_PASS_TIMESTAMP);
long currentStamp = PsiModificationTracker.SERVICE.getInstance(file.getProject()).getModificationCount();
return lastStamp != null && lastStamp == currentStamp || !ProblemHighlightFilter.shouldHighlightFile(file);
}
private static void markFileUpToDate(@NotNull PsiFile file) {
long lastStamp = PsiModificationTracker.SERVICE.getInstance(file.getProject()).getModificationCount();
file.putUserData(LAST_POST_PASS_TIMESTAMP, lastStamp);
}
private static boolean isInjected(@NotNull Project project, @NotNull PsiModifierListOwner modifierListOwner) {
return EntryPointsManagerBase.getInstance(project).isEntryPoint(modifierListOwner);
}
@Override
protected void collectInformationWithProgress(@NotNull final ProgressIndicator progress) {
DaemonCodeAnalyzerEx daemonCodeAnalyzer = DaemonCodeAnalyzerEx.getInstanceEx(myProject);
@@ -166,59 +179,23 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
protected void applyInformationWithProgress() {
if (myHighlights == null) return;
UpdateHighlightersUtil.setHighlightersToEditor(myProject, myDocument, myStartOffset, myEndOffset, myHighlights, getColorsScheme(), Pass.POST_UPDATE_ALL);
PostHighlightingPassFactory.markFileUpToDate(myFile);
markFileUpToDate(myFile);
Editor editor = myEditor;
if (editor != null && timeToOptimizeImports()) {
if (editor != null) {
optimizeImportsOnTheFly(editor);
}
}
private void optimizeImportsOnTheFly(@NotNull final Editor editor) {
if (myHasRedundantImports || myHasMissortedImports) {
final OptimizeImportsFix optimizeImportsFix = new OptimizeImportsFix();
IntentionAction optimizeImportsFix = QuickFixFactory.getInstance().createOptimizeImportsFix();
if (optimizeImportsFix.isAvailable(myProject, editor, myFile) && myFile.isWritable()) {
invokeOnTheFlyImportOptimizer(new Runnable() {
@Override
public void run() {
optimizeImportsFix.invoke(myProject, editor, myFile);
}
}, myFile, editor);
optimizeImportsFix.invoke(myProject, editor, myFile);
}
}
}
public static void invokeOnTheFlyImportOptimizer(@NotNull final Runnable runnable,
@NotNull final PsiFile file,
@NotNull final Editor editor) {
final long stamp = editor.getDocument().getModificationStamp();
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
if (file.getProject().isDisposed() || editor.isDisposed() || editor.getDocument().getModificationStamp() != stamp) return;
//no need to optimize imports on the fly during undo/redo
final UndoManager undoManager = UndoManager.getInstance(editor.getProject());
if (undoManager.isUndoInProgress() || undoManager.isRedoInProgress()) return;
PsiDocumentManager.getInstance(file.getProject()).commitAllDocuments();
String beforeText = file.getText();
final long oldStamp = editor.getDocument().getModificationStamp();
CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
@Override
public void run() {
ApplicationManager.getApplication().runWriteAction(runnable);
}
});
if (oldStamp != editor.getDocument().getModificationStamp()) {
String afterText = file.getText();
if (Comparing.strEqual(beforeText, afterText)) {
LOG.error(LogMessageEx.createEvent("Import optimizer hasn't optimized any imports", file.getViewProvider().getVirtualFile().getPath(),
AttachmentFactory.createAttachment(file.getViewProvider().getVirtualFile())));
}
}
}
});
}
// returns true if error highlight was created
private boolean collectHighlights(@NotNull Collection<PsiElement> elements,
@NotNull final List<HighlightInfo> result,
@@ -226,35 +203,24 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
ApplicationManager.getApplication().assertReadAccessAllowed();
InspectionProfile profile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile();
myUnusedSymbolKey = HighlightDisplayKey.find(UnusedSymbolLocalInspection.SHORT_NAME);
myUnusedSymbolKey = HighlightDisplayKey.find(UnusedSymbolLocalInspectionBase.SHORT_NAME);
boolean unusedSymbolEnabled = profile.isToolEnabled(myUnusedSymbolKey, myFile);
HighlightDisplayKey unusedImportKey = HighlightDisplayKey.find(UnusedImportLocalInspection.SHORT_NAME);
boolean unusedImportEnabled = profile.isToolEnabled(unusedImportKey, myFile);
myUnusedSymbolInspection = (UnusedSymbolLocalInspection)profile.getUnwrappedTool(UnusedSymbolLocalInspection.SHORT_NAME, myFile);
myUnusedSymbolInspection = (UnusedSymbolLocalInspectionBase)profile.getUnwrappedTool(UnusedSymbolLocalInspectionBase.SHORT_NAME, myFile);
LOG.assertTrue(ApplicationManager.getApplication().isUnitTestMode() || myUnusedSymbolInspection != null);
myDeadCodeKey = HighlightDisplayKey.find(UnusedDeclarationInspection.SHORT_NAME);
myDeadCodeInspection = (UnusedDeclarationInspection)profile.getUnwrappedTool(UnusedDeclarationInspection.SHORT_NAME, myFile);
myDeadCodeEnabled = profile.isToolEnabled(myDeadCodeKey, myFile);
myUnusedParametersInspection = (UnusedParametersInspection)profile.getUnwrappedTool(UnusedParametersInspection.SHORT_NAME, myFile);
LOG.assertTrue(ApplicationManager.getApplication().isUnitTestMode() || myUnusedParametersInspection != null);
if (unusedImportEnabled && JspPsiUtil.isInJspFile(myFile)) {
final JspFile jspFile = JspPsiUtil.getJspFile(myFile);
if (jspFile != null) {
unusedImportEnabled = !JspSpiUtil.isIncludedOrIncludesSomething(jspFile);
}
}
HighlightDisplayKey unusedImportKey = HighlightDisplayKey.find(UnusedImportLocalInspection.SHORT_NAME);
myDeadCodeInfoType = myDeadCodeKey == null
? null
? HighlightInfoType.UNUSED_SYMBOL
: new HighlightInfoType.HighlightInfoTypeImpl(profile.getErrorLevel(myDeadCodeKey, myFile).getSeverity(),
HighlightInfoType.UNUSED_SYMBOL.getAttributesKey());
GlobalUsageHelper helper = new GlobalUsageHelper() {
@Override
public boolean shouldCheckUsages(@NotNull PsiMember member) {
return !myInLibrary && myDeadCodeEnabled && !myDeadCodeInspection.isEntryPoint(member);
return !myInLibrary && !myIsEntryPointPredicate.apply(member);
}
@Override
@@ -282,7 +248,7 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
}
}
}
if (unusedImportEnabled && myFile instanceof PsiJavaFile && HighlightingLevelManager.getInstance(myProject).shouldHighlight(myFile)) {
if (myUnusedImportEnabled && myFile instanceof PsiJavaFile && HighlightingLevelManager.getInstance(myProject).shouldHighlight(myFile)) {
PsiImportList importList = ((PsiJavaFile)myFile).getImportList();
if (importList != null) {
final PsiImportStatementBase[] imports = importList.getAllImportStatements();
@@ -301,7 +267,7 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
}
@Nullable
private HighlightInfo processIdentifier(PsiIdentifier identifier, ProgressIndicator progress, GlobalUsageHelper helper) {
private HighlightInfo processIdentifier(@NotNull PsiIdentifier identifier, @NotNull ProgressIndicator progress, @NotNull GlobalUsageHelper helper) {
if (SuppressionUtil.inspectionResultSuppressed(identifier, myUnusedSymbolInspection)) return null;
PsiElement parent = identifier.getParent();
if (PsiUtilCore.hasErrorElementChild(parent)) return null;
@@ -310,17 +276,17 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
return processLocalVariable((PsiLocalVariable)parent, identifier, progress);
}
if (parent instanceof PsiField && myUnusedSymbolInspection.FIELD) {
return processField((PsiField)parent, identifier, progress, helper);
return processField(myProject, (PsiField)parent, identifier, progress, helper);
}
if (parent instanceof PsiParameter && myUnusedSymbolInspection.PARAMETER) {
if (SuppressionUtil.isSuppressed(identifier, UnusedParametersInspection.SHORT_NAME)) return null;
return processParameter((PsiParameter)parent, identifier, progress);
if (SuppressionUtil.isSuppressed(identifier, UnusedSymbolLocalInspectionBase.UNUSED_PARAMETERS_SHORT_NAME)) return null;
return processParameter(myProject, (PsiParameter)parent, identifier, progress);
}
if (parent instanceof PsiMethod && myUnusedSymbolInspection.METHOD) {
return processMethod((PsiMethod)parent, identifier, progress, helper);
return processMethod(myProject, (PsiMethod)parent, identifier, progress, helper);
}
if (parent instanceof PsiClass && myUnusedSymbolInspection.CLASS) {
return processClass((PsiClass)parent, identifier, progress, helper);
return processClass(myProject, (PsiClass)parent, identifier, progress, helper);
}
return null;
}
@@ -330,30 +296,30 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
@NotNull PsiIdentifier identifier,
@NotNull ProgressIndicator progress) {
if (variable instanceof PsiResourceVariable && PsiUtil.isIgnoredName(variable.getName())) return null;
if (isImplicitUsage(variable, progress)) return null;
if (isImplicitUsage(myProject, variable, progress)) return null;
if (!myRefCountHolder.isReferenced(variable)) {
String message = JavaErrorMessages.message("local.variable.is.never.used", identifier.getText());
HighlightInfo highlightInfo = createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL);
IntentionAction fix = variable instanceof PsiResourceVariable ? new RenameToIgnoredFix(variable) : new RemoveUnusedVariableFix(variable);
IntentionAction fix = variable instanceof PsiResourceVariable ? QuickFixFactory.getInstance().createRenameToIgnoredFix(variable) : QuickFixFactory.getInstance().createRemoveUnusedVariableFix(variable);
QuickFixAction.registerQuickFixAction(highlightInfo, fix, myUnusedSymbolKey);
return highlightInfo;
}
boolean referenced = myRefCountHolder.isReferencedForRead(variable);
if (!referenced && !isImplicitRead(variable, progress)) {
if (!referenced && !isImplicitRead(myProject, variable, progress)) {
String message = JavaErrorMessages.message("local.variable.is.not.used.for.reading", identifier.getText());
HighlightInfo highlightInfo = createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL);
QuickFixAction.registerQuickFixAction(highlightInfo, new RemoveUnusedVariableFix(variable), myUnusedSymbolKey);
QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createRemoveUnusedVariableFix(variable), myUnusedSymbolKey);
return highlightInfo;
}
if (!variable.hasInitializer()) {
referenced = myRefCountHolder.isReferencedForWrite(variable);
if (!referenced && !isImplicitWrite(variable, progress)) {
if (!referenced && !isImplicitWrite(myProject, variable, progress)) {
String message = JavaErrorMessages.message("local.variable.is.not.assigned", identifier.getText());
final HighlightInfo unusedSymbolInfo = createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL);
QuickFixAction.registerQuickFixAction(unusedSymbolInfo, new EmptyIntentionAction(UnusedSymbolLocalInspection.DISPLAY_NAME), myUnusedSymbolKey);
QuickFixAction.registerQuickFixAction(unusedSymbolInfo, new EmptyIntentionAction(UnusedSymbolLocalInspectionBase.DISPLAY_NAME), myUnusedSymbolKey);
return unusedSymbolInfo;
}
}
@@ -361,8 +327,10 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
return null;
}
public static boolean isImplicitUsage(final PsiModifierListOwner element, ProgressIndicator progress) {
if (UnusedSymbolLocalInspection.isInjected(element)) return true;
public static boolean isImplicitUsage(@NotNull Project project,
@NotNull PsiModifierListOwner element,
@NotNull ProgressIndicator progress) {
if (isInjected(project, element)) return true;
for (ImplicitUsageProvider provider : ourImplicitUsageProviders) {
progress.checkCanceled();
if (provider.isImplicitUsage(element)) {
@@ -373,28 +341,32 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
return false;
}
private static boolean isImplicitRead(final PsiVariable element, ProgressIndicator progress) {
private static boolean isImplicitRead(@NotNull Project project, @NotNull PsiVariable element, @NotNull ProgressIndicator progress) {
for(ImplicitUsageProvider provider: ourImplicitUsageProviders) {
progress.checkCanceled();
if (provider.isImplicitRead(element)) {
return true;
}
}
return UnusedSymbolLocalInspection.isInjected(element);
return isInjected(project, element);
}
private static boolean isImplicitWrite(final PsiVariable element, ProgressIndicator progress) {
private static boolean isImplicitWrite(@NotNull Project project,
@NotNull PsiVariable element,
@NotNull ProgressIndicator progress) {
for(ImplicitUsageProvider provider: ourImplicitUsageProviders) {
progress.checkCanceled();
if (provider.isImplicitWrite(element)) {
return true;
}
}
return UnusedSymbolLocalInspection.isInjected(element);
return isInjected(project, element);
}
@Nullable
public static HighlightInfo createUnusedSymbolInfo(@NotNull PsiElement element, @NotNull String message, @NotNull final HighlightInfoType highlightInfoType) {
@Nullable
public static HighlightInfo createUnusedSymbolInfo(@NotNull PsiElement element,
@NotNull String message,
@NotNull final HighlightInfoType highlightInfoType) {
HighlightInfo info = HighlightInfo.newHighlightInfo(highlightInfoType).range(element).descriptionAndTooltip(message).create();
if (info == null) {
return null; //filtered out
@@ -411,7 +383,8 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
}
@Nullable
private HighlightInfo processField(@NotNull final PsiField field,
private HighlightInfo processField(@NotNull final Project project,
@NotNull final PsiField field,
@NotNull PsiIdentifier identifier,
@NotNull ProgressIndicator progress,
@NotNull GlobalUsageHelper helper) {
@@ -419,18 +392,18 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
return null;
}
if (field.hasModifierProperty(PsiModifier.PRIVATE)) {
if (!myRefCountHolder.isReferenced(field) && !isImplicitUsage(field, progress)) {
if (!myRefCountHolder.isReferenced(field) && !isImplicitUsage(myProject, field, progress)) {
String message = JavaErrorMessages.message("private.field.is.not.used", identifier.getText());
HighlightInfo highlightInfo = suggestionsToMakeFieldUsed(field, identifier, message);
if (!field.hasInitializer()) {
QuickFixAction.registerQuickFixAction(highlightInfo, HighlightMethodUtil.getFixRange(field), new CreateConstructorParameterFromFieldFix(field));
QuickFixAction.registerQuickFixAction(highlightInfo, HighlightMethodUtil.getFixRange(field), QuickFixFactory.getInstance().createCreateConstructorParameterFromFieldFix(field));
}
return highlightInfo;
}
final boolean readReferenced = myRefCountHolder.isReferencedForRead(field);
if (!readReferenced && !isImplicitRead(field, progress)) {
if (!readReferenced && !isImplicitRead(project, field, progress)) {
String message = JavaErrorMessages.message("private.field.is.not.used.for.reading", identifier.getText());
return suggestionsToMakeFieldUsed(field, identifier, message);
}
@@ -439,44 +412,50 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
return null;
}
final boolean writeReferenced = myRefCountHolder.isReferencedForWrite(field);
if (!writeReferenced && !isImplicitWrite(field, progress)) {
if (!writeReferenced && !isImplicitWrite(project, field, progress)) {
String message = JavaErrorMessages.message("private.field.is.not.assigned", identifier.getText());
final HighlightInfo info = createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL);
QuickFixAction.registerQuickFixAction(info, new CreateGetterOrSetterFix(false, true, field), myUnusedSymbolKey);
QuickFixAction.registerQuickFixAction(info, HighlightMethodUtil.getFixRange(field), new CreateConstructorParameterFromFieldFix(field));
QuickFixAction.registerQuickFixAction(info, QuickFixFactory.getInstance().createCreateGetterOrSetterFix(false, true, field), myUnusedSymbolKey);
QuickFixAction.registerQuickFixAction(info, HighlightMethodUtil.getFixRange(field), QuickFixFactory.getInstance().createCreateConstructorParameterFromFieldFix(
field));
SpecialAnnotationsUtilBase.createAddToSpecialAnnotationFixes(field, new Processor<String>() {
@Override
public boolean process(final String annoName) {
QuickFixAction.registerQuickFixAction(info, UnusedSymbolLocalInspection.createQuickFix(annoName, "fields", field.getProject()));
QuickFixAction.registerQuickFixAction(info, QuickFixFactory.getInstance()
.createAddToDependencyInjectionAnnotationsFix(project, annoName, "fields"));
return true;
}
});
return info;
}
}
else if (isImplicitUsage(field, progress)) {
else if (isImplicitUsage(myProject, field, progress)) {
return null;
}
else if (isFieldUnused(field, progress, helper)) {
return formatUnusedSymbolHighlightInfo("field.is.not.used", field, "fields", myDeadCodeKey, myDeadCodeInfoType, identifier);
else if (isFieldUnused(myProject, myFile, field, progress, helper)) {
return formatUnusedSymbolHighlightInfo(project, "field.is.not.used", field, "fields", myDeadCodeKey, myDeadCodeInfoType, identifier);
}
return null;
}
public static boolean isFieldUnused(PsiField field, ProgressIndicator progress, GlobalUsageHelper helper) {
if (helper.isLocallyUsed(field) || !weAreSureThereAreNoUsages(field, progress, helper)) {
public static boolean isFieldUnused(@NotNull Project project,
@NotNull PsiFile containingFile,
@NotNull PsiField field,
@NotNull ProgressIndicator progress,
@NotNull GlobalUsageHelper helper) {
if (helper.isLocallyUsed(field) || !weAreSureThereAreNoUsages(project, containingFile, field, progress, helper)) {
return false;
}
return !(field instanceof PsiEnumConstant) || !isEnumValuesMethodUsed(field, progress, helper);
return !(field instanceof PsiEnumConstant) || !isEnumValuesMethodUsed(project, containingFile, field, progress, helper);
}
private HighlightInfo suggestionsToMakeFieldUsed(final PsiField field, final PsiIdentifier identifier, final String message) {
private HighlightInfo suggestionsToMakeFieldUsed(@NotNull PsiField field, @NotNull PsiIdentifier identifier, @NotNull String message) {
HighlightInfo highlightInfo = createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL);
QuickFixAction.registerQuickFixAction(highlightInfo, new RemoveUnusedVariableFix(field), myUnusedSymbolKey);
QuickFixAction.registerQuickFixAction(highlightInfo, new CreateGetterOrSetterFix(true, false, field), myUnusedSymbolKey);
QuickFixAction.registerQuickFixAction(highlightInfo, new CreateGetterOrSetterFix(false, true, field), myUnusedSymbolKey);
QuickFixAction.registerQuickFixAction(highlightInfo, new CreateGetterOrSetterFix(true, true, field), myUnusedSymbolKey);
QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createRemoveUnusedVariableFix(field), myUnusedSymbolKey);
QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createCreateGetterOrSetterFix(true, false, field), myUnusedSymbolKey);
QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createCreateGetterOrSetterFix(false, true, field), myUnusedSymbolKey);
QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createCreateGetterOrSetterFix(true, true, field), myUnusedSymbolKey);
return highlightInfo;
}
@@ -486,7 +465,8 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
}
@Nullable
private HighlightInfo processParameter(@NotNull PsiParameter parameter,
private HighlightInfo processParameter(@NotNull Project project,
@NotNull PsiParameter parameter,
@NotNull PsiIdentifier identifier,
@NotNull ProgressIndicator progress) {
PsiElement declarationScope = parameter.getDeclarationScope();
@@ -502,18 +482,10 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
!method.hasModifierProperty(PsiModifier.NATIVE) &&
!JavaHighlightUtil.isSerializationRelatedMethod(method, method.getContainingClass()) &&
!PsiClassImplUtil.isMainOrPremainMethod(method)) {
if (UnusedSymbolLocalInspection.isInjected(method)) return null;
if (isInjected(project, method)) return null;
HighlightInfo highlightInfo = checkUnusedParameter(parameter, identifier, progress);
if (highlightInfo != null) {
List<IntentionAction> options = new ArrayList<IntentionAction>();
options.addAll(IntentionManager.getInstance().getStandardIntentionOptions(myUnusedSymbolKey, myFile));
if (myUnusedParametersInspection != null) {
SuppressQuickFix[] batchSuppressActions = myUnusedParametersInspection.getBatchSuppressActions(parameter);
Collections.addAll(options, SuppressIntentionActionFromFix.convertBatchToSuppressIntentionActions(batchSuppressActions));
}
//need suppress from Unused Parameters but settings from Unused Symbol
QuickFixAction.registerQuickFixAction(highlightInfo, new RemoveUnusedParameterFix(parameter),
options, HighlightDisplayKey.getDisplayNameByKey(myUnusedSymbolKey));
QuickFixFactory.getInstance().registerFixesForUnusedParameter(parameter, highlightInfo);
return highlightInfo;
}
}
@@ -521,7 +493,7 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
else if (declarationScope instanceof PsiForeachStatement && !PsiUtil.isIgnoredName(parameter.getName())) {
HighlightInfo highlightInfo = checkUnusedParameter(parameter, identifier, progress);
if (highlightInfo != null) {
QuickFixAction.registerQuickFixAction(highlightInfo, new RenameToIgnoredFix(parameter), myUnusedSymbolKey);
QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createRenameToIgnoredFix(parameter), myUnusedSymbolKey);
return highlightInfo;
}
}
@@ -533,7 +505,7 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
private HighlightInfo checkUnusedParameter(@NotNull PsiParameter parameter,
@NotNull PsiIdentifier identifier,
@NotNull ProgressIndicator progress) {
if (!myRefCountHolder.isReferenced(parameter) && !isImplicitUsage(parameter, progress)) {
if (!myRefCountHolder.isReferenced(parameter) && !isImplicitUsage(myProject, parameter, progress)) {
String message = JavaErrorMessages.message("parameter.is.not.used", identifier.getText());
return createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL);
}
@@ -541,11 +513,12 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
}
@Nullable
private HighlightInfo processMethod(@NotNull final PsiMethod method,
private HighlightInfo processMethod(@NotNull final Project project,
@NotNull final PsiMethod method,
@NotNull PsiIdentifier identifier,
@NotNull ProgressIndicator progress,
@NotNull GlobalUsageHelper helper) {
if (isMethodReferenced(method, progress, helper)) return null;
if (isMethodReferenced(myProject, myFile, method, progress, helper)) return null;
HighlightInfoType highlightInfoType;
HighlightDisplayKey highlightDisplayKey;
String key;
@@ -562,26 +535,23 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
String symbolName = HighlightMessageUtil.getSymbolName(method, PsiSubstitutor.EMPTY);
String message = JavaErrorMessages.message(key, symbolName);
final HighlightInfo highlightInfo = createUnusedSymbolInfo(identifier, message, highlightInfoType);
QuickFixAction.registerQuickFixAction(highlightInfo, new SafeDeleteFix(method), highlightDisplayKey);
QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createSafeDeleteFix(method), highlightDisplayKey);
SpecialAnnotationsUtilBase.createAddToSpecialAnnotationFixes(method, new Processor<String>() {
@Override
public boolean process(final String annoName) {
QuickFixAction
.registerQuickFixAction(highlightInfo, UnusedSymbolLocalInspection.createQuickFix(annoName, "methods", method.getProject()));
IntentionAction fix = QuickFixFactory.getInstance().createAddToDependencyInjectionAnnotationsFix(project, annoName, "methods");
QuickFixAction.registerQuickFixAction(highlightInfo, fix);
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);
}
return highlightInfo;
}
public static boolean isMethodReferenced(PsiMethod method,
ProgressIndicator progress,
GlobalUsageHelper helper) {
public static boolean isMethodReferenced(@NotNull Project project,
@NotNull PsiFile containingFile,
@NotNull PsiMethod method,
@NotNull ProgressIndicator progress,
@NotNull GlobalUsageHelper helper) {
if (helper.isLocallyUsed(method)) return true;
boolean aPrivate = method.hasModifierProperty(PsiModifier.PRIVATE);
@@ -591,86 +561,102 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
if (isIntentionalPrivateConstructor(method, containingClass)) {
return true;
}
if (isImplicitUsage(method, progress)) {
if (isImplicitUsage(project, method, progress)) {
return true;
}
if (!helper.isCurrentFileAlreadyChecked()) {
return !weAreSureThereAreNoUsages(method, progress, helper);
return !weAreSureThereAreNoUsages(project, containingFile, 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
&& isClassUsed(containingClass, progress, helper)) {
&& isClassUsed(project, containingFile, containingClass, progress, helper)) {
return true;
}
if (isImplicitUsage(method, progress)) return true;
if (isImplicitUsage(project, method, progress)) return true;
if (method.findSuperMethods().length != 0) {
return true;
}
if (!weAreSureThereAreNoUsages(method, progress, helper)) {
if (!weAreSureThereAreNoUsages(project, containingFile, method, progress, helper)) {
return true;
}
}
return false;
}
private static boolean weAreSureThereAreNoUsages(@NotNull PsiMember member, ProgressIndicator progress, GlobalUsageHelper helper) {
private static boolean weAreSureThereAreNoUsages(@NotNull Project project,
@NotNull PsiFile containingFile,
@NotNull PsiMember member,
@NotNull ProgressIndicator progress,
@NotNull GlobalUsageHelper helper) {
if (!helper.shouldCheckUsages(member)) return false;
String name = member.getName();
if (name == null) return false;
SearchScope useScope = member.getUseScope();
Project project = member.getProject();
PsiSearchHelper searchHelper = PsiSearchHelper.SERVICE.getInstance(project);
PsiFile ignoreFile = helper.isCurrentFileAlreadyChecked() ? containingFile : null;
if (useScope instanceof GlobalSearchScope) {
// some classes may have references from within XML outside dependent modules, e.g. our actions
if (member instanceof PsiClass) {
useScope = GlobalSearchScope.projectScope(project).uniteWith((GlobalSearchScope)useScope);
}
PsiSearchHelper searchHelper = PsiSearchHelper.SERVICE.getInstance(project);
PsiFile file = member.getContainingFile();
PsiFile ignoreFile = helper.isCurrentFileAlreadyChecked() ? file : null;
PsiSearchHelper.SearchCostResult cheapEnough = searchHelper.isCheapEnoughToSearch(name, (GlobalSearchScope)useScope, ignoreFile, progress);
if (cheapEnough == TOO_MANY_OCCURRENCES) return false;
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 == ZERO_OCCURRENCES) {
if (!canBeReferencedViaWeirdNames(member)) return true;
if (cheapEnough == PsiSearchHelper.SearchCostResult.ZERO_OCCURRENCES && !canBeReferencedViaWeirdNames(member, containingFile)) {
return true;
}
if (member instanceof PsiMethod) {
String propertyName = PropertyUtil.getPropertyName(member);
if (propertyName != null && file != null) {
SearchScope fileScope = file.getUseScope();
if (propertyName != null) {
SearchScope fileScope = containingFile.getUseScope();
if (fileScope instanceof GlobalSearchScope &&
searchHelper.isCheapEnoughToSearch(propertyName, (GlobalSearchScope)fileScope, ignoreFile, progress) == TOO_MANY_OCCURRENCES) {
searchHelper.isCheapEnoughToSearch(propertyName, (GlobalSearchScope)fileScope, ignoreFile, progress) ==
PsiSearchHelper.SearchCostResult.TOO_MANY_OCCURRENCES) {
return false;
}
}
}
}
FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(project)).getFindUsagesManager();
FindUsagesHandler handler = new JavaFindUsagesHandler(member, new JavaFindUsagesHandlerFactory(project));
FindUsagesOptions findUsagesOptions = handler.getFindUsagesOptions().clone();
findUsagesOptions.searchScope = useScope;
findUsagesOptions.isSearchForTextOccurrences = true;
return !findUsagesManager.isUsed(member, findUsagesOptions);
if (ReferencesSearch.search(member, useScope, true).findFirst() != null) return false;
return !(useScope instanceof GlobalSearchScope) || !foundUsageInText(member, (GlobalSearchScope)useScope, searchHelper, ignoreFile);
}
private static boolean isEnumValuesMethodUsed(PsiMember member, ProgressIndicator progress, GlobalUsageHelper helper) {
private static boolean foundUsageInText(@NotNull PsiMember member,
@NotNull GlobalSearchScope scope,
@NotNull PsiSearchHelper searchHelper,
final PsiFile ignoreFile) {
return !searchHelper.processUsagesInNonJavaFiles(member, member.getName(), new PsiNonJavaFileReferenceProcessor() {
@Override
public boolean process(final PsiFile psiFile, final int startOffset, final int endOffset) {
if (psiFile == ignoreFile) return true; // ignore usages in containingFile because isLocallyUsed() method would have caught that
PsiElement element = psiFile.findElementAt(startOffset);
return element instanceof PsiComment; // ignore comments
}
}, scope);
}
private static boolean isEnumValuesMethodUsed(@NotNull Project project,
@NotNull PsiFile containingFile,
@NotNull PsiMember member,
@NotNull ProgressIndicator progress,
@NotNull GlobalUsageHelper helper) {
final PsiClass containingClass = member.getContainingClass();
if (containingClass == null || !(containingClass instanceof PsiClassImpl)) return true;
final PsiMethod valuesMethod = ((PsiClassImpl)containingClass).getValuesMethod();
return valuesMethod == null || isMethodReferenced(valuesMethod, progress, helper);
return valuesMethod == null || isMethodReferenced(project, containingFile, valuesMethod, progress, helper);
}
private static boolean canBeReferencedViaWeirdNames(PsiMember member) {
private static boolean canBeReferencedViaWeirdNames(@NotNull PsiMember member, @NotNull PsiFile containingFile) {
if (member instanceof PsiClass) return false;
PsiFile containingFile = member.getContainingFile();
if (!(containingFile instanceof PsiJavaFile)) return true; // Groovy field can be referenced from Java by getter
if (member instanceof PsiField) return false; //Java field cannot be referenced by anything but its name
if (member instanceof PsiMethod) {
@@ -680,11 +666,12 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
}
@Nullable
private HighlightInfo processClass(@NotNull PsiClass aClass,
private HighlightInfo processClass(@NotNull Project project,
@NotNull PsiClass aClass,
@NotNull PsiIdentifier identifier,
@NotNull ProgressIndicator progress,
@NotNull GlobalUsageHelper helper) {
if (isClassUsed(aClass, progress, helper)) return null;
if (isClassUsed(project, myFile, aClass, progress, helper)) return null;
String pattern;
HighlightDisplayKey highlightDisplayKey;
@@ -711,44 +698,53 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
highlightDisplayKey = myDeadCodeKey;
highlightInfoType = myDeadCodeInfoType;
}
return formatUnusedSymbolHighlightInfo(pattern, aClass, "classes", highlightDisplayKey, highlightInfoType, identifier);
return formatUnusedSymbolHighlightInfo(myProject, pattern, aClass, "classes", highlightDisplayKey, highlightInfoType, identifier);
}
public static boolean isClassUsed(PsiClass aClass, ProgressIndicator progress, GlobalUsageHelper helper) {
if (aClass == null) return true;
public static boolean isClassUsed(@NotNull Project project,
@NotNull PsiFile containingFile,
@NotNull PsiClass aClass,
@NotNull ProgressIndicator progress,
@NotNull GlobalUsageHelper helper) {
Boolean result = helper.unusedClassCache.get(aClass);
if (result == null) {
result = isReallyUsed(aClass, progress, helper);
result = isReallyUsed(project, containingFile, aClass, progress, helper);
helper.unusedClassCache.put(aClass, result);
}
return result;
}
private static boolean isReallyUsed(PsiClass aClass, ProgressIndicator progress, GlobalUsageHelper helper) {
if (isImplicitUsage(aClass, progress) || helper.isLocallyUsed(aClass)) return true;
private static boolean isReallyUsed(@NotNull Project project,
@NotNull PsiFile containingFile,
@NotNull PsiClass aClass,
@NotNull ProgressIndicator progress,
@NotNull GlobalUsageHelper helper) {
if (isImplicitUsage(project, aClass, progress) || helper.isLocallyUsed(aClass)) return true;
if (helper.isCurrentFileAlreadyChecked()) {
if (aClass.getContainingClass() != null && aClass.hasModifierProperty(PsiModifier.PRIVATE) ||
aClass.getParent() instanceof PsiDeclarationStatement ||
aClass instanceof PsiTypeParameter) return false;
}
return !weAreSureThereAreNoUsages(aClass, progress, helper);
return !weAreSureThereAreNoUsages(project, containingFile, aClass, progress, helper);
}
private static HighlightInfo formatUnusedSymbolHighlightInfo(@NotNull @PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) String pattern,
private static HighlightInfo formatUnusedSymbolHighlightInfo(@NotNull final Project project,
@NotNull @PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) String pattern,
@NotNull final PsiNameIdentifierOwner aClass,
@NotNull final String element,
@NotNull HighlightDisplayKey highlightDisplayKey,
HighlightDisplayKey highlightDisplayKey,
@NotNull HighlightInfoType highlightInfoType,
@NotNull PsiElement identifier) {
String symbolName = aClass.getName();
String message = JavaErrorMessages.message(pattern, symbolName);
final HighlightInfo highlightInfo = createUnusedSymbolInfo(identifier, message, highlightInfoType);
QuickFixAction.registerQuickFixAction(highlightInfo, new SafeDeleteFix(aClass), highlightDisplayKey);
QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createSafeDeleteFix(aClass), highlightDisplayKey);
SpecialAnnotationsUtilBase.createAddToSpecialAnnotationFixes((PsiModifierListOwner)aClass, new Processor<String>() {
@Override
public boolean process(final String annoName) {
QuickFixAction
.registerQuickFixAction(highlightInfo, UnusedSymbolLocalInspection.createQuickFix(annoName, element, aClass.getProject()));
.registerQuickFixAction(highlightInfo,
QuickFixFactory.getInstance().createAddToDependencyInjectionAnnotationsFix(project, annoName, element));
return true;
}
});
@@ -758,7 +754,7 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
@Nullable
private HighlightInfo processImport(@NotNull PsiImportStatementBase importStatement, @NotNull HighlightDisplayKey unusedImportKey) {
// jsp include directive hack
if (importStatement instanceof JspxImportStatement && ((JspxImportStatement)importStatement).isForeignFileImport()) return null;
if (importStatement.isForeignFileImport()) return null;
if (PsiUtilCore.hasErrorElementChild(importStatement)) return null;
@@ -799,43 +795,12 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
HighlightInfo.newHighlightInfo(JavaHighlightInfoTypes.UNUSED_IMPORT).range(importStatement).descriptionAndTooltip(description)
.create();
QuickFixAction.registerQuickFixAction(info, new OptimizeImportsFix(), unusedImportKey);
QuickFixAction.registerQuickFixAction(info, new EnableOptimizeImportsOnTheFlyFix(), unusedImportKey);
QuickFixAction.registerQuickFixAction(info, QuickFixFactory.getInstance().createOptimizeImportsFix(), unusedImportKey);
QuickFixAction.registerQuickFixAction(info, QuickFixFactory.getInstance().createEnableOptimizeImportsOnTheFlyFix(), unusedImportKey);
myHasRedundantImports = true;
return info;
}
private boolean timeToOptimizeImports() {
if (!CodeInsightSettings.getInstance().OPTIMIZE_IMPORTS_ON_THE_FLY) return false;
DaemonCodeAnalyzerEx codeAnalyzer = DaemonCodeAnalyzerEx.getInstanceEx(myProject);
PsiFile file = PsiDocumentManager.getInstance(myProject).getPsiFile(myDocument);
// dont optimize out imports in JSP since it can be included in other JSP
if (file == null || !codeAnalyzer.isHighlightingAvailable(file) || !(file instanceof PsiJavaFile) || file instanceof ServerPageFile) return false;
if (!codeAnalyzer.isErrorAnalyzingFinished(file)) return false;
boolean errors = containsErrorsPreventingOptimize(file);
return !errors && DaemonListeners.canChangeFileSilently(myFile);
}
private boolean containsErrorsPreventingOptimize(@NotNull PsiFile file) {
// ignore unresolved imports errors
PsiImportList importList = ((PsiJavaFile)file).getImportList();
final TextRange importsRange = importList == null ? TextRange.EMPTY_RANGE : importList.getTextRange();
boolean hasErrorsExceptUnresolvedImports = !DaemonCodeAnalyzerEx
.processHighlights(myDocument, myProject, HighlightSeverity.ERROR, 0, myDocument.getTextLength(), new Processor<HighlightInfo>() {
@Override
public boolean process(HighlightInfo error) {
int infoStart = error.getActualStartOffset();
int infoEnd = error.getActualEndOffset();
return importsRange.containsRange(infoStart, infoEnd) && error.type.equals(HighlightInfoType.WRONG_REF);
}
});
return hasErrorsExceptUnresolvedImports;
}
private static boolean isIntentionalPrivateConstructor(@NotNull PsiMethod method, PsiClass containingClass) {
return method.isConstructor() &&
@@ -62,8 +62,14 @@ public class GenericsHighlightUtil {
public static HighlightInfo checkInferredTypeArguments(PsiTypeParameterListOwner listOwner,
PsiElement call,
PsiSubstitutor substitutor) {
final Pair<PsiTypeParameter, PsiType> inferredTypeArgument =
GenericsUtil.findTypeParameterWithBoundError(listOwner.getTypeParameters(), substitutor, call, false);
return checkInferredTypeArguments(listOwner.getTypeParameters(), call, substitutor);
}
@Nullable
public static HighlightInfo checkInferredTypeArguments(PsiTypeParameter[] typeParameters,
PsiElement call,
PsiSubstitutor substitutor) {
final Pair<PsiTypeParameter, PsiType> inferredTypeArgument = GenericsUtil.findTypeParameterWithBoundError(typeParameters, substitutor, call, false);
if (inferredTypeArgument != null) {
final PsiType extendsType = inferredTypeArgument.second;
final PsiTypeParameter typeParameter = inferredTypeArgument.first;
@@ -40,6 +40,7 @@ import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.javadoc.PsiDocTagValue;
import com.intellij.psi.util.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.MostlySingularMultiMap;
import gnu.trove.THashMap;
@@ -1250,7 +1251,13 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
if (!myHolder.hasErrorResults() && method instanceof PsiTypeParameterListOwner) {
myHolder.add(GenericsHighlightUtil.checkInferredTypeArguments((PsiTypeParameterListOwner)method, expression, result.getSubstitutor()));
PsiTypeParameter[] typeParameters = ((PsiTypeParameterListOwner)method).getTypeParameters();
if (method instanceof PsiMethod) {
final PsiClass containingClass = ((PsiMethod)method).getContainingClass();
assert containingClass != null : method;
typeParameters = ArrayUtil.mergeArrays(typeParameters, containingClass.getTypeParameters());
}
myHolder.add(GenericsHighlightUtil.checkInferredTypeArguments(typeParameters, expression, result.getSubstitutor()));
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -435,7 +435,7 @@ public class UnusedDeclarationInspection extends GlobalInspectionTool {
myPhase = 1;
}
public boolean isEntryPoint(final RefElement owner) {
public boolean isEntryPoint(@NotNull RefElement owner) {
final PsiElement element = owner.getElement();
if (RefUtil.isImplicitUsage(element)) return true;
if (element instanceof PsiModifierListOwner) {
@@ -444,9 +444,11 @@ public class UnusedDeclarationInspection extends GlobalInspectionTool {
return true;
}
}
for (EntryPoint extension : myExtensions) {
if (extension.isEntryPoint(owner, element)) {
return true;
if (element != null) {
for (EntryPoint extension : myExtensions) {
if (extension.isEntryPoint(owner, element)) {
return true;
}
}
}
return false;
@@ -482,7 +484,7 @@ public class UnusedDeclarationInspection extends GlobalInspectionTool {
}
if (element instanceof PsiModifierListOwner) {
final EntryPointsManager entryPointsManager = EntryPointsManager.getInstance(project);
if (entryPointsManager.isEntryPoint((PsiModifierListOwner)element)) return true;
if (entryPointsManager.isEntryPoint(element)) return true;
//if (AnnotationUtil
// .checkAnnotatedUsingPatterns((PsiModifierListOwner)element, entryPointsManager.ADDITIONAL_ANNOTATIONS) ||
// AnnotationUtil
@@ -0,0 +1,54 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInspection.unusedSymbol;
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
import com.intellij.codeInspection.*;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
public class UnusedSymbolLocalInspectionBase extends AbstractBaseJavaLocalInspectionTool implements CustomSuppressableInspectionTool {
@NonNls public static final String SHORT_NAME = HighlightInfoType.UNUSED_SYMBOL_SHORT_NAME;
@NonNls public static final String DISPLAY_NAME = HighlightInfoType.UNUSED_SYMBOL_DISPLAY_NAME;
@NonNls public static final String UNUSED_PARAMETERS_SHORT_NAME = "UnusedParameters";
public boolean LOCAL_VARIABLE = true;
public boolean FIELD = true;
public boolean METHOD = true;
public boolean CLASS = true;
public boolean PARAMETER = true;
public boolean REPORT_PARAMETER_FOR_PUBLIC_METHODS = true;
@Override
public boolean isSuppressedFor(@NotNull PsiElement element) {
return isSuppressedFor(element, this);
}
public static boolean isSuppressedFor(@NotNull PsiElement element, @NotNull LocalInspectionTool tool) {
return BaseJavaBatchLocalInspectionTool.isSuppressedFor(element, tool);
}
@Override
public SuppressIntentionAction[] getSuppressActions(final PsiElement element) {
String shortName = getShortName();
HighlightDisplayKey key = HighlightDisplayKey.find(shortName);
if (key == null) {
throw new AssertionError("HighlightDisplayKey.find(" + shortName + ") is null. Inspection: "+getClass());
}
SuppressQuickFix[] batchSuppressActions = BatchSuppressManager.SERVICE.getInstance().createBatchSuppressActions(key);
return SuppressIntentionActionFromFix.convertBatchToSuppressIntentionActions(batchSuppressActions);
}
}
@@ -19,18 +19,25 @@ import com.intellij.codeHighlighting.MainHighlightingPassFactory;
import com.intellij.codeHighlighting.Pass;
import com.intellij.codeHighlighting.TextEditorHighlightingPass;
import com.intellij.codeHighlighting.TextEditorHighlightingPassRegistrar;
import com.intellij.codeInsight.daemon.ProblemHighlightFilter;
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightVisitorImpl;
import com.intellij.codeInspection.InspectionProfile;
import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection;
import com.intellij.codeInspection.unusedImport.UnusedImportLocalInspection;
import com.intellij.openapi.components.AbstractProjectComponent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.TextRange;
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
import com.intellij.psi.JspPsiUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.psi.jsp.JspFile;
import com.intellij.psi.jsp.JspSpiUtil;
import com.intellij.util.containers.Predicate;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -42,7 +49,7 @@ import java.util.Arrays;
*/
public class PostHighlightingPassFactory extends AbstractProjectComponent implements MainHighlightingPassFactory {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.PostHighlightingPassFactory");
private static final Key<Long> LAST_POST_PASS_TIMESTAMP = Key.create("LAST_POST_PASS_TIMESTAMP");
public PostHighlightingPassFactory(Project project, TextEditorHighlightingPassRegistrar highlightingPassRegistrar, HighlightVisitorImpl hvi) {
super(project);
highlightingPassRegistrar.registerTextEditorHighlightingPass(this, new int[]{Pass.UPDATE_ALL,}, null, true, Pass.POST_UPDATE_ALL);
@@ -65,26 +72,44 @@ public class PostHighlightingPassFactory extends AbstractProjectComponent implem
@Nullable
public TextEditorHighlightingPass createHighlightingPass(@NotNull PsiFile file, @NotNull final Editor editor) {
TextRange textRange = FileStatusMap.getDirtyTextRange(editor, Pass.UPDATE_ALL);
if (textRange == null) {
Long lastStamp = file.getUserData(LAST_POST_PASS_TIMESTAMP);
long currentStamp = PsiModificationTracker.SERVICE.getInstance(myProject).getModificationCount();
if (lastStamp != null && lastStamp == currentStamp || !ProblemHighlightFilter.shouldHighlightFile(file)) {
return null;
}
}
if (textRange == null && PostHighlightingPass.isUpToDate(file)) return null;
return new PostHighlightingPass(myProject, file, editor, editor.getDocument(), new DefaultHighlightInfoProcessor());
return create(file, editor.getDocument(), editor, new DefaultHighlightInfoProcessor());
}
@Override
public TextEditorHighlightingPass createMainHighlightingPass(@NotNull PsiFile file,
@NotNull Document document,
@NotNull HighlightInfoProcessor highlightInfoProcessor) {
return new PostHighlightingPass(myProject, file, null, document, highlightInfoProcessor);
return create(file, document, null, highlightInfoProcessor);
}
public static void markFileUpToDate(@NotNull PsiFile file) {
long lastStamp = PsiModificationTracker.SERVICE.getInstance(file.getProject()).getModificationCount();
file.putUserData(LAST_POST_PASS_TIMESTAMP, lastStamp);
private PostHighlightingPass create(@NotNull PsiFile file,
@NotNull Document document, Editor editor,
@NotNull HighlightInfoProcessor highlightInfoProcessor) {
HighlightDisplayKey unusedImportKey = HighlightDisplayKey.find(UnusedImportLocalInspection.SHORT_NAME);
InspectionProfile profile = InspectionProjectProfileManager.getInstance(file.getProject()).getInspectionProfile();
boolean importEnabled = isUnusedImportEnabled(unusedImportKey, file, profile);
final UnusedDeclarationInspection myDeadCodeInspection = (UnusedDeclarationInspection)profile.getUnwrappedTool(UnusedDeclarationInspection.SHORT_NAME, file);
HighlightDisplayKey myDeadCodeKey = HighlightDisplayKey.find(UnusedDeclarationInspection.SHORT_NAME);
final boolean myDeadCodeEnabled = profile.isToolEnabled(myDeadCodeKey, file);
return new PostHighlightingPass(myProject, file, editor, document, highlightInfoProcessor, importEnabled, new Predicate<PsiElement>() {
@Override
public boolean apply(PsiElement member) {
return !myDeadCodeEnabled || myDeadCodeInspection.isEntryPoint(member);
}
});
}
private static boolean isUnusedImportEnabled(HighlightDisplayKey unusedImportKey, @NotNull PsiFile file, InspectionProfile profile) {
boolean unusedImportEnabled = profile.isToolEnabled(unusedImportKey, file);
if (unusedImportEnabled && JspPsiUtil.isInJspFile(file)) {
final JspFile jspFile = JspPsiUtil.getJspFile(file);
if (jspFile != null) {
unusedImportEnabled = !JspSpiUtil.isIncludedOrIncludesSomething(jspFile);
}
}
return unusedImportEnabled;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -40,7 +40,7 @@ public class CreateGetterOrSetterFix implements IntentionAction, LowPriorityActi
private final PsiField myField;
private final String myPropertyName;
public CreateGetterOrSetterFix(boolean createGetter, boolean createSetter, PsiField field) {
public CreateGetterOrSetterFix(boolean createGetter, boolean createSetter, @NotNull PsiField field) {
myCreateGetter = createGetter;
myCreateSetter = createSetter;
myField = field;
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,30 +15,61 @@
*/
package com.intellij.codeInsight.intention.impl.config;
import com.intellij.codeInsight.CodeInsightSettings;
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
import com.intellij.codeInsight.daemon.QuickFixActionRegistrar;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerEx;
import com.intellij.codeInsight.daemon.impl.DaemonListeners;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
import com.intellij.codeInsight.daemon.impl.analysis.IncreaseLanguageLevelFix;
import com.intellij.codeInsight.daemon.impl.quickfix.ReplacePrimitiveWithBoxedTypeAction;
import com.intellij.codeInsight.daemon.impl.quickfix.*;
import com.intellij.codeInsight.daemon.quickFix.CreateClassOrPackageFix;
import com.intellij.codeInsight.daemon.quickFix.CreateFieldOrPropertyFix;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.IntentionManager;
import com.intellij.codeInsight.intention.QuickFixFactory;
import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement;
import com.intellij.codeInspection.LocalQuickFixOnPsiElement;
import com.intellij.codeInspection.*;
import com.intellij.codeInspection.ex.EntryPointsManagerBase;
import com.intellij.codeInspection.unusedParameters.UnusedParametersInspection;
import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection;
import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspectionBase;
import com.intellij.codeInspection.util.SpecialAnnotationsUtil;
import com.intellij.diagnostic.AttachmentFactory;
import com.intellij.diagnostic.LogMessageEx;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.undo.UndoManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.TextRange;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PropertyMemberType;
import com.intellij.psi.util.ClassKind;
import com.intellij.psi.util.PropertyMemberType;
import com.intellij.refactoring.changeSignature.ChangeSignatureGestureDetector;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.Processor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* @author cdr
*/
public class QuickFixFactoryImpl extends QuickFixFactory {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.intention.impl.config.QuickFixFactoryImpl");
@NotNull
@Override
public LocalQuickFixAndIntentionActionOnPsiElement createModifierListFix(@NotNull PsiModifierList modifierList,
@@ -561,9 +592,177 @@ public class QuickFixFactoryImpl extends QuickFixFactory {
PullAsAbstractUpFix.registerQuickFix(method, registrar);
}
@NotNull
@Override
public IntentionAction createCreateAnnotationMethodFromUsageFix(PsiNameValuePair pair) {
public IntentionAction createCreateAnnotationMethodFromUsageFix(@NotNull PsiNameValuePair pair) {
return new CreateAnnotationMethodFromUsageFix(pair);
}
@NotNull
@Override
public IntentionAction createOptimizeImportsFix() {
final OptimizeImportsFix fix = new OptimizeImportsFix();
return new IntentionAction() {
@NotNull
@Override
public String getText() {
return fix.getText();
}
@NotNull
@Override
public String getFamilyName() {
return fix.getFamilyName();
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
return timeToOptimizeImports(file) && fix.isAvailable(project, editor, file);
}
@Override
public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
invokeOnTheFlyImportOptimizer(new Runnable() {
@Override
public void run() {
fix.invoke(project, editor, file);
}
}, file, editor);
}
@Override
public boolean startInWriteAction() {
return fix.startInWriteAction();
}
};
}
@Override
public void registerFixesForUnusedParameter(@NotNull PsiParameter parameter, @NotNull Object highlightInfo) {
Project myProject = parameter.getProject();
InspectionProfile profile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile();
UnusedParametersInspection unusedParametersInspection =
(UnusedParametersInspection)profile.getUnwrappedTool(UnusedSymbolLocalInspectionBase.UNUSED_PARAMETERS_SHORT_NAME, parameter);
LOG.assertTrue(ApplicationManager.getApplication().isUnitTestMode() || unusedParametersInspection != null);
List<IntentionAction> options = new ArrayList<IntentionAction>();
HighlightDisplayKey myUnusedSymbolKey = HighlightDisplayKey.find(UnusedSymbolLocalInspection.SHORT_NAME);
options.addAll(IntentionManager.getInstance().getStandardIntentionOptions(myUnusedSymbolKey, parameter));
if (unusedParametersInspection != null) {
SuppressQuickFix[] batchSuppressActions = unusedParametersInspection.getBatchSuppressActions(parameter);
Collections.addAll(options, SuppressIntentionActionFromFix.convertBatchToSuppressIntentionActions(batchSuppressActions));
}
//need suppress from Unused Parameters but settings from Unused Symbol
QuickFixAction.registerQuickFixAction((HighlightInfo)highlightInfo, new RemoveUnusedParameterFix(parameter),
options, HighlightDisplayKey.getDisplayNameByKey(myUnusedSymbolKey));
}
@NotNull
@Override
public IntentionAction createAddToDependencyInjectionAnnotationsFix(@NotNull Project project,
@NotNull String qualifiedName,
@NotNull String element) {
final EntryPointsManagerBase entryPointsManager = EntryPointsManagerBase.getInstance(project);
return SpecialAnnotationsUtil.createAddToSpecialAnnotationsListIntentionAction(
QuickFixBundle.message("fix.unused.symbol.injection.text", element, qualifiedName),
QuickFixBundle.message("fix.unused.symbol.injection.family"),
entryPointsManager.ADDITIONAL_ANNOTATIONS, qualifiedName);
}
@NotNull
@Override
public IntentionAction createCreateGetterOrSetterFix(boolean createGetter, boolean createSetter, @NotNull PsiField field) {
return new CreateGetterOrSetterFix(createGetter, createSetter, field);
}
@NotNull
@Override
public IntentionAction createRenameToIgnoredFix(@NotNull PsiNamedElement namedElement) {
return new RenameToIgnoredFix(namedElement);
}
@NotNull
@Override
public IntentionAction createEnableOptimizeImportsOnTheFlyFix() {
return new EnableOptimizeImportsOnTheFlyFix();
}
@NotNull
@Override
public IntentionAction createSafeDeleteFix(@NotNull PsiElement element) {
if (element instanceof PsiMethod) {
PsiMethod method = (PsiMethod)element;
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(method.getProject()).dismissForElement(method);
}
}
return new SafeDeleteFix(element);
}
public static void invokeOnTheFlyImportOptimizer(@NotNull final Runnable runnable,
@NotNull final PsiFile file,
@NotNull final Editor editor) {
final long stamp = editor.getDocument().getModificationStamp();
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
if (file.getProject().isDisposed() || editor.isDisposed() || editor.getDocument().getModificationStamp() != stamp) return;
//no need to optimize imports on the fly during undo/redo
final UndoManager undoManager = UndoManager.getInstance(editor.getProject());
if (undoManager.isUndoInProgress() || undoManager.isRedoInProgress()) return;
PsiDocumentManager.getInstance(file.getProject()).commitAllDocuments();
String beforeText = file.getText();
final long oldStamp = editor.getDocument().getModificationStamp();
CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
@Override
public void run() {
ApplicationManager.getApplication().runWriteAction(runnable);
}
});
if (oldStamp != editor.getDocument().getModificationStamp()) {
String afterText = file.getText();
if (Comparing.strEqual(beforeText, afterText)) {
LOG.error(
LogMessageEx.createEvent("Import optimizer hasn't optimized any imports", file.getViewProvider().getVirtualFile().getPath(),
AttachmentFactory.createAttachment(file.getViewProvider().getVirtualFile())));
}
}
}
});
}
private static boolean timeToOptimizeImports(@NotNull PsiFile file) {
if (!CodeInsightSettings.getInstance().OPTIMIZE_IMPORTS_ON_THE_FLY) return false;
DaemonCodeAnalyzerEx codeAnalyzer = DaemonCodeAnalyzerEx.getInstanceEx(file.getProject());
// dont optimize out imports in JSP since it can be included in other JSP
if (file == null || !codeAnalyzer.isHighlightingAvailable(file) || !(file instanceof PsiJavaFile) || file instanceof ServerPageFile) return false;
if (!codeAnalyzer.isErrorAnalyzingFinished(file)) return false;
boolean errors = containsErrorsPreventingOptimize(file);
return !errors && DaemonListeners.canChangeFileSilently(file);
}
private static boolean containsErrorsPreventingOptimize(@NotNull PsiFile file) {
Document document = PsiDocumentManager.getInstance(file.getProject()).getDocument(file);
if (document == null) return true;
// ignore unresolved imports errors
PsiImportList importList = ((PsiJavaFile)file).getImportList();
final TextRange importsRange = importList == null ? TextRange.EMPTY_RANGE : importList.getTextRange();
boolean hasErrorsExceptUnresolvedImports = !DaemonCodeAnalyzerEx
.processHighlights(document, file.getProject(), HighlightSeverity.ERROR, 0, document.getTextLength(), new Processor<HighlightInfo>() {
@Override
public boolean process(HighlightInfo error) {
int infoStart = error.getActualStartOffset();
int infoEnd = error.getActualEndOffset();
return importsRange.containsRange(infoStart, infoEnd) && error.type.equals(HighlightInfoType.WRONG_REF);
}
});
return hasErrorsExceptUnresolvedImports;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,6 +30,7 @@ import com.intellij.codeInsight.daemon.GroupNames;
import com.intellij.codeInspection.*;
import com.intellij.codeInspection.ex.EntryPointsManager;
import com.intellij.codeInspection.reference.*;
import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspectionBase;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectUtil;
import com.intellij.openapi.util.Comparing;
@@ -43,7 +44,6 @@ import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.changeSignature.ChangeSignatureProcessor;
import com.intellij.refactoring.changeSignature.ParameterInfoImpl;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -54,8 +54,6 @@ import java.util.Collection;
import java.util.List;
public class UnusedParametersInspection extends GlobalJavaBatchInspectionTool {
@NonNls public static final String SHORT_NAME = "UnusedParameters";
@Override
@Nullable
public CommonProblemDescriptor[] checkElement(@NotNull final RefEntity refEntity,
@@ -229,7 +227,7 @@ public class UnusedParametersInspection extends GlobalJavaBatchInspectionTool {
@Override
@NotNull
public String getShortName() {
return SHORT_NAME;
return UnusedSymbolLocalInspectionBase.UNUSED_PARAMETERS_SHORT_NAME;
}
@Override
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,20 +17,13 @@
package com.intellij.codeInspection.unusedSymbol;
import com.intellij.codeInsight.daemon.GroupNames;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.BaseJavaLocalInspectionTool;
import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection;
import com.intellij.codeInspection.ex.EntryPointsManager;
import com.intellij.codeInspection.ex.EntryPointsManagerBase;
import com.intellij.codeInspection.ex.PairedUnfairLocalInspectionTool;
import com.intellij.codeInspection.util.SpecialAnnotationsUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectUtil;
import com.intellij.psi.PsiModifierListOwner;
import org.intellij.lang.annotations.Pattern;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -44,18 +37,7 @@ import java.awt.event.ActionListener;
* User: anna
* Date: 17-Feb-2006
*/
public class UnusedSymbolLocalInspection extends BaseJavaLocalInspectionTool implements PairedUnfairLocalInspectionTool {
@NonNls public static final String SHORT_NAME = HighlightInfoType.UNUSED_SYMBOL_SHORT_NAME;
@NonNls public static final String DISPLAY_NAME = HighlightInfoType.UNUSED_SYMBOL_DISPLAY_NAME;
public boolean LOCAL_VARIABLE = true;
public boolean FIELD = true;
public boolean METHOD = true;
public boolean CLASS = true;
public boolean PARAMETER = true;
public boolean REPORT_PARAMETER_FOR_PUBLIC_METHODS = true;
public class UnusedSymbolLocalInspection extends UnusedSymbolLocalInspectionBase implements PairedUnfairLocalInspectionTool {
@Override
@NotNull
public String getGroupDisplayName() {
@@ -154,16 +136,4 @@ public class UnusedSymbolLocalInspection extends BaseJavaLocalInspectionTool imp
public JComponent createOptionsPanel() {
return new OptionsPanel().getPanel();
}
public static IntentionAction createQuickFix(@NonNls String qualifiedName, @Nls String element, Project project) {
final EntryPointsManagerBase entryPointsManager = EntryPointsManagerBase.getInstance(project);
return SpecialAnnotationsUtil.createAddToSpecialAnnotationsListIntentionAction(
QuickFixBundle.message("fix.unused.symbol.injection.text", element, qualifiedName),
QuickFixBundle.message("fix.unused.symbol.injection.family"),
entryPointsManager.ADDITIONAL_ANNOTATIONS, qualifiedName);
}
public static boolean isInjected(final PsiModifierListOwner modifierListOwner) {
return EntryPointsManagerBase.getInstance(modifierListOwner.getProject()).isEntryPoint(modifierListOwner);
}
}
@@ -180,11 +180,12 @@ public class PullUpDialog extends PullUpDialogBase<MemberInfoStorage, MemberInfo
@Override
public boolean isMemberEnabled(MemberInfo member) {
PsiClass currentSuperClass = getSuperClass();
final PsiClass currentSuperClass = getSuperClass();
if(currentSuperClass == null) return true;
if (myMemberInfoStorage.getDuplicatedMemberInfos(currentSuperClass).contains(member)) return false;
if (myMemberInfoStorage.getExtending(currentSuperClass).contains(member.getMember())) return false;
if (!currentSuperClass.isInterface()) return true;
final boolean isInterface = currentSuperClass.isInterface();
if (!isInterface) return true;
PsiElement element = member.getMember();
if (element instanceof PsiClass && ((PsiClass) element).isInterface()) return true;
@@ -192,13 +193,11 @@ public class PullUpDialog extends PullUpDialogBase<MemberInfoStorage, MemberInfo
return ((PsiModifierListOwner) element).hasModifierProperty(PsiModifier.STATIC);
}
if (element instanceof PsiMethod) {
if (currentSuperClass.isInterface()) {
final PsiSubstitutor superSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(currentSuperClass, myClass, PsiSubstitutor.EMPTY);
final MethodSignature signature = ((PsiMethod) element).getSignature(superSubstitutor);
final PsiMethod superClassMethod = MethodSignatureUtil.findMethodBySignature(currentSuperClass, signature, false);
if (superClassMethod != null) return false;
}
return !((PsiModifierListOwner) element).hasModifierProperty(PsiModifier.STATIC);
final PsiSubstitutor superSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(currentSuperClass, myClass, PsiSubstitutor.EMPTY);
final MethodSignature signature = ((PsiMethod) element).getSignature(superSubstitutor);
final PsiMethod superClassMethod = MethodSignatureUtil.findMethodBySignature(currentSuperClass, signature, false);
if (superClassMethod != null) return false;
return !((PsiModifierListOwner) element).hasModifierProperty(PsiModifier.STATIC) || PsiUtil.isLanguageLevel8OrHigher(currentSuperClass);
}
return true;
}
@@ -218,8 +217,9 @@ public class PullUpDialog extends PullUpDialogBase<MemberInfoStorage, MemberInfo
PsiClass currentSuperClass = getSuperClass();
if(currentSuperClass == null) return false;
if (currentSuperClass.isInterface()) {
if (member.getMember() instanceof PsiMethod) {
return true;
final PsiMember psiMember = member.getMember();
if (psiMember instanceof PsiMethod) {
return !psiMember.hasModifierProperty(PsiModifier.STATIC);
}
}
return false;
@@ -475,7 +475,6 @@ public class TypeMigrationLabeler {
return JavaPsiFacade.getElementFactory(resolved.getProject()).createType((PsiClass)resolved, PsiSubstitutor.EMPTY);
}
}
LOG.error("should not happen: " + resolved.getClass());
return null;
}
@@ -257,6 +257,10 @@ public class TypeMigrationDialog extends RefactoringDialog {
return "type of variable " + ((PsiLocalVariable)element).getName();
}
if (element instanceof PsiReferenceParameterList) {
return "class type arguments ";
}
if (element instanceof PsiParameter) {
final PsiParameter param = (PsiParameter)element;
String result = "type of parameter " + param.getName();
@@ -767,7 +767,7 @@ public class RefactoringUtil {
}
public static void makeMethodDefault(@NotNull PsiMethod method) throws IncorrectOperationException {
PsiUtil.setModifierProperty(method, PsiModifier.DEFAULT, true);
PsiUtil.setModifierProperty(method, PsiModifier.DEFAULT, !method.hasModifierProperty(PsiModifier.STATIC));
PsiUtil.setModifierProperty(method, PsiModifier.ABSTRACT, false);
prepareForInterface(method);
@@ -18,12 +18,13 @@ package com.intellij.spi;
import com.intellij.icons.AllIcons;
import com.intellij.lang.spi.SPILanguage;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.LanguageFileType;
import com.intellij.openapi.fileTypes.*;
import com.intellij.openapi.fileTypes.ex.FileTypeIdentifiableByVirtualFile;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -49,7 +50,7 @@ public class SPIFileType extends LanguageFileType implements FileTypeIdentifiabl
for (Object condition : Extensions.getExtensions("com.intellij.vetoSPICondition")) {
if (((Condition<String>)condition).value(fileName)) return false;
}
return true;
return FileTypeRegistry.getInstance().getFileTypeByFileName(fileName) == FileTypes.UNKNOWN;
}
}
return false;
@@ -583,26 +583,6 @@ public class LambdaUtil {
return null;
}
@NotNull
public static PsiSubstitutor inferFromReturnType(@NotNull PsiTypeParameter[] typeParameters,
final PsiType returnType,
@Nullable final PsiType interfaceMethodReturnType,
@NotNull PsiSubstitutor psiSubstitutor,
final LanguageLevel languageLevel,
final Project project) {
if (returnType == PsiType.VOID || interfaceMethodReturnType == PsiType.VOID) return psiSubstitutor;
final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(project).getResolveHelper();
final PsiSubstitutor substitutor =
resolveHelper.inferTypeArguments(typeParameters, new PsiType[]{interfaceMethodReturnType}, new PsiType[]{returnType}, languageLevel);
for (PsiTypeParameter typeParameter : typeParameters) {
final PsiType inferredType = substitutor.substitute(typeParameter);
if (PsiUtil.resolveClassInType(inferredType) != typeParameter) {
psiSubstitutor = psiSubstitutor.put(typeParameter, inferredType);
}
}
return psiSubstitutor;
}
public static boolean notInferredType(PsiType typeByExpression) {
return typeByExpression instanceof PsiMethodReferenceType || typeByExpression instanceof PsiLambdaExpressionType || typeByExpression instanceof PsiLambdaParameterType;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -61,4 +61,6 @@ public interface PsiImportStatementBase extends PsiElement {
*/
@Nullable
PsiElement resolve();
boolean isForeignFileImport();
}
@@ -48,9 +48,7 @@ public class PsiMethodReferenceUtil {
final QualifierResolveResult qualifierResolveResult = getQualifierResolveResult(expression);
final PsiElement resolve = result.getElement();
if (resolve instanceof PsiMethod) {
PsiSubstitutor subst = PsiSubstitutor.EMPTY;
subst = subst.putAll(qualifierResolveResult.getSubstitutor());
subst = subst.putAll(result.getSubstitutor());
PsiSubstitutor subst = result.getSubstitutor();
final PsiType interfaceReturnType = LambdaUtil.getFunctionalInterfaceReturnType(functionalInterfaceType);
@@ -197,9 +195,7 @@ public class PsiMethodReferenceUtil {
final PsiElement resolve = result.getElement();
if (resolve instanceof PsiMethod) {
final MethodSignature signature1 = method.getSignature(LambdaUtil.getSubstitutor(method, resolveResult));
PsiSubstitutor subst = PsiSubstitutor.EMPTY;
subst = subst.putAll(TypeConversionUtil.getSuperClassSubstitutor(((PsiMethod)resolve).getContainingClass(), qualifierResolveResult.getContainingClass(), qualifierResolveResult.getSubstitutor()));
subst = subst.putAll(result.getSubstitutor());
PsiSubstitutor subst = result.getSubstitutor();
final MethodSignature signature2 = ((PsiMethod)resolve).getSignature(subst);
if (methodReferenceExpression.isExact()) {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -63,4 +63,9 @@ public abstract class PsiImportStatementBaseImpl extends JavaStubPsiElement<PsiI
final PsiJavaCodeReferenceElement reference = getImportReference();
return reference == null ? null : reference.resolve();
}
@Override
public boolean isForeignFileImport() {
return false;
}
}
@@ -130,7 +130,7 @@ public class PsiModifierListImpl extends JavaStubPsiElement<PsiModifierListStub>
return false;
}
if (type == JavaTokenType.ABSTRACT_KEYWORD) {
return getNode().findChildByType(JavaTokenType.DEFAULT_KEYWORD) == null;
return getNode().findChildByType(JavaTokenType.DEFAULT_KEYWORD) == null && getNode().findChildByType(JavaTokenType.STATIC_KEYWORD) == null;
}
}
}
@@ -173,9 +173,9 @@ public class FunctionalInterfaceParameterizationUtil {
if (bound == null) {
parameters[i] = Bi;
} else if (((PsiWildcardType)paramType).isExtends()){
parameters[i] = GenericsUtil.getGreatestLowerBound(Bi, bound);
parameters[i] = GenericsUtil.getGreatestLowerBound(Bi, GenericsUtil.eliminateWildcards(bound, false));
} else {
parameters[i] = bound;
parameters[i] = GenericsUtil.eliminateWildcards(bound, false);
}
}
}
@@ -330,7 +330,7 @@ public class InferenceSession {
}
}
private void registerConstraints(PsiType returnType, PsiType targetType) {
public void registerConstraints(PsiType returnType, PsiType targetType) {
final InferenceVariable inferenceVariable = shouldResolveAndInstantiate(returnType, targetType);
if (inferenceVariable != null) {
resolveBounds(Collections.singletonList(inferenceVariable), mySiteSubstitutor, true);
@@ -574,7 +574,7 @@ public class InferenceSession {
return dependencies != null ? !dependencies.isEmpty() : isProper;
}
protected boolean repeatInferencePhases(boolean incorporate) {
public boolean repeatInferencePhases(boolean incorporate) {
do {
if (!reduceConstraints()) {
//inference error occurred
@@ -17,7 +17,6 @@ package com.intellij.psi.impl.source.tree.java;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.TextRange;
import com.intellij.pom.java.LanguageLevel;
@@ -26,6 +25,8 @@ import com.intellij.psi.impl.PsiManagerEx;
import com.intellij.psi.impl.source.resolve.ParameterTypeInferencePolicy;
import com.intellij.psi.impl.source.resolve.ResolveCache;
import com.intellij.psi.impl.source.resolve.graphInference.FunctionalInterfaceParameterizationUtil;
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
import com.intellij.psi.impl.source.resolve.graphInference.constraints.TypeCompatibilityConstraint;
import com.intellij.psi.impl.source.tree.ChildRole;
import com.intellij.psi.impl.source.tree.FileElement;
import com.intellij.psi.impl.source.tree.JavaElementType;
@@ -328,7 +329,8 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
@NotNull
@Override
public ResolveResult[] resolve(@NotNull PsiJavaReference reference, boolean incompleteCode) {
final PsiMethodReferenceUtil.QualifierResolveResult qualifierResolveResult = PsiMethodReferenceUtil.getQualifierResolveResult(PsiMethodReferenceExpressionImpl.this);
final PsiMethodReferenceUtil.QualifierResolveResult qualifierResolveResult = PsiMethodReferenceUtil.getQualifierResolveResult(
PsiMethodReferenceExpressionImpl.this);
final PsiClass containingClass = qualifierResolveResult.getContainingClass();
PsiSubstitutor substitutor = qualifierResolveResult.getSubstitutor();
@@ -343,7 +345,7 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
PsiType functionalInterfaceType = null;
final Map<PsiMethodReferenceExpression,PsiType> map = PsiMethodReferenceUtil.ourRefs.get();
if (map != null) {
functionalInterfaceType = map.get(PsiMethodReferenceExpressionImpl.this);
functionalInterfaceType = FunctionalInterfaceParameterizationUtil.getGroundTargetType(map.get(PsiMethodReferenceExpressionImpl.this));
}
if (functionalInterfaceType == null) {
functionalInterfaceType = getFunctionalInterfaceType();
@@ -352,26 +354,20 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(resolveResult);
final MethodSignature signature = interfaceMethod != null ? interfaceMethod.getSignature(LambdaUtil.getSubstitutor(interfaceMethod, resolveResult)) : null;
final PsiType interfaceMethodReturnType = LambdaUtil.getFunctionalInterfaceReturnType(functionalInterfaceType);
PsiFile containingFile = getContainingFile();
final LanguageLevel languageLevel = PsiUtil.getLanguageLevel(containingFile);
if (isConstructor && interfaceMethod != null) {
final PsiTypeParameter[] typeParameters = containingClass.getTypeParameters();
final boolean isRawSubst = PsiUtil.isRawSubstitutor(containingClass, substitutor);
Project project = containingClass.getProject();
final PsiClassType returnType = JavaPsiFacade.getElementFactory(project).createType(containingClass,
isRawSubst ? PsiSubstitutor.EMPTY : substitutor);
substitutor = LambdaUtil.inferFromReturnType(typeParameters, returnType, GenericsUtil.eliminateWildcards(interfaceMethodReturnType), substitutor, languageLevel,
project);
if (containingClass.getConstructors().length == 0) {
ClassCandidateInfo candidateInfo = null;
if ((containingClass.getContainingClass() == null || !isLocatedInStaticContext(containingClass)) && signature.getParameterTypes().length == 0 ||
PsiMethodReferenceUtil.onArrayType(containingClass, signature)) {
candidateInfo = new ClassCandidateInfo(containingClass, substitutor);
}
return candidateInfo == null ? JavaResolveResult.EMPTY_ARRAY : new JavaResolveResult[]{candidateInfo};
if (isConstructor && interfaceMethod != null && containingClass.getConstructors().length == 0) {
final PsiClassType returnType = composeReturnType(containingClass, substitutor);
final InferenceSession session = new InferenceSession(containingClass.getTypeParameters(), substitutor, getManager(), null);
if (!(session.isProperType(returnType) && session.isProperType(interfaceMethodReturnType))) {
session.registerConstraints(returnType, interfaceMethodReturnType);
substitutor = session.infer();
}
ClassCandidateInfo candidateInfo = null;
if ((containingClass.getContainingClass() == null || !isLocatedInStaticContext(containingClass)) &&
signature.getParameterTypes().length == 0 ||
PsiMethodReferenceUtil.onArrayType(containingClass, signature)) {
candidateInfo = new ClassCandidateInfo(containingClass, substitutor);
}
return candidateInfo == null ? JavaResolveResult.EMPTY_ARRAY : new JavaResolveResult[]{candidateInfo};
}
final MethodReferenceConflictResolver conflictResolver =
@@ -379,13 +375,13 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
final PsiConflictResolver[] resolvers;
if (signature != null) {
final PsiType[] parameterTypes = signature.getParameterTypes();
resolvers = new PsiConflictResolver[]{conflictResolver, new MethodRefsSpecificResolver(parameterTypes, languageLevel)};
resolvers = new PsiConflictResolver[]{conflictResolver, new MethodRefsSpecificResolver(parameterTypes, PsiUtil.getLanguageLevel(PsiMethodReferenceExpressionImpl.this))};
}
else {
resolvers = new PsiConflictResolver[]{conflictResolver};
}
final MethodCandidatesProcessor processor =
new MethodCandidatesProcessor(PsiMethodReferenceExpressionImpl.this, containingFile, resolvers, new SmartList<CandidateInfo>()) {
new MethodCandidatesProcessor(PsiMethodReferenceExpressionImpl.this, getContainingFile(), resolvers, new SmartList<CandidateInfo>()) {
@Override
protected MethodCandidateInfo createCandidateInfo(final PsiMethod method,
final PsiSubstitutor substitutor,
@@ -399,7 +395,61 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
@NotNull
@Override
public PsiSubstitutor inferTypeArguments(@NotNull ParameterTypeInferencePolicy policy, boolean includeReturnConstraint) {
return inferTypeArgumentsFromInterfaceMethod(signature, interfaceMethodReturnType, method, substitutor, languageLevel, qualifierResolveResult);
if (interfaceMethod == null) return substitutor;
final PsiSubstitutor qualifierResultSubstitutor = qualifierResolveResult.getSubstitutor();
final InferenceSession session = new InferenceSession(method.getTypeParameters(), substitutor, getManager(), PsiMethodReferenceExpressionImpl.this);
final PsiParameter[] functionalMethodParameters = interfaceMethod.getParameterList().getParameters();
final PsiParameter[] parameters = method.getParameterList().getParameters();
if (parameters.length == functionalMethodParameters.length) {//static methods
if (method.isConstructor() && PsiUtil.isRawSubstitutor(containingClass, qualifierResultSubstitutor)) {
session.initBounds(containingClass.getTypeParameters());
}
for (int i = 0; i < functionalMethodParameters.length; i++) {
final PsiType pType = signature.getParameterTypes()[i];
session.addConstraint(new TypeCompatibilityConstraint(parameters[i].getType(), pType));
}
}
else if (parameters.length + 1 == functionalMethodParameters.length) { //instance methods
final PsiClass aClass = qualifierResolveResult.getContainingClass();
session.initBounds(aClass.getTypeParameters());
final PsiType pType = signature.getParameterTypes()[0];
PsiSubstitutor psiSubstitutor = qualifierResultSubstitutor;
// 15.28.1 If the ReferenceType is a raw type, and there exists a parameterization of this type, T, that is a supertype of P1,
// the type to search is the result of capture conversion (5.1.10) applied to T;
// otherwise, the type to search is the same as the type of the first search. Again, the type arguments, if any, are given by the method reference.
if (PsiUtil.isRawSubstitutor(containingClass, qualifierResultSubstitutor)) {
final PsiClassType.ClassResolveResult pResult = PsiUtil.resolveGenericsClassInType(pType);
final PsiClass pClass = pResult.getElement();
final PsiSubstitutor receiverSubstitutor = pClass != null ? TypeConversionUtil.getClassSubstitutor(containingClass, pClass, pResult.getSubstitutor()) : null;
if (receiverSubstitutor != null) {
psiSubstitutor = receiverSubstitutor;
}
}
final PsiType qType = JavaPsiFacade.getElementFactory(getProject()).createType(containingClass, psiSubstitutor);
session.addConstraint(new TypeCompatibilityConstraint(qType, pType));
for (int i = 0; i < parameters.length; i++) {
final PsiType interfaceParamType = signature.getParameterTypes()[i + 1];
session.addConstraint(new TypeCompatibilityConstraint(parameters[i].getType(), interfaceParamType));
}
}
else {
return substitutor;
}
boolean success = session.repeatInferencePhases(false);
final PsiType returnType = method.isConstructor() ? composeReturnType(containingClass, substitutor) : method.getReturnType();
if (returnType != null) {
session.registerConstraints(returnType, interfaceMethodReturnType);
}
return session.infer(parameters, null, null);
}
};
}
@@ -424,75 +474,10 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
return JavaResolveResult.EMPTY_ARRAY;
}
@NotNull
private PsiSubstitutor inferTypeArgumentsFromInterfaceMethod(@Nullable MethodSignature signature,
@Nullable PsiType interfaceMethodReturnType,
PsiMethod method,
PsiSubstitutor substitutor,
LanguageLevel languageLevel,
PsiMethodReferenceUtil.QualifierResolveResult qualifierResolveResult) {
if (signature == null) return PsiSubstitutor.EMPTY;
PsiType[] types = method.getSignature(PsiUtil.isRawSubstitutor(method, substitutor) ? PsiSubstitutor.EMPTY : substitutor).getParameterTypes();
final PsiClass qualifierClass = qualifierResolveResult.getContainingClass();
if (qualifierClass != null) {
substitutor = TypeConversionUtil.getSuperClassSubstitutor(method.getContainingClass(),
qualifierClass,
substitutor).putAll(substitutor);
}
PsiType[] rightTypes = signature.getParameterTypes();
if (!method.isVarArgs() || types.length == 0) {
PsiSubstitutor psiSubstitutor = null;
if (types.length < rightTypes.length) {
psiSubstitutor = getSubstitutor(rightTypes[0]);
} else if (types.length > rightTypes.length) {
psiSubstitutor = getSubstitutor(types[0]);
}
if (psiSubstitutor != null) {
return substitutor.putAll(psiSubstitutor);
}
} else {
if (rightTypes.length != types.length || rightTypes[rightTypes.length - 1].getArrayDimensions() != types[types.length-1].getArrayDimensions()) {
boolean expandTypeArray = types.length < rightTypes.length;
int min = Math.min(types.length, rightTypes.length);
types = Arrays.copyOf(types, min);
if (expandTypeArray) {
types[types.length - 1] = ((PsiArrayType)types[types.length - 1]).getComponentType();
}
rightTypes = Arrays.copyOf(rightTypes, min);
}
}
for (int i = 0; i < rightTypes.length; i++) {
rightTypes[i] = GenericsUtil.eliminateWildcards(rightTypes[i]);
}
final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(getProject()).getResolveHelper();
if (method.isConstructor()) {
return substitutor.putAll(resolveHelper.inferTypeArguments(method.getTypeParameters(), types, rightTypes, languageLevel));
}
return LambdaUtil.inferFromReturnType(method.getTypeParameters(),
method.getReturnType(),
GenericsUtil.eliminateWildcards(interfaceMethodReturnType),
substitutor.putAll(
resolveHelper.inferTypeArguments(method.getTypeParameters(), types, rightTypes, languageLevel)),
languageLevel, getProject());
}
@NotNull
private PsiSubstitutor getSubstitutor(@NotNull PsiType type) {
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(GenericsUtil.eliminateWildcards(type));
PsiSubstitutor psiSubstitutor = resolveResult.getSubstitutor();
if (type instanceof PsiClassType) {
final PsiClass psiClass = resolveResult.getElement();
if (psiClass instanceof PsiTypeParameter) {
for (PsiClass aClass : psiClass.getSupers()) {
psiSubstitutor = psiSubstitutor.putAll(TypeConversionUtil.getSuperClassSubstitutor(aClass, (PsiClassType)type));
}
}
}
return psiSubstitutor;
private PsiClassType composeReturnType(PsiClass containingClass, PsiSubstitutor substitutor) {
final boolean isRawSubst = PsiUtil.isRawSubstitutor(containingClass, substitutor);
return JavaPsiFacade.getElementFactory(containingClass.getProject())
.createType(containingClass, isRawSubst ? PsiSubstitutor.EMPTY : substitutor);
}
private class MethodReferenceConflictResolver implements PsiConflictResolver {
@@ -39,6 +39,6 @@ class MyTest1 {
static void foo(I3 i) {}
static {
foo<error descr="Cannot resolve method 'foo(<method reference>)'">(Foo::new)</error>;
foo<error descr="Ambiguous method call: both 'MyTest1.foo(I1)' and 'MyTest1.foo(I2)' match">(Foo::new)</error>;
}
}
@@ -67,7 +67,7 @@ class MyTest1 {
}
public static void main(String[] args) {
m<error descr="Ambiguous method call: both 'MyTest1.m(I2)' and 'MyTest1.m(I3)' match">(Foo::new)</error>;
m<error descr="Ambiguous method call: both 'MyTest1.m(I1)' and 'MyTest1.m(I2)' match">(Foo::new)</error>;
}
}
class MyTest2 {
@@ -104,6 +104,6 @@ class MyTest2 {
}
public static void main(String[] args) {
m<error descr="Ambiguous method call: both 'MyTest2.m(I2)' and 'MyTest2.m(I3)' match">(Foo::new)</error>;
m<error descr="Ambiguous method call: both 'MyTest2.m(I1)' and 'MyTest2.m(I2)' match">(Foo::new)</error>;
}
}
@@ -29,10 +29,10 @@ class Test {
static void meth4(I3 s) { }
static {
meth1<error descr="'meth1(Test.I1)' in 'Test' cannot be applied to '(<method reference>)'">(Foo::new)</error>;
meth1(<error descr="Inferred type 'java.lang.String' for type parameter 'X' is not within its bound; should extend 'java.lang.Number'">Foo::new</error>);
meth2(Foo::new);
meth3<error descr="'meth3(Test.I3)' in 'Test' cannot be applied to '(<method reference>)'">(Foo::new)</error>;
meth4<error descr="Cannot resolve method 'meth4(<method reference>)'">(Foo::new)</error>;
meth3(<error descr="Inferred type 'java.lang.Object' for type parameter 'X' is not within its bound; should extend 'java.lang.Number'">Foo::new</error>);
meth4<error descr="Ambiguous method call: both 'Test.meth4(I1)' and 'Test.meth4(I2)' match">(Foo::new)</error>;
meth1(<error descr="Inferred type 'java.lang.String' for type parameter 'X' is not within its bound; should extend 'java.lang.Number'">Test::foo</error>);
meth2(Test::foo);
@@ -0,0 +1,9 @@
import java.util.Comparator;
public class Test<T extends Test<T>> {
Comparator<Test<?>> bySize = Comparator.comparingInt(Test::size);
public int size() {
return 0;
}
}
@@ -0,0 +1,9 @@
class Test {
int b;
java.util.List<String> values = new java.util.ArrayList<String>();
int getB() {
<caret> java.util.List<String> values = new java.util.ArrayList<String>();
return b;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -109,8 +109,8 @@ public class LightAdvHighlightingJdk7Test extends LightDaemonAnalyzerTestCase {
ExtensionPoint<EntryPoint> point = Extensions.getRootArea().getExtensionPoint(ToolExtensionPoints.DEAD_CODE_TOOL);
EntryPoint extension = new EntryPoint() {
@NotNull @Override public String getDisplayName() { return "duh"; }
@Override public boolean isEntryPoint(RefElement refElement, PsiElement psiElement) { return false; }
@Override public boolean isEntryPoint(PsiElement psiElement) { return false; }
@Override public boolean isEntryPoint(@NotNull RefElement refElement, @NotNull PsiElement psiElement) { return false; }
@Override public boolean isEntryPoint(@NotNull PsiElement psiElement) { return false; }
@Override public boolean isSelected() { return false; }
@Override public void setSelected(boolean selected) { }
@Override public void readExternal(Element element) { }
@@ -234,12 +234,12 @@ public class LightAdvHighlightingTest extends LightDaemonAnalyzerTestCase {
}
@Override
public boolean isEntryPoint(RefElement refElement, PsiElement psiElement) {
public boolean isEntryPoint(@NotNull RefElement refElement, @NotNull PsiElement psiElement) {
return false;
}
@Override
public boolean isEntryPoint(PsiElement psiElement) {
public boolean isEntryPoint(@NotNull PsiElement psiElement) {
return psiElement instanceof PsiMethod && ((PsiMethod)psiElement).getName().equals("myTestMethod");
}
@@ -149,6 +149,10 @@ public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase {
doTest();
}
public void testIDEA120376() throws Exception {
doTest();
}
private void doTest() {
doTest(false);
}
@@ -0,0 +1,48 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.openapi.editor.impl;
import com.intellij.codeHighlighting.TextEditorHighlightingPass;
import com.intellij.codeInsight.daemon.impl.CodeFoldingPassFactory;
import com.intellij.mock.MockProgressIndicator;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.testFramework.EditorTestUtil;
import com.intellij.testFramework.LightCodeInsightTestCase;
public class FoldingExceptionTest extends LightCodeInsightTestCase {
public void test() {
configureByFile("/codeInsight/folding/FoldingExceptionTest.java");
EditorTestUtil.configureSoftWraps(myEditor, 120);
runFoldingPass();
deleteLine();
runFoldingPass();
// we just verify here that the operation completes normally - it was known to fail previously
}
private static void runFoldingPass() {
PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(getProject());
psiDocumentManager.commitAllDocuments();
PsiFile psiFile = psiDocumentManager.getPsiFile(myEditor.getDocument());
assertNotNull(psiFile);
CodeFoldingPassFactory factory = getProject().getComponent(CodeFoldingPassFactory.class);
TextEditorHighlightingPass highlightingPass = factory.createHighlightingPass(psiFile, myEditor);
highlightingPass.collectInformation(new MockProgressIndicator());
highlightingPass.doApplyInformationToEditor();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -89,7 +89,7 @@ class StubAstSwitchTest extends LightCodeInsightFixtureTestCase {
def oldClass = JavaPsiFacade.getInstance(project).findClass("A", GlobalSearchScope.allScope(project))
def pointer = SmartPointerManager.getInstance(project).createSmartPsiElementPointer(oldClass)
def document = FileDocumentManager.instance.getCachedDocument(file.virtualFile)
def document = FileDocumentManager.instance.getDocument(file.virtualFile)
assert document
assert file == PsiDocumentManager.getInstance(project).getCachedPsiFile(document)
assert document == PsiDocumentManager.getInstance(project).getCachedDocument(file)
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2010 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,7 +30,6 @@ import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.changeSignature.ChangeSignatureDetectorAction;
import com.intellij.refactoring.changeSignature.ChangeSignatureGestureDetector;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import junit.framework.Assert;
import java.util.List;
@@ -62,9 +61,10 @@ public class ChangeSignatureGestureTest extends LightCodeInsightFixtureTestCase
final IntentionAction intention = myFixture.findSingleIntention(hint);
myFixture.launchAction(intention);
myFixture.checkResultByFile("/refactoring/changeSignatureGesture/" + getTestName(false) + "_after.java");
} else {
}
else {
final List<IntentionAction> intentionActions = myFixture.filterAvailableIntentions(hint);
Assert.assertEquals(true, intentionActions.isEmpty());
assertEmpty(intentionActions);
}
}
finally {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,6 +22,5 @@ import com.intellij.psi.PsiImportStatement;
* @author peter
*/
public interface JspxImportStatement extends PsiImportStatement {
boolean isForeignFileImport();
PsiFile getDeclarationFile();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -188,12 +188,12 @@ public abstract class InspectionTestCase extends PsiTestCase {
}
@Override
public boolean isEntryPoint(RefElement refElement, PsiElement psiElement) {
public boolean isEntryPoint(@NotNull RefElement refElement, @NotNull PsiElement psiElement) {
return isEntryPoint(psiElement);
}
@Override
public boolean isEntryPoint(PsiElement psiElement) {
public boolean isEntryPoint(@NotNull PsiElement psiElement) {
return ext_src != null && VfsUtilCore.isAncestor(ext_src, PsiUtilCore.getVirtualFile(psiElement), false);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,8 +28,8 @@ public abstract class EntryPoint implements JDOMExternalizable , Cloneable {
@NotNull
public abstract String getDisplayName();
public abstract boolean isEntryPoint(RefElement refElement, PsiElement psiElement);
public abstract boolean isEntryPoint(PsiElement psiElement);
public abstract boolean isEntryPoint(@NotNull RefElement refElement, @NotNull PsiElement psiElement);
public abstract boolean isEntryPoint(@NotNull PsiElement psiElement);
public abstract boolean isSelected();
public abstract void setSelected(boolean selected);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,8 +20,6 @@ import com.intellij.CommonBundle;
import com.intellij.ide.BrowserUtil;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.extensions.Extensions;
@@ -117,7 +115,7 @@ class ExportToHTMLManager {
}
textPainter.paint(null, psiFile.getFileType());
if (exportToHTMLSettings.OPEN_IN_BROWSER) {
BrowserUtil.launchBrowser(textPainter.getHTMLFileName());
BrowserUtil.browse(textPainter.getHTMLFileName());
}
}
else {
@@ -269,7 +267,7 @@ class ExportToHTMLManager {
dirToShow += File.separatorChar;
}
dirToShow += PsiDirectoryFactory.getInstance(myProject).getQualifiedName(myPsiDirectory, false).replace('.', File.separatorChar);
BrowserUtil.launchBrowser(dirToShow);
BrowserUtil.browse(dirToShow);
}
}
}
@@ -970,10 +970,11 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
}
}
);
BrowserUtil.launchBrowser(urls != null && !urls.isEmpty() ? urls.get(0) : url);
String url1 = urls != null && !urls.isEmpty() ? urls.get(0) : url;
BrowserUtil.browse(url1);
}
else {
BrowserUtil.launchBrowser(url);
BrowserUtil.browse(url);
}
return "";
}
@@ -298,7 +298,7 @@ public class FindUsagesManager implements JDOMExternalizable {
return used.get();
}
private static boolean isInComment(Usage usage) {
private static boolean isInComment(@NotNull Usage usage) {
if (!(usage instanceof UsageInfo2UsageAdapter)) return false;
UsageInfo usageInfo = ((UsageInfo2UsageAdapter)usage).getUsageInfo();
if (!usageInfo.isNonCodeUsage()) return false;
@@ -95,13 +95,13 @@ public class ExternalJavaDocAction extends AnAction {
JBPopupFactory.getInstance().createListPopup(new BaseListPopupStep<String>("Choose external documentation root", ArrayUtil.toStringArray(set)) {
@Override
public PopupStep onChosen(final String selectedValue, final boolean finalChoice) {
BrowserUtil.launchBrowser(selectedValue);
BrowserUtil.browse(selectedValue);
return FINAL_CHOICE;
}
}).showInBestPositionFor(DataManager.getInstance().getDataContext());
}
else if (set.size() == 1) {
BrowserUtil.launchBrowser(urls.get(0));
BrowserUtil.browse(urls.get(0));
}
}
@@ -49,8 +49,8 @@ public class WebReference extends PsiReferenceBase<PsiElement> {
@Override
public void navigate(boolean requestFocus) {
BrowserUtil.launchBrowser(getValue());
}
BrowserUtil.browse(getValue());
}
@Override
public String getPresentableText() {
@@ -1322,20 +1322,21 @@ public class FileBasedIndexImpl extends FileBasedIndex {
if (status.compareAndSet(REQUIRES_REBUILD, REBUILD_IN_PROGRESS)) {
cleanupProcessedFlag();
try {
clearIndex(indexId);
} catch (StorageException ex) {
requestRebuild(indexId, new Throwable(ex));
}
advanceIndexVersion(indexId);
final Runnable rebuildRunnable = new Runnable() {
@Override
public void run() {
try {
doClearIndex(indexId);
if (!cleanupOnly) {
scheduleIndexRebuild(false);
}
}
catch (StorageException e) {
requestRebuild(indexId);
LOG.info(e);
}
finally {
status.compareAndSet(REBUILD_IN_PROGRESS, OK);
}
@@ -1381,9 +1382,17 @@ public class FileBasedIndexImpl extends FileBasedIndex {
}
private void clearIndex(@NotNull final ID<?, ?> indexId) throws StorageException {
advanceIndexVersion(indexId);
doClearIndex(indexId);
}
private void doClearIndex(ID<?, ?> indexId) throws StorageException {
final UpdatableIndex<?, ?, FileContent> index = getIndex(indexId);
assert index != null : "Index with key " + indexId + " not found or not registered properly";
index.clear();
}
private void advanceIndexVersion(ID<?, ?> indexId) {
try {
IndexInfrastructure.rewriteVersion(IndexInfrastructure.getVersionFile(indexId), myIndexIdToVersionMap.get(indexId));
}
@@ -1698,8 +1707,7 @@ public class FileBasedIndexImpl extends FileBasedIndex {
//noinspection ForLoopReplaceableByForEach
for (int i = 0, size = affectedIndexCandidates.size(); i < size; ++i) {
final ID<?, ?> indexId = affectedIndexCandidates.get(i);
if (myRequiringContentIndices.contains(indexId) && shouldIndexFile(file, indexId)) {
if (shouldIndexFile(file, indexId)) {
if (fc == null) {
byte[] currentBytes;
try {
@@ -2066,9 +2074,9 @@ public class FileBasedIndexImpl extends FileBasedIndex {
IndexingStamp.removeAllIndexedState(file);
}
});
// the file is for sure not a dir and it was previously indexed by at least one index
if (!isTooLarge(file)) scheduleForUpdate(file);
}
// the file is for sure not a dir and it was previously indexed by at least one index
if (!isTooLarge(file)) scheduleForUpdate(file);
}
else {
myFilesToUpdate.remove(file);
@@ -2170,7 +2178,7 @@ public class FileBasedIndexImpl extends FileBasedIndex {
}
}
public List<VirtualFile> getAllFilesToUpdate() {
public Collection<VirtualFile> getAllFilesToUpdate() {
if (myFilesToUpdate.isEmpty()) {
return Collections.emptyList();
}
@@ -2200,50 +2208,34 @@ public class FileBasedIndexImpl extends FileBasedIndex {
myUpdateSemaphoreRef.compareAndSet(semaphore, null);
}
private static final int MAX_FILES_TO_PROCESS_OUTSIDE_SCOPE = 5;
private void forceUpdate(@Nullable Project project, @Nullable GlobalSearchScope filter, @Nullable VirtualFile restrictedTo, boolean onlyRemoveOutdatedData) {
myChangedFilesCollector.ensureAllInvalidateTasksCompleted();
ProjectIndexableFilesFilter indexableFilesFilter = projectIndexableFiles(project);
int filesProcessedOutsideScope = 0;
UpdateSemaphore updateSemaphore;
do{
updateSemaphore = obtainForceUpdateSemaphore();
try {
List<VirtualFile> filesToUpdate = getAllFilesToUpdate();
//noinspection ForLoopReplaceableByForEach
for (int i = 0, size = filesToUpdate.size(); i < size; ++i) {
VirtualFile file = filesToUpdate.get(i);
if ((indexableFilesFilter != null && // project files filtering
file instanceof VirtualFileWithId &&
!indexableFilesFilter.containsFileId(((VirtualFileWithId)file).getId())
) ||
filter != null && !filter.accept(file) ||
restrictedTo != null && restrictedTo != file
) {
if (filesProcessedOutsideScope >= MAX_FILES_TO_PROCESS_OUTSIDE_SCOPE) continue;
// In order to have myFilesToUpdate empty for avoiding contention on scanning large concurrent set
// we need eventually to process all files in it including the ones that do not belong to any project or current scope
// e.g. the files that have vfs built but avoided due to project / scope exclusion: workspace.xml / files under .git / user home / etc
++filesProcessedOutsideScope;
for (VirtualFile file : getAllFilesToUpdate()) {
if (indexableFilesFilter != null && file instanceof VirtualFileWithId && !indexableFilesFilter.containsFileId(
((VirtualFileWithId)file).getId())) {
continue;
}
try {
updateSemaphore.down();
// process only files that can affect result
processFileImpl(project, new com.intellij.ide.caches.FileContent(file), onlyRemoveOutdatedData);
if (filter == null || filter.accept(file) || Comparing.equal(file, restrictedTo)) {
try {
updateSemaphore.down();
// process only files that can affect result
processFileImpl(project, new com.intellij.ide.caches.FileContent(file), onlyRemoveOutdatedData);
}
catch (ProcessCanceledException e) {
updateSemaphore.reportUpdateCanceled();
throw e;
}
finally {
updateSemaphore.up();
}
}
catch (ProcessCanceledException e) {
updateSemaphore.reportUpdateCanceled();
throw e;
}
finally {
updateSemaphore.up();
}
}
// If several threads entered the method at the same time and there were files to update,
@@ -2464,11 +2456,17 @@ public class FileBasedIndexImpl extends FileBasedIndex {
if (file != null) {
VirtualFile virtualFile = file.getVirtualFile();
if (virtualFile instanceof VirtualFileWithId) {
boolean wasIndexed = false;
for(ID<?,?> psiBackedIndex:myPsiDependentIndices) {
IndexingStamp.update(virtualFile, psiBackedIndex, IndexInfrastructure.INVALID_STAMP2);
if (isFileIndexed(virtualFile, psiBackedIndex)) {
IndexingStamp.update(virtualFile, psiBackedIndex, IndexInfrastructure.INVALID_STAMP2);
wasIndexed = true;
}
}
if (wasIndexed) {
myChangedFilesCollector.scheduleForUpdate(virtualFile);
IndexingStamp.flushCache(virtualFile);
}
myChangedFilesCollector.scheduleForUpdate(virtualFile);
IndexingStamp.flushCache(virtualFile);
}
}
}
@@ -275,16 +275,26 @@ public class ManagePackagesDialog extends DialogWrapper {
}
private void updateInstalledPackages() {
try {
Collection<InstalledPackage> installedPackages = myController.getInstalledPackages();
myInstalledPackages.clear();
for (InstalledPackage pkg : installedPackages) {
myInstalledPackages.add(pkg.getName());
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
@Override
public void run() {
try {
final Collection<InstalledPackage> installedPackages = myController.getInstalledPackages();
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
myInstalledPackages.clear();
for (InstalledPackage pkg : installedPackages) {
myInstalledPackages.add(pkg.getName());
}
}
});
}
catch(IOException e) {
LOG.info("Error updating list of installed packages:" + e);
}
}
}
catch(IOException e) {
LOG.info("Error updating list of installed packages:" + e);
}
});
}
public void initModel() {
@@ -138,7 +138,7 @@ public class ChangeListStorageImpl implements ChangeListStorage {
@NotNull HyperlinkEvent event) {
if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
if ("url".equals(event.getDescription())) {
BrowserUtil.launchBrowser("http://youtrack.jetbrains.net/issue/IDEA-71270");
BrowserUtil.browse("http://youtrack.jetbrains.net/issue/IDEA-71270");
}
else {
File file = new File(logFile);
@@ -22,7 +22,6 @@ import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.openapi.vfs.encoding.EncodingManager;
import com.intellij.openapi.vfs.encoding.EncodingProjectManager;
import com.intellij.util.EnvironmentUtil;
import com.intellij.util.PlatformUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -73,8 +72,7 @@ public class EncodingEnvironmentUtil {
}
if (commandLine.isPassParentEnvironment()) {
// 'parentEnv' calculation logic should be kept in sync with GeneralCommandLine.setupEnvironment
Map<String, String> parentEnv = PlatformUtils.isAppCode() ? System.getenv() // Temporarily fix for OC-8606
: EnvironmentUtil.getEnvironmentMap();
Map<String, String> parentEnv = commandLine.isPassShellEnvironmentAsParent() ? EnvironmentUtil.getEnvironmentMap() : System.getenv();
if (isLocaleDefined(parentEnv)) {
return true;
}
@@ -58,6 +58,7 @@ public class GeneralCommandLine implements UserDataHolder {
private File myWorkDirectory = null;
private final Map<String, String> myEnvParams = new MyTHashMap();
private boolean myPassParentEnvironment = true;
private boolean myPassShellEnvironmentAsParent = !PlatformUtils.isAppCode();
private final ParametersList myProgramParams = new ParametersList();
private Charset myCharset = CharsetToolkit.getDefaultSystemCharset();
private boolean myRedirectErrorStream = false;
@@ -142,6 +143,19 @@ public class GeneralCommandLine implements UserDataHolder {
return myPassParentEnvironment;
}
/**
* @param passShellEnvironmentAsParent if true, a shell (Terminal.app) environment will be used as parent (see {@link EnvironmentUtil#getEnvironmentMap}).
* Otherwise, {@link System#getenv()} will be used.
*/
public void setPassShellEnvironmentAsParent(boolean passShellEnvironmentAsParent) {
// Temporarily fix for OC-8606
myPassShellEnvironmentAsParent = passShellEnvironmentAsParent;
}
public boolean isPassShellEnvironmentAsParent() {
return myPassShellEnvironmentAsParent;
}
public void addParameters(final String... parameters) {
for (String parameter : parameters) {
addParameter(parameter);
@@ -278,8 +292,7 @@ public class GeneralCommandLine implements UserDataHolder {
environment.clear();
if (myPassParentEnvironment) {
environment.putAll(PlatformUtils.isAppCode() ? System.getenv() // Temporarily fix for OC-8606
: EnvironmentUtil.getEnvironmentMap());
environment.putAll(myPassShellEnvironmentAsParent ? EnvironmentUtil.getEnvironmentMap() : System.getenv());
}
if (!myEnvParams.isEmpty()) {
@@ -33,6 +33,6 @@ public class BrowserHyperlinkInfo implements HyperlinkInfo {
}
public static void openUrl(String url) {
BrowserUtil.launchBrowser(url);
BrowserUtil.browse(url);
}
}
@@ -15,55 +15,29 @@
*/
package com.intellij.ide;
import com.intellij.CommonBundle;
import com.intellij.Patches;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.util.ExecUtil;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Ref;
import com.intellij.ide.browsers.BrowserLauncher;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.*;
import com.intellij.ui.GuiUtils;
import com.intellij.util.io.ZipUtil;
import com.intellij.util.ui.OptionsDialog;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.*;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import static com.intellij.util.containers.ContainerUtil.newSmartList;
import static com.intellij.util.containers.ContainerUtilRt.newArrayList;
public class BrowserUtil {
private static final Logger LOG = Logger.getInstance(BrowserUtil.class);
// The pattern for 'scheme' mainly according to RFC1738.
// We have to violate the RFC since we need to distinguish
// real schemes from local Windows paths; The only difference
@@ -101,147 +75,32 @@ public class BrowserUtil {
browse(url.toExternalForm());
}
@Deprecated
/**
* @deprecated Use {@link #browse(String)}
*/
public static void launchBrowser(@NotNull @NonNls String url) {
browse(url);
}
public static void browse(@NotNull @NonNls String url) {
openOrBrowse(url, true);
BrowserLauncher.getInstance().openOrBrowse(url, true);
}
public static void open(@NotNull @NonNls String url) {
openOrBrowse(url, false);
}
private static void openOrBrowse(@NotNull @NonNls String url, boolean browse) {
url = url.trim();
if (url.startsWith("jar:")) {
String files = extractFiles(url);
if (files == null) {
return;
}
url = files;
}
URI uri;
if (isAbsoluteURL(url)) {
uri = VfsUtil.toUri(url);
}
else {
File file = new File(url);
if (!browse && isDesktopActionSupported(Desktop.Action.OPEN)) {
try {
Desktop.getDesktop().open(file);
return;
}
catch (IOException e) {
LOG.debug(e);
}
}
browse(file);
return;
}
if (uri == null) {
showErrorMessage(IdeBundle.message("error.malformed.url", url), CommonBundle.getErrorTitle());
}
else {
browse(uri);
}
BrowserLauncher.getInstance().openOrBrowse(url, false);
}
/**
* Main method: tries to launch a browser using every possible way
*/
public static void browse(@NotNull URI uri) {
LOG.debug("Launch browser: [" + uri + "]");
GeneralSettings settings = getGeneralSettingsInstance();
if (settings.isUseDefaultBrowser()) {
if (isDesktopActionSupported(Desktop.Action.BROWSE)) {
try {
Desktop.getDesktop().browse(uri);
LOG.debug("Browser launched using JDK 1.6 API");
return;
}
catch (Exception e) {
LOG.warn("Error while using Desktop API, fallback to CLI", e);
}
}
List<String> command = getDefaultBrowserCommand();
if (command != null) {
launchBrowserByCommand(uri, command);
return;
}
}
String browserPath = settings.getBrowserPath();
if (StringUtil.isEmptyOrSpaces(browserPath)) {
String message = IdeBundle.message("error.please.specify.path.to.web.browser", CommonBundle.settingsActionPath());
showErrorMessage(message, IdeBundle.message("title.browser.not.found"));
return;
}
launchBrowserByCommand(uri, getOpenBrowserCommand(browserPath));
}
private static boolean isDesktopActionSupported(Desktop.Action action) {
return !Patches.SUN_BUG_ID_6457572 && !Patches.SUN_BUG_ID_6486393 &&
Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(action);
}
private static GeneralSettings getGeneralSettingsInstance() {
if (ApplicationManager.getApplication() != null) {
GeneralSettings settings = GeneralSettings.getInstance();
if (settings != null) {
return settings;
}
}
return new GeneralSettings();
}
public static boolean canStartDefaultBrowser() {
return isDesktopActionSupported(Desktop.Action.BROWSE) ||
SystemInfo.isMac || SystemInfo.isWindows ||
SystemInfo.isUnix && SystemInfo.hasXdgOpen();
}
@Nullable
@NonNls
private static List<String> getDefaultBrowserCommand() {
if (SystemInfo.isWindows) {
return newArrayList(ExecUtil.getWindowsShellName(), "/c", "start", GeneralCommandLine.inescapableQuote(""));
}
else if (SystemInfo.isMac) {
return newSmartList(ExecUtil.getOpenCommandPath());
}
else if (SystemInfo.isUnix && SystemInfo.hasXdgOpen()) {
return newSmartList("xdg-open");
}
return null;
}
private static void launchBrowserByCommand(@NotNull final URI uri, @NotNull final List<String> command) {
try {
GeneralCommandLine commandLine = new GeneralCommandLine(command);
commandLine.addParameter(uri.toString());
commandLine.createProcess();
if (LOG.isDebugEnabled()) {
LOG.debug("Browser launched with command line: " + commandLine);
}
}
catch (ExecutionException e) {
showErrorMessage(IdeBundle.message("error.cannot.start.browser", e.getMessage()), CommonBundle.getErrorTitle());
}
BrowserLauncher.getInstance().browse(uri);
}
@SuppressWarnings("UnusedDeclaration")
@NotNull
@Deprecated
public static List<String> getOpenBrowserCommand(@NonNls @NotNull String browserPathOrName) {
return getOpenBrowserCommand(browserPathOrName, false);
}
@@ -266,210 +125,10 @@ public class BrowserUtil {
}
}
private static void showErrorMessage(final String message, final String title) {
final Application app = ApplicationManager.getApplication();
if (app == null) {
return; // Not started yet. Not able to show message up. (Could happen in License panel under Linux).
}
Runnable runnable = new Runnable() {
@Override
public void run() {
Messages.showMessageDialog(message, title, Messages.getErrorIcon());
}
};
if (app.isDispatchThread()) {
runnable.run();
}
else {
app.invokeLater(runnable, ModalityState.NON_MODAL);
}
}
@Nullable
private static String extractFiles(String url) {
try {
int sharpPos = url.indexOf('#');
String anchor = "";
if (sharpPos != -1) {
anchor = url.substring(sharpPos);
url = url.substring(0, sharpPos);
}
VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(url);
if (file == null || !(file.getFileSystem() instanceof JarFileSystem)) return null;
JarFileSystem jarFileSystem = (JarFileSystem)file.getFileSystem();
VirtualFile jarVirtualFile = jarFileSystem.getVirtualFileForJar(file);
if (jarVirtualFile == null) return null;
String targetFilePath = file.getPath();
String targetFileRelativePath = StringUtil.substringAfter(targetFilePath, JarFileSystem.JAR_SEPARATOR);
LOG.assertTrue(targetFileRelativePath != null);
String jarVirtualFileLocationHash = jarVirtualFile.getName() + Integer.toHexString(jarVirtualFile.getUrl().hashCode());
final File outputDir = new File(getExtractedFilesDir(), jarVirtualFileLocationHash);
final String currentTimestamp = String.valueOf(new File(jarVirtualFile.getPath()).lastModified());
final File timestampFile = new File(outputDir, ".idea.timestamp");
String previousTimestamp = null;
if (timestampFile.exists()) {
previousTimestamp = FileUtil.loadFile(timestampFile);
}
if (!currentTimestamp.equals(previousTimestamp)) {
final Ref<Boolean> extract = new Ref<Boolean>();
Runnable r = new Runnable() {
@Override
public void run() {
final ConfirmExtractDialog dialog = new ConfirmExtractDialog();
if (dialog.isToBeShown()) {
dialog.show();
extract.set(dialog.isOK());
}
else {
dialog.close(DialogWrapper.OK_EXIT_CODE);
extract.set(true);
}
}
};
try {
GuiUtils.runOrInvokeAndWait(r);
}
catch (InvocationTargetException ignored) {
extract.set(false);
}
catch (InterruptedException ignored) {
extract.set(false);
}
if (!extract.get()) return null;
@SuppressWarnings("ConstantConditions")
final ZipFile zipFile = jarFileSystem.getJarFile(file).getZipFile();
if (zipFile == null) return null;
ZipEntry entry = zipFile.getEntry(targetFileRelativePath);
if (entry == null) return null;
InputStream is = zipFile.getInputStream(entry);
try {
ZipUtil.extractEntry(entry, is, outputDir);
}
finally {
is.close();
}
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
new Task.Backgroundable(null, "Extracting files...", true) {
@Override
public void run(@NotNull final ProgressIndicator indicator) {
final int size = zipFile.size();
final int[] counter = new int[]{0};
class MyFilter implements FilenameFilter {
private final Set<File> myImportantDirs = new HashSet<File>(
Arrays.asList(outputDir, new File(outputDir, "resources")));
private final boolean myImportantOnly;
private MyFilter(boolean importantOnly) {
myImportantOnly = importantOnly;
}
@Override
public boolean accept(@NotNull File dir, @NotNull String name) {
indicator.checkCanceled();
boolean result = myImportantOnly == myImportantDirs.contains(dir);
if (result) {
indicator.setFraction(((double)counter[0]) / size);
counter[0]++;
}
return result;
}
}
try {
ZipUtil.extract(zipFile, outputDir, new MyFilter(true));
ZipUtil.extract(zipFile, outputDir, new MyFilter(false));
FileUtil.writeToFile(timestampFile, currentTimestamp.getBytes());
}
catch (IOException ignore) {
}
}
}.queue();
}
});
}
return VfsUtilCore.pathToUrl(FileUtil.toSystemIndependentName(new File(outputDir, targetFileRelativePath).getPath())) + anchor;
}
catch (IOException e) {
LOG.warn(e);
Messages.showErrorDialog("Cannot extract files: " + e.getMessage(), "Error");
return null;
}
}
public static void clearExtractedFiles() {
FileUtil.delete(getExtractedFilesDir());
}
private static File getExtractedFilesDir() {
return new File(PathManager.getSystemPath(), "ExtractedFiles");
}
public static boolean isOpenCommandSupportArgs() {
return SystemInfo.isMacOSSnowLeopard;
}
private static class ConfirmExtractDialog extends OptionsDialog {
private ConfirmExtractDialog() {
super(null);
setTitle("Confirmation");
init();
}
@Override
protected boolean isToBeShown() {
return getGeneralSettingsInstance().isConfirmExtractFiles();
}
@Override
protected void setToBeShown(boolean value, boolean onOk) {
getGeneralSettingsInstance().setConfirmExtractFiles(value);
}
@Override
protected boolean shouldSaveOptionsOnCancel() {
return true;
}
@Override
@NotNull
protected Action[] createActions() {
setOKButtonText(CommonBundle.getYesButtonText());
return new Action[]{getOKAction(), getCancelAction()};
}
@Override
protected JComponent createCenterPanel() {
JPanel panel = new JPanel(new BorderLayout());
String message = "The files are inside an archive, do you want them to be extracted?";
JLabel label = new JLabel(message);
label.setIconTextGap(10);
label.setIcon(Messages.getQuestionIcon());
panel.add(label, BorderLayout.CENTER);
panel.add(Box.createVerticalStrut(10), BorderLayout.SOUTH);
return panel;
}
}
@NotNull
public static String getDefaultAlternativeBrowserPath() {
if (SystemInfo.isWindows) {
@@ -0,0 +1,84 @@
package com.intellij.ide.browsers;
import com.intellij.icons.AllIcons;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.browsers.chrome.ChromeSettings;
import com.intellij.ide.browsers.firefox.FirefoxSettings;
import com.intellij.openapi.util.Iconable;
import com.intellij.openapi.util.SystemInfo;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
public enum BrowserFamily implements Iconable {
CHROME(IdeBundle.message("browsers.chrome"), "chrome", "google-chrome", "Google Chrome", AllIcons.Xml.Browsers.Chrome16) {
@Override
public BrowserSpecificSettings createBrowserSpecificSettings() {
return new ChromeSettings();
}
},
EXPLORER(IdeBundle.message("browsers.explorer"), "iexplore", null, null, AllIcons.Xml.Browsers.Explorer16),
FIREFOX(IdeBundle.message("browsers.firefox"), "firefox", "firefox", "Firefox", AllIcons.Xml.Browsers.Firefox16) {
@Override
public BrowserSpecificSettings createBrowserSpecificSettings() {
return new FirefoxSettings();
}
},
OPERA(IdeBundle.message("browsers.opera"), "opera", "opera", "Opera", AllIcons.Xml.Browsers.Opera16),
SAFARI(IdeBundle.message("browsers.safari"), "safari", null, "Safari", AllIcons.Xml.Browsers.Safari16);
private final String myName;
private final String myWindowsPath;
private final String myUnixPath;
private final String myMacPath;
private final Icon myIcon;
BrowserFamily(@NotNull String name,
@NotNull final String windowsPath,
@Nullable final String unixPath,
@Nullable final String macPath,
@NotNull Icon icon) {
myName = name;
myWindowsPath = windowsPath;
myUnixPath = unixPath;
myMacPath = macPath;
myIcon = icon;
}
@Nullable
public BrowserSpecificSettings createBrowserSpecificSettings() {
return null;
}
@Nullable
public String getExecutionPath() {
if (SystemInfo.isWindows) {
return myWindowsPath;
}
else if (SystemInfo.isMac) {
return myMacPath;
}
else {
return myUnixPath;
}
}
public String getName() {
return myName;
}
public Icon getIcon() {
return myIcon;
}
@Override
public String toString() {
return myName;
}
@Override
public Icon getIcon(@IconFlags int flags) {
return getIcon();
}
}
@@ -0,0 +1,47 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.ide.browsers;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.net.URI;
public abstract class BrowserLauncher {
public static BrowserLauncher getInstance() {
return ServiceManager.getService(BrowserLauncher.class);
}
public abstract void browse(@NotNull URI uri);
public abstract void openOrBrowse(@NotNull String url, boolean browse);
public abstract void browse(@NotNull String url, @Nullable WebBrowser browser);
public abstract void browse(@NotNull String url, @Nullable WebBrowser browser, @Nullable Project project);
public abstract boolean browse(@Nullable String url,
@NotNull WebBrowser browser,
@Nullable Project project,
@NotNull String... additionalParameters);
public abstract boolean browse(@Nullable String url,
@Nullable String browserPath,
@Nullable WebBrowser browser,
@Nullable Project project);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,35 +15,29 @@
*/
package com.intellij.ide.browsers;
import com.intellij.ide.BrowserUtil;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@SuppressWarnings("deprecation")
public abstract class UrlOpener {
public static final ExtensionPointName<UrlOpener> EP_NAME = ExtensionPointName.create("org.jetbrains.urlOpener");
public static void launchBrowser(final @Nullable BrowsersConfiguration.BrowserFamily family, final @NotNull String url) {
launchBrowser(url, family == null ? null : WebBrowserManager.getInstance().findBrowser(family));
}
@Deprecated
/**
* @deprecated Use {@link com.intellij.ide.browsers.BrowserLauncher#browse(String, WebBrowser)}
*/
public static void launchBrowser(@NotNull String url, @Nullable WebBrowser browser) {
launchBrowser(url, browser, null);
BrowserLauncher.getInstance().browse(url, browser);
}
// different params order in order not to break compilation for launchBrowser(null, url)
@Deprecated
/**
* @deprecated Use {@link com.intellij.ide.browsers.BrowserLauncher#browse(String, WebBrowser, com.intellij.openapi.project.Project)}
*/
public static void launchBrowser(@NotNull String url, @Nullable WebBrowser browser, @Nullable Project project) {
if (browser == null) {
BrowserUtil.launchBrowser(url);
}
else {
for (UrlOpener urlOpener : EP_NAME.getExtensions()) {
if (urlOpener.openUrl(browser, url, null)) {
return;
}
}
}
BrowserLauncher.getInstance().browse(url, browser, project);
}
public abstract boolean openUrl(@NotNull WebBrowser browser, @NotNull String url, @Nullable Project project);
@@ -0,0 +1,30 @@
package com.intellij.ide.browsers;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.UUID;
public abstract class WebBrowser {
@NotNull
public abstract String getName();
@NotNull
public abstract UUID getId();
@NotNull
public abstract BrowserFamily getFamily();
@NotNull
public abstract Icon getIcon();
@Nullable
public abstract String getPath();
@NotNull
public abstract String getBrowserNotFoundMessage();
@Nullable
public abstract BrowserSpecificSettings getSpecificSettings();
}
@@ -29,19 +29,19 @@
<properties/>
<border type="none"/>
<children>
<component id="852e3" class="javax.swing.JLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="messages/XmlBundle" key="label.text.path.to.profiles.ini"/>
</properties>
</component>
<hspacer id="d637d">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</hspacer>
<component id="852e3" class="javax.swing.JLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="messages/IdeBundle" key="label.text.path.to.profiles.ini"/>
</properties>
</component>
</children>
</grid>
<component id="a31a5" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myProfilesIniPathField">
@@ -66,7 +66,7 @@
</constraints>
<properties>
<labelFor value="c6e14"/>
<text resource-bundle="messages/XmlBundle" key="label.text.profile"/>
<text resource-bundle="messages/IdeBundle" key="label.text.profile"/>
</properties>
</component>
<hspacer id="d3289">
@@ -15,6 +15,7 @@
*/
package com.intellij.ide.browsers.firefox;
import com.intellij.ide.IdeBundle;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileChooser.PathChooserDialog;
import com.intellij.openapi.options.Configurable;
@@ -25,7 +26,6 @@ import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.DocumentAdapter;
import com.intellij.xml.XmlBundle;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.Nullable;
@@ -50,7 +50,7 @@ public class FirefoxSettingsConfigurable implements Configurable {
public FirefoxSettingsConfigurable(FirefoxSettings settings) {
mySettings = settings;
myProfilesIniPathField.addBrowseFolderListener(XmlBundle.message("chooser.title.select.profiles.ini.file"), null, null, PROFILES_INI_CHOOSER_DESCRIPTOR);
myProfilesIniPathField.addBrowseFolderListener(IdeBundle.message("chooser.title.select.profiles.ini.file"), null, null, PROFILES_INI_CHOOSER_DESCRIPTOR);
myProfilesIniPathField.getTextField().getDocument().addDocumentListener(new DocumentAdapter() {
@Override
protected void textChanged(DocumentEvent e) {
@@ -144,7 +144,7 @@ public class FirefoxSettingsConfigurable implements Configurable {
@Override
@Nls
public String getDisplayName() {
return XmlBundle.message("display.name.firefox.settings");
return IdeBundle.message("display.name.firefox.settings");
}
@Override
@@ -147,7 +147,7 @@ public class HyperlinkLabel extends HighlightableComponent {
myHyperlinkListener = new HyperlinkListener() {
@Override
public void hyperlinkUpdate(HyperlinkEvent e) {
BrowserUtil.launchBrowser(url);
BrowserUtil.browse(url);
}
};
addHyperlinkListener(myHyperlinkListener);
@@ -933,7 +933,7 @@ public class SimpleColoredComponent extends JComponent implements Accessible, Co
@Override
public void run() {
BrowserUtil.launchBrowser(myUrl);
BrowserUtil.browse(myUrl);
}
}
@@ -94,7 +94,7 @@ public class JetBrainsAccountDialog extends DialogWrapper {
new ClickListener() {
@Override
public boolean onClick(@NotNull MouseEvent e, int clickCount) {
BrowserUtil.launchBrowser("http://account.jetbrains.com");
BrowserUtil.browse("http://account.jetbrains.com");
return true;
}
}.installOn(myCreateAccountLabel);
@@ -64,7 +64,7 @@ public class HelpManagerImpl extends HelpManager {
}
if (myHelpSet == null) {
BrowserUtil.launchBrowser(ApplicationInfoEx.getInstanceEx().getWebHelpUrl() + "?" + id);
BrowserUtil.browse(ApplicationInfoEx.getInstanceEx().getWebHelpUrl() + "?" + id);
return;
}
@@ -45,7 +45,7 @@ class IdeaHelpContentViewUI extends BasicContentViewerUI{
protected void linkActivated(URL u){
String url=u.toExternalForm();
if(url.startsWith("http") || url.startsWith("ftp")){
BrowserUtil.launchBrowser(url);
BrowserUtil.browse(url);
} else{
super.linkActivated(u);
}
@@ -219,7 +219,7 @@ public class AboutDialog extends JDialog {
public void mousePressed(MouseEvent event) {
if (myActiveLink != null) {
event.consume();
BrowserUtil.launchBrowser(myActiveLink.url);
BrowserUtil.browse(myActiveLink.url);
}
}
});
@@ -26,7 +26,7 @@ import com.intellij.openapi.project.DumbAware;
*/
public class OnlineDocAction extends AnAction implements DumbAware {
public void actionPerformed(AnActionEvent e) {
BrowserUtil.launchBrowser(ApplicationInfoImpl.getShadowInstance().getDocumentationUrl());
BrowserUtil.browse(ApplicationInfoImpl.getShadowInstance().getDocumentationUrl());
}
public void update(final AnActionEvent e) {
@@ -44,7 +44,7 @@ public class RefCardAction extends AnAction implements DumbAware {
final ApplicationInfoEx appInfo = ApplicationInfoEx.getInstanceEx();
String webUrl = SystemInfo.isMac ? appInfo.getMacKeymapUrl() : appInfo.getWinKeymapUrl();
if (webUrl != null) {
BrowserUtil.launchBrowser(webUrl);
BrowserUtil.browse(webUrl);
}
}
}
@@ -35,7 +35,7 @@ public class SearchWebAction extends AnAction implements DumbAware {
provider.performCopy(dataContext);
String string = CopyPasteManager.getInstance().getContents(DataFlavor.stringFlavor);
if (StringUtil.isNotEmpty(string)) {
BrowserUtil.launchBrowser("http://www.google.com/search?q="+ URLEncoder.encode(string));
BrowserUtil.browse("http://www.google.com/search?q=" + URLEncoder.encode(string));
}
}
@@ -46,7 +46,7 @@ public class SendFeedbackAction extends AnAction implements DumbAware {
.replace("$TIMEZONE", System.getProperty("user.timezone"))
.replace("$EVAL", isEvaluationLicense() ? "true" : "false")
.replace("$DESCR", getDescription());
BrowserUtil.launchBrowser(urlTemplate);
BrowserUtil.browse(urlTemplate);
}
private static String getDescription() {
@@ -30,7 +30,7 @@ import com.intellij.openapi.project.DumbAware;
public class TechnicalSupportAction extends AnAction implements DumbAware {
public void actionPerformed(AnActionEvent e) {
BrowserUtil.launchBrowser(ApplicationInfoImpl.getShadowInstance().getSupportUrl());
BrowserUtil.browse(ApplicationInfoImpl.getShadowInstance().getSupportUrl());
}
@Override
@@ -28,7 +28,7 @@ import com.intellij.openapi.project.DumbAware;
*/
public class WhatsNewAction extends AnAction implements DumbAware {
public void actionPerformed(AnActionEvent e) {
BrowserUtil.launchBrowser(ApplicationInfoEx.getInstanceEx().getWhatsNewUrl());
BrowserUtil.browse(ApplicationInfoEx.getInstanceEx().getWhatsNewUrl());
}
@Override
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2010 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,10 +30,19 @@ import java.awt.*;
public class ArrowPainter {
private final ColorProvider myColorHolder;
private final Computable<Integer> myWidthProvider;
private final Computable<Integer> myHeightProvider;
public ArrowPainter(@NotNull ColorProvider colorHolder, @NotNull Computable<Integer> heightProvider) {
/**
* Creates an ArrowPainter with specified parameters.
*
* @param colorHolder defines arrow color
* @param widthProvider defines character width, it is used to calculate an inset for the arrow's tip
* @param heightProvider defines character height, it's used to calculate an arrow's width and height
*/
public ArrowPainter(@NotNull ColorProvider colorHolder, @NotNull Computable<Integer> widthProvider, @NotNull Computable<Integer> heightProvider) {
myColorHolder = colorHolder;
myWidthProvider = widthProvider;
myHeightProvider = heightProvider;
}
@@ -46,7 +55,7 @@ public class ArrowPainter {
* @param stop ending <code>'x'</code> position to use during drawing
*/
public void paint(Graphics g, int y, int start, int stop) {
stop -= g.getFontMetrics().charWidth(' ') / 2;
stop -= myWidthProvider.compute() / 2;
Color oldColor = g.getColor();
g.setColor(myColorHolder.getColor());
final int height = myHeightProvider.compute();
@@ -729,6 +729,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
private void initTabPainter() {
myTabPainter = new ArrowPainter(
ColorProvider.byColorsScheme(myScheme, EditorColors.WHITESPACES_COLOR),
new Computable.PredefinedValueComputable(EditorUtil.getSpaceWidth(Font.PLAIN, this)),
new Computable<Integer>() {
@Override
public Integer compute() {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -70,7 +70,6 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi
private final FoldProcessingEndTask myFoldProcessingEndTask = new FoldProcessingEndTask();
private final List<DocumentListener> myDocumentListeners = new ArrayList<DocumentListener>();
private final List<SoftWrapFoldingListener> myFoldListeners = new ArrayList<SoftWrapFoldingListener>();
private final List<SoftWrapChangeListener> mySoftWrapListeners = new ArrayList<SoftWrapChangeListener>();
/**
@@ -160,7 +159,6 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi
myVisualSizeManager = new SoftWrapAwareVisualSizeManager(painter);
myDocumentListeners.add(myApplianceManager);
myFoldListeners.add(myApplianceManager);
applianceManager.addListener(myVisualSizeManager);
applianceManager.addListener(new SoftWrapAwareDocumentParsingListenerAdapter() {
@Override
@@ -624,7 +622,9 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi
myDirty = true;
return;
}
// We delay processing of changed fold regions till the invocation of onFoldProcessingEnd(), as
// FoldingModel can return inconsistent data before that moment.
myDeferredFoldRegions.add(new FoldRegionInfo(region));
}
@@ -689,7 +689,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi
try {
task.run(true);
} catch (Throwable e) {
if (Boolean.getBoolean(DEBUG_PROPERTY_NAME)) {
if (Boolean.getBoolean(DEBUG_PROPERTY_NAME) || ApplicationManager.getApplication().isUnitTestMode()) {
String info = "";
if (myEditor instanceof EditorImpl) {
info = ((EditorImpl)myEditor).dumpState();
@@ -813,28 +813,26 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi
}
try {
for (FoldRegionInfo info : myDeferredFoldRegions) {
// There is a possible case that given fold region is contained inside another collapsed fold region. We don't want to process
// such nested region then.
FoldRegion outerRegion = myEditor.getFoldingModel().getCollapsedRegionAtOffset(info.start);
if (outerRegion != null && outerRegion != info.region && outerRegion.getStartOffset() <= info.start
&& outerRegion.getEndOffset() >= info.end)
{
continue;
}
for (SoftWrapFoldingListener listener : myFoldListeners) {
listener.onFoldRegionStateChange(info.start, info.end);
if (!myDirty) { // no need to recalculate specific areas if the whole document will be reprocessed
for (FoldRegionInfo info : myDeferredFoldRegions) {
// There is a possible case that given fold region is contained inside another collapsed fold region. We don't want to process
// such nested region then.
FoldRegion outerRegion = myEditor.getFoldingModel().getCollapsedRegionAtOffset(info.start);
if (outerRegion != null && outerRegion != info.region && outerRegion.getStartOffset() <= info.start
&& outerRegion.getEndOffset() >= info.end)
{
continue;
}
myApplianceManager.onFoldRegionStateChange(info.start, info.end);
}
}
}
finally {
myDeferredFoldRegions.clear();
}
for (SoftWrapFoldingListener listener : myFoldListeners) {
listener.onFoldProcessingEnd();
}
myApplianceManager.onFoldProcessingEnd();
}
@Override
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2010 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -43,7 +43,7 @@ public class ArrowSoftWrapPainter implements SoftWrapPainter {
public ArrowSoftWrapPainter(Editor editor) {
myEditor = editor;
myArrowPainter = new ArrowPainter(ColorProvider.byColor(myEditor.getColorsScheme().getDefaultForeground()), myHeightProvider);
myArrowPainter = new ArrowPainter(ColorProvider.byColor(myEditor.getColorsScheme().getDefaultForeground()), new WidthProvider(), myHeightProvider);
}
@Override
@@ -102,4 +102,11 @@ public class ArrowSoftWrapPainter implements SoftWrapPainter {
return myHeight;
}
}
private class WidthProvider implements Computable<Integer> {
@Override
public Integer compute() {
return EditorUtil.getSpaceWidth(Font.PLAIN, myEditor);
}
}
}
@@ -1,51 +0,0 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.openapi.editor.impl.softwrap;
import com.intellij.openapi.editor.FoldRegion;
import com.intellij.openapi.editor.ex.FoldingListener;
/**
* Adapts {@link FoldingListener} to soft wraps specific.
* <p/>
* Generally, replaces {@link FoldingListener#onFoldRegionStateChange(FoldRegion)} by {@link #onFoldRegionStateChange(int, int)}.
* The reason is that soft wraps are assumed to be processed after fold regions, i.e. every time the document is changed, folding
* is processed at first place (notifying soft wraps via {@link FoldingListener}) and soft wraps are assumed to be processed
* only on {@link #onFoldProcessingEnd()}. Hence, there is a possible case that changed {@link FoldRegion} object
* is out-of-date (e.g. its offsets info is dropped if the region is removed), so, we can't use
* {@link FoldingListener#onFoldRegionStateChange(FoldRegion)}.
*
* @author Denis Zhdanov
* @since 5/4/11 3:48 PM
*/
public interface SoftWrapFoldingListener {
/**
* Informs that <code>'collapsed'</code> state of fold region that is/was located at the target range is just changed.
* <p/>
* <b>Note:</b> listener should delay fold region state processing until {@link #onFoldProcessingEnd()} is called.
* I.e. folding model may return inconsistent data between current moment and {@link #onFoldProcessingEnd()}.
*
* @param startOffset start offset of the target fold region (inclusive)
* @param endOffset end offset of the target fold region (exclusive)
*/
void onFoldRegionStateChange(int startOffset, int endOffset);
/**
* Informs that fold processing is done.
*/
void onFoldProcessingEnd();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -56,7 +56,7 @@ import java.util.List;
* @author Denis Zhdanov
* @since Jul 5, 2010 10:01:27 AM
*/
public class SoftWrapApplianceManager implements SoftWrapFoldingListener, DocumentListener, Dumpable {
public class SoftWrapApplianceManager implements DocumentListener, Dumpable {
private static final Logger LOG = Logger.getInstance("#" + SoftWrapApplianceManager.class.getName());
@@ -986,7 +986,6 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume
}
}
@Override
public void onFoldRegionStateChange(int startOffset, int endOffset) {
assert ApplicationManagerEx.getApplicationEx().isDispatchThread();
@@ -1002,7 +1001,6 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume
myEventsStorage.add(document, new IncrementalCacheUpdateEvent(document, recalculationStartOffset, recalculationEndOffset));
}
@Override
public void onFoldProcessingEnd() {
//CachingSoftWrapDataMapper.log("xxxxxxxxxxx On fold region processing end");
recalculateSoftWraps();
@@ -77,7 +77,7 @@ class NewChannelDialog extends AbstractUpdateDialog {
public void actionPerformed(ActionEvent e) {
LicensingFacade facade = LicensingFacade.getInstance();
assert facade != null;
BrowserUtil.launchBrowser(facade.getUpgradeUrl());
BrowserUtil.browse(facade.getUpgradeUrl());
doCancelAction();
}
});
@@ -108,7 +108,7 @@ class NewChannelDialog extends AbstractUpdateDialog {
@Override
protected void doOKAction() {
BrowserUtil.launchBrowser(myChannel.getHomePageUrl());
BrowserUtil.browse(myChannel.getHomePageUrl());
super.doOKAction();
}
@@ -123,7 +123,7 @@ class UpdateInfoDialog extends AbstractUpdateDialog {
}
private void openDownloadPage() {
BrowserUtil.launchBrowser(myUpdatedChannel.getHomePageUrl());
BrowserUtil.browse(myUpdatedChannel.getHomePageUrl());
}
private static class ButtonAction extends AbstractAction {
@@ -136,7 +136,7 @@ class UpdateInfoDialog extends AbstractUpdateDialog {
@Override
public void actionPerformed(ActionEvent e) {
BrowserUtil.launchBrowser(myUrl);
BrowserUtil.browse(myUrl);
}
}
@@ -42,6 +42,6 @@ public class JetBrainsTvAction extends AnAction implements DumbAware {
@Override
public void actionPerformed(AnActionEvent e) {
BrowserUtil.launchBrowser(myUrl);
BrowserUtil.browse(myUrl);
}
}
@@ -38,7 +38,7 @@ public class UrlPsiReference extends PsiReferenceBase<PsiElement> {
@Override
public void navigate(boolean requestFocus) {
BrowserUtil.launchBrowser(getValue());
BrowserUtil.browse(getValue());
}
};
}
@@ -1650,8 +1650,14 @@ public class AbstractPopup implements JBPopup {
if (size == null) {
myMinSize = myHeaderPanel.getPreferredSize();
} else {
myMinSize.setSize(Math.min(size.width, myHeaderPanel.getPreferredSize().width),
Math.min(size.height, myHeaderPanel.getPreferredSize().height));
final int width = Math.min(size.width, myHeaderPanel.getPreferredSize().width);
final int height = Math.min(size.height, myHeaderPanel.getPreferredSize().height);
if (myMinSize == null) {
myMinSize = new Dimension(width, height);
}
else {
myMinSize.setSize(width, height);
}
}
if (myWindow != null) {
@@ -132,7 +132,6 @@ public final class Urls {
Matcher matcher = URI_PATTERN.matcher(urlToParse);
if (!matcher.matches()) {
LOG.warn("Cannot parse url " + url);
return null;
}
String scheme = matcher.group(1);
@@ -1,10 +1,21 @@
title.cannot.start.browser=Cannot start browser
error.malformed.url=Malformed url: {0}
error.cannot.start.browser=Cannot start browser: {0}
error.please.specify.path.to.web.browser=Please specify a path to web browser in {0} | Web Browsers
error.0.browser.path.not.specified={0} browser path is not specified in {1} | Web Browsers
title.browser.not.found=Browser Not Found
title.browser.path.not.found=Browser Path Not Found
browser.error=Browser Error
error.0.browser.path.not.specified={0} browser path is not specified.
chooser.title.select.profiles.ini.file=Select \"profiles.ini\" File
label.text.path.to.profiles.ini=Path to \"profiles.ini\":
label.text.profile=&Profile:
button.text.settings=Settings...
display.name.firefox.settings=Firefox Settings
browsers.explorer=Internet Explorer
browsers.safari=Safari
browsers.opera=Opera
browsers.firefox=Firefox
browsers.chrome=Chrome
action.sort.alphabetically=Sort Alphabetically
button.finish=&Finish
button.ok=&OK
@@ -1006,7 +1017,7 @@ error.file.download.failed=Failed to download ''{0}'': {1}
maven.repository.presentable.name=Maven repository
label.missed.libraries.prefix=The following libraries are missing:
label.missed.libraries.text=''{0}'' library not found in the module dependencies list
missing.libraries.fix.button=Fix...
button.fix=Fix\u2026
setup.library.dialog.title=Setup Library
label.library.will.be.created.description.text={0} level library <b>{1}</b> with {2} {2, choice, 1#file|2#files} will be created
new.library.file.chooser.title=New Library Files
@@ -145,16 +145,6 @@ xml.folding.settings=Code Folding Settings
cannot.resolve.anchor=Cannot resolve anchor #{0}
cannot.resolve.anchor.in.file=Cannot resolve anchor #{0} in file {1}
# web browsers
browsers.configuration.name=Web Browsers
browsers.explorer=Internet Explorer
browsers.safari=Safari
browsers.opera=Opera
browsers.firefox=Firefox
browsers.chrome=Chrome
browser.description=Open file in {0}
browser.error=Browser Error
web.editor.configuration.title=Web
browser.select.in.default.name=Web Browser
@@ -224,12 +214,6 @@ cant.rename.file=Can't rename {0} to {1}
cant.delete.file=Can't delete file {0}
select.xsd.schema.dialog.title=Select XSD Schema
chooser.title.select.profiles.ini.file=Select \"profiles.ini\" File
label.text.path.to.profiles.ini=Path to \"profiles.ini\":
label.text.profile=&Profile:
button.text.settings=Settings...
display.name.firefox.settings=Firefox Settings
emmet.title=Emmet
emmet.configuration.title=Emmet (Zen Coding)
emmet.enable.label=&Enable XML Emmet
@@ -361,3 +361,4 @@ ide.open.file.in.temp.project.dir=true
ide.open.file.in.temp.project.dir.description=Enables opening file in temp project directory
editor.allow.multiple.carets=false
embed.scene.builder=false
@@ -213,5 +213,7 @@
<with attribute="schemeClass" implements="com.intellij.openapi.options.Scheme"/>
<with attribute="implementationClass" implements="com.intellij.openapi.options.SchemeImporter"/>
</extensionPoint>
<extensionPoint qualifiedName="org.jetbrains.urlOpener" interface="com.intellij.ide.browsers.UrlOpener"/>
</extensionPoints>
</idea-plugin>
@@ -70,7 +70,6 @@
<extensionPoint name="xml.html5SchemaProvider" interface="com.intellij.xml.Html5SchemaProvider"/>
<extensionPoint name="xml.implicitIdRefProvider" interface="com.intellij.psi.impl.source.resolve.reference.impl.providers.ImplicitIdRefProvider"/>
<extensionPoint qualifiedName="org.jetbrains.urlOpener" interface="com.intellij.ide.browsers.UrlOpener"/>
<extensionPoint qualifiedName="org.jetbrains.javaScriptDebuggerStarter" interface="com.intellij.ide.browsers.JavaScriptDebuggerStarter"/>
<extensionPoint qualifiedName="org.jetbrains.openInBrowserAction" interface="com.intellij.ide.browsers.actions.OpenInBrowserActionProducer"/>
@@ -194,9 +193,6 @@
serviceImplementation="com.intellij.application.options.XmlSettings"/>
<exportable serviceInterface="com.intellij.application.options.XmlSettings"/>
<applicationService serviceInterface="com.intellij.ide.browsers.BrowsersConfiguration"
serviceImplementation="com.intellij.ide.browsers.BrowsersConfiguration"/>
<applicationService serviceInterface="com.intellij.ide.browsers.WebBrowserManager"
serviceImplementation="com.intellij.ide.browsers.WebBrowserManager"/>
@@ -365,6 +361,8 @@
<applicationService serviceInterface="com.intellij.ide.browsers.WebBrowserService"
serviceImplementation="com.intellij.ide.browsers.impl.WebBrowserServiceImpl"/>
<applicationService serviceInterface="com.intellij.ide.browsers.BrowserLauncher" serviceImplementation="com.intellij.ide.browsers.BrowserLauncherImpl"/>
<patterns.patternClass className="com.intellij.patterns.XmlPatterns" alias="xml"/>
<lang.smartEnterProcessor language="XML" implementationClass="com.intellij.codeInsight.completion.XmlSmartEnterProcessor"/>
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,10 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.util.containers;
import junit.framework.TestCase;
import org.junit.Test;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
@@ -24,20 +23,17 @@ import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
public class WeakListTest extends TestCase {
private final WeakList<Object> myWeakList = new WeakList<Object>();
protected final List<Object> myHolder = new ArrayList<Object>();
private void addElement(Object element) {
myWeakList.add(element);
myHolder.add(element);
}
import static org.junit.Assert.*;
public class WeakListTest {
private static final String HARD_REFERENCED = "xxx";
private final WeakList<Object> myWeakList = new WeakList<Object>();
private final List<Object> myHolder = new ArrayList<Object>();
@Test
public void testCompresses() {
for (int i = 0; i < 20; i++) {
addElement(new Object());
}
fillWithObjects(20);
assertEquals(20, myWeakList.listSize());
addElement(HARD_REFERENCED);
assertEquals(21, myWeakList.listSize());
@@ -55,37 +51,26 @@ public class WeakListTest extends TestCase {
assertEquals(1, myWeakList.listSize());
}
private static void gc() {
ConcurrentMapsTest.tryGcSoftlyReachableObjects();
WeakReference<Object> weakReference = new WeakReference<Object>(new Object());
do {
System.gc();
}
while (weakReference.get() != null);
}
@Test
public void testClear() {
for (int i = 0; i < 20; i++) {
addElement(new Object());
}
fillWithObjects(20);
assertEquals(20, myWeakList.listSize());
myHolder.clear();
gc();
myWeakList.clear();
assertFalse(myWeakList.iterator().hasNext());
}
@Test
public void testIterator() {
int N = 10;
for (int i=0; i< N;i++) {
addElement(i);
}
fillWithInts(N);
gc();
Iterator<Integer> iterator = (Iterator)myWeakList.iterator();
for (int i=0; i< N;i++) {
Iterator<?> iterator = myWeakList.iterator();
for (int i = 0; i < N; i++) {
assertTrue(iterator.hasNext());
assertTrue(iterator.hasNext());
int element = iterator.next();
int element = (Integer)iterator.next();
assertEquals(i, element);
}
assertFalse(iterator.hasNext());
@@ -97,7 +82,8 @@ public class WeakListTest extends TestCase {
}
assertEquals(N, elementCount);
}
@Test
public void testRemoveViaIterator() {
addElement(new Object());
addElement(new Object());
@@ -115,14 +101,13 @@ public class WeakListTest extends TestCase {
myHolder.remove(1);
}
@Test
public void testRemoveAllViaIterator() {
int N = 10;
for (int i=0; i< N;i++) {
addElement(i);
}
fillWithInts(N);
gc();
Iterator<Object> iterator = myWeakList.iterator();
for (int i=0; i< N;i++) {
for (int i = 0; i < N; i++) {
assertTrue(iterator.hasNext());
int element = (Integer)iterator.next();
assertEquals(i, element);
@@ -132,6 +117,7 @@ public class WeakListTest extends TestCase {
assertTrue(myWeakList.toStrongList().isEmpty());
}
@Test
public void testRemoveLastViaIterator() {
addElement(new Object());
addElement(new Object());
@@ -143,6 +129,7 @@ public class WeakListTest extends TestCase {
iterator.remove();
}
@Test
public void testIteratorKeepsFirstElement() {
addElement(new Object());
addElement(new Object());
@@ -153,7 +140,8 @@ public class WeakListTest extends TestCase {
assertNotNull(iterator.next());
assertFalse(iterator.hasNext());
}
@Test
public void testIteratorKeepsNextElement() {
addElement(new Object());
addElement(new Object());
@@ -167,6 +155,7 @@ public class WeakListTest extends TestCase {
assertFalse(iterator.hasNext());
}
@Test
public void testIteratorRemoveEmpty() {
Iterator<Object> iterator = myWeakList.iterator();
assertFalse(iterator.hasNext());
@@ -184,16 +173,13 @@ public class WeakListTest extends TestCase {
}
}
public void testElementGetsGcedInTheMiddleAndListRebuildsItself() {
@Test
public void testElementGetsCollectedInTheMiddleAndListRebuildsItself() {
int N = 200;
for (int i = 0; i < N; i++) {
addElement(new Object());
}
fillWithObjects(N);
String x = new String("xxx");
addElement(x);
for (int i = 0; i < N; i++) {
addElement(new Object());
}
fillWithObjects(N);
gc();
assertEquals(N + 1 + N, myWeakList.listSize());
myHolder.clear();
@@ -209,6 +195,7 @@ public class WeakListTest extends TestCase {
assertSame(x, element);
}
@Test
public void testIsEmpty() {
assertTrue(myWeakList.isEmpty());
addElement(new Object());
@@ -218,4 +205,30 @@ public class WeakListTest extends TestCase {
assertEquals(1, myWeakList.listSize());
assertTrue(myWeakList.isEmpty());
}
private void addElement(Object element) {
myWeakList.add(element);
myHolder.add(element);
}
private void fillWithObjects(int n) {
for (int i = n - 1; i >= 0; i--) {
addElement(new Object());
}
}
private void fillWithInts(int n) {
for (int i = 0; i < n; i++) {
addElement(i);
}
}
private static void gc() {
ConcurrentMapsTest.tryGcSoftlyReachableObjects();
WeakReference<Object> weakReference = new WeakReference<Object>(new Object());
do {
System.gc();
}
while (weakReference.get() != null);
}
}

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