Merge remote-tracking branch 'origin/master'

This commit is contained in:
Dmitry Batkovich
2016-06-30 10:44:04 +03:00
155 changed files with 3585 additions and 3639 deletions
+2 -2
View File
@@ -1,8 +1,7 @@
<component name="libraryTable">
<library name="Mocks">
<CLASSES>
<root url="jar://$PROJECT_DIR$/lib/dev/easymock.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/dev/easymockclassextension.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/dev/easymock-3.4.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/dev/jmock-2.5.1.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/dev/jmock-junit4-2.5.1.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/dev/jmock-legacy-2.5.1.jar!/" />
@@ -10,6 +9,7 @@
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$PROJECT_DIR$/lib/dev/easymock-3.4-sources.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/dev/jmock-2.5.1.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/dev/jmock-junit4-2.5.1.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/dev/jmock-legacy-2.5.1.jar!/" />
+2 -2
View File
@@ -1,11 +1,11 @@
<component name="libraryTable">
<library name="pty4j">
<CLASSES>
<root url="jar://$PROJECT_DIR$/lib/pty4j-0.7.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/pty4j-0.7.1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$PROJECT_DIR$/lib/src/pty4j-0.7-src.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/src/pty4j-0.7.1-src.jar!/" />
</SOURCES>
</library>
</component>
+1 -1
View File
@@ -279,7 +279,7 @@ libraryLicense(name: "Plexus Utils", libraryName: "plexus-utils-1.5.5.jar", vers
libraryLicense(name: "pockets", attachedTo: "python-helpers", version: "0.2.4", license: "BSD", url: "http://pockets.readthedocs.org/")
libraryLicense(name: "protobuf", version: "2.5.0", license: "New BSD", url: "http://code.google.com/p/protobuf/", licenseUrl: "https://github.com/google/protobuf/blob/master/LICENSE")
libraryLicense(name: "proxy-vole", libraryName: "proxy-vole", version: "20131209", license: "New BSD License", url: "http://code.google.com/p/proxy-vole/", licenseUrl: "http://opensource.org/licenses/BSD-3-Clause")
libraryLicense(name: "pty4j", libraryName: "pty4j", version: "0.7", license: "Eclipse Public License v1.0", url: "https://github.com/traff/pty4j")
libraryLicense(name: "pty4j", libraryName: "pty4j", version: "0.7.1", license: "Eclipse Public License v1.0", url: "https://github.com/traff/pty4j")
libraryLicense(name: "PureJavaComm", libraryName: "purejavacomm", version: "0.0.16", license: "BSD", url: "http://www.sparetimelabs.com/purejavacomm")
libraryLicense(name: "ReflectASM", libraryName: "reflectasm-1.0.7.jar", version: "1.0.7", license: "BSD", url: "https://github.com/EsotericSoftware/reflectasm", licenseUrl: "http://opensource.org/licenses/BSD-3-Clause")
libraryLicense(name: "Relax NG Object Model", libraryName: "rngom-20051226-patched.jar", license: "MIT", url: "http://java.net/projects/rngom/", licenseUrl: "http://www.opensource.org/licenses/mit-license.php")
@@ -56,9 +56,15 @@ public class SdkSettingsStep extends ModuleWizardStep {
private final JPanel myJdkPanel;
public SdkSettingsStep(SettingsStep settingsStep, @NotNull ModuleBuilder moduleBuilder,
@NotNull Condition<SdkTypeId> sdkFilter) {
@NotNull Condition<SdkTypeId> sdkTypeIdFilter) {
this(settingsStep.getContext(), moduleBuilder, sdkFilter);
this(settingsStep, moduleBuilder, sdkTypeIdFilter, null);
}
public SdkSettingsStep(SettingsStep settingsStep, @NotNull ModuleBuilder moduleBuilder,
@NotNull Condition<SdkTypeId> sdkTypeIdFilter, @Nullable Condition<Sdk> sdkFilter) {
this(settingsStep.getContext(), moduleBuilder, sdkTypeIdFilter, sdkFilter);
if (!isEmpty()) {
settingsStep.addSettingsField(getSdkFieldLabel(settingsStep.getContext().getProject()), myJdkPanel);
}
@@ -66,7 +72,8 @@ public class SdkSettingsStep extends ModuleWizardStep {
public SdkSettingsStep(WizardContext context,
@NotNull ModuleBuilder moduleBuilder,
@NotNull Condition<SdkTypeId> sdkFilter) {
@NotNull Condition<SdkTypeId> sdkTypeIdFilter,
@Nullable Condition<Sdk> sdkFilter) {
myModuleBuilder = moduleBuilder;
myWizardContext = context;
@@ -74,7 +81,11 @@ public class SdkSettingsStep extends ModuleWizardStep {
Project project = myWizardContext.getProject();
myModel.reset(project);
myJdkComboBox = new JdkComboBox(myModel, sdkFilter, sdkFilter, false);
if (sdkFilter == null) {
sdkFilter = JdkComboBox.getSdkFilter(sdkTypeIdFilter);
}
myJdkComboBox = new JdkComboBox(myModel, sdkFilter, sdkTypeIdFilter, false);
myJdkPanel = new JPanel(new GridBagLayout());
final PropertiesComponent component = project == null ? PropertiesComponent.getInstance() : PropertiesComponent.getInstance(project);
@@ -91,7 +102,7 @@ public class SdkSettingsStep extends ModuleWizardStep {
}
});
Sdk sdk = getPreselectedSdk(project, component.getValue(selectedJdkProperty), sdkFilter);
Sdk sdk = getPreselectedSdk(project, component.getValue(selectedJdkProperty), sdkTypeIdFilter);
myJdkComboBox.setSelectedJdk(sdk);
JButton button = new JButton("Ne\u001Bw...");
@@ -103,7 +114,7 @@ public class SdkSettingsStep extends ModuleWizardStep {
myJdkPanel.add(myJdkComboBox, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0, CENTER, HORIZONTAL, JBUI.emptyInsets(), 0, 0));
myJdkPanel.add(myJdkComboBox.getSetUpButton(), new GridBagConstraints(1, 0, 1, 1, 0, 0, WEST, NONE, JBUI.insetsLeft(4), 0, 0));
if (myJdkComboBox.getItemCount() == 0) {
SdkType type = ContainerUtil.find(SdkType.getAllTypes(), sdkFilter);
SdkType type = ContainerUtil.find(SdkType.getAllTypes(), sdkTypeIdFilter);
if (type != null && type.getDownloadSdkUrl() != null) {
HyperlinkLabel label = new HyperlinkLabel("Download " + type.getPresentableName());
label.setHyperlinkTarget(type.getDownloadSdkUrl());
@@ -55,7 +55,7 @@ public class JdkComboBox extends ComboBoxWithWidePopup {
private static final Icon EMPTY_ICON = EmptyIcon.create(1, 16);
@Nullable
private final Condition<SdkTypeId> myFilter;
private final Condition<Sdk> myFilter;
@Nullable
private final Condition<SdkTypeId> myCreationFilter;
private JButton mySetUpButton;
@@ -66,11 +66,11 @@ public class JdkComboBox extends ComboBoxWithWidePopup {
public JdkComboBox(@NotNull final ProjectSdksModel jdkModel,
@Nullable Condition<SdkTypeId> filter) {
this(jdkModel, filter, filter, false);
this(jdkModel, getSdkFilter(filter), filter, false);
}
public JdkComboBox(@NotNull final ProjectSdksModel jdkModel,
@Nullable Condition<SdkTypeId> filter,
@Nullable Condition<Sdk> filter,
@Nullable Condition<SdkTypeId> creationFilter,
boolean addSuggestedItems) {
super(new JdkComboBoxModel(jdkModel, filter, addSuggestedItems));
@@ -280,7 +280,7 @@ public class JdkComboBox extends ComboBoxWithWidePopup {
final ProjectSdksModel projectJdksModel = ProjectStructureConfigurable.getInstance(project).getProjectJdksModel();
List<Sdk> projectJdks = new ArrayList<Sdk>(projectJdksModel.getProjectSdks().values());
if (myFilter != null) {
projectJdks = ContainerUtil.filter(projectJdks, getSdkFilter(myFilter));
projectJdks = ContainerUtil.filter(projectJdks, myFilter);
}
Collections.sort(projectJdks, (o1, o2) -> o1.getName().compareToIgnoreCase(o2.getName()));
for (Sdk projectJdk : projectJdks) {
@@ -289,11 +289,11 @@ public class JdkComboBox extends ComboBoxWithWidePopup {
}
private static class JdkComboBoxModel extends DefaultComboBoxModel {
public JdkComboBoxModel(final ProjectSdksModel jdksModel, @Nullable Condition<SdkTypeId> sdkFilter, boolean addSuggested) {
public JdkComboBoxModel(final ProjectSdksModel jdksModel, @Nullable Condition<Sdk> sdkFilter, boolean addSuggested) {
Sdk[] jdks = jdksModel.getSdks();
Arrays.sort(jdks, (s1, s2) -> s1.getName().compareToIgnoreCase(s2.getName()));
for (Sdk jdk : jdks) {
if (sdkFilter == null || sdkFilter.value(jdk.getSdkType())) {
if (sdkFilter == null || sdkFilter.value(jdk)) {
addElement(new JdkComboBoxItem(jdk));
}
}
@@ -302,10 +302,10 @@ public class JdkComboBox extends ComboBoxWithWidePopup {
}
}
protected void addSuggestedItems(@Nullable Condition<SdkTypeId> sdkFilter, Sdk[] jdks) {
protected void addSuggestedItems(@Nullable Condition<Sdk> sdkFilter, Sdk[] jdks) {
SdkType[] types = SdkType.getAllTypes();
for (SdkType type : types) {
if (sdkFilter == null || sdkFilter.value(type) && ContainerUtil.find(jdks, sdk -> sdk.getSdkType() == type) == null) {
if (sdkFilter == null || ContainerUtil.find(jdks, sdkFilter) == null) {
String homePath = type.suggestHomePath();
if (homePath != null && type.isValidSdkHome(homePath)) {
addElement(new SuggestedJdkItem(type, homePath));
@@ -321,7 +321,7 @@ public class JdkComboBox extends ComboBoxWithWidePopup {
}
}
private static Condition<Sdk> getSdkFilter(@Nullable final Condition<SdkTypeId> filter) {
public static Condition<Sdk> getSdkFilter(@Nullable final Condition<SdkTypeId> filter) {
return filter == null ? Conditions.<Sdk>alwaysTrue() : (Condition<Sdk>)sdk -> filter.value(sdk.getSdkType());
}
@@ -406,12 +406,6 @@ class PostHighlightingVisitor {
@NotNull PsiIdentifier identifier,
@NotNull ProgressIndicator progress) {
if (!myRefCountHolder.isReferenced(parameter) && !UnusedSymbolUtil.isImplicitUsage(myProject, parameter, progress)) {
//parameter is defined by functional interface
final PsiElement declarationScope = parameter.getDeclarationScope();
if (declarationScope instanceof PsiMethod &&
myRefCountHolder.isReferencedByMethodReference((PsiMethod)declarationScope, myLanguageLevel)) {
return null;
}
String message = JavaErrorMessages.message("parameter.is.not.used", identifier.getText());
return UnusedSymbolUtil.createUnusedSymbolInfo(identifier, message, myDeadCodeInfoType);
}
@@ -222,26 +222,6 @@ class RefCountHolder {
return usedStatus == Boolean.TRUE;
}
boolean isReferencedByMethodReference(@NotNull PsiMethod method, @NotNull LanguageLevel languageLevel) {
if (!languageLevel.isAtLeast(LanguageLevel.JDK_1_8)) return false;
Collection<PsiReference> array;
synchronized (myLocalRefsMap) {
array = myLocalRefsMap.get(method);
}
if (!array.isEmpty()) {
for (PsiReference reference : array) {
final PsiElement element = reference.getElement();
if (element instanceof PsiMethodReferenceExpression) {
return true;
}
}
}
return false;
}
private static boolean isParameterUsedRecursively(@NotNull PsiElement element, @NotNull Collection<PsiReference> array) {
if (!(element instanceof PsiParameter)) return false;
PsiParameter parameter = (PsiParameter)element;
@@ -18,6 +18,7 @@ package com.intellij.psi.stubsHierarchy.impl;
import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree;
import com.intellij.util.BitUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.HashSet;
@@ -69,7 +70,7 @@ public class StubResolver {
private void findType(Symbol startScope, int name, Set<Symbol> symbols) throws IncompleteHierarchyException {
// looking up
for (Symbol s = startScope; s != null; s = s.myOwner)
findMemberType(s, name, symbols, new HashSet<Symbol>());
findMemberType(s, name, symbols);
// type from current package
findIdentInPackage(startScope.pkg(), name, IndexTree.CLASS, symbols);
}
@@ -79,7 +80,7 @@ public class StubResolver {
if (receiver.isPackage())
findIdentInPackage((Symbol.PackageSymbol)receiver, name, kind, symbols);
else
findMemberType(receiver, name, symbols, new HashSet<Symbol>());
findMemberType(receiver, name, symbols);
}
private void findIdentInPackage(Symbol.PackageSymbol pck, int name, int kind, Set<Symbol> symbols) {
@@ -97,19 +98,34 @@ public class StubResolver {
}
}
private void findMemberType(Symbol s, int name, Set<Symbol> symbols, Set<Symbol> processed) throws IncompleteHierarchyException {
if (!processed.add(s)) {
return;
private void findMemberType(Symbol s, int name, Set<Symbol> symbols) throws IncompleteHierarchyException {
if (s.isClass()) {
processInheritedMembers((Symbol.ClassSymbol)s, name, false, symbols, null);
} else {
processMembers(s.getMembers(), name, symbols, false);
}
processMembers(s.getMembers(), name, symbols, false);
if (s.isClass())
findInheritedMemberType((Symbol.ClassSymbol)s, name, symbols, processed);
}
private void findInheritedMemberType(Symbol.ClassSymbol c, int name, Set<Symbol> symbols, Set<Symbol> processed)
throws IncompleteHierarchyException {
for (Symbol.ClassSymbol st : c.getSuperClasses(myConnector))
findMemberType(st, name, symbols, processed);
private void processInheritedMembers(Symbol.ClassSymbol s,
int name,
boolean requireStatic,
Set<Symbol> symbols,
@Nullable Set<Symbol> processed) throws IncompleteHierarchyException {
processMembers(s.getMembers(), name, symbols, requireStatic);
@CompactArray(Symbol.ClassSymbol.class) Object supers = s.getSuperClasses(myConnector);
if (supers == null) return;
if (processed == null) processed = new HashSet<>();
if (!processed.add(s)) return;
if (supers instanceof Symbol.ClassSymbol) {
processInheritedMembers((Symbol.ClassSymbol)supers, name, requireStatic, symbols, processed);
} else if (supers instanceof Symbol.ClassSymbol[]) {
for (Symbol.ClassSymbol st : (Symbol.ClassSymbol[])supers) {
processInheritedMembers(st, name, requireStatic, symbols, processed);
}
}
}
private Symbol.ClassSymbol[] loadClass(@NotNull QualifiedName fqn) {
@@ -171,16 +187,7 @@ public class StubResolver {
// handling of import static `tsym.name` as
private void importNamedStatic(final Symbol.ClassSymbol tsym, final int name, final Set<Symbol> symbols) throws IncompleteHierarchyException {
new Object() {
Set<Symbol> processed = new HashSet<Symbol>();
void importFrom(Symbol.ClassSymbol cs) throws IncompleteHierarchyException {
if (cs == null || !processed.add(cs))
return;
for (Symbol.ClassSymbol c : cs.getSuperClasses(myConnector))
importFrom(c);
processMembers(cs.getMembers(), name, symbols, true);
}
}.importFrom(tsym);
processInheritedMembers(tsym, name, true, symbols, null);
}
private static void processMembers(Symbol.ClassSymbol[] members, int name, Set<Symbol> symbols, boolean requireStatic) {
@@ -19,6 +19,7 @@ import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree;
import com.intellij.util.BitUtil;
import gnu.trove.TIntHashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.Comparator;
@@ -125,13 +126,14 @@ public abstract class Symbol {
return BitUtil.isSet(myFlags, CONNECT_STARTED);
}
@NotNull
ClassSymbol[] getSuperClasses(StubHierarchyConnector connector) throws IncompleteHierarchyException {
@Nullable
@CompactArray(ClassSymbol.class)
Object getSuperClasses(StubHierarchyConnector connector) throws IncompleteHierarchyException {
connect(connector);
if (isHierarchyIncomplete()) {
throw IncompleteHierarchyException.INSTANCE;
}
return rawSuperClasses();
return mySuperClasses;
}
@NotNull
@@ -20,6 +20,7 @@ import com.intellij.codeInsight.TargetElementUtil;
import com.intellij.codeInsight.highlighting.HighlightManager;
import com.intellij.codeInsight.intention.QuickFixFactory;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
@@ -27,6 +28,7 @@ import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.wm.WindowManager;
@@ -77,38 +79,43 @@ public class InlineLocalHandler extends JavaInlineActionHandler {
final String localName = local.getName();
final Query<PsiReference> query = ReferencesSearch.search(local, local.getUseScope());
if (query.findFirst() == null){
LOG.assertTrue(refExpr == null);
String message = RefactoringBundle.message("variable.is.never.used", localName);
CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.INLINE_VARIABLE);
return;
}
final PsiClass containingClass = PsiTreeUtil.getParentOfType(local, PsiClass.class);
final List<PsiElement> innerClassesWithUsages = Collections.synchronizedList(new ArrayList<PsiElement>());
final List<PsiElement> innerClassUsages = Collections.synchronizedList(new ArrayList<PsiElement>());
query.forEach(psiReference -> {
final PsiElement element = psiReference.getElement();
PsiElement innerClass = PsiTreeUtil.getParentOfType(element, PsiClass.class, PsiLambdaExpression.class);
while (innerClass != containingClass && innerClass != null) {
final PsiClass parentPsiClass = PsiTreeUtil.getParentOfType(innerClass, PsiClass.class, true);
if (parentPsiClass == containingClass) {
if (innerClass instanceof PsiLambdaExpression) {
if (PsiTreeUtil.isAncestor(innerClass, local, false)) {
innerClassesWithUsages.add(element);
innerClass = parentPsiClass;
continue;
}
}
innerClassesWithUsages.add(innerClass);
innerClassUsages.add(element);
}
innerClass = parentPsiClass;
final PsiClass containingClass = PsiTreeUtil.getParentOfType(local, PsiClass.class);
final Query<PsiReference> query = ReferencesSearch.search(local, local.getUseScope());
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(() -> {
if (query.findFirst() == null){
LOG.assertTrue(refExpr == null);
ApplicationManager.getApplication().invokeLater(() -> {
String message = RefactoringBundle.message("variable.is.never.used", localName);
CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.INLINE_VARIABLE);
}, ModalityState.NON_MODAL);
return;
}
return true;
});
query.forEach(psiReference -> {
final PsiElement element = psiReference.getElement();
PsiElement innerClass = PsiTreeUtil.getParentOfType(element, PsiClass.class, PsiLambdaExpression.class);
while (innerClass != containingClass && innerClass != null) {
final PsiClass parentPsiClass = PsiTreeUtil.getParentOfType(innerClass, PsiClass.class, true);
if (parentPsiClass == containingClass) {
if (innerClass instanceof PsiLambdaExpression) {
if (PsiTreeUtil.isAncestor(innerClass, local, false)) {
innerClassesWithUsages.add(element);
innerClass = parentPsiClass;
continue;
}
}
innerClassesWithUsages.add(innerClass);
innerClassUsages.add(element);
}
innerClass = parentPsiClass;
}
return true;
});
}, "Find Usages", true, project)) {
return;
}
final PsiCodeBlock containerBlock = PsiTreeUtil.getParentOfType(local, PsiCodeBlock.class);
if (containerBlock == null) {
final String message = RefactoringBundle.getCannotRefactorMessage("Variable is declared outside a code block");
@@ -116,9 +123,7 @@ public class InlineLocalHandler extends JavaInlineActionHandler {
return;
}
final PsiExpression defToInline = innerClassesWithUsages.isEmpty()
? getDefToInline(local, refExpr, containerBlock)
: getDefToInline(local, innerClassesWithUsages.get(0), containerBlock);
final PsiExpression defToInline = getDefToInline(local, innerClassesWithUsages.isEmpty() ? refExpr : innerClassesWithUsages.get(0), containerBlock);
if (defToInline == null){
final String key = refExpr == null ? "variable.has.no.initializer" : "variable.has.no.dominating.definition";
String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message(key, localName));
@@ -150,7 +155,7 @@ public class InlineLocalHandler extends JavaInlineActionHandler {
}
if (refExpr != null && inlineLocalDialog.isInlineThis()) {
refsToInlineList = Collections.<PsiElement>singletonList(refExpr);
refsToInlineList = Collections.singletonList(refExpr);
inlineAll.set(false);
}
}
@@ -183,11 +183,7 @@ public class PsiElementFactoryImpl extends PsiJavaParserFacadeImpl implements Ps
if (type instanceof PsiClassReferenceType) {
return ((PsiClassReferenceType)type).getReference();
}
final PsiClassType.ClassResolveResult resolveResult = type.resolveGenerics();
final PsiClass refClass = resolveResult.getElement();
assert refClass != null : type;
return new LightClassReference(myManager, type.getCanonicalText(true), refClass, resolveResult.getSubstitutor());
return new LightClassTypeReference(myManager, type);
}
@NotNull
@@ -15,27 +15,21 @@
*/
package com.intellij.psi.impl.light;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class LightClassReference extends LightElement implements PsiJavaCodeReferenceElement {
private final String myText;
public class LightClassReference extends LightClassReferenceBase implements PsiJavaCodeReferenceElement {
private final String myClassName;
private final PsiElement myContext;
@NotNull private final GlobalSearchScope myResolveScope;
private final PsiClass myRefClass;
private final PsiSubstitutor mySubstitutor;
private LightReferenceParameterList myParameterList;
private LightClassReference(@NotNull PsiManager manager,
@NotNull @NonNls String text,
@Nullable @NonNls String className,
@@ -43,8 +37,7 @@ public class LightClassReference extends LightElement implements PsiJavaCodeRefe
@NotNull GlobalSearchScope resolveScope,
@Nullable PsiElement context,
@Nullable PsiClass refClass) {
super(manager, JavaLanguage.INSTANCE);
myText = text;
super(manager, text);
myClassName = className;
myResolveScope = resolveScope;
@@ -107,32 +100,6 @@ public class LightClassReference extends LightElement implements PsiJavaCodeRefe
return new CandidateInfo(resolved, substitutor);
}
@Override
@NotNull
public JavaResolveResult[] multiResolve(boolean incompleteCode){
final JavaResolveResult result = advancedResolve(incompleteCode);
if(result != JavaResolveResult.EMPTY) return new JavaResolveResult[]{result};
return JavaResolveResult.EMPTY_ARRAY;
}
@Override
public void processVariants(@NotNull PsiScopeProcessor processor){
throw new RuntimeException("Variants are not available for light references");
}
@Override
public PsiElement getReferenceNameElement() {
return null;
}
@Override
public PsiReferenceParameterList getParameterList() {
if (myParameterList == null) {
myParameterList = new LightReferenceParameterList(myManager, PsiTypeElement.EMPTY_ARRAY);
}
return myParameterList;
}
@Override
public String getQualifiedName() {
if (myClassName != null) {
@@ -162,36 +129,6 @@ public class LightClassReference extends LightElement implements PsiJavaCodeRefe
}
}
@Override
public String getText() {
return myText;
}
@Override
public PsiReference getReference() {
return this;
}
@Override
@NotNull
public String getCanonicalText() {
String name = getQualifiedName();
if (name == null) return "";
PsiType[] types = getTypeParameters();
if (types.length == 0) return name;
StringBuilder buf = new StringBuilder();
buf.append(name);
buf.append('<');
for (int i = 0; i < types.length; i++) {
if (i > 0) buf.append(',');
buf.append(types[i].getCanonicalText());
}
buf.append('>');
return buf.toString();
}
@Override
public PsiElement copy() {
if (myClassName != null) {
@@ -207,79 +144,11 @@ public class LightClassReference extends LightElement implements PsiJavaCodeRefe
}
}
@Override
public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
//TODO?
throw new UnsupportedOperationException();
}
@Override
public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
//TODO?
throw new UnsupportedOperationException();
}
@Override
public void accept(@NotNull PsiElementVisitor visitor) {
if (visitor instanceof JavaElementVisitor) {
((JavaElementVisitor)visitor).visitReferenceElement(this);
}
else {
visitor.visitElement(this);
}
}
public String toString() {
return "LightClassReference:" + myText;
}
@Override
public boolean isReferenceTo(PsiElement element) {
return element instanceof PsiClass && getManager().areElementsEquivalent(resolve(), element);
}
@Override
@NotNull
public Object[] getVariants() {
throw new RuntimeException("Variants are not available for light references");
}
@Override
public boolean isSoft(){
return false;
}
@Override
public TextRange getRangeInElement() {
return new TextRange(0, getTextLength());
}
@Override
public PsiElement getElement() {
return this;
}
@Override
public boolean isValid() {
return myRefClass == null || myRefClass.isValid();
}
@Override
@NotNull
public PsiType[] getTypeParameters() {
return PsiType.EMPTY_ARRAY;
}
@Override
public PsiElement getQualifier() {
return null;
}
@Override
public boolean isQualified() {
return false;
}
@NotNull
@Override
public GlobalSearchScope getResolveScope() {
@@ -0,0 +1,168 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.impl.light;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
abstract class LightClassReferenceBase extends LightElement implements PsiJavaCodeReferenceElement {
protected final String myText;
private LightReferenceParameterList myParameterList;
protected LightClassReferenceBase(@NotNull PsiManager manager, @NotNull String text) {
super(manager, JavaLanguage.INSTANCE);
myText = text;
}
@Override
@NotNull
public JavaResolveResult[] multiResolve(boolean incompleteCode) {
final JavaResolveResult result = advancedResolve(incompleteCode);
if (result != JavaResolveResult.EMPTY) return new JavaResolveResult[]{result};
return JavaResolveResult.EMPTY_ARRAY;
}
@Override
public void processVariants(@NotNull PsiScopeProcessor processor) {
throw new RuntimeException("Variants are not available for light references");
}
@Override
public PsiElement getReferenceNameElement() {
return null;
}
@Override
public PsiReferenceParameterList getParameterList() {
if (myParameterList == null) {
myParameterList = new LightReferenceParameterList(myManager, PsiTypeElement.EMPTY_ARRAY);
}
return myParameterList;
}
@Override
public String getQualifiedName() {
PsiClass psiClass = (PsiClass)resolve();
if (psiClass != null) {
return psiClass.getQualifiedName();
}
return null;
}
@Override
public String getText() {
return myText;
}
@Override
public PsiReference getReference() {
return this;
}
@Override
@NotNull
public String getCanonicalText() {
String name = getQualifiedName();
if (name == null) return "";
PsiType[] types = getTypeParameters();
if (types.length == 0) return name;
StringBuilder buf = new StringBuilder();
buf.append(name);
buf.append('<');
for (int i = 0; i < types.length; i++) {
if (i > 0) buf.append(',');
buf.append(types[i].getCanonicalText());
}
buf.append('>');
return buf.toString();
}
@Override
public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
//TODO?
throw new UnsupportedOperationException();
}
@Override
public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
//TODO?
throw new UnsupportedOperationException();
}
@Override
public void accept(@NotNull PsiElementVisitor visitor) {
if (visitor instanceof JavaElementVisitor) {
((JavaElementVisitor)visitor).visitReferenceElement(this);
}
else {
visitor.visitElement(this);
}
}
public String toString() {
return getClass().getSimpleName() + getText();
}
@Override
public boolean isReferenceTo(PsiElement element) {
return element instanceof PsiClass && getManager().areElementsEquivalent(resolve(), element);
}
@Override
@NotNull
public Object[] getVariants() {
throw new RuntimeException("Variants are not available for light references");
}
@Override
public boolean isSoft() {
return false;
}
@Override
public TextRange getRangeInElement() {
return new TextRange(0, getTextLength());
}
@Override
public PsiElement getElement() {
return this;
}
@Override
@NotNull
public PsiType[] getTypeParameters() {
return PsiType.EMPTY_ARRAY;
}
@Override
public PsiElement getQualifier() {
return null;
}
@Override
public boolean isQualified() {
return false;
}
}
@@ -0,0 +1,69 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.impl.light;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class LightClassTypeReference extends LightClassReferenceBase implements PsiJavaCodeReferenceElement {
private final @NotNull PsiClassType myType;
private LightClassTypeReference(@NotNull PsiManager manager, @NotNull String text, @NotNull PsiClassType type) {
super(manager, text);
myType = type;
}
public LightClassTypeReference(@NotNull PsiManager manager, @NotNull PsiClassType type) {
this(manager, type.getCanonicalText(true), type);
}
@Nullable
@Override
public PsiElement resolve() {
return myType.resolve();
}
@NotNull
@Override
public JavaResolveResult advancedResolve(boolean incompleteCode) {
return myType.resolveGenerics();
}
@Nullable
@Override
public String getReferenceName() {
return myType.getClassName();
}
@Override
public PsiElement copy() {
return new LightClassTypeReference(myManager, myText, myType);
}
@Override
public boolean isValid() {
return myType.isValid();
}
@NotNull
@Override
public GlobalSearchScope getResolveScope() {
return myType.getResolveScope();
}
}
@@ -20,6 +20,7 @@ import com.intellij.navigation.ColoredItemPresentation;
import com.intellij.navigation.LocationPresentation;
import com.intellij.openapi.editor.colors.CodeInsightColors;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.project.IndexNotReadyException;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
@@ -104,7 +105,12 @@ public abstract class JavaClassTreeElementBase<Value extends PsiElement> extends
@Override
public TextAttributesKey getTextAttributesKey() {
return isDeprecated() ? CodeInsightColors.DEPRECATED_ATTRIBUTES : null;
try {
return isDeprecated() ? CodeInsightColors.DEPRECATED_ATTRIBUTES : null;
}
catch (IndexNotReadyException ignore) {
return null; // do not show deprecated elements while indexing
}
}
private boolean isDeprecated(){
@@ -14,7 +14,7 @@ class Test {
class Test2 {
static void m(Integer i) { }
static void m(Integer <warning descr="Parameter 'i' is never used">i</warning>) { }
interface I1 {
void m(int x);
@@ -77,7 +77,7 @@ abstract class AbstractCollection<E> implements Collection<E> {
public boolean add(E e) {
return true;
}
public boolean addAll(Collection<? extends E> c) {
public boolean addAll(Collection<? extends E> <warning descr="Parameter 'c' is never used">c</warning>) {
boolean modified = false;
return modified;
}
@@ -6,11 +6,11 @@ class Test {
Test m(List<Integer> l1, List<Integer> l2);
}
static Test meth(List<Integer>... lli) {
static Test meth(List<Integer>... <warning descr="Parameter 'lli' is never used">lli</warning>) {
return null;
}
Test(List<Integer>... lli) {}
Test(List<Integer>... <warning descr="Parameter 'lli' is never used">lli</warning>) {}
{
I <warning descr="Variable 'i1' is never used">i1</warning> = <warning descr="Unchecked generics array creation for varargs parameter">Test::meth</warning>;
@@ -1,7 +1,7 @@
import java.util.stream.Stream;
class A {
private void test5(Integer i, String... strings) {}
private void test5(Integer <warning descr="Parameter 'i' is never used">i</warning>, String... <warning descr="Parameter 'strings' is never used">strings</warning>) {}
private void <warning descr="Private method 'test5(java.lang.Integer, java.lang.Integer, java.lang.String...)' is never used">test5</warning>(Integer i, Integer b, String... strings) {
System.out.println(i);
System.out.println(b);
@@ -12,7 +12,7 @@ class MyTest<T> {
public static class Builder<E> {
public Builder<E> add(E element) {
public Builder<E> add(E <warning descr="Parameter 'element' is never used">element</warning>) {
return this;
}
@@ -8,6 +8,6 @@ class Main {
}
public static boolean checkForJdk(String <warning descr="Parameter 'homePath' is never used">homePath</warning>) {return false;}
public static boolean checkForJdk(File homePath) {return false;}
public static boolean checkForJdk(File <warning descr="Parameter 'homePath' is never used">homePath</warning>) {return false;}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
+1 -1
View File
@@ -55,7 +55,7 @@ oromatcher.jar
picocontainer.jar
protobuf-2.5.0.jar
proxy-vole_20131209.jar
pty4j-0.7.jar
pty4j-0.7.1.jar
purejavacomm.jar
resolver.jar
rhino-js-1_7R4.jar
@@ -32,13 +32,13 @@ public abstract class LookAheadLexer extends LexerBase{
private final Queue<IElementType> myTypeCache;
private final Queue<Integer> myEndOffsetCache;
public LookAheadLexer(final Lexer baseLexer, int capacity) {
public LookAheadLexer(@NotNull Lexer baseLexer, int capacity) {
myBaseLexer = baseLexer;
myTypeCache = new Queue<IElementType>(capacity);
myEndOffsetCache = new Queue<Integer>(capacity);
}
public LookAheadLexer(final Lexer baseLexer) {
public LookAheadLexer(@NotNull Lexer baseLexer) {
this(baseLexer, 64);
}
@@ -52,7 +52,7 @@ public abstract class LookAheadLexer extends LexerBase{
myEndOffsetCache.addLast(endOffset);
}
protected void lookAhead(Lexer baseLexer) {
protected void lookAhead(@NotNull Lexer baseLexer) {
advanceLexer(baseLexer);
}
@@ -1,23 +0,0 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.concurrency;
import org.jetbrains.annotations.NotNull;
public interface AsyncFunction<PARAM, RESULT> {
@NotNull
Promise<RESULT> fun(PARAM param);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 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.
@@ -203,7 +203,7 @@ public class AsyncPromise<T> extends Promise<T> implements Getter<T> {
@Override
@NotNull
public <SUB_RESULT> Promise<SUB_RESULT> thenAsync(@NotNull final AsyncFunction<? super T, SUB_RESULT> fulfilled) {
public <SUB_RESULT> Promise<SUB_RESULT> thenAsync(@NotNull final Function<? super T, Promise<SUB_RESULT>> fulfilled) {
switch (state) {
case PENDING:
break;
@@ -1,39 +0,0 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.concurrency;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
class CountDownConsumer<T> implements Consumer<T> {
private volatile int countDown;
private final AsyncPromise<T> promise;
private final T totalResult;
public CountDownConsumer(int countDown, @NotNull AsyncPromise<T> promise, @Nullable T totalResult) {
this.countDown = countDown;
this.promise = promise;
this.totalResult = totalResult;
}
@Override
public void consume(T t) {
if (--countDown == 0) {
promise.setResult(totalResult);
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 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.
@@ -68,7 +68,7 @@ class DonePromise<T> extends Promise<T> implements Getter<T> {
@NotNull
@Override
public <SUB_RESULT> Promise<SUB_RESULT> thenAsync(@NotNull AsyncFunction<? super T, SUB_RESULT> done) {
public <SUB_RESULT> Promise<SUB_RESULT> thenAsync(@NotNull Function<? super T, Promise<SUB_RESULT>> done) {
return done.fun(result);
}
@@ -1,19 +0,0 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.concurrency;
public interface ObsolescentAsyncFunction<PARAM, RESULT> extends AsyncFunction<PARAM, RESULT>, Obsolescent {
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 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,7 +28,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.List;
public abstract class Promise<T> {
public static final Promise<Void> DONE = new DonePromise<Void>(null);
@@ -70,40 +69,6 @@ public abstract class Promise<T> {
}
}
@NotNull
public static Promise<?> all(@NotNull Collection<Promise<?>> promises) {
if (promises.size() == 1) {
return promises instanceof List ? ((List<Promise<?>>)promises).get(0) : promises.iterator().next();
}
else {
return all(promises, null);
}
}
@NotNull
public static <T> Promise<T> all(@NotNull Collection<Promise<?>> promises, @Nullable T totalResult) {
if (promises.isEmpty()) {
//noinspection unchecked
return (Promise<T>)DONE;
}
final AsyncPromise<T> totalPromise = new AsyncPromise<T>();
Consumer done = new CountDownConsumer<T>(promises.size(), totalPromise, totalResult);
Consumer<Throwable> rejected = new Consumer<Throwable>() {
@Override
public void consume(Throwable error) {
totalPromise.setError(error);
}
};
for (Promise<?> promise : promises) {
//noinspection unchecked
promise.done(done);
promise.rejected(rejected);
}
return totalPromise;
}
public static <T> Promise<T> any(@NotNull final Collection<Promise<T>> promises, @NotNull final String totalError) {
if (promises.isEmpty()) {
//noinspection unchecked
@@ -187,7 +152,7 @@ public abstract class Promise<T> {
public abstract <SUB_RESULT> Promise<SUB_RESULT> then(@NotNull Function<? super T, ? extends SUB_RESULT> done);
@NotNull
public abstract <SUB_RESULT> Promise<SUB_RESULT> thenAsync(@NotNull AsyncFunction<? super T, SUB_RESULT> done);
public abstract <SUB_RESULT> Promise<SUB_RESULT> thenAsync(@NotNull Function<? super T, Promise<SUB_RESULT>> done);
@NotNull
public abstract State getState();
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 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,7 +63,7 @@ class RejectedPromise<T> extends Promise<T> {
@NotNull
@Override
public <SUB_RESULT> Promise<SUB_RESULT> thenAsync(@NotNull AsyncFunction<? super T, SUB_RESULT> done) {
public <SUB_RESULT> Promise<SUB_RESULT> thenAsync(@NotNull Function<? super T, Promise<SUB_RESULT>> done) {
//noinspection unchecked
return (Promise<SUB_RESULT>)this;
}
@@ -1153,7 +1153,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
childNode.putUserData(BlockSupport.TREE_DEPTH_LIMIT_EXCEEDED, Boolean.TRUE);
}
assert rootNode.textMatches(myText) : rootNode.getElementType();
assert rootNode.getTextLength() == myText.length() : rootNode.getElementType();
return rootNode;
}
@@ -15,8 +15,11 @@
*/
package com.intellij.psi.impl.source;
import com.intellij.concurrency.JobScheduler;
import com.intellij.extapi.psi.StubBasedPsiElementBase;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.LowMemoryWatcher;
import com.intellij.openapi.util.UserDataHolderEx;
import com.intellij.psi.impl.source.tree.AstPath;
import com.intellij.psi.impl.source.tree.CompositeElement;
import com.intellij.reference.SoftReference;
@@ -27,7 +30,6 @@ import org.jetbrains.annotations.Nullable;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
/**
* A weak cache for all instantiated stub-based PSI to allow {@link CompositeElement#getPsi()} return it when AST is reloaded.<p/>
@@ -35,24 +37,22 @@ import java.util.concurrent.TimeUnit;
*/
class AstPathPsiMap {
/**
* Not using ConcurrentWeakValueMap because we need to clean them up as ASTs in thousands of files are created and gc-ed.
* So we have a single shared reference queue {@link MyReference#ourQueue} for that.
* Not using ConcurrentWeakValueMap because we need to clean each of them up separately, when ASTs in thousands of files are created and gc-ed.
* So we have a per-project single shared reference queue {@link #myQueue} for that.
* Otherwise the files end up retaining lots of maps with all-gc-ed stuff inside, but the maps are still very large.
*/
private final ConcurrentMap<AstPath, MyReference> myMap = ContainerUtil.newConcurrentMap();
static {
JobScheduler.getScheduler().scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
// clean up AstPath objects when no PSI is accessed, e.g. after project closing
processQueue();
}
}, 5, 5, TimeUnit.SECONDS);
private static final Key<MyReferenceQueue> STUB_PSI_REFS = Key.create("STUB_PSI_REFS");
private final MyReferenceQueue myQueue;
AstPathPsiMap(@NotNull Project project) {
MyReferenceQueue queue = project.getUserData(STUB_PSI_REFS);
myQueue = queue != null ? queue : ((UserDataHolderEx)project).putUserDataIfAbsent(STUB_PSI_REFS, new MyReferenceQueue());
}
void invalidatePsi() {
processQueue();
myQueue.cleanupStaleReferences();
for (MyReference reference : myMap.values()) {
StubBasedPsiElementBase<?> psi = SoftReference.dereference(reference);
if (psi != null) {
@@ -63,7 +63,7 @@ class AstPathPsiMap {
}
void switchToStrongRefs() {
processQueue();
myQueue.cleanupStaleReferences();
for (MyReference reference : myMap.values()) {
StubBasedPsiElementBase<?> psi = SoftReference.dereference(reference);
if (psi != null) {
@@ -82,30 +82,38 @@ class AstPathPsiMap {
@NotNull
StubBasedPsiElementBase<?> cachePsi(@NotNull AstPath key, @NotNull StubBasedPsiElementBase psi) {
processQueue();
myMap.put(key, new MyReference(psi, key));
myQueue.cleanupStaleReferences();
myMap.put(key, new MyReference(psi, key, myQueue));
psi.setSubstrateRef(key);
return psi;
}
private static void processQueue() {
while (true) {
MyReference reference = (MyReference)MyReference.ourQueue.poll();
if (reference == null) break;
AstPath key = reference.pathRef;
key.getContainingFile().getRefToPsi().myMap.remove(key, reference);
}
}
private static class MyReference extends WeakReference<StubBasedPsiElementBase<?>> {
static final ReferenceQueue<StubBasedPsiElementBase<?>> ourQueue = new ReferenceQueue<StubBasedPsiElementBase<?>>();
final AstPath pathRef;
MyReference(StubBasedPsiElementBase psi, AstPath ref) {
super(psi, ourQueue);
MyReference(StubBasedPsiElementBase psi, AstPath ref, ReferenceQueue<StubBasedPsiElementBase<?>> queue) {
super(psi, queue);
pathRef = ref;
}
}
private static class MyReferenceQueue extends ReferenceQueue<StubBasedPsiElementBase<?>> {
@SuppressWarnings("unused") LowMemoryWatcher watcher = LowMemoryWatcher.register(new Runnable() {
@Override
public void run() {
cleanupStaleReferences();
}
});
void cleanupStaleReferences() {
while (true) {
MyReference reference = (MyReference)poll();
if (reference == null) break;
AstPath key = reference.pathRef;
key.getContainingFile().getRefToPsi().myMap.remove(key, reference);
}
}
}
}
@@ -73,7 +73,7 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF
private boolean myInvalidated;
private volatile boolean myAstLoaded;
private volatile boolean myUseStrongRefs;
private AstPathPsiMap myRefToPsi = new AstPathPsiMap();
private AstPathPsiMap myRefToPsi;
private final ThreadLocal<FileElement> myFileElementBeingLoaded = new ThreadLocal<FileElement>();
protected final PsiManagerEx myManager;
private volatile Getter<FileElement> myTreeElementPointer; // SoftReference/WeakReference to ASTNode or a strong reference to a tree if the file is a DummyHolder
@@ -87,6 +87,7 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF
protected PsiFileImpl(@NotNull FileViewProvider provider ) {
myManager = (PsiManagerEx)provider.getManager();
myViewProvider = provider;
myRefToPsi = new AstPathPsiMap(getProject());
}
public void setContentElementType(final IElementType contentElementType) {
@@ -482,7 +483,7 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF
PsiFileImpl clone = BlockSupportImpl.getFileCopy(this, providerCopy);
copyCopyableDataTo(clone);
clone.myRefToPsi = new AstPathPsiMap();
clone.myRefToPsi = new AstPathPsiMap(getProject());
if (getTreeElement() != null) {
// not set by provider in clone
final FileElement treeClone = (FileElement)calcTreeElement().clone();
@@ -776,7 +777,7 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF
protected PsiFileImpl cloneImpl(FileElement treeElementClone) {
PsiFileImpl clone = (PsiFileImpl)super.clone();
clone.myRefToPsi = new AstPathPsiMap();
clone.myRefToPsi = new AstPathPsiMap(getProject());
clone.setTreeElementPointer(treeElementClone); // should not use setTreeElement here because cloned file still have VirtualFile (SCR17963)
treeElementClone.setPsi(clone);
return clone;
@@ -38,8 +38,9 @@ public class PsiMultiReference implements PsiPolyVariantReference {
public static final Comparator<PsiReference> COMPARATOR = new Comparator<PsiReference>() {
@Override
public int compare(final PsiReference ref1, final PsiReference ref2) {
if (ref1.isSoft() && !ref2.isSoft()) return 1;
if (!ref1.isSoft() && ref2.isSoft()) return -1;
boolean soft1 = ref1.isSoft();
boolean soft2 = ref2.isSoft();
if (soft1 != soft2) return soft1 ? 1 : -1;
boolean resolves1 = resolves(ref1);
boolean resolves2 = resolves(ref2);
@@ -210,7 +210,7 @@ public class LazyParseableElement extends CompositeElement {
AstPath.cacheNodePaths(this);
assert super.textMatches(text) : "Text mismatch in " + getElementType();
assertTextLengthIntact(text.length());
myText = new SoftReference<CharSequence>(text);
}
}
@@ -219,6 +219,14 @@ public class LazyParseableElement extends CompositeElement {
}
}
private void assertTextLengthIntact(int expected) {
int length = 0;
for (ASTNode node : getChildren(null)) {
length += node.getTextLength();
}
assert length == expected : "Text mismatch in " + getElementType();
}
@Override
public void rawAddChildrenWithoutNotifications(@NotNull TreeElement first) {
if (!isParsed()) {
@@ -20,6 +20,7 @@ import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeRegistry;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Processor;
import com.intellij.util.indexing.*;
import com.intellij.util.io.EnumeratorStringDescriptor;
import com.intellij.util.io.KeyDescriptor;
@@ -38,11 +39,6 @@ import java.util.Map;
public class FileTypeIndex extends ScalarIndexExtension<FileType>
implements FileBasedIndex.InputFilter, KeyDescriptor<FileType>, DataIndexer<FileType, Void, FileContent> {
@NotNull
public static Collection<VirtualFile> getFiles(@NotNull FileType fileType, @NotNull GlobalSearchScope scope) {
return FileBasedIndex.getInstance().getContainingFiles(NAME, fileType, scope);
}
public static final ID<FileType, Void> NAME = ID.create("filetypes");
private final FileTypeRegistry myFileTypeManager;
@@ -130,11 +126,24 @@ public class FileTypeIndex extends ScalarIndexExtension<FileType>
}
public static boolean containsFileOfType(@NotNull FileType type, @NotNull GlobalSearchScope scope) {
return !FileBasedIndex.getInstance().processValues(NAME, type, null, new FileBasedIndex.ValueProcessor<Void>() {
@Override
public boolean process(VirtualFile file, Void value) {
return false;
}
}, scope);
return !processFiles(type, file -> false, scope);
}
@NotNull
public static Collection<VirtualFile> getFiles(@NotNull FileType fileType, @NotNull GlobalSearchScope scope) {
return FileBasedIndex.getInstance().getContainingFiles(NAME, fileType, scope);
}
public static boolean processFiles(@NotNull FileType fileType, @NotNull Processor<VirtualFile> processor, GlobalSearchScope scope) {
return FileBasedIndex.getInstance().processValues(
NAME,
fileType,
null,
new FileBasedIndex.ValueProcessor<Void>() {
@Override
public boolean process(VirtualFile file, Void value) {
return processor.process(file);
}
}, scope);
}
}
@@ -195,6 +195,10 @@ public class FilenameIndex extends ScalarIndexExtension<String> {
return result.toArray(new PsiFile[result.size()]);
}
public static void processAllFileNames(@NotNull Processor<String> processor, @NotNull GlobalSearchScope scope, @NotNull IdFilter filter) {
FileBasedIndex.getInstance().processAllKeys(NAME, processor, scope, filter);
}
private static class MyDataIndexer implements DataIndexer<String, Void, FileContent> {
@Override
@NotNull
@@ -18,6 +18,7 @@ package com.intellij.application.options.colors;
import com.intellij.application.options.EditorFontsConstants;
import com.intellij.icons.AllIcons;
import com.intellij.ide.IdeTooltipManager;
import com.intellij.ide.ui.AntialiasingType;
import com.intellij.ide.ui.UISettings;
import com.intellij.openapi.application.ApplicationBundle;
@@ -27,10 +28,7 @@ import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.colors.FontPreferences;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.ui.DocumentAdapter;
import com.intellij.ui.FontComboBox;
import com.intellij.ui.FontInfoRenderer;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.*;
import com.intellij.ui.components.JBCheckBox;
import com.intellij.util.EventDispatcher;
import com.intellij.util.ui.JBUI;
@@ -105,7 +103,11 @@ public class FontOptions extends JPanel implements OptionsPanel{
myEnableLigaturesCheckbox.setBorder(null);
panel.add(myEnableLigaturesCheckbox);
JLabel warningIcon = new JLabel(AllIcons.General.BalloonWarning);
warningIcon.setToolTipText(ApplicationBundle.message("ligatures.jre.warning", ApplicationNamesInfo.getInstance().getFullProductName()));
IdeTooltipManager.getInstance().setCustomTooltip(
warningIcon,
new TooltipWithClickableLinks.ForBrowser(warningIcon,
ApplicationBundle.message("ligatures.jre.warning",
ApplicationNamesInfo.getInstance().getFullProductName())));
warningIcon.setBorder(JBUI.Borders.emptyLeft(5));
updateWarningIconVisibility(warningIcon);
panel.add(warningIcon);
@@ -144,6 +144,9 @@ public class PsiElementListNavigator {
}).
setCancelCallback(() -> {
HintUpdateSupply.hideHint(list);
if (listUpdaterTask != null) {
return listUpdaterTask.cancelTask();
}
return true;
});
final Ref<UsageView> usageView = new Ref<UsageView>();
@@ -300,7 +300,9 @@ public class ShowImplementationsAction extends AnAction implements PopupAction {
})
.setCancelCallback(() -> {
ImplementationsUpdaterTask task = SoftReference.dereference(myTaskRef);
cancelTask(task);
if (task != null) {
task.cancelTask();
}
return Boolean.TRUE;
})
.createPopup();
@@ -314,17 +316,6 @@ public class ShowImplementationsAction extends AnAction implements PopupAction {
}
}
private static boolean cancelTask(@Nullable ImplementationsUpdaterTask task) {
if (task != null) {
ProgressIndicator indicator = task.myIndicator;
if (indicator != null) {
indicator.cancel();
}
return task.setCanceled();
}
return false;
}
private void updateInBackground(Editor editor,
@Nullable PsiElement element,
@NotNull ImplementationViewComponent component,
@@ -332,7 +323,9 @@ public class ShowImplementationsAction extends AnAction implements PopupAction {
@NotNull AbstractPopup popup,
@NotNull Ref<UsageView> usageView) {
final ImplementationsUpdaterTask updaterTask = SoftReference.dereference(myTaskRef);
cancelTask(updaterTask);
if (updaterTask != null) {
updaterTask.cancelTask();
}
if (element == null) return; //already found
final ImplementationsUpdaterTask task = new ImplementationsUpdaterTask(element, editor, title, isIncludeAlwaysSelf());
@@ -412,7 +405,6 @@ public class ShowImplementationsAction extends AnAction implements PopupAction {
private final PsiElement myElement;
private final boolean myIncludeSelf;
private PsiElement[] myElements;
private volatile ProgressIndicator myIndicator;
private ImplementationsUpdaterTask(@NotNull PsiElement element, final Editor editor, final String caption, boolean includeSelf) {
super(element.getProject(), ImplementationSearcher.SEARCHING_FOR_IMPLEMENTATIONS);
@@ -445,7 +437,6 @@ public class ShowImplementationsAction extends AnAction implements PopupAction {
@Override
public void run(@NotNull final ProgressIndicator indicator) {
myIndicator = indicator;
super.run(indicator);
final ImplementationSearcher.BackgroundableImplementationSearcher implementationSearcher =
new ImplementationSearcher.BackgroundableImplementationSearcher() {
@@ -477,7 +468,7 @@ public class ShowImplementationsAction extends AnAction implements PopupAction {
@Override
public void onSuccess() {
if (!cancelTask(this)) {
if (!cancelTask()) {
myComponent.update(myElements, myComponent.getIndex());
}
super.onSuccess();
@@ -52,6 +52,7 @@ public abstract class BackgroundUpdaterTask<T> extends Task.Backgroundable {
private volatile boolean myCanceled;
private volatile boolean myFinished;
private volatile ProgressIndicator myIndicator;
public BackgroundUpdaterTask(Project project, String title, boolean canBeCancelled) {
super(project, title, canBeCancelled);
@@ -132,6 +133,7 @@ public abstract class BackgroundUpdaterTask<T> extends Task.Backgroundable {
@Override
public void run(@NotNull ProgressIndicator indicator) {
paintBusy(true);
myIndicator = indicator;
}
@Override
@@ -148,4 +150,12 @@ public abstract class BackgroundUpdaterTask<T> extends Task.Backgroundable {
public boolean isFinished() {
return myFinished;
}
public boolean cancelTask() {
ProgressIndicator indicator = myIndicator;
if (indicator != null) {
indicator.cancel();
}
return setCanceled();
}
}
@@ -182,6 +182,10 @@ public abstract class GotoTargetHandler implements CodeInsightActionHandler {
setMovable(true).
setCancelCallback(() -> {
HintUpdateSupply.hideHint(list);
final ListBackgroundUpdaterTask task = gotoData.listUpdaterTask;
if (task != null) {
return task.cancelTask();
}
return true;
}).
setCouldPin(popup1 -> {
@@ -26,6 +26,7 @@ import com.intellij.ide.util.gotoByName.GotoActionModel;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.ex.ActionUtil;
import com.intellij.openapi.actionSystem.impl.ActionMenu;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.application.TransactionGuard;
@@ -53,10 +54,7 @@ import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.*;
import java.util.Set;
public class GotoActionAction extends GotoActionBase implements DumbAware {
@@ -110,6 +108,9 @@ public class GotoActionAction extends GotoActionBase implements DumbAware {
if (text != null && myDropdownPopup != null) {
myDropdownPopup.setAdText(text, SwingConstants.LEFT);
}
String description = getValueDescription(value);
ActionMenu.showDescriptionInStatusBar(true, myList, description);
}
@Nullable
@@ -124,6 +125,28 @@ public class GotoActionAction extends GotoActionBase implements DumbAware {
return getAdText();
}
});
myList.addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
int index = myList.locationToIndex(e.getPoint());
if (index == -1) return;
Object value = myList.getModel().getElementAt(index);
String description = getValueDescription(value);
ActionMenu.showDescriptionInStatusBar(true, myList, description);
}
});
}
@Nullable
private String getValueDescription(@Nullable Object value) {
if (value instanceof GotoActionModel.MatchedValue) {
GotoActionModel.MatchedValue mv = (GotoActionModel.MatchedValue)value;
if (mv.value instanceof GotoActionModel.ActionWrapper) {
AnAction action = ((GotoActionModel.ActionWrapper)mv.value).getAction();
return action.getTemplatePresentation().getDescription();
}
}
return null;
}
@NotNull
@@ -144,7 +167,9 @@ public class GotoActionAction extends GotoActionBase implements DumbAware {
public void setDisposed(boolean disposedFlag) {
super.setDisposed(disposedFlag);
Disposer.dispose(disposable);
ActionMenu.showDescriptionInStatusBar(true, myList, null);
for (ListSelectionListener listener : myList.getListSelectionListeners()) {
myList.removeListSelectionListener(listener);
}
@@ -69,7 +69,7 @@ public class DefaultFileNavigationContributor implements ChooseByNameContributor
@Override
public void processNames(@NotNull final Processor<String> processor, @NotNull GlobalSearchScope scope, IdFilter filter) {
long started = System.currentTimeMillis();
FileBasedIndex.getInstance().processAllKeys(FilenameIndex.NAME, s -> processor.process(s), scope, filter);
FilenameIndex.processAllFileNames(processor, scope, filter);
if (IdFilter.LOG.isDebugEnabled()) {
IdFilter.LOG.debug("All names retrieved:" + (System.currentTimeMillis() - started));
}
@@ -541,6 +541,7 @@ public class GotoActionModel implements ChooseByNameModel, Comparator<Object>, E
panel.add(createIconLabel(presentation.getIcon()), BorderLayout.WEST);
}
appendWithColoredMatches(nameComponent, getName(presentation.getText(), groupName, toggle), pattern, fg, isSelected);
panel.setToolTipText(presentation.getDescription());
Shortcut[] shortcuts = KeymapManager.getInstance().getActiveKeymap().getShortcuts(ActionManager.getInstance().getId(anAction));
String shortcutText = KeymapUtil.getPreferredShortcutText(
@@ -22,11 +22,14 @@ import com.intellij.psi.PsiFile;
import com.intellij.psi.SingleRootFileViewProvider;
import com.intellij.psi.impl.PsiManagerEx;
import com.intellij.psi.impl.file.impl.FileManager;
import com.intellij.util.containers.WeakFactoryMap;
import com.intellij.util.containers.ConcurrentWeakFactoryMap;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.FactoryMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Map;
/**
* @author peter
@@ -35,7 +38,12 @@ public class MockFileManager implements FileManager {
private final PsiManagerEx myManager;
// in mock tests it's LightVirtualFile, they're only alive when they're referenced,
// and there can not be several instances representing the same file
private final WeakFactoryMap<VirtualFile, FileViewProvider> myViewProviders = new WeakFactoryMap<VirtualFile, FileViewProvider>() {
private final FactoryMap<VirtualFile, FileViewProvider> myViewProviders = new ConcurrentWeakFactoryMap<VirtualFile, FileViewProvider>() {
@Override
protected Map<VirtualFile, FileViewProvider> createMap() {
return ContainerUtil.createConcurrentWeakKeyWeakValueMap();
}
@Override
protected FileViewProvider create(VirtualFile key) {
return new SingleRootFileViewProvider(myManager, key);
@@ -22,13 +22,11 @@ import com.intellij.internal.statistic.beans.UsageDescriptor;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.search.FileTypeIndex;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.NotNullFunction;
import com.intellij.util.ThreeState;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.indexing.FileBasedIndex;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -64,21 +62,14 @@ public class FileTypeUsagesCollector extends AbstractApplicationUsagesCollector
}
final String ideaDirPath = getIdeaDirPath(project);
ApplicationManager.getApplication().runReadAction(() -> {
FileBasedIndex.getInstance().processValues(
FileTypeIndex.NAME,
fileType,
null,
new FileBasedIndex.ValueProcessor<Void>() {
@Override
public boolean process(VirtualFile file, Void value) {
//skip files from .idea directory otherwise 99% of projects would have XML and PLAIN_TEXT file types
if (ideaDirPath == null || FileUtil.isAncestorThreeState(ideaDirPath, file.getPath(), true) == ThreeState.NO) {
usedFileTypes.add(fileType);
return false;
}
return true;
}
}, GlobalSearchScope.projectScope(project));
FileTypeIndex.processFiles(fileType, file -> {
//skip files from .idea directory otherwise 99% of projects would have XML and PLAIN_TEXT file types
if (ideaDirPath == null || FileUtil.isAncestorThreeState(ideaDirPath, file.getPath(), true) == ThreeState.NO) {
usedFileTypes.add(fileType);
return false;
}
return true;
}, GlobalSearchScope.projectScope(project));
});
}
return ContainerUtil.map2Set(usedFileTypes, (NotNullFunction<FileType, UsageDescriptor>)fileType -> new UsageDescriptor(fileType.getName(), 1));
@@ -86,8 +86,7 @@ public abstract class LevelChooserAction extends ComboBoxAction implements DumbA
return getSeverities(severityRegistrar, true);
}
public static List<HighlightSeverity> getSeverities(final SeverityRegistrar severityRegistrar,
boolean includeDoNotShow) {
public static List<HighlightSeverity> getSeverities(final SeverityRegistrar severityRegistrar, boolean includeDoNotShow) {
final List<HighlightSeverity> severities = new ArrayList<HighlightSeverity>();
for (final SeverityRegistrar.SeverityBasedTextAttributes type : SeverityUtil.getRegisteredHighlightingInfoTypes(severityRegistrar)) {
severities.add(type.getSeverity());
@@ -95,7 +94,7 @@ public abstract class LevelChooserAction extends ComboBoxAction implements DumbA
if (includeDoNotShow) {
severities.add(HighlightSeverity.INFORMATION);
}
Collections.sort(severities, (a, b) -> -severityRegistrar.compare(a, b));
Collections.sort(severities, severityRegistrar.reversed());
return severities;
}
@@ -270,7 +270,7 @@ public class CopyFilesOrDirectoriesDialog extends DialogWrapper {
return;
}
if (myFileCopy) {
if (myFileCopy && myTargetDirectory != null) {
if (FileTypeChooser.getKnownFileTypeOrAssociate(myTargetDirectory.getVirtualFile(), newName, myProject) == null) {
myUnknownFileType = true;
}
@@ -29,12 +29,12 @@ import com.intellij.openapi.editor.colors.EditorFontType;
import com.intellij.openapi.editor.ex.EditorGutterComponentEx;
import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.progress.PerformInBackgroundOption;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.actions.ActiveAnnotationGutter;
@@ -47,10 +47,14 @@ import com.intellij.openapi.vcs.history.VcsHistorySession;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.text.DateFormatUtil;
import com.intellij.util.ui.update.MergingUpdateQueue;
import com.intellij.util.ui.update.Update;
import com.intellij.vcs.history.VcsHistoryProviderEx;
import com.intellij.vcsUtil.VcsUtil;
import com.intellij.xml.util.XmlStringUtil;
import org.jetbrains.annotations.CalledInAwt;
import org.jetbrains.annotations.CalledWithReadLock;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -59,18 +63,13 @@ import java.awt.*;
import java.util.*;
import java.util.List;
/**
* @author Konstantin Bulenkov
*/
public class AnnotateStackTraceAction extends AnAction implements DumbAware {
public class AnnotateStackTraceAction extends DumbAwareAction {
private static final Logger LOG = Logger.getInstance(AnnotateStackTraceAction.class);
private final EditorHyperlinkSupport myHyperlinks;
private Map<Integer, LastRevision> cache;
private Date newestDate;
private int maxDateLength = 0;
private final Editor myEditor;
private boolean myGutterShowed = false;
private boolean myIsLoading = false;
public AnnotateStackTraceAction(@NotNull Editor editor, @NotNull EditorHyperlinkSupport hyperlinks) {
super("Show files modification info", null, AllIcons.Actions.Annotate);
@@ -78,101 +77,37 @@ public class AnnotateStackTraceAction extends AnAction implements DumbAware {
myEditor = editor;
}
@Override
public void update(AnActionEvent e) {
boolean isShown = myEditor.getGutter().isAnnotationsShown();
e.getPresentation().setEnabled(!isShown && !myIsLoading);
}
@Override
public void actionPerformed(final AnActionEvent e) {
cache = new HashMap<Integer, LastRevision>();
myIsLoading = true;
ProgressManager.getInstance().run(new Task.Backgroundable(myEditor.getProject(), "Getting File History", true) {
private final Object LOCK = new Object();
private final MergingUpdateQueue myUpdateQueue = new MergingUpdateQueue("AnnotateStackTraceAction", 200, true, null);
private MyActiveAnnotationGutter myGutter;
ProgressManager.getInstance().run(
new Task.Backgroundable(myEditor.getProject(), "Getting File History", true, PerformInBackgroundOption.ALWAYS_BACKGROUND) {
@Override
public boolean shouldStartInBackground() {
return true;
public void onCancel() {
myEditor.getGutter().closeAllAnnotations();
}
@Override
public void onSuccess() {
}
private void showGutter() {
ActiveAnnotationGutter gutter = new ActiveAnnotationGutter() {
@Override
public void doAction(int lineNum) {
final LastRevision revision = cache.get(lineNum);
if (revision == null) return;
VirtualFile file = getHyperlinkVirtualFile(myHyperlinks.findAllHyperlinksOnLine(lineNum));
if (file == null) return;
final Project project = getProject();
final AbstractVcs vcs = ProjectLevelVcsManager.getInstance(project).getVcsFor(file);
if (vcs != null) {
final VcsRevisionNumber number = revision.getNumber();
final VcsKey vcsKey = vcs.getKeyInstanceMethod();
ShowAllAffectedGenericAction.showSubmittedFiles(project, number, file, vcsKey);
}
}
@Override
public Cursor getCursor(int lineNum) {
return cache.containsKey(lineNum) ? Cursor.getPredefinedCursor(Cursor.HAND_CURSOR) : Cursor.getDefaultCursor();
}
@Override
public String getLineText(int line, Editor editor) {
final LastRevision revision = cache.get(line);
if (revision != null) {
return String.format("%"+maxDateLength+"s", DateFormatUtil.formatPrettyDate(revision.getDate())) + " " + revision.getAuthor();
}
return "";
}
@Override
public String getToolTip(int line, Editor editor) {
final LastRevision revision = cache.get(line);
if (revision != null) {
return XmlStringUtil.escapeString(
revision.getAuthor() + " " + DateFormatUtil.formatDateTime(revision.getDate()) + "\n" +
revision.getMessage()
);
}
return null;
}
@Override
public EditorFontType getStyle(int line, Editor editor) {
LastRevision revision = cache.get(line);
return revision != null && revision.getDate().equals(newestDate) ? EditorFontType.BOLD : EditorFontType.PLAIN;
}
@Override
public ColorKey getColor(int line, Editor editor) {
return AnnotationSource.LOCAL.getColor();
}
@Override
public Color getBgColor(int line, Editor editor) {
return null;
}
@Override
public List<AnAction> getPopupActions(int line, Editor editor) {
return Collections.emptyList();
}
@Override
public void gutterClosed() {
myGutterShowed = false;
}
};
myEditor.getGutter().registerTextAnnotation(gutter, gutter);
myGutterShowed = true;
public void onFinished() {
myIsLoading = false;
Disposer.dispose(myUpdateQueue);
}
@Override
public void run(@NotNull final ProgressIndicator indicator) {
final List<VirtualFile> files = new ArrayList<VirtualFile>();
final HashMap<VirtualFile, List<Integer>> files2lines = new HashMap<VirtualFile, List<Integer>>();
public void run(@NotNull ProgressIndicator indicator) {
MultiMap<VirtualFile, Integer> files2lines = new MultiMap<>();
Map<Integer, LastRevision> revisions = ContainerUtil.newHashMap();
ApplicationManager.getApplication().runReadAction(() -> {
for (int line = 0; line < myEditor.getDocument().getLineCount(); line++) {
@@ -180,52 +115,58 @@ public class AnnotateStackTraceAction extends AnAction implements DumbAware {
VirtualFile file = getHyperlinkVirtualFile(myHyperlinks.findAllHyperlinksOnLine(line));
if (file == null) continue;
if (files2lines.containsKey(file)) {
files2lines.get(file).add(line);
}
else {
final ArrayList<Integer> lines = new ArrayList<Integer>();
lines.add(line);
files2lines.put(file, lines);
files.add(file);
}
files2lines.putValue(file, line);
}
});
for (VirtualFile file : files) {
files2lines.entrySet().forEach(entry -> {
indicator.checkCanceled();
VirtualFile file = entry.getKey();
Collection<Integer> lines = entry.getValue();
LastRevision revision = getLastRevision(file);
if (revision != null) {
final List<Integer> lines = files2lines.get(file);
if (revision == null) return;
final Date date = revision.getDate();
if (newestDate == null || date.after(newestDate)) {
newestDate = date;
}
final int length = DateFormatUtil.formatPrettyDate(date).length();
if (length > maxDateLength) {
maxDateLength = length;
}
synchronized (LOCK) {
for (Integer line : lines) {
cache.put(line, revision);
revisions.put(line, revision);
}
ApplicationManager.getApplication().invokeLater(() -> {
if (!myGutterShowed) {
showGutter();
}
else {
((EditorGutterComponentEx)myEditor.getGutter()).revalidateMarkup();
}
});
}
myUpdateQueue.queue(new Update("update") {
@Override
public void run() {
updateGutter(indicator, revisions);
}
});
});
// myUpdateQueue can be disposed before the last revisions are passed to the gutter
ApplicationManager.getApplication().invokeLater(() -> updateGutter(indicator, revisions));
}
@CalledInAwt
private void updateGutter(@NotNull ProgressIndicator indicator, @NotNull Map<Integer, LastRevision> revisions) {
if (indicator.isCanceled()) return;
if (myGutter == null) {
myGutter = new MyActiveAnnotationGutter(getProject(), myHyperlinks, indicator);
myEditor.getGutter().registerTextAnnotation(myGutter, myGutter);
}
Map<Integer, LastRevision> revisionsCopy;
synchronized (LOCK) {
revisionsCopy = ContainerUtil.newHashMap(revisions);
}
myGutter.updateData(revisionsCopy);
((EditorGutterComponentEx)myEditor.getGutter()).revalidateMarkup();
}
@Nullable
private LastRevision getLastRevision(@NotNull VirtualFile file) {
try {
final AbstractVcs vcs = VcsUtil.getVcsFor(myEditor.getProject(), file);
AbstractVcs vcs = VcsUtil.getVcsFor(myEditor.getProject(), file);
if (vcs == null) return null;
VcsHistoryProvider historyProvider = vcs.getVcsHistoryProvider();
@@ -237,7 +178,8 @@ public class AnnotateStackTraceAction extends AnAction implements DumbAware {
VcsFileRevision revision = ((VcsHistoryProviderEx)historyProvider).getLastRevision(filePath);
if (revision == null) return null;
return LastRevision.create(revision);
} else {
}
else {
VcsHistorySession session = historyProvider.createSessionFor(filePath);
if (session == null) return null;
@@ -255,11 +197,6 @@ public class AnnotateStackTraceAction extends AnAction implements DumbAware {
});
}
@Override
public void update(AnActionEvent e) {
e.getPresentation().setEnabled(!myGutterShowed);
}
@Nullable
@CalledWithReadLock
private static VirtualFile getHyperlinkVirtualFile(@NotNull List<RangeHighlighter> links) {
@@ -313,4 +250,112 @@ public class AnnotateStackTraceAction extends AnAction implements DumbAware {
return myMessage;
}
}
private static class MyActiveAnnotationGutter implements ActiveAnnotationGutter {
@NotNull private final Project myProject;
@NotNull private final EditorHyperlinkSupport myHyperlinks;
@NotNull private final ProgressIndicator myIndicator;
@NotNull private Map<Integer, LastRevision> myRevisions = Collections.emptyMap();
private Date myNewestDate = null;
private int myMaxDateLength = 0;
public MyActiveAnnotationGutter(@NotNull Project project,
@NotNull EditorHyperlinkSupport hyperlinks,
@NotNull ProgressIndicator indicator) {
myProject = project;
myHyperlinks = hyperlinks;
myIndicator = indicator;
}
@Override
public void doAction(int lineNum) {
LastRevision revision = myRevisions.get(lineNum);
if (revision == null) return;
VirtualFile file = getHyperlinkVirtualFile(myHyperlinks.findAllHyperlinksOnLine(lineNum));
if (file == null) return;
AbstractVcs vcs = ProjectLevelVcsManager.getInstance(myProject).getVcsFor(file);
if (vcs != null) {
VcsRevisionNumber number = revision.getNumber();
VcsKey vcsKey = vcs.getKeyInstanceMethod();
ShowAllAffectedGenericAction.showSubmittedFiles(myProject, number, file, vcsKey);
}
}
@Override
public Cursor getCursor(int lineNum) {
return myRevisions.containsKey(lineNum) ? Cursor.getPredefinedCursor(Cursor.HAND_CURSOR) : Cursor.getDefaultCursor();
}
@Override
public String getLineText(int line, Editor editor) {
LastRevision revision = myRevisions.get(line);
if (revision != null) {
return String.format("%" + myMaxDateLength + "s", DateFormatUtil.formatPrettyDate(revision.getDate())) + " " + revision.getAuthor();
}
return "";
}
@Override
public String getToolTip(int line, Editor editor) {
LastRevision revision = myRevisions.get(line);
if (revision != null) {
return XmlStringUtil.escapeString(
revision.getAuthor() + " " + DateFormatUtil.formatDateTime(revision.getDate()) + "\n" +
revision.getMessage()
);
}
return null;
}
@Override
public EditorFontType getStyle(int line, Editor editor) {
LastRevision revision = myRevisions.get(line);
return revision != null && revision.getDate().equals(myNewestDate) ? EditorFontType.BOLD : EditorFontType.PLAIN;
}
@Override
public ColorKey getColor(int line, Editor editor) {
return AnnotationSource.LOCAL.getColor();
}
@Override
public Color getBgColor(int line, Editor editor) {
return null;
}
@Override
public List<AnAction> getPopupActions(int line, Editor editor) {
return Collections.emptyList();
}
@Override
public void gutterClosed() {
myIndicator.cancel();
}
@CalledInAwt
public void updateData(@NotNull Map<Integer, LastRevision> revisions) {
myRevisions = revisions;
Date newestDate = null;
int maxDateLength = 0;
for (LastRevision revision : myRevisions.values()) {
Date date = revision.getDate();
if (newestDate == null || date.after(newestDate)) {
newestDate = date;
}
int length = DateFormatUtil.formatPrettyDate(date).length();
if (length > maxDateLength) {
maxDateLength = length;
}
}
myNewestDate = newestDate;
myMaxDateLength = maxDateLength;
}
}
}
@@ -38,7 +38,6 @@ import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.progress.impl.BackgroundableProcessIndicator;
import com.intellij.openapi.project.*;
import com.intellij.openapi.roots.*;
@@ -119,10 +118,6 @@ public class FileBasedIndexImpl extends FileBasedIndex {
private final List<IndexableFileSet> myIndexableSets = ContainerUtil.createLockFreeCopyOnWriteList();
private final Map<IndexableFileSet, Project> myIndexableSetToProjectMap = new THashMap<IndexableFileSet, Project>();
private static final int OK = 1;
private static final int REQUIRES_REBUILD = 2;
private static final Map<ID<?, ?>, AtomicInteger> ourRebuildStatus = new THashMap<ID<?, ?>, AtomicInteger>();
private final MessageBusConnection myConnection;
private final FileDocumentManager myFileDocumentManager;
private final FileTypeManagerImpl myFileTypeManager;
@@ -521,8 +516,8 @@ public class FileBasedIndexImpl extends FileBasedIndex {
for (ID<?, ?> indexId : state.getIndexIDs()) {
final UpdatableIndex<?, ?, FileContent> index = state.getIndex(indexId);
assert index != null;
if(ourRebuildStatus.get(indexId).get() != OK) {
doClearIndex(indexId); // if the index was scheduled for rebuild, only clean it
if (!RebuildStatus.isOk(indexId)) {
index.clear(); // if the index was scheduled for rebuild, only clean it
}
index.dispose();
}
@@ -706,7 +701,7 @@ public class FileBasedIndexImpl extends FileBasedIndex {
try {
if (isUpToDateCheckEnabled()) {
try {
if (ourRebuildStatus.get(indexId).get() != OK) {
if (!RebuildStatus.isOk(indexId)) {
throw new ProcessCanceledException();
}
forceUpdate(project, filter, restrictedFile);
@@ -1178,12 +1173,21 @@ public class FileBasedIndexImpl extends FileBasedIndex {
}
}
private void clearIndex(@NotNull final ID<?, ?> indexId) throws StorageException {
advanceIndexVersion(indexId);
doClearIndex(indexId);
void clearIndicesIfNecessary() {
for (ID<?, ?> indexId : getState().getIndexIDs()) {
try {
RebuildStatus.clearIndexIfNecessary(indexId, getIndex(indexId)::clear);
}
catch (StorageException e) {
requestRebuild(indexId);
LOG.error(e);
}
}
}
private void doClearIndex(ID<?, ?> indexId) throws StorageException {
private void clearIndex(@NotNull final ID<?, ?> indexId) throws StorageException {
advanceIndexVersion(indexId);
final UpdatableIndex<?, ?, FileContent> index = myState.getIndex(indexId);
assert index != null : "Index with key " + indexId + " not found or not registered properly";
index.clear();
@@ -1419,10 +1423,7 @@ public class FileBasedIndexImpl extends FileBasedIndex {
@Override
public void requestRebuild(final ID<?, ?> indexId, final Throwable throwable) {
cleanupProcessedFlag();
final AtomicInteger status = ourRebuildStatus.get(indexId);
boolean requiresRebuildWasSet = status.compareAndSet(OK, REQUIRES_REBUILD);
if (requiresRebuildWasSet) {
if (RebuildStatus.requestRebuild(indexId)) {
String message = "Rebuild requested for index " + indexId;
Application app = ApplicationManager.getApplication();
if (app.isUnitTestMode() && app.isReadAccessAllowed() && !app.isDispatchThread()) {
@@ -1438,34 +1439,13 @@ public class FileBasedIndexImpl extends FileBasedIndex {
if (!myInitialized) return;
advanceIndexVersion(indexId);
final Runnable rebuildRunnable = () -> {
final Ref<Boolean> success = Ref.create(true);
new Task.Modal(null, "Updating index", false) {
@Override
public void run(@NotNull final ProgressIndicator indicator) {
indicator.setIndeterminate(true);
try {
doClearIndex(indexId);
}
catch (StorageException e) {
success.set(false);
requestRebuild(indexId);
LOG.info(e);
}
}
}.queue();
if (success.get()) {
scheduleIndexRebuild("checkRebuild");
status.compareAndSet(REQUIRES_REBUILD, OK);
}
};
Runnable rebuildRunnable = () -> scheduleIndexRebuild("checkRebuild");
if (myIsUnitTestMode) {
rebuildRunnable.run();
}
else {
// we do invoke later since we can have read lock acquired
//noinspection SSBasedInspection
TransactionGuard.getInstance().submitTransactionLater(app, rebuildRunnable);
}
}
@@ -1646,12 +1626,7 @@ public class FileBasedIndexImpl extends FileBasedIndex {
void updateSingleIndex(@NotNull ID<?, ?> indexId, VirtualFile file, final int inputId, @Nullable FileContent currentFC)
throws StorageException {
AtomicInteger rebuildStatus = ourRebuildStatus.get(indexId);
if (rebuildStatus == null) {
LOG.error("Problem updating " + indexId + " for " + inputId + "," + file + " with content:" + currentFC + ", initialized:" + myInitialized);
return;
}
if (rebuildStatus.get() == REQUIRES_REBUILD && !myIsUnitTestMode) {
if (!RebuildStatus.isOk(indexId) && !myIsUnitTestMode) {
return; // the index is scheduled for rebuild, no need to update
}
myLocalModCount++;
@@ -2356,7 +2331,7 @@ public class FileBasedIndexImpl extends FileBasedIndex {
public FileIndexDataInitialization(FileBasedIndexExtension[] extensions) {
for (FileBasedIndexExtension<?, ?> extension : extensions) {
ID<?, ?> name = extension.getName();
ourRebuildStatus.put(name, new AtomicInteger(OK));
RebuildStatus.registerIndex(name);
myUnsavedDataUpdateTasks.put(name, new DocumentUpdateTask(name));
@@ -2426,14 +2401,12 @@ public class FileBasedIndexImpl extends FileBasedIndex {
myState = state; // memory barrier
// check if rebuild was requested for any index during registration
for (ID<?, ?> indexId : state.getIndexIDs()) {
if (ourRebuildStatus.get(indexId).compareAndSet(REQUIRES_REBUILD, OK)) {
try {
clearIndex(indexId);
}
catch (StorageException e) {
requestRebuild(indexId);
LOG.error(e);
}
try {
RebuildStatus.clearIndexIfNecessary(indexId, () -> clearIndex(indexId));
}
catch (StorageException e) {
requestRebuild(indexId);
LOG.error(e);
}
}
@@ -0,0 +1,81 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.util.indexing;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.util.ThrowableRunnable;
import com.intellij.util.TimeoutUtil;
import com.intellij.util.containers.ContainerUtil;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
/**
* @author peter
*/
enum RebuildStatus {
OK,
REQUIRES_REBUILD,
DOING_REBUILD;
private static final Map<ID<?, ?>, AtomicReference<RebuildStatus>> ourRebuildStatus = ContainerUtil.newTroveMap();
static void registerIndex(ID<?, ?> indexId) {
ourRebuildStatus.put(indexId, new AtomicReference<>(OK));
}
static boolean isOk(ID<?, ?> indexId) {
return ourRebuildStatus.get(indexId).get() == OK;
}
static boolean requestRebuild(ID<?, ?> indexId) {
return ourRebuildStatus.get(indexId).compareAndSet(OK, REQUIRES_REBUILD);
}
static void clearIndexIfNecessary(ID<?, ?> indexId, ThrowableRunnable<StorageException> clearAction) throws StorageException {
AtomicReference<RebuildStatus> rebuildStatus = ourRebuildStatus.get(indexId);
if (rebuildStatus == null) {
throw new StorageException("Problem updating " + indexId);
}
if (rebuildStatus.compareAndSet(REQUIRES_REBUILD, DOING_REBUILD)) {
doClear(clearAction, rebuildStatus);
} else {
waitUntilIndexReady(rebuildStatus);
}
}
private static void doClear(ThrowableRunnable<StorageException> clearAction, AtomicReference<RebuildStatus> status) throws StorageException {
try {
clearAction.run();
}
catch (StorageException e) {
status.compareAndSet(DOING_REBUILD, REQUIRES_REBUILD);
throw e;
}
if (!status.compareAndSet(DOING_REBUILD, OK)) {
FileBasedIndexImpl.LOG.error("Unexpected status " + status.get());
}
}
private static void waitUntilIndexReady(AtomicReference<RebuildStatus> rebuildStatus) {
while (rebuildStatus.get() != OK) {
ProgressManager.checkCanceled();
TimeoutUtil.sleep(50);
}
}
}
@@ -18,7 +18,6 @@ package com.intellij.util.indexing;
import com.intellij.ProjectTopics;
import com.intellij.diagnostic.PerformanceWatcher;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.caches.FileContent;
import com.intellij.ide.startup.impl.StartupManagerImpl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
@@ -34,7 +33,6 @@ import com.intellij.openapi.roots.ModuleRootEvent;
import com.intellij.openapi.roots.impl.PushedFilePropertiesUpdater;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.NotNull;
import java.util.List;
@@ -71,6 +69,8 @@ public class UnindexedFilesUpdater extends DumbModeTask {
indicator.setIndeterminate(true);
indicator.setText(IdeBundle.message("progress.indexing.scanning"));
myIndex.clearIndicesIfNecessary();
CollectingContentIterator finder = myIndex.createContentIterator(indicator);
snapshot = PerformanceWatcher.takeSnapshot();
+1
View File
@@ -36,5 +36,6 @@
<orderEntry type="library" name="Guava" level="project" />
<orderEntry type="library" name="http-client" level="project" />
<orderEntry type="library" name="jna" level="project" />
<orderEntry type="library" name="KotlinJavaRuntime" level="project" />
</component>
</module>
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 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.
@@ -31,11 +31,8 @@ import com.intellij.openapi.util.registry.RegistryValue;
import com.intellij.ui.LoadingNode;
import com.intellij.ui.treeStructure.AlwaysExpandedTree;
import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.Alarm;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Consumer;
import com.intellij.util.SmartList;
import com.intellij.util.concurrency.WorkerThread;
import com.intellij.util.*;
import com.intellij.util.concurrency.QueueProcessor;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashSet;
import com.intellij.util.enumeration.EnumerationCopy;
@@ -49,6 +46,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.concurrency.AsyncPromise;
import org.jetbrains.concurrency.Promise;
import org.jetbrains.concurrency.Promises;
import javax.swing.*;
import javax.swing.event.*;
@@ -96,7 +94,10 @@ public class AbstractTreeUi {
private TreeExpansionListener myExpansionListener;
private MySelectionListener mySelectionListener;
private WorkerThread myWorker = null;
private final QueueProcessor<Runnable> myWorker = new QueueProcessor<Runnable>(runnable -> {
runnable.run();
TimeoutUtil.sleep(1);
});
private final Set<Runnable> myActiveWorkerTasks = new HashSet<Runnable>();
private ProgressIndicator myProgress;
@@ -455,10 +456,8 @@ public class AbstractTreeUi {
disposeNode(getRootNode());
myElementToNodeMap.clear();
getUpdater().cancelAllRequests();
if (myWorker != null) {
myWorker.dispose(true);
clearWorkerTasks();
}
myWorker.clear();
clearWorkerTasks();
TREE_NODE_WRAPPER.setValue(null);
if (myProgress != null) {
myProgress.cancel();
@@ -468,7 +467,6 @@ public class AbstractTreeUi {
myTree = null;
setUpdater(null);
myWorker = null;
myTreeStructure = null;
myBuilder.releaseUi();
myBuilder = null;
@@ -941,7 +939,7 @@ public class AbstractTreeUi {
return update.get();
}
catch (IndexNotReadyException e) {
warnOnIndexNotReady();
warnOnIndexNotReady(e);
return false;
}
}
@@ -1621,7 +1619,7 @@ public class AbstractTreeUi {
});
}
catch (IndexNotReadyException e) {
warnOnIndexNotReady();
warnOnIndexNotReady(e);
return ArrayUtil.EMPTY_OBJECT_ARRAY;
}
finally {
@@ -1653,10 +1651,10 @@ public class AbstractTreeUi {
return passOne.get();
}
private void warnOnIndexNotReady() {
private void warnOnIndexNotReady(IndexNotReadyException e) {
if (!myWasEverIndexNotReady) {
myWasEverIndexNotReady = true;
LOG.warn("Tree is not dumb-mode-aware; treeBuilder=" + getBuilder() + " treeStructure=" + getTreeStructure());
LOG.error("Tree is not dumb-mode-aware; treeBuilder=" + getBuilder() + " treeStructure=" + getTreeStructure(), e);
}
}
@@ -1729,7 +1727,7 @@ public class AbstractTreeUi {
}
}
}
return Promise.all(promises);
return Promises.all(promises);
}
}, pass, node);
}
@@ -3446,18 +3444,8 @@ public class AbstractTreeUi {
execute(pooledThreadRunnable);
}
else {
if (myWorker == null || myWorker.isDisposed()) {
myWorker = new WorkerThread("AbstractTreeBuilder.Worker", 1);
myWorker.start();
myWorker.addTaskFirst(pooledThreadRunnable);
myWorker.dispose(false);
}
else {
myWorker.addTaskFirst(pooledThreadRunnable);
}
myWorker.addFirst(pooledThreadRunnable);
}
return result;
}
@@ -4737,11 +4725,7 @@ public class AbstractTreeUi {
myUnbuiltNodes.clear();
myUpdateFromRootRequested = true;
if (myWorker != null) {
Disposer.dispose(myWorker);
myWorker = null;
}
myWorker.clear();
myTree.invalidate();
state.restore(null);
@@ -1,129 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.util.concurrency;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.util.TimeoutUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.util.LinkedList;
/**
* @deprecated use lightweight com.intellij.util.concurrency.QueueProcessor instead
*/
public class WorkerThread implements Runnable, Disposable {
private final LinkedList<Runnable> myTasks = new LinkedList<Runnable>();
private boolean myToDispose = false;
private boolean myDisposed = false;
private final int mySleep;
private final String myName;
public WorkerThread(@NonNls String name, int sleep) {
mySleep = sleep;
myName = name;
}
public void start() {
ApplicationManager.getApplication().executeOnPooledThread(this);
}
public boolean addTask(Runnable action) {
synchronized(myTasks){
if(myDisposed) return false;
myTasks.add(action);
myTasks.notifyAll();
return true;
}
}
public boolean addTaskFirst(@NotNull Runnable action) {
synchronized(myTasks){
if(myDisposed) return false;
myTasks.add(0, action);
myTasks.notifyAll();
return true;
}
}
@Override
public void dispose() {
dispose(true);
}
public void dispose(boolean cancelTasks){
synchronized(myTasks){
if (cancelTasks){
myTasks.clear();
}
myToDispose = true;
myTasks.notifyAll();
}
}
public void cancelTasks() {
synchronized(myTasks){
myTasks.clear();
myTasks.notifyAll();
}
}
public boolean isDisposeRequested() {
synchronized(myTasks){
return myToDispose;
}
}
public boolean isDisposed() {
synchronized(myTasks){
return myDisposed;
}
}
@Override
public void run() {
while (true) {
while (true) {
Runnable task;
synchronized (myTasks) {
if (myTasks.isEmpty()) break;
task = myTasks.removeFirst();
}
task.run();
if (mySleep > 0) {
TimeoutUtil.sleep(mySleep);
}
}
synchronized (myTasks) {
if (myToDispose && myTasks.isEmpty()) {
myDisposed = true;
return;
}
try {
myTasks.wait();
}
catch (InterruptedException ignored) {
}
}
}
}
}
@@ -0,0 +1,49 @@
/*
* Copyright 2000-2016 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.
*/
@file:JvmName("Promises")
package org.jetbrains.concurrency
import com.intellij.util.Consumer
fun resolvedPromise(): Promise<*> = Promise.DONE
fun <T> resolvedPromise(result: T) = Promise.resolve(result)
fun all(promises: Collection<Promise<*>>) = if (promises.size == 1) promises.first() else all(promises, null)
fun <T> all(promises: Collection<Promise<*>>, totalResult: T?): Promise<T> {
if (promises.isEmpty()) {
return resolvedPromise(null)
}
val totalPromise = AsyncPromise<T>()
val done = CountDownConsumer(promises.size, totalPromise, totalResult)
val rejected = Consumer<Throwable> { error -> totalPromise.setError(error) }
for (promise in promises) {
promise.done(done)
promise.rejected(rejected)
}
return totalPromise
}
private class CountDownConsumer<T>(@Volatile private var countDown: Int, private val promise: AsyncPromise<T>, private val totalResult: T?) : Consumer<Any?> {
override fun consume(t: Any?) {
if (--countDown == 0) {
promise.setResult(totalResult)
}
}
}
@@ -38,6 +38,7 @@ import com.intellij.ui.*;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.ui.components.panels.Wrapper;
import com.intellij.util.Alarm;
import com.intellij.util.ObjectUtils;
import com.intellij.util.ui.Html;
import com.intellij.util.ui.JBInsets;
import com.intellij.util.ui.JBUI;
@@ -57,6 +58,7 @@ import java.awt.event.AWTEventListener;
import java.awt.event.MouseEvent;
public class IdeTooltipManager implements ApplicationComponent, AWTEventListener {
private static final String CUSTOM_TOOLTIP = "custom.tooltip";
public static final String IDE_TOOLTIP_PLACE = "IdeTooltip";
public static final Color GRAPHITE_COLOR = new Color(100, 100, 100, 230);
@@ -177,7 +179,7 @@ public class IdeTooltipManager implements ApplicationComponent, AWTEventListener
}
String tooltipText = comp.getToolTipText(me);
if (tooltipText == null || tooltipText.trim().isEmpty()) return;
if ((tooltipText == null || tooltipText.trim().isEmpty()) && getCustomTooltip(comp) == null) return;
boolean centerDefault = Boolean.TRUE.equals(comp.getClientProperty(UIUtil.CENTER_TOOLTIP_DEFAULT));
@@ -199,29 +201,40 @@ public class IdeTooltipManager implements ApplicationComponent, AWTEventListener
}
private void queueShow(final JComponent c, final MouseEvent me, final boolean toCenter, int shift, int posChangeX, int posChangeY) {
String aText = String.valueOf(c.getToolTipText(me));
final IdeTooltip tooltip = new IdeTooltip(c, me.getPoint(), null, /*new Object()*/c, aText) {
@Override
protected boolean beforeShow() {
myCurrentEvent = me;
IdeTooltip tooltip = getCustomTooltip(c);
if (tooltip == null) {
String aText = String.valueOf(c.getToolTipText(me));
tooltip = new IdeTooltip(c, me.getPoint(), null, /*new Object()*/c, aText) {
@Override
protected boolean beforeShow() {
myCurrentEvent = me;
if (!c.isShowing()) return false;
if (!c.isShowing()) return false;
String text = c.getToolTipText(myCurrentEvent);
if (text == null || text.trim().isEmpty()) return false;
String text = c.getToolTipText(myCurrentEvent);
if (text == null || text.trim().isEmpty()) return false;
JLayeredPane layeredPane = UIUtil.getParentOfType(JLayeredPane.class, c);
JLayeredPane layeredPane = UIUtil.getParentOfType(JLayeredPane.class, c);
final JEditorPane pane = initPane(text, new HintHint(me).setAwtTooltip(true), layeredPane);
final Wrapper wrapper = new Wrapper(pane);
setTipComponent(wrapper);
return true;
}
}.setToCenter(toCenter).setCalloutShift(shift).setPositionChangeShift(posChangeX, posChangeY).setLayer(Balloon.Layer.top);
final JEditorPane pane = initPane(text, new HintHint(me).setAwtTooltip(true), layeredPane);
final Wrapper wrapper = new Wrapper(pane);
setTipComponent(wrapper);
return true;
}
}.setToCenter(toCenter).setCalloutShift(shift).setPositionChangeShift(posChangeX, posChangeY).setLayer(Balloon.Layer.top);
}
show(tooltip, false);
}
public void setCustomTooltip(JComponent component, IdeTooltip tooltip) {
component.putClientProperty(CUSTOM_TOOLTIP, tooltip);
}
public IdeTooltip getCustomTooltip(JComponent component) {
return ObjectUtils.tryCast(component.getClientProperty(CUSTOM_TOOLTIP), IdeTooltip.class);
}
public IdeTooltip show(final IdeTooltip tooltip, boolean now) {
return show(tooltip, now, true);
}
@@ -30,9 +30,11 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.TransactionGuard;
import com.intellij.openapi.components.ApplicationComponent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.keymap.impl.IdeKeyEventDispatcher;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.ui.mac.foundation.Foundation;
import com.intellij.ui.mac.foundation.ID;
import com.sun.jna.Callback;
@@ -40,6 +42,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.Component;
import java.awt.color.ColorSpace;
import java.awt.color.ICC_ColorSpace;
import java.awt.color.ICC_Profile;
@@ -47,12 +50,14 @@ import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* @author max
*/
public class MacOSApplicationProvider implements ApplicationComponent {
private static final Logger LOG = Logger.getInstance(MacOSApplicationProvider.class);
private static final AtomicBoolean ENABLED = new AtomicBoolean(true);
private static final Callback IMPL = new Callback() {
@SuppressWarnings("unused")
public void callback(ID self, String selector) {
@@ -129,13 +134,13 @@ public class MacOSApplicationProvider implements ApplicationComponent {
@Override
public void handlePreferences(ApplicationEvent applicationEvent) {
Project project = getNotNullProject();
TransactionGuard.submitTransaction(project, () -> ShowSettingsAction.perform(project));
submit(() -> ShowSettingsAction.perform(project));
applicationEvent.setHandled(true);
}
@Override
public void handleQuit(ApplicationEvent applicationEvent) {
TransactionGuard.submitTransaction(ApplicationManager.getApplication(), ExitAction::perform);
submit(ExitAction::perform);
}
@Override
@@ -144,7 +149,7 @@ public class MacOSApplicationProvider implements ApplicationComponent {
String filename = applicationEvent.getFilename();
if (filename == null) return;
TransactionGuard.submitTransaction(ApplicationManager.getApplication(), () -> {
submit(() -> {
File file = new File(filename);
if (ProjectUtil.openOrImport(file.getAbsolutePath(), project, true) != null) {
IdeaApplication.getInstance().setPerformProjectLoad(false);
@@ -201,5 +206,22 @@ public class MacOSApplicationProvider implements ApplicationComponent {
Project project = getProject();
return project != null ? project : ProjectManager.getInstance().getDefaultProject();
}
private static void submit(@NotNull Runnable task) {
if (!ENABLED.get()) return;
Component component = IdeFocusManager.getGlobalInstance().getFocusOwner();
if (component == null || IdeKeyEventDispatcher.isModalContext(component)) return;
ENABLED.set(false);
TransactionGuard.submitTransaction(ApplicationManager.getApplication(), () -> {
try {
task.run();
}
finally {
ENABLED.set(true);
}
});
}
}
}
@@ -0,0 +1,59 @@
/*
* Copyright 2000-2016 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.ui;
import com.intellij.ide.BrowserUtil;
import com.intellij.ide.IdeTooltip;
import com.intellij.ide.IdeTooltipManager;
import com.intellij.ide.TooltipEvent;
import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import java.awt.*;
/**
* Custom tooltip implementation which supports clickable links in HTML text
*
* @see IdeTooltipManager#setCustomTooltip(JComponent, IdeTooltip)
*/
public class TooltipWithClickableLinks extends IdeTooltip {
public TooltipWithClickableLinks(JComponent component, String htmlText, HyperlinkListener hyperlinkListener) {
super(component, new Point(), createTipComponent(htmlText, hyperlinkListener), component, htmlText);
}
private static JComponent createTipComponent(String text, HyperlinkListener hyperlinkListener) {
JEditorPane pane = IdeTooltipManager.initPane(text, new HintHint().setAwtTooltip(true), null);
pane.addHyperlinkListener(hyperlinkListener);
return pane;
}
@Override
protected boolean canAutohideOn(TooltipEvent event) {
return !event.isIsEventInsideBalloon();
}
public static class ForBrowser extends TooltipWithClickableLinks {
public ForBrowser(JComponent component, String htmlText) {
super(component, htmlText, new HyperlinkAdapter() {
@Override
protected void hyperlinkActivated(HyperlinkEvent e) {
BrowserUtil.browse(e.getURL());
}
});
}
}
}
@@ -59,7 +59,7 @@ fun Path.delete() {
}
}
fun Path.deleteRecursively(): Path = if (exists()) Files.walkFileTree(this, object : SimpleFileVisitor<Path>() {
fun Path.deleteRecursively(): Path = if (exists()) Files.walkFileTree (this, object : SimpleFileVisitor<Path>() {
override fun visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult {
file.delete()
return FileVisitResult.CONTINUE
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 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.
@@ -25,7 +25,7 @@ private val rejectedPromise = Promise.reject<Any?>("rejected")
// only internal usage
interface ObsolescentFunction<Param, Result> : Function<Param, Result>, Obsolescent
abstract class ValueNodeAsyncFunction<PARAM, RESULT>(private val node: Obsolescent) : AsyncFunction<PARAM, RESULT>, Obsolescent {
abstract class ValueNodeAsyncFunction<PARAM, RESULT>(private val node: Obsolescent) : Function<PARAM, Promise<RESULT>>, Obsolescent {
override fun isObsolete() = node.isObsolete
}
@@ -69,9 +69,9 @@ inline fun <T> Promise<T>.thenAsyncAccept(node: Obsolescent, crossinline handler
override fun `fun`(param: T) = handler(param) as Promise<Any?>
})
inline fun <T> Promise<T>.thenAsyncAccept(crossinline handler: (T) -> Promise<*>) = thenAsync(AsyncFunction<T, kotlin.Any?> { param ->
inline fun <T> Promise<T>.thenAsyncAccept(crossinline handler: (T) -> Promise<*>) = thenAsync(Function<T, Promise<kotlin.Any?>> { param ->
@Suppress("UNCHECKED_CAST")
(return@AsyncFunction handler(param) as Promise<Any?>)
(return@Function handler(param) as Promise<Any?>)
})
@@ -80,15 +80,11 @@ inline fun Promise<*>.rejected(node: Obsolescent, crossinline handler: (Throwabl
})
fun resolvedPromise(): Promise<*> = Promise.DONE
fun <T> resolvedPromise(result: T) = Promise.resolve(result)
fun <T> rejectedPromise(error: String): Promise<T> = Promise.reject(error)
fun <T> rejectedPromise(error: Throwable): Promise<T> = Promise.reject(error)
@Suppress("CAST_NEVER_SUCCEEDS")
@Suppress("UNCHECKED_CAST")
fun <T> rejectedPromise(): Promise<T> = rejectedPromise as Promise<T>
val Promise<*>.isRejected: Boolean
@@ -119,7 +115,7 @@ fun <T> collectResults(promises: List<Promise<T>>): Promise<List<T>> {
for (promise in promises) {
promise.done { results.add(it) }
}
return Promise.all(promises, results)
return all(promises, results)
}
fun createError(error: String, log: Boolean): RuntimeException = Promise.MessageError(error, log)
@@ -533,7 +533,7 @@ checkbox.show.only.monospaced.fonts=Show only monospaced fonts
primary.font=Primary font:
secondary.font=Secondary font:
use.ligatures=Enable font ligatures
ligatures.jre.warning=The JRE you are running {0} with might have\nfunctional and performance issues related to ligatures support.\nTo avoid such issues, run IntelliJ IDEA with the bundled JRE.
ligatures.jre.warning=<html>The JRE you are running {0} with might have<br>functional and performance issues related to ligatures support.<br>To avoid such issues, run {0} with <a href="https://confluence.jetbrains.com/display/IDEADEV/JetBrains+Runtime+Environment">JetBrains Runtime</a>.
editbox.enter.tag.name=Enter tag name:
title.tag.name=Tag Name
title.xml=XML
@@ -30,7 +30,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import java.io.IOException;
import static org.easymock.classextension.EasyMock.*;
import static org.easymock.EasyMock.*;
public class SelectionHistoryDialogTest extends LocalHistoryUITestCase {
private VirtualFile f;
@@ -29,7 +29,7 @@ import org.junit.Test;
import java.util.List;
import static org.easymock.classextension.EasyMock.*;
import static org.easymock.EasyMock.*;
public class SelectionCalculatorTest extends LocalHistoryTestCase {
IdeaGateway gw = new MyIdeaGateway();
@@ -20,7 +20,7 @@ import com.intellij.openapi.diff.*;
import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.util.ArrayUtil;
import org.easymock.classextension.EasyMock;
import org.easymock.EasyMock;
import org.jetbrains.annotations.NotNull;
import org.junit.Test;
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 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.
@@ -23,6 +23,7 @@ import com.intellij.util.Url
import com.intellij.util.containers.ContainerUtil
import gnu.trove.TObjectHashingStrategy
import org.jetbrains.concurrency.Promise
import org.jetbrains.concurrency.all
import org.jetbrains.concurrency.rejectedPromise
import org.jetbrains.concurrency.resolvedPromise
import java.util.concurrent.ConcurrentMap
@@ -90,7 +91,7 @@ abstract class BreakpointManagerBase<T : BreakpointBase<*>> : BreakpointManager
promises.add(doClearBreakpoint(b))
}
}
return Promise.all(promises)
return all(promises)
}
protected abstract fun doClearBreakpoint(breakpoint: T): Promise<*>
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 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,8 +17,9 @@ package org.jetbrains.debugger.values
import com.intellij.util.SmartList
import org.jetbrains.concurrency.Obsolescent
import org.jetbrains.concurrency.ObsolescentAsyncFunction
import org.jetbrains.concurrency.ObsolescentFunction
import org.jetbrains.concurrency.Promise
import org.jetbrains.concurrency.all
import org.jetbrains.debugger.EvaluateContext
import org.jetbrains.debugger.Variable
import org.jetbrains.debugger.VariablesHost
@@ -30,7 +31,7 @@ abstract class ObjectValueBase<VALUE_LOADER : ValueManager>(type: ValueType) : V
override val properties: Promise<List<Variable>>
get() = childrenManager.get()
internal abstract inner class MyObsolescentAsyncFunction<PARAM, RESULT>(private val obsolescent: Obsolescent) : ObsolescentAsyncFunction<PARAM, RESULT> {
internal abstract inner class MyObsolescentAsyncFunction<PARAM, RESULT>(private val obsolescent: Obsolescent) : ObsolescentFunction<PARAM, Promise<RESULT>> {
override fun isObsolete() = obsolescent.isObsolete || childrenManager.valueManager.isObsolete
}
@@ -43,7 +44,7 @@ abstract class ObjectValueBase<VALUE_LOADER : ValueManager>(type: ValueType) : V
override fun getIndexedProperties(from: Int, to: Int, bucketThreshold: Int, consumer: IndexedVariablesConsumer, componentType: ValueType?): Promise<*> = Promise.REJECTED
@Suppress("CAST_NEVER_SUCCEEDS")
@Suppress("UNCHECKED_CAST")
override val variablesHost: VariablesHost<ValueManager>
get() = childrenManager as VariablesHost<ValueManager>
}
@@ -57,9 +58,7 @@ fun getSpecifiedProperties(variables: List<Variable>, names: List<String>, evalu
}
if (!properties.isEmpty()) {
Collections.sort(properties, object : Comparator<Variable> {
override fun compare(o1: Variable, o2: Variable) = names.indexOf(o1.name) - names.indexOf(o2.name)
})
Collections.sort(properties) { o1, o2 -> names.indexOf(o1.name) - names.indexOf(o2.name) }
}
properties.add(property)
@@ -80,6 +79,6 @@ fun getSpecifiedProperties(variables: List<Variable>, names: List<String>, evalu
promises.add(valueModifier!!.evaluateGet(variable, evaluateContext))
}
}
return Promise.all<List<Variable>>(promises, properties)
return all(promises, properties)
}
}
@@ -26,6 +26,7 @@ import com.intellij.xdebugger.breakpoints.XLineBreakpoint
import gnu.trove.THashMap
import gnu.trove.THashSet
import org.jetbrains.concurrency.Promise
import org.jetbrains.concurrency.all
import org.jetbrains.concurrency.resolvedPromise
import java.util.concurrent.atomic.AtomicBoolean
@@ -113,7 +114,7 @@ abstract class LineBreakpointManager(internal val debugProcess: DebugProcessImpl
promises.add(breakpointManager.remove(vmBreakpoint))
}
}
return Promise.all(promises)
return all(promises)
}
fun setBreakpoint(vm: Vm, breakpoint: XLineBreakpoint<*>, locations: List<Location>, promiseRef: Ref<Promise<out Breakpoint>>? = null) {
@@ -233,11 +234,11 @@ abstract class LineBreakpointManager(internal val debugProcess: DebugProcessImpl
}
fun clearRunToLocationBreakpoints(vm: Vm) {
var breakpoints = synchronized (lock) {
val breakpoints = synchronized (lock) {
if (runToLocationBreakpoints.isEmpty) {
return@clearRunToLocationBreakpoints
}
var breakpoints = runToLocationBreakpoints.toArray<Breakpoint>(arrayOfNulls<Breakpoint>(runToLocationBreakpoints.size))
val breakpoints = runToLocationBreakpoints.toArray<Breakpoint>(arrayOfNulls<Breakpoint>(runToLocationBreakpoints.size))
runToLocationBreakpoints.clear()
breakpoints
}
@@ -185,7 +185,7 @@ class VariableView(override val variableName: String, private val variable: Vari
}
if (hasIndexedProperties == hasNamedProperties || additionalProperties != null) {
Promise.all(promises).processed(node) { node.addChildren(XValueChildrenList.EMPTY, true) }
all(promises).processed(node) { node.addChildren(XValueChildrenList.EMPTY, true) }
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 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.
@@ -18,12 +18,13 @@ package org.jetbrains.debugger;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Conditions;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.util.Function;
import com.intellij.xdebugger.frame.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.concurrency.AsyncFunction;
import org.jetbrains.concurrency.AsyncPromise;
import org.jetbrains.concurrency.Promise;
import org.jetbrains.concurrency.Promises;
import org.jetbrains.debugger.values.ObjectValue;
import javax.swing.*;
@@ -105,7 +106,7 @@ public class TestCompositeNode implements XCompositeNode {
assert content == null;
content = new Content();
return result.thenAsync(new AsyncFunction<XValueChildrenList, Content>() {
return result.thenAsync(new Function<XValueChildrenList, Promise<Content>>() {
private void resolveGroups(@NotNull List<XValueGroup> valueGroups, @NotNull List<TestCompositeNode> resultNodes, @NotNull List<Promise<?>> promises) {
for (XValueGroup group : valueGroups) {
TestCompositeNode node = new TestCompositeNode(group);
@@ -115,7 +116,7 @@ public class TestCompositeNode implements XCompositeNode {
}
resultNodes.add(node);
if (computeChildren) {
promises.add(node.loadContent(Conditions.<XValueGroup>alwaysFalse(), valueSubContentResolveCondition));
promises.add(node.loadContent(Conditions.alwaysFalse(), valueSubContentResolveCondition));
}
}
}
@@ -142,7 +143,7 @@ public class TestCompositeNode implements XCompositeNode {
resolveGroups(children.getBottomGroups(), content.bottomGroups, promises);
return Promise.all(promises, content);
return Promises.all(promises, content);
}
});
}
@@ -19,7 +19,7 @@ import com.intellij.execution.testframework.Filter;
import com.intellij.execution.testframework.TestConsoleProperties;
import com.intellij.execution.testframework.sm.runner.ui.MockPrinter;
import com.intellij.psi.search.GlobalSearchScope;
import org.easymock.classextension.EasyMock;
import org.easymock.EasyMock;
import static com.intellij.execution.testframework.sm.runner.states.TestStateInfo.Magnitude;
@@ -1,57 +0,0 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.util.containers;
import java.util.concurrent.ConcurrentMap;
import static com.intellij.util.ObjectUtils.NULL;
/**
* @author peter
*/
public abstract class WeakFactoryMap<T,V> {
private final ConcurrentMap<T, V> myMap = ContainerUtil.createConcurrentWeakKeyWeakValueMap();
protected abstract V create(T key);
public final V get(T key) {
final V v = myMap.get(key);
if (v != null) {
return v == NULL ? null : v;
}
final V value = create(key);
V prev = myMap.putIfAbsent(key, notNull(value));
return prev == null || prev == NULL ? value : prev;
}
public final boolean containsKey(T key) {
return myMap.containsKey(key);
}
public void clear() {
myMap.clear();
}
private static <K> K notNull(K key) {
//noinspection unchecked
return key == null ? (K)NULL : key;
}
public void put(T key, V value) {
myMap.put(notNull(key), notNull(value));
}
}
@@ -213,7 +213,7 @@ class VisiblePackBuilder {
Set<VirtualFile> visibleRoots =
VcsLogUtil.getAllVisibleRoots(providers.keySet(), filterCollection.getRootFilter(), filterCollection.getStructureFilter());
Collection<CommitId> logs = ContainerUtil.newArrayList();
Collection<CommitId> commits = ContainerUtil.newArrayList();
for (Map.Entry<VirtualFile, VcsLogProvider> entry : providers.entrySet()) {
final VirtualFile root = entry.getKey();
@@ -230,10 +230,10 @@ class VisiblePackBuilder {
}
List<TimedVcsCommit> matchingCommits = entry.getValue().getCommitsMatchingFilter(root, rootSpecificCollection, maxCount);
logs.addAll(ContainerUtil.map(matchingCommits, commit -> new CommitId(commit.getId(), root)));
commits.addAll(ContainerUtil.map(matchingCommits, commit -> new CommitId(commit.getId(), root)));
}
return logs;
return commits;
}
@NotNull
@@ -135,7 +135,14 @@ public class GraphColorManagerImpl implements GraphColorManager<Integer> {
}
VcsRef bestRef = ContainerUtil.sorted(ContainerUtil.concat(refs1, refs2), refManager1.getBranchLayoutComparator()).get(0);
return refs1.contains(bestRef) ? -1 : 1;
if (refs1.contains(bestRef)) {
if (refs2.contains(bestRef)) {
LOG.error(
"Different heads " + myHashGetter.fun(head1) + " and " + myHashGetter.fun(head2) + " contain the same reference " + bestRef);
}
return -1;
}
return 1;
}
}
}
@@ -2559,6 +2559,10 @@
key="split.try.with.multiple.resources.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.code.style.issues" enabledByDefault="true" level="INFORMATION"
implementationClass="com.siyeh.ig.exceptions.SplitTryWithMultipleResourcesInspection"/>
<localInspection groupPath="Java" language="JAVA" shortName="SplitMultiCatch" bundle="com.siyeh.InspectionGadgetsBundle"
key="split.try.with.multiple.resources.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.code.style.issues" enabledByDefault="true" level="INFORMATION"
implementationClass="com.siyeh.ig.exceptions.SplitMultiCatchInspection"/>
<!--group.names.threading.issues-->
<localInspection groupPath="Java" language="JAVA" suppressId="AccessToNonThreadSafeStaticField" shortName="AccessToNonThreadSafeStaticFieldFromInstance"
@@ -2189,3 +2189,5 @@ replace.method.ref.with.lambda.name=Replace method reference with lambda
replace.method.ref.with.lambda.descriptor=Replace method reference with lambda
split.try.with.multiple.resources.name=Split Try Statement with Multiple Resources
split.try.with.multiple.resources.descriptor=Split 'try' statement with multiple resources
split.multi.catch.name=Split Multi-Catch into Separate Catch Blocks
split.multi.catch.descriptor=Split multi-catch into separate 'catch' blocks
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2013 Bas Leijdekkers
* Copyright 2010-2016 Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -41,6 +41,7 @@ public class FormatUtils {
formatMethodNames.add("format");
formatMethodNames.add("printf");
formatClassNames.add("java.io.Console");
formatClassNames.add("java.io.PrintWriter");
formatClassNames.add("java.io.PrintStream");
formatClassNames.add("java.util.Formatter");
@@ -68,7 +68,12 @@ public class StaticInitializerReferencesSubClassInspection extends BaseJavaBatch
scope.accept(new PsiRecursiveElementWalkingVisitor() {
@Override
public void visitElement(PsiElement element) {
if (element instanceof PsiClass || element instanceof PsiReferenceParameterList || element instanceof PsiTypeElement) return;
if (element instanceof PsiClass ||
element instanceof PsiReferenceParameterList ||
element instanceof PsiTypeElement ||
element instanceof PsiLambdaExpression) {
return;
}
PsiClass targetClass = extractClass(element);
if (targetClass != null && targetClass.isInheritor(baseClass, true) && !hasSingleInitializationPlace(targetClass)) {
@@ -0,0 +1,141 @@
/*
* Copyright 2011 Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.siyeh.ig.exceptions;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import static com.intellij.util.ObjectUtils.assertNotNull;
public class SplitMultiCatchInspection extends BaseInspection {
@Nls
@NotNull
@Override
public String getDisplayName() {
return InspectionGadgetsBundle.message("split.multi.catch.name");
}
@NotNull
@Override
protected String buildErrorString(Object... infos) {
return InspectionGadgetsBundle.message("split.multi.catch.descriptor");
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new SplitMultiCatchVisitor();
}
@Nullable
@Override
protected InspectionGadgetsFix buildFix(Object... infos) {
return new SplitMultiCatchFix();
}
private static void doFixImpl(@NotNull PsiElement element) throws IncorrectOperationException {
final PsiElement parent = element.getParent();
if (!(parent instanceof PsiCatchSection)) {
return;
}
final PsiCatchSection catchSection = (PsiCatchSection)parent;
final PsiElement grandParent = catchSection.getParent();
if (!(grandParent instanceof PsiTryStatement)) {
return;
}
final PsiParameter parameter = catchSection.getParameter();
if (parameter == null) {
return;
}
final PsiType type = parameter.getType();
if (!(type instanceof PsiDisjunctionType)) {
return;
}
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(element.getProject());
final JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(element.getProject());
for (PsiType disjunction : ((PsiDisjunctionType)type).getDisjunctions()) {
final PsiCatchSection copy = (PsiCatchSection)catchSection.copy();
final PsiTypeElement typeElement = assertNotNull(assertNotNull(copy.getParameter()).getTypeElement());
final PsiTypeElement newTypeElement = factory.createTypeElementFromText(disjunction.getCanonicalText(true), catchSection);
final PsiElement replaced = typeElement.replace(newTypeElement);
grandParent.addBefore(copy, catchSection);
styleManager.shortenClassReferences(replaced);
}
catchSection.delete();
}
private static boolean isAcceptable(@NotNull PsiElement element) {
final PsiElement parent = element.getParent();
if (parent instanceof PsiCatchSection) {
final PsiType type = ((PsiCatchSection)parent).getCatchType();
return type instanceof PsiDisjunctionType;
}
return false;
}
private static class SplitMultiCatchVisitor extends BaseInspectionVisitor {
@Override
public void visitParameter(PsiParameter parameter) {
super.visitParameter(parameter);
if (isAcceptable(parameter)) {
registerError(parameter);
}
}
@Override
public void visitKeyword(PsiKeyword keyword) {
super.visitKeyword(keyword);
if (isAcceptable(keyword)) {
registerError(keyword);
}
}
}
private static class SplitMultiCatchFix extends InspectionGadgetsFix {
@Nls
@NotNull
@Override
public String getName() {
return InspectionGadgetsBundle.message("split.multi.catch.descriptor");
}
@Nls
@NotNull
@Override
public String getFamilyName() {
return getName();
}
@Override
protected void doFix(Project project, ProblemDescriptor descriptor) {
doFixImpl(descriptor.getPsiElement());
}
}
}
@@ -60,7 +60,7 @@ public class SplitTryWithMultipleResourcesInspection extends BaseInspection {
private static void doFixImpl(@NotNull PsiElement element) throws IncorrectOperationException {
final PsiTryStatement tryStatement = (PsiTryStatement)element.getParent();
final PsiResourceList resourceList = tryStatement.getResourceList();
if (resourceList == null) {
if (resourceList == null || resourceList.getResourceVariablesCount() <= 1) {
return;
}
final StringBuilder newTryStatementText = new StringBuilder();
@@ -0,0 +1,6 @@
<html>
<body>
This inspection splits a multi-catch section into separate <b>catch</b> blocks.
<br><br>
</body>
</html>
@@ -0,0 +1,10 @@
import java.io.*;
public class AtCodeBlock {
void foo() {
try {
Reader reader = new FileReader("");
} catch (IndexOutOfBoundsException | FileNotFoundException e) {<caret>
}
}
}
@@ -0,0 +1,16 @@
import java.io.IOException;
import java.net.*;
public class AtParameter {
void f() {
try {
throw new NoRouteToHostException();
} catch (NoRouteToHostException e) {
e.printStackTrace();
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@@ -0,0 +1,12 @@
import java.io.IOException;
import java.net.*;
public class AtParameter {
void f() {
try {
throw new NoRouteToHostException();
} catch (NoRouteToHostException | SocketException | IOException<caret> e) {
e.printStackTrace();
}
}
}
@@ -7,6 +7,7 @@ class Super {
static Super USED_PRIVATE = new <warning descr="Referencing subclass MyUsedSub from superclass Super initializer might lead to class loading deadlock">MyUsedSub</warning>();
static Object OK_INSIDE_ANONYMOUS = new Object() {{ Sub s = new Sub(); }};
static Runnable OK_INSIDE_LAMBDA = () -> { Sub s = new Sub(); };
static Object OK_UNRELATED = "abc";
static Super OK_SAME = new Super();
static Super OK_SAME_ANONYMOUS = new Super(){};
@@ -0,0 +1,35 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.siyeh.ig.fixes.exceptions;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.IGQuickFixesTestCase;
import com.siyeh.ig.exceptions.SplitMultiCatchInspection;
public class SplitMultiCatchFixTest extends IGQuickFixesTestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
myFixture.enableInspections(new SplitMultiCatchInspection());
myDefaultHint = InspectionGadgetsBundle.message("split.multi.catch.descriptor");
myRelativePath = "exceptions/split_multi_catch";
}
public void testSimple() { doTest(); }
public void testTypeAnno() { doTest(); }
public void testAtParameter() { doTest(); }
public void testAtCodeBlock() { assertQuickfixNotAvailable(); }
}

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