mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -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);
|
||||
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -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"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -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
-1
@@ -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.
|
||||
+193
-228
@@ -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() &&
|
||||
+8
-2
@@ -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;
|
||||
|
||||
+8
-1
@@ -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()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+8
-6
@@ -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
|
||||
|
||||
+54
@@ -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);
|
||||
}
|
||||
}
|
||||
+41
-16
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -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;
|
||||
|
||||
+205
-6
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+3
-5
@@ -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
|
||||
|
||||
+2
-32
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
+79
-94
@@ -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 {
|
||||
|
||||
+1
-1
@@ -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>;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -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>;
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -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);
|
||||
|
||||
+9
@@ -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;
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -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) { }
|
||||
|
||||
+2
-2
@@ -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");
|
||||
}
|
||||
|
||||
|
||||
+4
@@ -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
-2
@@ -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
-1
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -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);
|
||||
|
||||
+1
-3
@@ -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;
|
||||
}
|
||||
|
||||
+15
-2
@@ -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);
|
||||
}
|
||||
+12
-18
@@ -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();
|
||||
}
|
||||
+9
-9
@@ -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">
|
||||
+3
-3
@@ -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() {
|
||||
|
||||
+19
-21
@@ -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
|
||||
|
||||
+9
-2
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-51
@@ -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();
|
||||
}
|
||||
+2
-4
@@ -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();
|
||||
|
||||
+2
-2
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -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
Reference in New Issue
Block a user