mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
+45
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -16,12 +16,17 @@
|
||||
package com.intellij.openapi.roots.ui.configuration.libraryEditor;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.lang.LangBundle;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
|
||||
import com.intellij.openapi.project.ProjectBundle;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.projectRoots.ui.SdkPathEditor;
|
||||
import com.intellij.openapi.roots.OrderRootType;
|
||||
import com.intellij.openapi.roots.ui.OrderRootTypeUIFactory;
|
||||
import com.intellij.openapi.vfs.JrtFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.components.JBList;
|
||||
import com.intellij.util.PlatformIcons;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
@@ -33,7 +38,7 @@ public class ClassesOrderRootTypeUIFactory implements OrderRootTypeUIFactory {
|
||||
@Override
|
||||
public SdkPathEditor createPathEditor(Sdk sdk) {
|
||||
FileChooserDescriptor descriptor = new FileChooserDescriptor(true, true, true, false, true, true);
|
||||
return new SdkPathEditor(ProjectBundle.message("sdk.configure.classpath.tab"), OrderRootType.CLASSES, descriptor);
|
||||
return new MySdkPathEditor(descriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -45,4 +50,42 @@ public class ClassesOrderRootTypeUIFactory implements OrderRootTypeUIFactory {
|
||||
public String getNodeText() {
|
||||
return ProjectBundle.message("library.classes.node");
|
||||
}
|
||||
|
||||
private static class MySdkPathEditor extends SdkPathEditor {
|
||||
public MySdkPathEditor(FileChooserDescriptor descriptor) {
|
||||
super(ProjectBundle.message("sdk.configure.classpath.tab"), OrderRootType.CLASSES, descriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isRemoveActionEnabled(Object[] values) {
|
||||
if (!super.isRemoveActionEnabled(values)) {
|
||||
return false;
|
||||
}
|
||||
for (Object value : values) {
|
||||
if (isJrtRoot(value)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ListCellRenderer createListCellRenderer(JBList list) {
|
||||
return new PathCellRenderer() {
|
||||
@Override
|
||||
protected String getItemText(Object value) {
|
||||
return isJrtRoot(value) ? LangBundle.message("jrt.node.long") : super.getItemText(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Icon getItemIcon(Object value) {
|
||||
return isJrtRoot(value) ? PlatformIcons.JAR_ICON : super.getItemIcon(value);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isJrtRoot(Object value) {
|
||||
return value instanceof VirtualFile && JrtFileSystem.isRoot((VirtualFile)value);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-6
@@ -82,24 +82,20 @@ public class InferredAnnotationsManagerImpl extends InferredAnnotationsManager {
|
||||
if (owner instanceof PsiMethod && PsiUtil.canBeOverriden((PsiMethod)owner)) {
|
||||
return true;
|
||||
}
|
||||
if (ORG_JETBRAINS_ANNOTATIONS_CONTRACT.equals(annotationFQN) && hasHardcodedContracts(owner)) {
|
||||
if (ORG_JETBRAINS_ANNOTATIONS_CONTRACT.equals(annotationFQN) && HardcodedContracts.hasHardcodedContracts(owner)) {
|
||||
return true;
|
||||
}
|
||||
if (AnnotationUtil.NOT_NULL.equals(annotationFQN) && owner instanceof PsiParameter && owner.getParent() != null) {
|
||||
if (AnnotationUtil.isAnnotated(owner, NullableNotNullManager.getInstance(owner.getProject()).getNullables(), false, false)) {
|
||||
return true;
|
||||
}
|
||||
if (hasHardcodedContracts(owner.getParent().getParent())) {
|
||||
if (HardcodedContracts.hasHardcodedContracts(owner)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean hasHardcodedContracts(PsiElement owner) {
|
||||
return owner instanceof PsiMethod && !HardcodedContracts.getHardcodedContracts((PsiMethod)owner, null).isEmpty();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private PsiAnnotation getInferredContractAnnotation(PsiMethod method) {
|
||||
if (method.getModifierList().findAnnotation(ORG_JETBRAINS_ANNOTATIONS_CONTRACT) != null) {
|
||||
|
||||
+1
-1
@@ -1173,7 +1173,7 @@ public class GenericsHighlightUtil {
|
||||
public static HighlightInfo checkEnumMustNotBeLocal(final PsiClass aClass) {
|
||||
if (!aClass.isEnum()) return null;
|
||||
PsiElement parent = aClass.getParent();
|
||||
if (!(parent instanceof PsiClass || parent instanceof PsiFile)) {
|
||||
if (!(parent instanceof PsiClass || parent instanceof PsiFile || parent instanceof PsiClassLevelDeclarationStatement)) {
|
||||
String description = JavaErrorMessages.message("local.enum");
|
||||
TextRange textRange = HighlightNamesUtil.getClassDeclarationTextRange(aClass);
|
||||
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(textRange).descriptionAndTooltip(description).create();
|
||||
|
||||
+2
-1
@@ -35,6 +35,7 @@ import com.intellij.psi.controlFlow.AnalysisCanceledException;
|
||||
import com.intellij.psi.controlFlow.ControlFlow;
|
||||
import com.intellij.psi.controlFlow.ControlFlowUtil;
|
||||
import com.intellij.psi.impl.source.resolve.DefaultParameterTypeInferencePolicy;
|
||||
import com.intellij.psi.impl.source.resolve.graphInference.FunctionalInterfaceParameterizationUtil;
|
||||
import com.intellij.psi.infos.MethodCandidateInfo;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
@@ -439,7 +440,7 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
|
||||
PsiAnonymousClass aClass) {
|
||||
myMethod = method;
|
||||
myAnonymClass = aClass;
|
||||
final PsiType inferredType = getInferredType(aClass);
|
||||
final PsiType inferredType = FunctionalInterfaceParameterizationUtil.getGroundTargetType(getInferredType(aClass));
|
||||
myEqualInference = !aClass.getBaseClassType().equals(inferredType);
|
||||
}
|
||||
|
||||
|
||||
+12
@@ -164,4 +164,16 @@ public class HardcodedContracts {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean hasHardcodedContracts(@Nullable PsiElement element) {
|
||||
if (element instanceof PsiMethod) {
|
||||
return !getHardcodedContracts((PsiMethod)element, null).isEmpty();
|
||||
}
|
||||
|
||||
if (element instanceof PsiParameter) {
|
||||
return hasHardcodedContracts(element.getParent().getParent());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+27
@@ -20,6 +20,7 @@
|
||||
*/
|
||||
package com.intellij.codeInspection.reference;
|
||||
|
||||
import com.intellij.codeInsight.ExceptionUtil;
|
||||
import com.intellij.codeInspection.InspectionsBundle;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
@@ -30,6 +31,9 @@ import com.intellij.util.VisibilityUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
public class RefJavaUtilImpl extends RefJavaUtil{
|
||||
|
||||
@Override
|
||||
@@ -114,6 +118,29 @@ public class RefJavaUtilImpl extends RefJavaUtil{
|
||||
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(aClass);
|
||||
if (interfaceMethod != null) {
|
||||
refFrom.addReference(refFrom.getRefManager().getReference(interfaceMethod), interfaceMethod, psiFrom, false, true, null);
|
||||
|
||||
PsiElement body = null;
|
||||
PsiElement topElement = null;
|
||||
if (expression instanceof PsiLambdaExpression) {
|
||||
body = ((PsiLambdaExpression)expression).getBody();
|
||||
topElement = expression;
|
||||
}
|
||||
else {
|
||||
final PsiElement resolve = ((PsiMethodReferenceExpression)expression).resolve();
|
||||
if (resolve instanceof PsiMethod) {
|
||||
body = ((PsiMethod)resolve).getBody();
|
||||
topElement = resolve;
|
||||
}
|
||||
}
|
||||
|
||||
final Collection<PsiClassType> exceptionTypes = body != null ? ExceptionUtil.collectUnhandledExceptions(body, topElement, false)
|
||||
: Collections.<PsiClassType>emptyList();
|
||||
RefElement refResolved = refFrom.getRefManager().getReference(interfaceMethod);
|
||||
if (refResolved instanceof RefMethodImpl) {
|
||||
for (final PsiClassType exceptionType : exceptionTypes) {
|
||||
((RefMethodImpl)refResolved).updateThrowsList(exceptionType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-6
@@ -24,7 +24,7 @@ import org.intellij.lang.annotations.Pattern;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class UnusedSymbolLocalInspectionBase extends BaseJavaLocalInspectionTool implements PairedUnfairLocalInspectionTool {
|
||||
public class UnusedSymbolLocalInspectionBase extends BaseJavaLocalInspectionTool {
|
||||
@NonNls public static final String SHORT_NAME = HighlightInfoType.UNUSED_SYMBOL_SHORT_NAME;
|
||||
@NonNls public static final String DISPLAY_NAME = HighlightInfoType.UNUSED_SYMBOL_DISPLAY_NAME;
|
||||
@NonNls public static final String UNUSED_PARAMETERS_SHORT_NAME = "UnusedParameters";
|
||||
@@ -74,9 +74,4 @@ public class UnusedSymbolLocalInspectionBase extends BaseJavaLocalInspectionTool
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getInspectionForBatchShortName() {
|
||||
return UnusedDeclarationInspectionBase.SHORT_NAME;
|
||||
}
|
||||
}
|
||||
|
||||
+6
@@ -15,13 +15,19 @@
|
||||
*/
|
||||
package com.intellij.codeInsight;
|
||||
|
||||
import com.intellij.codeInspection.dataFlow.HardcodedContracts;
|
||||
import com.intellij.openapi.components.State;
|
||||
import com.intellij.openapi.components.Storage;
|
||||
import com.intellij.openapi.components.StoragePathMacros;
|
||||
import com.intellij.psi.PsiElement;
|
||||
|
||||
@State(
|
||||
name = "NullableNotNullManager",
|
||||
storages = {@Storage(file = StoragePathMacros.PROJECT_FILE)}
|
||||
)
|
||||
public class NullableNotNullManagerImpl extends NullableNotNullManager {
|
||||
protected boolean hasHardcodedContracts(PsiElement element) {
|
||||
return HardcodedContracts.hasHardcodedContracts(element);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -27,7 +27,6 @@ package com.intellij.codeInsight.completion;
|
||||
import com.intellij.codeInsight.lookup.CharFilter;
|
||||
import com.intellij.codeInsight.lookup.Lookup;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.impl.LookupImpl;
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.patterns.PsiJavaPatterns;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
@@ -61,6 +60,9 @@ public class JavaCharFilter extends CharFilter {
|
||||
final PsiType type = ((PsiMethod)o).getReturnType();
|
||||
if (type != null && PsiType.BOOLEAN.isAssignableFrom(type)) return Result.SELECT_ITEM_AND_FINISH_LOOKUP;
|
||||
}
|
||||
if (o instanceof PsiKeyword && ((PsiKeyword)o).textMatches(PsiKeyword.INSTANCEOF)) {
|
||||
return Result.SELECT_ITEM_AND_FINISH_LOOKUP;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -19,10 +19,7 @@ import com.intellij.codeInsight.ExpectedTypeInfo;
|
||||
import com.intellij.codeInsight.TailType;
|
||||
import com.intellij.codeInsight.TailTypes;
|
||||
import com.intellij.codeInsight.completion.util.ParenthesesInsertHandler;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupItem;
|
||||
import com.intellij.codeInsight.lookup.PsiTypeLookupItem;
|
||||
import com.intellij.codeInsight.lookup.TailTypeDecorator;
|
||||
import com.intellij.codeInsight.lookup.*;
|
||||
import com.intellij.patterns.ElementPattern;
|
||||
import com.intellij.patterns.PsiJavaElementPattern;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
@@ -491,7 +488,29 @@ public class JavaCompletionData extends JavaAwareCompletionData {
|
||||
}
|
||||
|
||||
if (isInstanceofPlace(position)) {
|
||||
result.addElement(TailTypeDecorator.withTail(createKeyword(position, PsiKeyword.INSTANCEOF), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
result.addElement(LookupElementDecorator.withInsertHandler(
|
||||
createKeyword(position, PsiKeyword.INSTANCEOF),
|
||||
new InsertHandler<LookupElementDecorator<LookupElement>>() {
|
||||
@Override
|
||||
public void handleInsert(InsertionContext context, LookupElementDecorator<LookupElement> item) {
|
||||
TailType tailType = TailType.HUMBLE_SPACE_BEFORE_WORD;
|
||||
if (tailType.isApplicable(context)) {
|
||||
tailType.processTail(context.getEditor(), context.getTailOffset());
|
||||
}
|
||||
|
||||
if ('!' == context.getCompletionChar()) {
|
||||
context.setAddCompletionChar(false);
|
||||
context.commitDocument();
|
||||
PsiInstanceOfExpression expr =
|
||||
PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getStartOffset(), PsiInstanceOfExpression.class, false);
|
||||
if (expr != null) {
|
||||
String space = context.getCodeStyleSettings().SPACE_WITHIN_PARENTHESES ? " " : "";
|
||||
context.getDocument().insertString(expr.getTextRange().getStartOffset(), "!(" + space);
|
||||
context.getDocument().insertString(context.getTailOffset(), space + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
if (isSuitableForClass(position)) {
|
||||
|
||||
+13
-4
@@ -18,6 +18,7 @@ package com.intellij.codeInsight.completion;
|
||||
import com.intellij.codeInsight.generation.*;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
||||
import com.intellij.codeInspection.ex.GlobalInspectionContextBase;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.util.Iconable;
|
||||
import com.intellij.openapi.util.Key;
|
||||
@@ -30,10 +31,7 @@ import com.intellij.util.VisibilityUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
import static com.intellij.patterns.PlatformPatterns.psiElement;
|
||||
|
||||
@@ -137,6 +135,17 @@ public class JavaGenerateMemberCompletionContributor {
|
||||
List<PsiGenerationInfo<PsiMethod>> newInfos = GenerateMembersUtil
|
||||
.insertMembersAtOffset(context.getFile(), context.getStartOffset(), infos);
|
||||
if (!newInfos.isEmpty()) {
|
||||
final List<PsiElement> elements = new ArrayList<PsiElement>();
|
||||
for (GenerationInfo member : newInfos) {
|
||||
if (!(member instanceof TemplateGenerationInfo)) {
|
||||
final PsiMember psiMember = member.getPsiMember();
|
||||
if (psiMember != null) {
|
||||
elements.add(psiMember);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GlobalInspectionContextBase.cleanupElements(context.getProject(), null, elements.toArray(new PsiElement[elements.size()]));
|
||||
newInfos.get(0).positionCaret(context.getEditor(), true);
|
||||
}
|
||||
}
|
||||
|
||||
+10
-5
@@ -33,11 +33,16 @@ public class JavadocCompletionConfidence extends CompletionConfidence {
|
||||
@NotNull
|
||||
@Override
|
||||
public ThreeState shouldSkipAutopopup(@NotNull PsiElement contextElement, @NotNull PsiFile psiFile, int offset) {
|
||||
if (psiElement().inside(PsiDocTag.class).accepts(contextElement) && findJavaReference(psiFile, offset - 1) != null) {
|
||||
return ThreeState.NO;
|
||||
}
|
||||
if (PlatformPatterns.psiElement(JavaDocTokenType.DOC_TAG_NAME).accepts(contextElement)) {
|
||||
return ThreeState.NO;
|
||||
if (psiElement().inside(PsiDocTag.class).accepts(contextElement)) {
|
||||
if (findJavaReference(psiFile, offset - 1) != null) {
|
||||
return ThreeState.NO;
|
||||
}
|
||||
if (PlatformPatterns.psiElement(JavaDocTokenType.DOC_TAG_NAME).accepts(contextElement)) {
|
||||
return ThreeState.NO;
|
||||
}
|
||||
if (contextElement.textMatches("#")) {
|
||||
return ThreeState.NO;
|
||||
}
|
||||
}
|
||||
return super.shouldSkipAutopopup(contextElement, psiFile, offset);
|
||||
}
|
||||
|
||||
+2
-2
@@ -171,8 +171,8 @@ public class AddExceptionToCatchFix extends BaseIntentionAction {
|
||||
if (element == null) return null;
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
final PsiElement parent = PsiTreeUtil.getParentOfType(element, PsiTryStatement.class, PsiMethod.class);
|
||||
if (parent == null || parent instanceof PsiMethod) return null;
|
||||
final PsiElement parent = PsiTreeUtil.getParentOfType(element, PsiTryStatement.class, PsiMethod.class, PsiFunctionalExpression.class);
|
||||
if (parent == null || parent instanceof PsiMethod || parent instanceof PsiFunctionalExpression) return null;
|
||||
final PsiTryStatement statement = (PsiTryStatement) parent;
|
||||
|
||||
final PsiCodeBlock tryBlock = statement.getTryBlock();
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ public class GeneralizeCatchFix implements IntentionAction {
|
||||
myTryStatement = (PsiTryStatement)element.getParent();
|
||||
break;
|
||||
}
|
||||
if (element instanceof PsiMethod || (element instanceof PsiClass && !(element instanceof PsiAnonymousClass))) break;
|
||||
if (element instanceof PsiMethod || element instanceof PsiFunctionalExpression || (element instanceof PsiClass && !(element instanceof PsiAnonymousClass))) break;
|
||||
element = element.getParent();
|
||||
}
|
||||
if (myTryStatement == null) return false;
|
||||
|
||||
@@ -16,9 +16,11 @@
|
||||
package com.intellij.ide.navigationToolbar;
|
||||
|
||||
import com.intellij.analysis.AnalysisScopeBundle;
|
||||
import com.intellij.lang.LangBundle;
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.vfs.JrtFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.presentation.java.ClassPresentationUtil;
|
||||
@@ -39,6 +41,9 @@ public class JavaNavBarExtension extends AbstractNavBarModelExtension {
|
||||
final String name = ((PsiPackage)object).getName();
|
||||
return name != null ? name : AnalysisScopeBundle.message("dependencies.tree.node.default.package.abbreviation");
|
||||
}
|
||||
else if (object instanceof PsiDirectory && JrtFileSystem.isRoot(((PsiDirectory)object).getVirtualFile())) {
|
||||
return LangBundle.message("jrt.node.short");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+6
@@ -20,8 +20,10 @@ import com.intellij.ide.projectView.impl.nodes.PackageElement;
|
||||
import com.intellij.ide.projectView.impl.nodes.PackageUtil;
|
||||
import com.intellij.ide.projectView.impl.nodes.ProjectViewDirectoryHelper;
|
||||
import com.intellij.ide.util.treeView.TreeViewUtil;
|
||||
import com.intellij.lang.LangBundle;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.impl.DirectoryIndex;
|
||||
import com.intellij.openapi.vfs.JrtFileSystem;
|
||||
import com.intellij.psi.JavaDirectoryService;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiPackage;
|
||||
@@ -61,6 +63,10 @@ public class JavaProjectViewDirectoryHelper extends ProjectViewDirectoryHelper {
|
||||
@Nullable
|
||||
@Override
|
||||
public String getNodeName(final ViewSettings settings, final Object parentValue, final PsiDirectory directory) {
|
||||
if (JrtFileSystem.isRoot(directory.getVirtualFile())) {
|
||||
return LangBundle.message("jrt.node.short");
|
||||
}
|
||||
|
||||
PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage(directory);
|
||||
|
||||
PsiPackage parentPackage;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -15,8 +15,10 @@
|
||||
*/
|
||||
package com.intellij.openapi.projectRoots.impl;
|
||||
|
||||
import com.intellij.execution.configurations.GeneralCommandLine;
|
||||
import com.intellij.execution.util.ExecUtil;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.lang.LangBundle;
|
||||
import com.intellij.openapi.actionSystem.DataKey;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
@@ -28,12 +30,12 @@ import com.intellij.openapi.roots.JavadocOrderRootType;
|
||||
import com.intellij.openapi.roots.OrderRootType;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.*;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.model.java.impl.JavaSdkUtil;
|
||||
@@ -51,13 +53,14 @@ import java.util.regex.Pattern;
|
||||
*/
|
||||
public class JavaSdkImpl extends JavaSdk {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.projectRoots.impl.JavaSdkImpl");
|
||||
// do not use javaw.exe for Windows because of issues with encoding
|
||||
@NonNls private static final String VM_EXE_NAME = "java";
|
||||
@NonNls private final Pattern myVersionStringPattern = Pattern.compile("^(.*)java version \"([1234567890_.]*)\"(.*)$");
|
||||
@NonNls private static final String JAVA_VERSION_PREFIX = "java version ";
|
||||
@NonNls private static final String OPENJDK_VERSION_PREFIX = "openjdk version ";
|
||||
|
||||
public static final DataKey<Boolean> KEY = DataKey.create("JavaSdk");
|
||||
|
||||
private static final String VM_EXE_NAME = "java"; // do not use JavaW.exe for Windows because of issues with encoding
|
||||
private static final Pattern VERSION_STRING_PATTERN = Pattern.compile("^(.*)java version \"([1234567890_.]*)\"(.*)$");
|
||||
private static final String JAVA_VERSION_PREFIX = "java version ";
|
||||
private static final String OPENJDK_VERSION_PREFIX = "openjdk version ";
|
||||
|
||||
public JavaSdkImpl() {
|
||||
super("JavaSDK");
|
||||
}
|
||||
@@ -83,7 +86,6 @@ public class JavaSdkImpl extends JavaSdk {
|
||||
return AllIcons.General.AddJdk;
|
||||
}
|
||||
|
||||
@NonNls
|
||||
@Override
|
||||
@Nullable
|
||||
public String getDefaultDocumentationUrl(@NotNull final Sdk sdk) {
|
||||
@@ -119,7 +121,6 @@ public class JavaSdkImpl extends JavaSdk {
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNls
|
||||
public String getToolsPath(@NotNull Sdk sdk) {
|
||||
final String versionString = sdk.getVersionString();
|
||||
final boolean isJdk1_x = versionString != null && (versionString.contains("1.0") || versionString.contains("1.1"));
|
||||
@@ -128,11 +129,6 @@ public class JavaSdkImpl extends JavaSdk {
|
||||
|
||||
@Override
|
||||
public String getVMExecutablePath(@NotNull Sdk sdk) {
|
||||
/*
|
||||
if ("64".equals(System.getProperty("sun.arch.data.model"))) {
|
||||
return getBinPath(sdk) + File.separator + System.getProperty("os.arch") + File.separator + VM_EXE_NAME;
|
||||
}
|
||||
*/
|
||||
return getBinPath(sdk) + File.separator + VM_EXE_NAME;
|
||||
}
|
||||
|
||||
@@ -150,8 +146,8 @@ public class JavaSdkImpl extends JavaSdk {
|
||||
@SuppressWarnings({"HardCodedStringLiteral"})
|
||||
public String suggestHomePath() {
|
||||
if (SystemInfo.isMac) {
|
||||
if (new File("/usr/libexec/java_home").exists()) {
|
||||
final String path = ExecUtil.execAndReadLine("/usr/libexec/java_home");
|
||||
if (new File("/usr/libexec/java_home").canExecute()) {
|
||||
String path = ExecUtil.execAndReadLine(new GeneralCommandLine("/usr/libexec/java_home"));
|
||||
if (path != null && new File(path).exists()) {
|
||||
return path;
|
||||
}
|
||||
@@ -180,6 +176,7 @@ public class JavaSdkImpl extends JavaSdk {
|
||||
return javaHome.getAbsolutePath();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -239,20 +236,27 @@ public class JavaSdkImpl extends JavaSdk {
|
||||
|
||||
@Override
|
||||
public FileChooserDescriptor getHomeChooserDescriptor() {
|
||||
FileChooserDescriptor descriptor = super.getHomeChooserDescriptor();
|
||||
final FileChooserDescriptor baseDescriptor = super.getHomeChooserDescriptor();
|
||||
final FileChooserDescriptor descriptor = new FileChooserDescriptor(baseDescriptor) {
|
||||
@Override
|
||||
public void validateSelectedFiles(VirtualFile[] files) throws Exception {
|
||||
if (files.length > 0 && JrtFileSystem.isModularJdk(files[0].getPath()) && !JrtFileSystem.isSupported()) {
|
||||
throw new Exception(LangBundle.message("jrt.not.available.message"));
|
||||
}
|
||||
baseDescriptor.validateSelectedFiles(files);
|
||||
}
|
||||
};
|
||||
descriptor.putUserData(KEY, Boolean.TRUE);
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
@NonNls public static final String MAC_HOME_PATH = "/Home";
|
||||
|
||||
@Override
|
||||
public String adjustSelectedSdkHome(String homePath) {
|
||||
if (SystemInfo.isMac) {
|
||||
File home = new File(homePath, MAC_HOME_PATH);
|
||||
File home = new File(homePath, "/Home");
|
||||
if (home.exists()) return home.getPath();
|
||||
|
||||
home = new File(new File(homePath, "Contents"), "Home");
|
||||
home = new File(homePath, "Contents/Home");
|
||||
if (home.exists()) return home.getPath();
|
||||
}
|
||||
|
||||
@@ -261,14 +265,20 @@ public class JavaSdkImpl extends JavaSdk {
|
||||
|
||||
@Override
|
||||
public boolean isValidSdkHome(String path) {
|
||||
return checkForJdk(new File(path));
|
||||
if (!checkForJdk(new File(path))) {
|
||||
return false;
|
||||
}
|
||||
if (JrtFileSystem.isModularJdk(path) && !JrtFileSystem.isSupported()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String suggestSdkName(String currentSdkName, String sdkHome) {
|
||||
final String suggestedName;
|
||||
if (currentSdkName != null && !currentSdkName.isEmpty()) {
|
||||
final Matcher matcher = myVersionStringPattern.matcher(currentSdkName);
|
||||
final Matcher matcher = VERSION_STRING_PATTERN.matcher(currentSdkName);
|
||||
final boolean replaceNameWithVersion = matcher.matches();
|
||||
if (replaceNameWithVersion){
|
||||
// user did not change name -> set it automatically
|
||||
@@ -315,13 +325,16 @@ public class JavaSdkImpl extends JavaSdk {
|
||||
@Override
|
||||
@SuppressWarnings({"HardCodedStringLiteral"})
|
||||
public void setupSdkPaths(@NotNull Sdk sdk) {
|
||||
final File jdkHome = new File(sdk.getHomePath());
|
||||
String homePath = sdk.getHomePath();
|
||||
assert homePath != null : sdk;
|
||||
|
||||
File jdkHome = new File(homePath);
|
||||
List<VirtualFile> classes = findClasses(jdkHome, false);
|
||||
VirtualFile sources = findSources(jdkHome);
|
||||
VirtualFile docs = findDocs(jdkHome, "docs/api");
|
||||
SdkModificator sdkModificator = sdk.getSdkModificator();
|
||||
|
||||
final SdkModificator sdkModificator = sdk.getSdkModificator();
|
||||
final Set<VirtualFile> previousRoots = new LinkedHashSet<VirtualFile>(Arrays.asList(sdkModificator.getRoots(OrderRootType.CLASSES)));
|
||||
Set<VirtualFile> previousRoots = new LinkedHashSet<VirtualFile>(Arrays.asList(sdkModificator.getRoots(OrderRootType.CLASSES)));
|
||||
sdkModificator.removeRoots(OrderRootType.CLASSES);
|
||||
previousRoots.removeAll(new HashSet<VirtualFile>(classes));
|
||||
for (VirtualFile aClass : classes) {
|
||||
@@ -330,14 +343,16 @@ public class JavaSdkImpl extends JavaSdk {
|
||||
for (VirtualFile root : previousRoots) {
|
||||
sdkModificator.addRoot(root, OrderRootType.CLASSES);
|
||||
}
|
||||
if(sources != null){
|
||||
|
||||
if (sources != null) {
|
||||
sdkModificator.addRoot(sources, OrderRootType.SOURCES);
|
||||
}
|
||||
final VirtualFile javaFxSources = findSources(jdkHome, "javafx-src");
|
||||
VirtualFile javaFxSources = findSources(jdkHome, "javafx-src");
|
||||
if (javaFxSources != null) {
|
||||
sdkModificator.addRoot(javaFxSources, OrderRootType.SOURCES);
|
||||
}
|
||||
if(docs != null){
|
||||
|
||||
if (docs != null) {
|
||||
sdkModificator.addRoot(docs, JavadocOrderRootType.getInstance());
|
||||
}
|
||||
else if (SystemInfo.isMac) {
|
||||
@@ -366,12 +381,14 @@ public class JavaSdkImpl extends JavaSdk {
|
||||
sdkModificator.addRoot(VirtualFileManager.getInstance().findFileByUrl(url), JavadocOrderRootType.getInstance());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (getVersion(sdk) == JavaSdkVersion.JDK_1_7) {
|
||||
sdkModificator.addRoot(VirtualFileManager.getInstance().findFileByUrl("http://docs.oracle.com/javafx/2/api/"), JavadocOrderRootType.getInstance());
|
||||
}
|
||||
}
|
||||
else if (getVersion(sdk) == JavaSdkVersion.JDK_1_7) {
|
||||
VirtualFile url = VirtualFileManager.getInstance().findFileByUrl("http://docs.oracle.com/javafx/2/api/");
|
||||
sdkModificator.addRoot(url, JavadocOrderRootType.getInstance());
|
||||
}
|
||||
|
||||
attachJdkAnnotations(sdkModificator);
|
||||
|
||||
sdkModificator.commitChanges();
|
||||
}
|
||||
|
||||
@@ -399,19 +416,14 @@ public class JavaSdkImpl extends JavaSdk {
|
||||
private final Map<String, String> myCachedVersionStrings = new HashMap<String, String>();
|
||||
|
||||
@Override
|
||||
public final String getVersionString(final String sdkHome) {
|
||||
if (myCachedVersionStrings.containsKey(sdkHome)) {
|
||||
return myCachedVersionStrings.get(sdkHome);
|
||||
public final String getVersionString(String sdkHome) {
|
||||
String versionString = myCachedVersionStrings.get(sdkHome);
|
||||
if (versionString == null) {
|
||||
versionString = getJdkVersion(sdkHome);
|
||||
if (!StringUtil.isEmpty(versionString)) {
|
||||
myCachedVersionStrings.put(sdkHome, versionString);
|
||||
}
|
||||
}
|
||||
String versionString = getJdkVersion(sdkHome);
|
||||
if (versionString != null && versionString.isEmpty()) {
|
||||
versionString = null;
|
||||
}
|
||||
|
||||
if (versionString != null){
|
||||
myCachedVersionStrings.put(sdkHome, versionString);
|
||||
}
|
||||
|
||||
return versionString;
|
||||
}
|
||||
|
||||
@@ -464,17 +476,22 @@ public class JavaSdkImpl extends JavaSdk {
|
||||
}
|
||||
|
||||
private static List<VirtualFile> findClasses(File file, boolean isJre) {
|
||||
List<VirtualFile> result = ContainerUtil.newArrayList();
|
||||
List<File> roots = JavaSdkUtil.getJdkClassesRoots(file, isJre);
|
||||
List<String> urls = ContainerUtil.newArrayListWithCapacity(roots.size() + 1);
|
||||
if (JrtFileSystem.isModularJdk(file.getPath())) {
|
||||
urls.add(VirtualFileManager.constructUrl(JrtFileSystem.PROTOCOL, FileUtil.toSystemIndependentName(file.getPath()) + JrtFileSystem.SEPARATOR));
|
||||
}
|
||||
for (File root : roots) {
|
||||
urls.add(VfsUtil.getUrlForLibraryRoot(root));
|
||||
}
|
||||
|
||||
List<File> rootFiles = JavaSdkUtil.getJdkClassesRoots(file, isJre);
|
||||
for (File child : rootFiles) {
|
||||
String url = VfsUtil.getUrlForLibraryRoot(child);
|
||||
List<VirtualFile> result = ContainerUtil.newArrayListWithCapacity(urls.size());
|
||||
for (String url : urls) {
|
||||
VirtualFile vFile = VirtualFileManager.getInstance().findFileByUrl(url);
|
||||
if (vFile != null) {
|
||||
result.add(vFile);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* 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.openapi.vfs;
|
||||
|
||||
import com.intellij.ide.AppLifecycleListener;
|
||||
import com.intellij.lang.LangBundle;
|
||||
import com.intellij.notification.Notification;
|
||||
import com.intellij.notification.NotificationType;
|
||||
import com.intellij.notification.Notifications;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.JavaSdkType;
|
||||
import com.intellij.openapi.projectRoots.ProjectJdkTable;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.impl.ArchiveHandler;
|
||||
import com.intellij.openapi.vfs.newvfs.ArchiveFileSystem;
|
||||
import com.intellij.openapi.vfs.newvfs.VfsImplUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.messages.MessageBusConnection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class JrtFileSystem extends ArchiveFileSystem {
|
||||
public static final String PROTOCOL = "jrt";
|
||||
public static final String SEPARATOR = JarFileSystem.JAR_SEPARATOR;
|
||||
|
||||
public JrtFileSystem() {
|
||||
scheduleConfiguredSdkCheck();
|
||||
}
|
||||
|
||||
private static void scheduleConfiguredSdkCheck() {
|
||||
if (isSupported()) return;
|
||||
final MessageBusConnection connection = ApplicationManager.getApplication().getMessageBus().connect();
|
||||
connection.subscribe(AppLifecycleListener.TOPIC, new AppLifecycleListener.Adapter() {
|
||||
@Override
|
||||
public void appStarting(Project project) {
|
||||
for (Sdk sdk : ProjectJdkTable.getInstance().getAllJdks()) {
|
||||
if (getHomePathIfModular(sdk) != null) {
|
||||
String title = LangBundle.message("jrt.not.available.title", sdk.getName());
|
||||
String message = LangBundle.message("jrt.not.available.message");
|
||||
Notifications.Bus.notify(new Notification(Notifications.SYSTEM_MESSAGES_GROUP_ID, title, message, NotificationType.WARNING));
|
||||
}
|
||||
}
|
||||
connection.disconnect();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static String getHomePathIfModular(Sdk sdk) {
|
||||
if (sdk != null && sdk.getSdkType() instanceof JavaSdkType) {
|
||||
String homePath = sdk.getHomePath();
|
||||
if (homePath != null && isModularJdk(homePath)) {
|
||||
return homePath;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getProtocol() {
|
||||
return PROTOCOL;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected String extractLocalPath(@NotNull String rootPath) {
|
||||
return StringUtil.trimEnd(rootPath, SEPARATOR);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected String composeRootPath(@NotNull String localPath) {
|
||||
return localPath + SEPARATOR;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected String extractRootPath(@NotNull String entryPath) {
|
||||
int separatorIndex = entryPath.indexOf(SEPARATOR);
|
||||
assert separatorIndex >= 0 : "Path passed to JrtFileSystem must have a separator '!/': " + entryPath;
|
||||
return entryPath.substring(0, separatorIndex + SEPARATOR.length());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected ArchiveHandler getHandler(@NotNull VirtualFile entryFile) {
|
||||
final String homePath = extractLocalPath(extractRootPath(entryFile.getPath()));
|
||||
return VfsImplUtil.getHandler(this, homePath + "/lib/modules", new Function<String, ArchiveHandler>() {
|
||||
@Override
|
||||
public ArchiveHandler fun(String localPath) {
|
||||
return isSupported() ? new JrtHandler(homePath) : new JrtHandlerStub(homePath);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public VirtualFile findFileByPath(@NotNull String path) {
|
||||
return VfsImplUtil.findFileByPath(this, path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VirtualFile findFileByPathIfCached(@NotNull String path) {
|
||||
return VfsImplUtil.findFileByPathIfCached(this, path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VirtualFile refreshAndFindFileByPath(@NotNull String path) {
|
||||
return VfsImplUtil.refreshAndFindFileByPath(this, path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh(boolean asynchronous) {
|
||||
VfsImplUtil.refresh(this, asynchronous);
|
||||
}
|
||||
|
||||
public static boolean isSupported() {
|
||||
return SystemInfo.isJavaVersionAtLeast("1.8") && !SystemInfo.isJavaVersionAtLeast("1.9");
|
||||
}
|
||||
|
||||
public static boolean isModularJdk(@NotNull String homePath) {
|
||||
return new File(homePath, "lib/modules").isDirectory();
|
||||
}
|
||||
|
||||
public static boolean isRoot(@NotNull VirtualFile file) {
|
||||
return file.getParent() == null && file.getFileSystem() instanceof JrtFileSystem;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* 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.openapi.vfs;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.impl.ArchiveHandler;
|
||||
import com.intellij.reference.SoftReference;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.*;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
class JrtHandler extends ArchiveHandler {
|
||||
private static final URI ROOT_URI = URI.create("jrt:/");
|
||||
private static final Map<String, Object> EMPTY_ENV = Collections.emptyMap();
|
||||
|
||||
private static class JrtEntryInfo extends EntryInfo {
|
||||
private final String myModule;
|
||||
|
||||
public JrtEntryInfo(EntryInfo parent, @NotNull String shortName, @NotNull String module, long length, long timestamp) {
|
||||
super(parent, shortName, false, length, timestamp);
|
||||
myModule = module;
|
||||
}
|
||||
}
|
||||
|
||||
private SoftReference<Object> myFileSystem;
|
||||
|
||||
public JrtHandler(@NotNull String path) {
|
||||
super(path);
|
||||
}
|
||||
|
||||
private synchronized Object getFileSystem() throws IOException {
|
||||
Object fs = SoftReference.dereference(myFileSystem);
|
||||
if (fs == null) {
|
||||
URL url = new File(getFile(), "jrt-fs.jar").toURI().toURL();
|
||||
ClassLoader loader = new URLClassLoader(new URL[]{url}, null);
|
||||
//fs = FileSystems.newFileSystem(ROOT_URI, EMPTY_ENV, loader);
|
||||
fs = call(newFileSystem, ROOT_URI, EMPTY_ENV, loader);
|
||||
myFileSystem = new SoftReference<Object>(fs);
|
||||
}
|
||||
return fs;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Map<String, EntryInfo> createEntriesMap() throws IOException {
|
||||
final Map<String, EntryInfo> map = ContainerUtil.newHashMap();
|
||||
map.put("", createRootEntry());
|
||||
|
||||
//FileSystem fs = (FileSystem)getFileSystem();
|
||||
//Path root = fs.getPath("/");
|
||||
//Files.walk(root).forEachOrdered((p) -> {
|
||||
Object fs = getFileSystem();
|
||||
Object root = call(getPath, fs, "/", ArrayUtil.EMPTY_STRING_ARRAY);
|
||||
Object stream = call(walk, root, Array.newInstance(cls("java.nio.file.FileVisitOption"), 0));
|
||||
call(forEachOrdered, stream, Proxy.newProxyInstance(
|
||||
getClass().getClassLoader(), new Class[]{cls("java.util.function.Consumer")}, new InvocationHandler() {
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
//String path = p.toString();
|
||||
String path = args[0].toString();
|
||||
|
||||
int p = path.indexOf('/', 1);
|
||||
if (p < 0) return null;
|
||||
String module = path.substring(1, p);
|
||||
path = path.substring(p + 1);
|
||||
if (map.containsKey(path)) return null;
|
||||
|
||||
String shortName;
|
||||
EntryInfo parent;
|
||||
|
||||
p = path.lastIndexOf('/');
|
||||
if (p < 0) {
|
||||
shortName = path;
|
||||
parent = map.get("");
|
||||
}
|
||||
else {
|
||||
shortName = path.substring(p + 1);
|
||||
parent = map.get(path.substring(0, p));
|
||||
}
|
||||
assert parent != null : path;
|
||||
|
||||
//BasicFileAttributes attributes = Files.readAttributes(p, BasicFileAttributes.class);
|
||||
//boolean dir = attributes.isDirectory();
|
||||
//long length = attributes.size();
|
||||
//long modified = attributes.lastModifiedTime().toMillis();
|
||||
Object attributes = call(readAttributes, args[0], cls("java.nio.file.attribute.BasicFileAttributes"), linkOptions);
|
||||
boolean dir = (Boolean)call(isDirectory, attributes);
|
||||
long length = (Long)call(size, attributes);
|
||||
long modified = (Long)call(toMillis, call(lastModifiedTime, attributes));
|
||||
EntryInfo entry = dir ? new EntryInfo(parent, shortName, true, length, modified)
|
||||
: new JrtEntryInfo(parent, shortName, module, length, modified);
|
||||
map.put(path, entry);
|
||||
|
||||
return null;
|
||||
}
|
||||
}));
|
||||
//});
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public byte[] contentsToByteArray(@NotNull String relativePath) throws IOException {
|
||||
EntryInfo entry = getEntryInfo(relativePath);
|
||||
if (!(entry instanceof JrtEntryInfo)) {
|
||||
return ArrayUtil.EMPTY_BYTE_ARRAY;
|
||||
}
|
||||
|
||||
//FileSystem fs = (FileSystem)getFileSystem();
|
||||
//Path path = fs.getPath(((JrtEntryInfo)entry).myModule, relativePath);
|
||||
//return Files.readAllBytes(path);
|
||||
Object fs = getFileSystem();
|
||||
Object path = call(getPath, fs, ((JrtEntryInfo)entry).myModule, new String[]{relativePath});
|
||||
return (byte[])call(readAllBytes, path);
|
||||
}
|
||||
|
||||
// reflection stuff
|
||||
// todo[r.sh] drop reflection after migration to Java 8
|
||||
|
||||
private static final Method newFileSystem = method("java.nio.file.FileSystems#newFileSystem", URI.class, Map.class, ClassLoader.class);
|
||||
private static final Method getPath = method("java.nio.file.FileSystem#getPath", String.class, String[].class);
|
||||
private static final Method walk = method("java.nio.file.Files#walk", cls("java.nio.file.Path"), cls("java.nio.file.FileVisitOption", true));
|
||||
private static final Method forEachOrdered = method("java.util.stream.Stream#forEachOrdered", cls("java.util.function.Consumer"));
|
||||
private static final Method readAttributes =
|
||||
method("java.nio.file.Files#readAttributes", cls("java.nio.file.Path"), Class.class, cls("java.nio.file.LinkOption", true));
|
||||
private static final Method isDirectory = method("java.nio.file.attribute.BasicFileAttributes#isDirectory");
|
||||
private static final Method size = method("java.nio.file.attribute.BasicFileAttributes#size");
|
||||
private static final Method lastModifiedTime = method("java.nio.file.attribute.BasicFileAttributes#lastModifiedTime");
|
||||
private static final Method toMillis = method("java.nio.file.attribute.FileTime#toMillis");
|
||||
private static final Method readAllBytes = method("java.nio.file.Files#readAllBytes", cls("java.nio.file.Path"));
|
||||
private static final Object linkOptions = Array.newInstance(cls("java.nio.file.LinkOption"), 0);
|
||||
|
||||
private static Class<?> cls(String name) {
|
||||
return cls(name, false);
|
||||
}
|
||||
|
||||
private static Class<?> cls(String name, boolean array) {
|
||||
try {
|
||||
if (array) name = "[L" + name + ";";
|
||||
return Class.forName(name);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static Method method(String name, Class<?>... parameterTypes) {
|
||||
try {
|
||||
List<String> parts = StringUtil.split(name, "#");
|
||||
Class<?> aClass = cls(parts.get(0));
|
||||
Method method = aClass.getMethod(parts.get(1), parameterTypes);
|
||||
method.setAccessible(true);
|
||||
return method;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static Object call(Method method, Object... args) {
|
||||
try {
|
||||
if (Modifier.isStatic(method.getModifiers())) {
|
||||
return method.invoke(null, args);
|
||||
}
|
||||
else {
|
||||
return method.invoke(args[0], Arrays.copyOfRange(args, 1, args.length));
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -13,28 +13,29 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.plugins.coursecreator;
|
||||
package com.intellij.openapi.vfs;
|
||||
|
||||
import com.jetbrains.python.PythonFileType;
|
||||
import com.intellij.openapi.vfs.impl.ArchiveHandler;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class CCAnswerFileType extends PythonFileType {
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDefaultExtension() {
|
||||
return "answer";
|
||||
class JrtHandlerStub extends ArchiveHandler {
|
||||
public JrtHandlerStub(@NotNull String path) {
|
||||
super(path);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Answer file";
|
||||
protected Map<String, EntryInfo> createEntriesMap() throws IOException {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Answer";
|
||||
public byte[] contentsToByteArray(@NotNull String relativePath) throws IOException {
|
||||
return new byte[0];
|
||||
}
|
||||
}
|
||||
@@ -26,8 +26,8 @@ import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.roots.SourceFolder;
|
||||
import com.intellij.openapi.roots.ui.configuration.SourceRootPresentation;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.vfs.JarFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.newvfs.ArchiveFileSystem;
|
||||
import com.intellij.psi.JavaDirectoryService;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiElement;
|
||||
@@ -43,7 +43,7 @@ import javax.swing.*;
|
||||
public class JavaDirectoryIconProvider extends IconProvider implements DumbAware {
|
||||
@Override
|
||||
@Nullable
|
||||
public Icon getIcon(@NotNull final PsiElement element, final int flags) {
|
||||
public Icon getIcon(@NotNull PsiElement element, int flags) {
|
||||
if (element instanceof PsiDirectory) {
|
||||
final PsiDirectory psiDirectory = (PsiDirectory)element;
|
||||
final VirtualFile vFile = psiDirectory.getVirtualFile();
|
||||
@@ -51,7 +51,7 @@ public class JavaDirectoryIconProvider extends IconProvider implements DumbAware
|
||||
|
||||
SourceFolder sourceFolder;
|
||||
Icon symbolIcon;
|
||||
if (vFile.getParent() == null && vFile.getFileSystem() instanceof JarFileSystem) {
|
||||
if (vFile.getParent() == null && vFile.getFileSystem() instanceof ArchiveFileSystem) {
|
||||
symbolIcon = PlatformIcons.JAR_ICON;
|
||||
}
|
||||
else if (ProjectRootsUtil.isModuleContentRoot(vFile, project)) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -314,6 +314,10 @@ public class UnscrambleDialog extends DialogWrapper {
|
||||
builder.append(trimSuffix(line)).append("\n");
|
||||
continue;
|
||||
}
|
||||
if (line.startsWith("at breakpoint")) { // possible thread status mixed with "at ..."
|
||||
builder.append(" ").append(trimSuffix(line));
|
||||
continue;
|
||||
}
|
||||
if (!first && mustHaveNewLineBefore(line)) {
|
||||
builder.append("\n");
|
||||
if (line.startsWith("\"")) builder.append("\n"); // Additional line break for thread names
|
||||
|
||||
@@ -53,9 +53,6 @@ public abstract class InferredAnnotationsManager {
|
||||
*
|
||||
* {@link Contract} and {@link NotNull} annotations on methods are not necessarily applicable to the overridden implementations, so they're ignored, too.<p/>
|
||||
*
|
||||
* In addition, package-default annotations like @ParametersAreNonnullByDefault are not honored for parameters where
|
||||
* {@link NotNull} inference is ignored.
|
||||
*
|
||||
* @return whether inference is to be suppressed the given annotation on the given method or parameter
|
||||
*/
|
||||
public abstract boolean ignoreInference(@NotNull PsiModifierListOwner owner, @Nullable String annotationFQN);
|
||||
|
||||
@@ -36,7 +36,7 @@ import java.util.*;
|
||||
* User: anna
|
||||
* Date: 1/25/11
|
||||
*/
|
||||
public class NullableNotNullManager implements PersistentStateComponent<Element> {
|
||||
public abstract class NullableNotNullManager implements PersistentStateComponent<Element> {
|
||||
private static final Logger LOG = Logger.getInstance("#" + NullableNotNullManager.class.getName());
|
||||
|
||||
public String myDefaultNullable = AnnotationUtil.NULLABLE;
|
||||
@@ -184,14 +184,16 @@ public class NullableNotNullManager implements PersistentStateComponent<Element>
|
||||
if (AnnotationUtil.isAnnotated(owner, nullable ? Arrays.asList(DEFAULT_NOT_NULLS) : Arrays.asList(DEFAULT_NULLABLES), checkBases, false)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!nullable && InferredAnnotationsManager.getInstance(owner.getProject()).ignoreInference(owner, AnnotationUtil.NOT_NULL)) {
|
||||
|
||||
if (!nullable && hasHardcodedContracts(owner)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
return findNullabilityDefaultInHierarchy(owner, nullable);
|
||||
}
|
||||
|
||||
protected abstract boolean hasHardcodedContracts(PsiElement element);
|
||||
|
||||
@Nullable
|
||||
private static PsiType getOwnerType(PsiModifierListOwner owner) {
|
||||
if (owner instanceof PsiVariable) return ((PsiVariable)owner).getType();
|
||||
|
||||
@@ -549,6 +549,14 @@ public class RedundantCastUtil {
|
||||
final PsiExpression initializer = ((PsiLocalVariable)declarationStatement.getDeclaredElements()[0]).getInitializer();
|
||||
LOG.assertTrue(initializer != null, operand.getText());
|
||||
opType = initializer.getType();
|
||||
|
||||
if (opType != null) {
|
||||
final PsiExpression expr = PsiUtil.skipParenthesizedExprDown(operand);
|
||||
if (expr instanceof PsiConditionalExpression) {
|
||||
if (!isApplicableForConditionalBranch(opType, ((PsiConditionalExpression)expr).getThenExpression())) return;
|
||||
if (!isApplicableForConditionalBranch(opType, ((PsiConditionalExpression)expr).getElseExpression())) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IncorrectOperationException ignore) {}
|
||||
}
|
||||
@@ -631,6 +639,16 @@ public class RedundantCastUtil {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isApplicableForConditionalBranch(PsiType opType, PsiExpression thenExpression) {
|
||||
if (thenExpression != null) {
|
||||
final PsiType thenType = thenExpression.getType();
|
||||
if (thenType != null && !TypeConversionUtil.isAssignable(opType, thenType)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean arrayAccessAtTheLeftSideOfAssignment(PsiElement element) {
|
||||
PsiAssignmentExpression assignment = PsiTreeUtil.getParentOfType(element, PsiAssignmentExpression.class, false, PsiMember.class);
|
||||
if (assignment == null) return false;
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
class Foo {
|
||||
void test() {
|
||||
if (o in<caret>x) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
class Foo {
|
||||
void test() {
|
||||
if (!(o instanceof <caret>)x) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
// "Add 'catch' clause(s)" "true"
|
||||
import java.io.IOException;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
class C {
|
||||
static Object get() throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
void method() {
|
||||
try {
|
||||
Supplier<Object> lambda1 = () -> {
|
||||
try {
|
||||
return C.get();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
};
|
||||
} catch( Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// "Add 'catch' clause(s)" "false"
|
||||
import java.util.function.Supplier;
|
||||
|
||||
class C {
|
||||
static Object get() throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
void method() {
|
||||
try {
|
||||
Supplier<Object> lambda1 = () -> C.ge<caret>t();
|
||||
} catch( Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
// "Add 'catch' clause(s)" "true"
|
||||
import java.io.IOException;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
class C {
|
||||
static Object get() throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
void method() {
|
||||
try {
|
||||
Supplier<Object> lambda1 = () -> {
|
||||
try {
|
||||
return C.ge<caret>t();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
};
|
||||
} catch( Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// "Add 'catch' clause(s)" "false"
|
||||
import java.util.function.Supplier;
|
||||
|
||||
class C {
|
||||
static Object get() throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
void method() {
|
||||
try {
|
||||
Supplier<Object> lambda1 = C::g<caret>et;
|
||||
} catch( Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
// "Replace with lambda" "true"
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
class Test {
|
||||
|
||||
void f(List<Status> r){
|
||||
List<Status> l = r.stream().filter(status -> stringContainingSort(status))
|
||||
.map(Status::new)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
boolean stringContainingSort(Object text) {
|
||||
return true;
|
||||
}
|
||||
|
||||
class Status {
|
||||
public Status(Status s) {}
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -1,9 +1,10 @@
|
||||
// "Replace with lambda" "true"
|
||||
import javax.swing.*;
|
||||
class Test {
|
||||
String c = null;
|
||||
|
||||
public void main(String[] args){
|
||||
SwingUtilities.invokeLater(() -> c.substring(0).toString());
|
||||
invokeLater(() -> c.substring(0).toString());
|
||||
}
|
||||
|
||||
public void invokeLater(Runnable r) {}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// "Replace with lambda" "true"
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
class Test {
|
||||
|
||||
void f(List<Status> r){
|
||||
List<Status> l = r.stream().filter(new Pr<caret>edicate<Status>() {
|
||||
@Override
|
||||
public boolean test(Status status) {
|
||||
return stringContainingSort(status);
|
||||
}
|
||||
})
|
||||
.map(Status::new)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
boolean stringContainingSort(Object text) {
|
||||
return true;
|
||||
}
|
||||
|
||||
class Status {
|
||||
public Status(Status s) {}
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -1,13 +1,14 @@
|
||||
// "Replace with lambda" "true"
|
||||
import javax.swing.*;
|
||||
class Test {
|
||||
String c = null;
|
||||
|
||||
public void main(String[] args){
|
||||
SwingUtilities.invokeLater(new Runna<caret>ble() {
|
||||
invokeLater(new Runna<caret>ble() {
|
||||
public void run() {
|
||||
c.substring(0).toString();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void invokeLater(Runnable r) {}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// "Generalize catch for 'java.lang.Exception' to 'java.lang.Exception'" "false"
|
||||
import java.util.function.Supplier;
|
||||
|
||||
class C {
|
||||
static Object get() throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
void method() {
|
||||
try {
|
||||
Supplier<Object> lambda1 = () -> C.ge<caret>t();
|
||||
} catch( Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// "Generalize catch for 'java.lang.Exception' to 'java.lang.Exception'" "false"
|
||||
import java.util.function.Supplier;
|
||||
|
||||
class C {
|
||||
static Object get() throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
void method() {
|
||||
try {
|
||||
Supplier<Object> lambda1 = C::g<caret>et;
|
||||
} catch( Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import foo.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
class Some {
|
||||
void foo(@NotNull String s) {
|
||||
@@ -18,6 +19,16 @@ class Some {
|
||||
@bar.MethodsAreNotNullByDefault
|
||||
class NotNullClass {
|
||||
static native Object foo(String s);
|
||||
|
||||
public Object foo() {
|
||||
return <warning descr="'null' is returned by the method declared as @NotNull">null</warning>;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Object foo2() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
class NullableClass {
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems/>
|
||||
@@ -0,0 +1,5 @@
|
||||
class Test {
|
||||
public static void foo(Object[] objectArray, boolean check) {
|
||||
String kv = (String)(check ? "N" : objectArray[0]) ;
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems>
|
||||
<problem>
|
||||
<file>Foo.java</file>
|
||||
<line>21</line>
|
||||
<description>ObjectStreamException</description>
|
||||
</problem>
|
||||
</problems>
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
import java.io.*;
|
||||
|
||||
class ExceptionTest {
|
||||
|
||||
MyFunction method() {
|
||||
return () -> {
|
||||
throw new EOFException();
|
||||
};
|
||||
}
|
||||
|
||||
MyFunction method1() {
|
||||
return this::e;
|
||||
}
|
||||
|
||||
private void e() throws FileNotFoundException {
|
||||
throw new FileNotFoundException();
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
private interface MyFunction {
|
||||
void call() throws FileNotFoundException, EOFException, ObjectStreamException;
|
||||
}
|
||||
}
|
||||
@@ -256,6 +256,17 @@ class JavaAutoPopupTest extends CompletionAutoPopupTestCase {
|
||||
assert lookup
|
||||
}
|
||||
|
||||
public void "test popup after hash in javadoc"() {
|
||||
myFixture.configureByText("a.java", """
|
||||
/**
|
||||
* {@link String<caret>}
|
||||
*/
|
||||
class Foo {}
|
||||
""")
|
||||
type '#'
|
||||
assert lookup
|
||||
}
|
||||
|
||||
public void "test popup in javadoc local reference"() {
|
||||
myFixture.configureByText("a.java", """
|
||||
/**
|
||||
|
||||
@@ -101,6 +101,13 @@ public class KeywordCompletionTest extends LightCompletionTestCase {
|
||||
public void testSpaceAfterInstanceof() throws Exception { doTest(false); }
|
||||
public void testInstanceofAfterUnresolved() throws Exception { doTest(1, "instanceof"); }
|
||||
public void testInstanceofAfterStatementStart() throws Exception { doTest(1, "instanceof"); }
|
||||
|
||||
public void testInstanceofNegation() {
|
||||
configureByFile(BASE_PATH + "/" + getTestName(true) + ".java");
|
||||
selectItem(myItems[0], '!');
|
||||
checkResultByFile(BASE_PATH + "/" + getTestName(true) + "_after.java");
|
||||
}
|
||||
|
||||
public void testAbstractInInterface() throws Exception { doTest(1, "abstract"); }
|
||||
public void testCharInAnnotatedParameter() throws Exception { doTest(1, "char"); }
|
||||
public void testReturnInTernary() throws Exception { doTest(1, "return"); }
|
||||
|
||||
+11
@@ -27,6 +27,7 @@ import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.psi.PsiMethod
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager
|
||||
import com.intellij.psi.codeStyle.CommonCodeStyleSettings
|
||||
import com.siyeh.ig.style.UnqualifiedFieldAccessInspection
|
||||
|
||||
public class NormalCompletionTest extends LightFixtureCompletionTestCase {
|
||||
@Override
|
||||
@@ -1484,5 +1485,15 @@ class Bar {
|
||||
myFixture.assertPreferredCompletionItems(0, "xcreateZoo", "xcreateElephant");
|
||||
}
|
||||
|
||||
public void "test code cleanup during completion generation"() {
|
||||
myFixture.configureByText "a.java", "class Foo {int i; ge<caret>}"
|
||||
myFixture.enableInspections(new UnqualifiedFieldAccessInspection())
|
||||
myFixture.complete(CompletionType.BASIC)
|
||||
myFixture.checkResult '''class Foo {int i;
|
||||
|
||||
public int getI() {
|
||||
return this.i;
|
||||
}
|
||||
}'''
|
||||
}
|
||||
}
|
||||
|
||||
+8
@@ -1,5 +1,8 @@
|
||||
package com.intellij.codeInsight.daemon.quickFix;
|
||||
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
|
||||
public class AddExceptionToCatchTest extends LightQuickFixParameterizedTestCase {
|
||||
public void test() throws Exception {
|
||||
doAllTests();
|
||||
@@ -9,4 +12,9 @@ public class AddExceptionToCatchTest extends LightQuickFixParameterizedTestCase
|
||||
protected String getBasePath() {
|
||||
return "/codeInsight/daemonCodeAnalyzer/quickFix/addCatchBlock";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sdk getProjectJDK() {
|
||||
return IdeaTestUtil.getMockJdk18();
|
||||
}
|
||||
}
|
||||
|
||||
+7
@@ -17,6 +17,9 @@ package com.intellij.codeInsight.daemon.quickFix;
|
||||
|
||||
import com.intellij.codeInspection.AnonymousCanBeLambdaInspection;
|
||||
import com.intellij.codeInspection.LocalInspectionTool;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
@@ -36,4 +39,8 @@ public class Anonymous2LambdaInspectionTest extends LightQuickFixParameterizedTe
|
||||
return "/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sdk getProjectJDK() {
|
||||
return IdeaTestUtil.getMockJdk18();
|
||||
}
|
||||
}
|
||||
+8
@@ -1,5 +1,8 @@
|
||||
package com.intellij.codeInsight.daemon.quickFix;
|
||||
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
|
||||
public class GeneralizeCatchTest extends LightQuickFixParameterizedTestCase {
|
||||
public void test() throws Exception {
|
||||
doAllTests();
|
||||
@@ -9,4 +12,9 @@ public class GeneralizeCatchTest extends LightQuickFixParameterizedTestCase {
|
||||
protected String getBasePath() {
|
||||
return "/codeInsight/daemonCodeAnalyzer/quickFix/generalizeCatch";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sdk getProjectJDK() {
|
||||
return IdeaTestUtil.getMockJdk18();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ public class RedundantCast18Test extends InspectionTestCase {
|
||||
public void testMethodRefContext() throws Exception { doTest(); }
|
||||
public void testExpectedSupertype() throws Exception { doTest(); }
|
||||
public void testForeachValue() throws Exception { doTest(); }
|
||||
public void testConditional() throws Exception { doTest(); }
|
||||
|
||||
@Override
|
||||
protected Sdk getTestProjectSdk() {
|
||||
|
||||
@@ -17,6 +17,10 @@ package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInspection.unneededThrows.RedundantThrows;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
import com.intellij.testFramework.InspectionTestCase;
|
||||
|
||||
public class RedundantThrowTest extends InspectionTestCase {
|
||||
@@ -60,4 +64,15 @@ public class RedundantThrowTest extends InspectionTestCase {
|
||||
public void testSelfCall() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testThrownClausesInFunctionalExpressions() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sdk getTestProjectSdk() {
|
||||
Sdk sdk = IdeaTestUtil.getMockJdk17();
|
||||
LanguageLevelProjectExtension.getInstance(getProject()).setLanguageLevel(LanguageLevel.JDK_1_8);
|
||||
return sdk;
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -194,10 +194,12 @@ public class BytecodeAnalysisTest extends JavaCodeInsightFixtureTestCase {
|
||||
}
|
||||
|
||||
private void checkCompoundId(Method method, PsiMethod psiMethod, boolean noKey) throws IOException {
|
||||
/*
|
||||
System.out.println();
|
||||
System.out.println(method.internalClassName);
|
||||
System.out.println(method.methodName);
|
||||
System.out.println(method.methodDesc);
|
||||
*/
|
||||
|
||||
|
||||
HKey psiKey = BytecodeAnalysisConverter.psiKey(psiMethod, Direction.Out, myMessageDigest);
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.openapi.vfs;
|
||||
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.testFramework.IdeaTestCase;
|
||||
import com.intellij.testFramework.LightPlatformTestCase;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assume.assumeNotNull;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
public class JrtFileSystemTest {
|
||||
private static String ourJdkHome = System.getenv("JDK_19");
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass() {
|
||||
assumeTrue("skipped: java=" + SystemInfo.JAVA_VERSION, JrtFileSystem.isSupported());
|
||||
assumeTrue("skipped: JDK_19=" + ourJdkHome, ourJdkHome != null && JrtFileSystem.isModularJdk(ourJdkHome));
|
||||
|
||||
IdeaTestCase.initPlatformPrefix();
|
||||
LightPlatformTestCase.initApplication();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBasicOps() throws IOException {
|
||||
String url = VirtualFileManager.constructUrl(JrtFileSystem.PROTOCOL, FileUtil.toSystemIndependentName(ourJdkHome) + JrtFileSystem.SEPARATOR);
|
||||
VirtualFile root = VirtualFileManager.getInstance().findFileByUrl(url);
|
||||
assertNotNull(root);
|
||||
assertTrue(JrtFileSystem.isRoot(root));
|
||||
|
||||
assumeNotNull(root.findChild("java"));
|
||||
assumeNotNull(root.findChild("javax"));
|
||||
|
||||
VirtualFile object = root.findFileByRelativePath("java/lang/Object.class");
|
||||
assertNotNull(object);
|
||||
|
||||
byte[] bytes = object.contentsToByteArray();
|
||||
assertTrue(bytes.length > 10);
|
||||
assertEquals(0xCAFEBABE, ByteBuffer.wrap(bytes).getInt());
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -23,6 +23,10 @@ import org.jetbrains.jps.model.library.JpsOrderRootType;
|
||||
public class JpsAnnotationRootType extends JpsOrderRootType {
|
||||
public static final JpsAnnotationRootType INSTANCE = new JpsAnnotationRootType();
|
||||
|
||||
private JpsAnnotationRootType() {
|
||||
private JpsAnnotationRootType() { }
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "annotation root";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -23,6 +23,10 @@ import org.jetbrains.jps.model.library.JpsOrderRootType;
|
||||
public class JpsNativeLibraryRootType extends JpsOrderRootType {
|
||||
public static final JpsNativeLibraryRootType INSTANCE = new JpsNativeLibraryRootType();
|
||||
|
||||
private JpsNativeLibraryRootType() {
|
||||
private JpsNativeLibraryRootType() { }
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "native lib root";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -20,9 +20,21 @@ package org.jetbrains.jps.model.library;
|
||||
*/
|
||||
public abstract class JpsOrderRootType {
|
||||
public static final JpsOrderRootType COMPILED = new JpsOrderRootType() {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "compiled root";
|
||||
}
|
||||
};
|
||||
public static final JpsOrderRootType SOURCES = new JpsOrderRootType() {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "sources root";
|
||||
}
|
||||
};
|
||||
public static final JpsOrderRootType DOCUMENTATION = new JpsOrderRootType() {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "documentation root";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -33,13 +33,6 @@ import java.util.Set;
|
||||
public class JavaSdkUtil {
|
||||
@NotNull
|
||||
public static List<File> getJdkClassesRoots(@NotNull File home, boolean isJre) {
|
||||
FileFilter jarFileFilter = new FileFilter() {
|
||||
@Override
|
||||
public boolean accept(@NotNull File f) {
|
||||
return !f.isDirectory() && f.getName().endsWith(".jar");
|
||||
}
|
||||
};
|
||||
|
||||
File[] jarDirs;
|
||||
if (SystemInfo.isMac && !home.getName().startsWith("mockJDK")) {
|
||||
File openJdkRtJar = new File(home, "jre/lib/rt.jar");
|
||||
@@ -58,7 +51,7 @@ public class JavaSdkUtil {
|
||||
jarDirs = new File[]{libEndorsedDir, libDir, classesDir, libExtDir};
|
||||
}
|
||||
}
|
||||
else if (new File(home, "lib/modules").exists()) {
|
||||
else if (new File(home, "lib/modules").isDirectory()) {
|
||||
File libDir = new File(home, "lib");
|
||||
jarDirs = new File[]{libDir};
|
||||
}
|
||||
@@ -69,6 +62,12 @@ public class JavaSdkUtil {
|
||||
jarDirs = new File[]{libEndorsedDir, libDir, libExtDir};
|
||||
}
|
||||
|
||||
FileFilter jarFileFilter = new FileFilter() {
|
||||
@Override
|
||||
public boolean accept(@NotNull File f) {
|
||||
return !f.isDirectory() && f.getName().endsWith(".jar");
|
||||
}
|
||||
};
|
||||
Set<String> pathFilter = ContainerUtil.newTroveSet(FileUtil.PATH_HASHING_STRATEGY);
|
||||
List<File> rootFiles = ContainerUtil.newArrayList();
|
||||
for (File jarDir : jarDirs) {
|
||||
@@ -104,9 +103,11 @@ public class JavaSdkUtil {
|
||||
}
|
||||
}
|
||||
|
||||
File classesDir = new File(home, "classes");
|
||||
if (rootFiles.isEmpty() && classesDir.isDirectory()) {
|
||||
rootFiles.add(classesDir);
|
||||
if (rootFiles.isEmpty()) {
|
||||
File classesDir = new File(home, "classes");
|
||||
if (classesDir.isDirectory()) {
|
||||
rootFiles.add(classesDir);
|
||||
}
|
||||
}
|
||||
|
||||
return rootFiles;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -138,7 +138,9 @@ public class JpsLibraryImpl<P extends JpsElement> extends JpsNamedCompositeEleme
|
||||
List<String> urls = getRootUrls(rootType);
|
||||
List<File> files = new ArrayList<File>(urls.size());
|
||||
for (String url : urls) {
|
||||
files.add(JpsPathUtil.urlToFile(url));
|
||||
if (!url.startsWith("jrt://")) {
|
||||
files.add(JpsPathUtil.urlToFile(url));
|
||||
}
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
+1
-1
@@ -438,7 +438,7 @@ public class GlobalInspectionContextBase extends UserDataHolderBase implements G
|
||||
};
|
||||
|
||||
Application application = ApplicationManager.getApplication();
|
||||
if (application.isWriteAccessAllowed()) {
|
||||
if (application.isWriteAccessAllowed() && !application.isUnitTestMode()) {
|
||||
application.invokeLater(cleanupRunnable);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -88,8 +88,12 @@ public class PushController implements Disposable {
|
||||
myPushLog.getTree().addPropertyChangeListener(PushLogTreeUtil.EDIT_MODE_PROP, new PropertyChangeListener() {
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
// when user starts edit we need to force disable ok actions, because tree.isEditing() still false;
|
||||
// after editing completed okActions will be enabled automatically by dialog validation
|
||||
Boolean isEditMode = (Boolean)evt.getNewValue();
|
||||
myDialog.enableOkActions(!isEditMode && isPushAllowed());
|
||||
if (isEditMode) {
|
||||
myDialog.disableOkActions();
|
||||
}
|
||||
}
|
||||
});
|
||||
startLoadingCommits();
|
||||
@@ -234,7 +238,7 @@ public class PushController implements Disposable {
|
||||
|
||||
@Override
|
||||
public void onSelectionChanged(boolean isSelected) {
|
||||
myDialog.enableOkActions(isPushAllowed());
|
||||
myDialog.updateOkActions();
|
||||
if (isSelected) {
|
||||
boolean forceLoad = myExcludedRepositoryRoots.remove(model.getRepository().getRoot().getPath());
|
||||
if (!model.hasCommitInfo() && (forceLoad || !model.getSupport().shouldRequestIncomingChangesForNotCheckedRepositories())) {
|
||||
@@ -277,21 +281,21 @@ public class PushController implements Disposable {
|
||||
return names;
|
||||
}
|
||||
|
||||
public boolean isPushAllowed() {
|
||||
public boolean isPushAllowed(final boolean force) {
|
||||
JTree tree = myPushLog.getTree();
|
||||
return !tree.isEditing() &&
|
||||
ContainerUtil.exists(myPushSupports, new Condition<PushSupport<?, ?, ?>>() {
|
||||
@Override
|
||||
public boolean value(PushSupport<?, ?, ?> support) {
|
||||
return isPushAllowed(support);
|
||||
return isPushAllowed(support, force);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean isPushAllowed(@NotNull PushSupport<?, ?, ?> pushSupport) {
|
||||
private boolean isPushAllowed(@NotNull PushSupport<?, ?, ?> pushSupport, boolean force) {
|
||||
Collection<RepositoryNode> nodes = getNodesForSupport(pushSupport);
|
||||
if (hasSomethingToPush(nodes)) return true;
|
||||
if (hasCheckedNodesWithContent(nodes, myDialog.getAdditionalOptionValue(pushSupport) != null)) {
|
||||
if (hasCheckedNodesWithContent(nodes, force || myDialog.getAdditionalOptionValue(pushSupport) != null)) {
|
||||
return !pushSupport.getRepositoryManager().isSyncEnabled() || allNodesAreLoaded(nodes);
|
||||
}
|
||||
return false;
|
||||
@@ -399,7 +403,7 @@ public class PushController implements Disposable {
|
||||
if (shouldBeSelected) { // never remove selection; initially all checkboxes are not selected
|
||||
node.setChecked(true);
|
||||
}
|
||||
myDialog.enableOkActions(isPushAllowed());
|
||||
myDialog.updateOkActions();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@ public class VcsPushDialog extends DialogWrapper {
|
||||
|
||||
private static final String ID = "Vcs.Push.Dialog";
|
||||
|
||||
@NotNull private final Project myProject;
|
||||
private final PushLog myListPanel;
|
||||
private final PushController myController;
|
||||
private final Map<PushSupport, VcsPushOptionsPanel> myAdditionalPanels;
|
||||
@@ -48,13 +47,12 @@ public class VcsPushDialog extends DialogWrapper {
|
||||
@NotNull List<? extends Repository> selectedRepositories,
|
||||
@Nullable Repository currentRepo) {
|
||||
super(project);
|
||||
myProject = project;
|
||||
myController = new PushController(project, this, selectedRepositories, currentRepo);
|
||||
myAdditionalPanels = myController.createAdditionalPanels();
|
||||
myListPanel = myController.getPushPanelLog();
|
||||
|
||||
init();
|
||||
enableOkActions(myController.isPushAllowed());
|
||||
updateOkActions();
|
||||
setOKButtonText("Push");
|
||||
setOKButtonMnemonic('P');
|
||||
setTitle("Push Commits");
|
||||
@@ -80,7 +78,7 @@ public class VcsPushDialog extends DialogWrapper {
|
||||
@Nullable
|
||||
@Override
|
||||
protected ValidationInfo doValidate() {
|
||||
enableOkActions(myController.isPushAllowed());
|
||||
updateOkActions();
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -103,8 +101,12 @@ public class VcsPushDialog extends DialogWrapper {
|
||||
return actions.toArray(new Action[actions.size()]);
|
||||
}
|
||||
|
||||
private boolean canPush() {
|
||||
return myController.isPushAllowed(false);
|
||||
}
|
||||
|
||||
private boolean canForcePush() {
|
||||
return myController.isForcePushEnabled() && myController.getProhibitedTarget() == null;
|
||||
return myController.isForcePushEnabled() && myController.getProhibitedTarget() == null && myController.isPushAllowed(true);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -123,11 +125,12 @@ public class VcsPushDialog extends DialogWrapper {
|
||||
protected String getHelpId() {
|
||||
return ID;
|
||||
}
|
||||
public void enableOkActions(boolean isEnabled) {
|
||||
myPushAction.setEnabled(isEnabled);
|
||||
|
||||
public void updateOkActions() {
|
||||
myPushAction.setEnabled(canPush());
|
||||
if (myForcePushAction != null) {
|
||||
boolean canForcePush = canForcePush();
|
||||
myForcePushAction.setEnabled(isEnabled && canForcePush);
|
||||
myForcePushAction.setEnabled(canForcePush);
|
||||
String tooltip = null;
|
||||
if (!canForcePush) {
|
||||
PushTarget target = myController.getProhibitedTarget();
|
||||
@@ -139,6 +142,10 @@ public class VcsPushDialog extends DialogWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
public void disableOkActions() {
|
||||
myPushAction.setEnabled(false);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public VcsPushOptionValue getAdditionalOptionValue(@NotNull PushSupport support) {
|
||||
VcsPushOptionsPanel panel = myAdditionalPanels.get(support);
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import javax.swing.*;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
import java.awt.*;
|
||||
import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.Collections;
|
||||
@@ -40,6 +41,7 @@ public abstract class ListTableWithButtons<T> extends Observable {
|
||||
private final List<T> myElements = ContainerUtil.newArrayList();
|
||||
private final JPanel myPanel;
|
||||
private final TableView<T> myTableView;
|
||||
private final CommonActionsPanel myActionsPanel;
|
||||
private boolean myIsEnabled = true;
|
||||
|
||||
protected ListTableWithButtons() {
|
||||
@@ -55,6 +57,7 @@ public abstract class ListTableWithButtons<T> extends Observable {
|
||||
final int column = myTableView.getEditingColumn();
|
||||
final int row = myTableView.getEditingRow();
|
||||
if (e.getModifiers() == 0 && (e.getKeyCode() == KeyEvent.VK_ENTER || e.getKeyCode() == KeyEvent.VK_TAB)) {
|
||||
e.consume();
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -69,6 +72,7 @@ public abstract class ListTableWithButtons<T> extends Observable {
|
||||
nextRow = 0;
|
||||
}
|
||||
}
|
||||
myTableView.scrollRectToVisible(myTableView.getCellRect(nextRow, nextColumn, true));
|
||||
myTableView.editCellAt(nextRow, nextColumn);
|
||||
}
|
||||
});
|
||||
@@ -79,19 +83,24 @@ public abstract class ListTableWithButtons<T> extends Observable {
|
||||
}
|
||||
};
|
||||
myTableView.setRowHeight(new JTextField().getPreferredSize().height);
|
||||
myTableView.setIntercellSpacing(new Dimension(0, 0));
|
||||
myTableView.setStriped(true);
|
||||
|
||||
myTableView.getTableViewModel().setSortable(false);
|
||||
myPanel = ToolbarDecorator.createDecorator(myTableView)
|
||||
ToolbarDecorator decorator = ToolbarDecorator.createDecorator(myTableView);
|
||||
myPanel = decorator
|
||||
.setAddAction(new AnActionButtonRunnable() {
|
||||
@Override
|
||||
public void run(AnActionButton button) {
|
||||
if (!myElements.isEmpty() && isEmpty(myElements.get(myElements.size() - 1))) return;
|
||||
myTableView.stopEditing();
|
||||
setModified();
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myElements.add(createElement());
|
||||
myTableView.getTableViewModel().setItems(myElements);
|
||||
if (myElements.isEmpty() || !isEmpty(myElements.get(myElements.size() - 1))) {
|
||||
myElements.add(createElement());
|
||||
myTableView.getTableViewModel().setItems(myElements);
|
||||
}
|
||||
myTableView.scrollRectToVisible(myTableView.getCellRect(myElements.size() - 1, 0, true));
|
||||
myTableView.getComponent().editCellAt(myElements.size() - 1, 0);
|
||||
}
|
||||
@@ -105,6 +114,7 @@ public abstract class ListTableWithButtons<T> extends Observable {
|
||||
T selected = getSelection();
|
||||
if (selected != null) {
|
||||
int selectedIndex = myElements.indexOf(selected);
|
||||
myTableView.scrollRectToVisible(myTableView.getCellRect(selectedIndex, 0, true));
|
||||
myElements.remove(selected);
|
||||
myTableView.getTableViewModel().setItems(myElements);
|
||||
|
||||
@@ -133,6 +143,7 @@ public abstract class ListTableWithButtons<T> extends Observable {
|
||||
}
|
||||
});
|
||||
|
||||
myActionsPanel = decorator.getActionsPanel();
|
||||
|
||||
myTableView.getComponent().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
}
|
||||
@@ -157,6 +168,10 @@ public abstract class ListTableWithButtons<T> extends Observable {
|
||||
return myPanel;
|
||||
}
|
||||
|
||||
public CommonActionsPanel getActionsPanel() {
|
||||
return myActionsPanel;
|
||||
}
|
||||
|
||||
public void setEnabled() {
|
||||
myTableView.getComponent().setEnabled(true);
|
||||
myIsEnabled = true;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -26,10 +26,7 @@ import com.intellij.openapi.fileChooser.FileChooserDescriptor;
|
||||
import com.intellij.openapi.fileTypes.FileTypes;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.vfs.JarFileSystem;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.*;
|
||||
import com.intellij.openapi.vfs.ex.http.HttpFileSystem;
|
||||
import com.intellij.ui.*;
|
||||
import com.intellij.ui.components.JBList;
|
||||
@@ -111,33 +108,36 @@ public class PathEditor {
|
||||
myList = new JBList(getListModel());
|
||||
myList.setCellRenderer(createListCellRenderer(myList));
|
||||
|
||||
ToolbarDecorator toolbarDecorator = ToolbarDecorator.createDecorator(myList).disableUpDownActions()
|
||||
ToolbarDecorator toolbarDecorator = ToolbarDecorator.createDecorator(myList)
|
||||
.disableUpDownActions()
|
||||
.setAddActionUpdater(new AnActionButtonUpdater() {
|
||||
@Override
|
||||
public boolean isEnabled(AnActionEvent e) {
|
||||
return myEnabled;
|
||||
}
|
||||
})
|
||||
.setRemoveActionUpdater(new AnActionButtonUpdater() {
|
||||
@Override
|
||||
public boolean isEnabled(AnActionEvent e) {
|
||||
return isRemoveActionEnabled(PathEditor.this.getSelectedRoots());
|
||||
}
|
||||
})
|
||||
.setAddAction(new AnActionButtonRunnable() {
|
||||
@Override
|
||||
public void run(AnActionButton button) {
|
||||
final VirtualFile[] added = doAdd();
|
||||
final VirtualFile[] added = doAddItems();
|
||||
if (added.length > 0) {
|
||||
setModified(true);
|
||||
}
|
||||
requestDefaultFocus();
|
||||
setSelectedRoots(added);
|
||||
}
|
||||
}).setRemoveAction(new AnActionButtonRunnable() {
|
||||
})
|
||||
.setRemoveAction(new AnActionButtonRunnable() {
|
||||
@Override
|
||||
public void run(AnActionButton button) {
|
||||
int[] idxs = myList.getSelectedIndices();
|
||||
doRemoveItems(idxs, myList);
|
||||
}
|
||||
}).setAddActionUpdater(new AnActionButtonUpdater() {
|
||||
@Override
|
||||
public boolean isEnabled(AnActionEvent e) {
|
||||
return myEnabled;
|
||||
}
|
||||
}).setRemoveActionUpdater(new AnActionButtonUpdater() {
|
||||
@Override
|
||||
public boolean isEnabled(AnActionEvent e) {
|
||||
Object[] values = getSelectedRoots();
|
||||
return values.length > 0 && myEnabled;
|
||||
int[] indices = myList.getSelectedIndices();
|
||||
doRemoveItems(indices, myList);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -152,28 +152,11 @@ public class PathEditor {
|
||||
protected void addToolbarButtons(ToolbarDecorator toolbarDecorator) {
|
||||
}
|
||||
|
||||
protected void doRemoveItems(int[] idxs, JList list) {
|
||||
List removedItems = ListUtil.removeIndices(list, idxs);
|
||||
itemsRemoved(removedItems);
|
||||
protected boolean isRemoveActionEnabled(Object[] values) {
|
||||
return values.length > 0 && myEnabled;
|
||||
}
|
||||
|
||||
protected DefaultListModel createListModel() {
|
||||
return new DefaultListModel();
|
||||
}
|
||||
|
||||
protected ListCellRenderer createListCellRenderer(JBList list) {
|
||||
return new MyCellRenderer();
|
||||
}
|
||||
|
||||
protected void itemsRemoved(List removedItems) {
|
||||
myAllFiles.removeAll(removedItems);
|
||||
if (removedItems.size() > 0) {
|
||||
setModified(true);
|
||||
}
|
||||
requestDefaultFocus();
|
||||
}
|
||||
|
||||
protected VirtualFile[] doAdd() {
|
||||
protected VirtualFile[] doAddItems() {
|
||||
Project project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(myPanel));
|
||||
VirtualFile[] files = FileChooser.chooseFiles(myDescriptor, myPanel, project, myAddBaseDir);
|
||||
files = adjustAddedFileSet(myPanel, files);
|
||||
@@ -183,7 +166,28 @@ public class PathEditor {
|
||||
added.add(vFile);
|
||||
}
|
||||
}
|
||||
return VfsUtil.toVirtualFileArray(added);
|
||||
return VfsUtilCore.toVirtualFileArray(added);
|
||||
}
|
||||
|
||||
protected void doRemoveItems(int[] indices, JList list) {
|
||||
List removedItems = ListUtil.removeIndices(list, indices);
|
||||
itemsRemoved(removedItems);
|
||||
}
|
||||
|
||||
protected DefaultListModel createListModel() {
|
||||
return new DefaultListModel();
|
||||
}
|
||||
|
||||
protected ListCellRenderer createListCellRenderer(JBList list) {
|
||||
return new PathCellRenderer();
|
||||
}
|
||||
|
||||
protected void itemsRemoved(List removedItems) {
|
||||
myAllFiles.removeAll(removedItems);
|
||||
if (removedItems.size() > 0) {
|
||||
setModified(true);
|
||||
}
|
||||
requestDefaultFocus();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -284,17 +288,18 @@ public class PathEditor {
|
||||
|
||||
private void keepSelectionState() {
|
||||
final Object[] selectedItems = getSelectedRoots();
|
||||
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (selectedItems != null) {
|
||||
if (selectedItems != null) {
|
||||
//noinspection SSBasedInspection
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
setSelectedRoots(selectedItems);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
protected Object[] getSelectedRoots() {
|
||||
return myList.getSelectedValues();
|
||||
}
|
||||
@@ -332,59 +337,46 @@ public class PathEditor {
|
||||
}).booleanValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return icon for displaying parameter (ProjectRoot or VirtualFile)
|
||||
* If parameter is not ProjectRoot or VirtualFile, returns empty icon "/nodes/emptyNode.png"
|
||||
*/
|
||||
private static Icon getIconForRoot(Object projectRoot) {
|
||||
if (projectRoot instanceof VirtualFile) {
|
||||
final VirtualFile file = (VirtualFile)projectRoot;
|
||||
VirtualFile file = (VirtualFile)projectRoot;
|
||||
if (!file.isValid()) {
|
||||
return AllIcons.Nodes.PpInvalid;
|
||||
}
|
||||
else if (isHttpRoot(file)) {
|
||||
else if (file.getFileSystem() instanceof HttpFileSystem) {
|
||||
return PlatformIcons.WEB_ICON;
|
||||
}
|
||||
else {
|
||||
return isJarFile(file) ? PlatformIcons.JAR_ICON : PlatformIcons.FILE_ICON;
|
||||
else if (isJarFile(file)) {
|
||||
return PlatformIcons.JAR_ICON;
|
||||
}
|
||||
return PlatformIcons.FILE_ICON;
|
||||
}
|
||||
|
||||
return AllIcons.Nodes.EmptyNode;
|
||||
}
|
||||
|
||||
private static boolean isHttpRoot(VirtualFile virtualFileOrProjectRoot) {
|
||||
if (virtualFileOrProjectRoot != null) {
|
||||
return (virtualFileOrProjectRoot.getFileSystem() instanceof HttpFileSystem);
|
||||
protected static class PathCellRenderer extends DefaultListCellRenderer {
|
||||
protected String getItemText(Object value) {
|
||||
return value instanceof VirtualFile ? ((VirtualFile)value).getPresentableUrl() : "UNKNOWN OBJECT";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private final class MyCellRenderer extends DefaultListCellRenderer {
|
||||
private String getPresentableString(final Object value) {
|
||||
return ApplicationManager.getApplication().runReadAction(new Computable<String>() {
|
||||
@Override
|
||||
public String compute() {
|
||||
//noinspection HardCodedStringLiteral
|
||||
return (value instanceof VirtualFile) ? ((VirtualFile)value).getPresentableUrl() : "UNKNOWN OBJECT";
|
||||
}
|
||||
});
|
||||
protected Icon getItemIcon(Object value) {
|
||||
return getIconForRoot(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
super.getListCellRendererComponent(list, getPresentableString(value), index, isSelected, cellHasFocus);
|
||||
public final Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
super.getListCellRendererComponent(list, getItemText(value), index, isSelected, cellHasFocus);
|
||||
|
||||
if (isSelected) {
|
||||
setForeground(UIUtil.getListSelectionForeground());
|
||||
}
|
||||
else {
|
||||
if (value instanceof VirtualFile) {
|
||||
VirtualFile file = (VirtualFile)value;
|
||||
if (!file.isValid()) {
|
||||
setForeground(INVALID_COLOR);
|
||||
}
|
||||
}
|
||||
else if (value instanceof VirtualFile && !((VirtualFile)value).isValid()) {
|
||||
setForeground(INVALID_COLOR);
|
||||
}
|
||||
setIcon(getIconForRoot(value));
|
||||
|
||||
setIcon(getItemIcon(value));
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -56,5 +56,4 @@ public class SdkPathEditor extends PathEditor {
|
||||
setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -382,6 +382,7 @@ public class QuickEditHandler extends DocumentAdapter implements Disposable {
|
||||
commitToOriginalInner();
|
||||
}
|
||||
});
|
||||
PsiDocumentManager.getInstance(myProject).doPostponedOperationsAndUnblockDocument(myOrigDocument);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
|
||||
@@ -450,6 +450,9 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data
|
||||
else {
|
||||
nothingToSearchFor();
|
||||
}
|
||||
if (mySearchField instanceof JTextArea) {
|
||||
UIUtil.adjustRows((JTextArea)mySearchField, 2, 6);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isRegexp() {
|
||||
@@ -637,6 +640,9 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data
|
||||
private void replaceFieldDocumentChanged() {
|
||||
setMatchesLimit(LivePreviewController.MATCHES_LIMIT);
|
||||
myFindModel.setStringToReplace(myReplaceField.getText());
|
||||
if (myReplaceField instanceof JTextArea) {
|
||||
UIUtil.adjustRows((JTextArea)myReplaceField, 2, 6);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean canReplaceCurrent() {
|
||||
@@ -697,12 +703,17 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data
|
||||
super.paintBorder(g);
|
||||
paintBorderOfTextField(g);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
return super.getPreferredSize();
|
||||
}
|
||||
};
|
||||
((JTextArea)editorTextField).setColumns(25);
|
||||
((JTextArea)editorTextField).setRows(3);
|
||||
((JTextArea)editorTextField).setRows(2);
|
||||
final JScrollPane scrollPane = new JBScrollPane(editorTextField,
|
||||
ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER,
|
||||
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
|
||||
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
||||
myLeftComponent.add(scrollPane, constraint);
|
||||
componentRef.set(scrollPane);
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@ import com.intellij.ui.components.JBScrollPane;
|
||||
import com.intellij.ui.table.JBTable;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.usages.*;
|
||||
import com.intellij.usages.impl.UsagePreviewPanel;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.Processor;
|
||||
@@ -70,14 +71,14 @@ import org.jetbrains.annotations.Nullable;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
import javax.swing.table.DefaultTableModel;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
@@ -123,7 +124,9 @@ public class FindDialog extends DialogWrapper {
|
||||
private static boolean myPreviewResultsTabWasSelected;
|
||||
private static final int RESULTS_PREVIEW_TAB_INDEX = 1;
|
||||
|
||||
private Splitter myPreviewSplitter;
|
||||
private JBTable myResultsPreviewTable;
|
||||
private UsagePreviewPanel myUsagePreviewPanel;
|
||||
private TabbedPane myContent;
|
||||
private volatile ProgressIndicatorBase myResultsPreviewSearchProgress;
|
||||
|
||||
@@ -173,6 +176,7 @@ public class FindDialog extends DialogWrapper {
|
||||
@Override
|
||||
protected void dispose() {
|
||||
finishPreviousPreviewSearch();
|
||||
if (myUsagePreviewPanel != null) Disposer.dispose(myUsagePreviewPanel);
|
||||
for(Map.Entry<EditorTextField, DocumentAdapter> e: myComboBoxListeners.entrySet()) {
|
||||
e.getKey().removeDocumentListener(e.getValue());
|
||||
}
|
||||
@@ -489,8 +493,29 @@ public class FindDialog extends DialogWrapper {
|
||||
}
|
||||
};
|
||||
table.setShowColumns(false);
|
||||
table.setShowGrid(false);
|
||||
new NavigateToSourceListener().installOn(table);
|
||||
|
||||
Splitter previewSplitter = new Splitter(true, 0.5f, 0.1f, 0.9f);
|
||||
myUsagePreviewPanel = new UsagePreviewPanel(myProject, new UsageViewPresentation());
|
||||
myResultsPreviewTable = table;
|
||||
myResultsPreviewTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
if (e.getValueIsAdjusting()) return;
|
||||
int index = myResultsPreviewTable.getSelectionModel().getLeadSelectionIndex();
|
||||
if (index != -1) {
|
||||
UsageInfo usageInfo = ((UsageInfo2UsageAdapter)myResultsPreviewTable.getModel().getValueAt(index, 0)).getUsageInfo();
|
||||
myUsagePreviewPanel.updateLayout(Collections.singletonList(usageInfo));
|
||||
}
|
||||
else {
|
||||
myUsagePreviewPanel.updateLayout(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
previewSplitter.setFirstComponent(new JBScrollPane(myResultsPreviewTable));
|
||||
previewSplitter.setSecondComponent(myUsagePreviewPanel.createComponent());
|
||||
myPreviewSplitter = previewSplitter;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -513,10 +538,10 @@ public class FindDialog extends DialogWrapper {
|
||||
resultsOptionPanel.add(myCbToOpenInNewTab);
|
||||
}
|
||||
|
||||
if (myResultsPreviewTable != null) {
|
||||
if (myPreviewSplitter != null) {
|
||||
TabbedPane pane = new TabbedPaneImpl(SwingConstants.TOP);
|
||||
pane.insertTab("Options", null, optionsPanel, null, 0);
|
||||
pane.insertTab("Preview", null, new JBScrollPane(myResultsPreviewTable), null, RESULTS_PREVIEW_TAB_INDEX);
|
||||
pane.insertTab("Preview", null, myPreviewSplitter, null, RESULTS_PREVIEW_TAB_INDEX);
|
||||
myContent = pane;
|
||||
if (myPreviewResultsTabWasSelected) myContent.setSelectedIndex(RESULTS_PREVIEW_TAB_INDEX);
|
||||
|
||||
@@ -1389,36 +1414,46 @@ public class FindDialog extends DialogWrapper {
|
||||
}
|
||||
|
||||
private static class UsageTableCellRenderer extends JPanel implements TableCellRenderer {
|
||||
private SimpleColoredComponent myUsageRenderer = new SimpleColoredComponent();
|
||||
private SimpleColoredComponent myFileAndLineNumber = new SimpleColoredComponent();
|
||||
private ColoredTableCellRenderer myUsageRenderer = new ColoredTableCellRenderer() {
|
||||
@Override
|
||||
protected void customizeCellRenderer(JTable table, Object value, boolean selected, boolean hasFocus, int row, int column) {
|
||||
if (value instanceof UsageInfo2UsageAdapter) {
|
||||
TextChunk[] text = ((UsageInfo2UsageAdapter)value).getPresentation().getText();
|
||||
|
||||
// skip line number / file info
|
||||
for (int i = 1; i < text.length; ++i) {
|
||||
TextChunk textChunk = text[i];
|
||||
myUsageRenderer.append(textChunk.getText(), textChunk.getSimpleAttributesIgnoreBackground());
|
||||
}
|
||||
}
|
||||
setBorder(null);
|
||||
}
|
||||
};
|
||||
private ColoredTableCellRenderer myFileAndLineNumber = new ColoredTableCellRenderer() {
|
||||
@Override
|
||||
protected void customizeCellRenderer(JTable table, Object value, boolean selected, boolean hasFocus, int row, int column) {
|
||||
if (value instanceof UsageInfo2UsageAdapter) {
|
||||
TextChunk[] text = ((UsageInfo2UsageAdapter)value).getPresentation().getText();
|
||||
// line number / file info
|
||||
append(((UsageInfo2UsageAdapter)value).getFile().getName() + " " + text[0].getText(), SimpleTextAttributes.GRAYED_ITALIC_ATTRIBUTES);
|
||||
}
|
||||
setBorder(null);
|
||||
}
|
||||
};
|
||||
|
||||
UsageTableCellRenderer() {
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
add(myUsageRenderer, BorderLayout.WEST);
|
||||
add(myFileAndLineNumber, BorderLayout.EAST);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
myUsageRenderer.clear();
|
||||
myFileAndLineNumber.clear();
|
||||
setBackground(isSelected && hasFocus ? UIUtil.getTableSelectionBackground() : UIUtil.getTableBackground());
|
||||
setBackground(UIUtil.getTableBackground(isSelected));
|
||||
myUsageRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
||||
myFileAndLineNumber.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
||||
|
||||
if (value instanceof UsageInfo2UsageAdapter) {
|
||||
UsageInfo2UsageAdapter usageAdapter = (UsageInfo2UsageAdapter)value;
|
||||
UsagePresentation presentation = usageAdapter.getPresentation();
|
||||
TextChunk[] text = presentation.getText();
|
||||
|
||||
// put line number / file info at the right
|
||||
for (int i = 1; i < text.length; ++i) {
|
||||
TextChunk textChunk = text[i];
|
||||
SimpleTextAttributes simples = textChunk.getSimpleAttributesIgnoreBackground();
|
||||
myUsageRenderer.append(textChunk.getText(), simples);
|
||||
}
|
||||
|
||||
myFileAndLineNumber.append(usageAdapter.getFile().getName() + " " + text[0].getText(),
|
||||
SimpleTextAttributes.GRAYED_ITALIC_ATTRIBUTES);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -158,6 +158,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
private JBList myList;
|
||||
private JCheckBox myNonProjectCheckBox;
|
||||
private AnActionEvent myActionEvent;
|
||||
private Set<AnAction> myDisabledActions = new HashSet<AnAction>();
|
||||
private Component myContextComponent;
|
||||
private CalcThread myCalcThread;
|
||||
private static AtomicBoolean ourShiftIsPressed = new AtomicBoolean(false);
|
||||
@@ -1040,6 +1041,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
}
|
||||
};
|
||||
SearchEverywherePsiRenderer myFileRenderer = new SearchEverywherePsiRenderer(myList);
|
||||
ListCellRenderer myActionsRenderer = new GotoActionModel.GotoActionListCellRenderer(Function.TO_STRING);
|
||||
|
||||
private String myLocationString;
|
||||
private DefaultPsiElementCellRenderer myPsiRenderer = new DefaultPsiElementCellRenderer() {
|
||||
@@ -1080,6 +1082,8 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
} else if (value instanceof PsiElement) {
|
||||
myFileRenderer.setPatternMatcher(matcher);
|
||||
cmp = myFileRenderer.getListCellRendererComponent(list, value, index, isSelected, isSelected);
|
||||
} else if (value instanceof GotoActionModel.ActionWrapper) {
|
||||
cmp = myActionsRenderer.getListCellRendererComponent(list, new GotoActionModel.MatchedValue(((GotoActionModel.ActionWrapper)value), pattern), index, isSelected, isSelected);
|
||||
} else {
|
||||
cmp = super.getListCellRendererComponent(list, value, index, isSelected, isSelected);
|
||||
final JPanel p = new JPanel(new BorderLayout());
|
||||
@@ -1464,7 +1468,10 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
result.add(object);
|
||||
}
|
||||
} else if (actions && !isToolWindowAction(object) && isActionValue(object)) {
|
||||
result.add(object);
|
||||
AnAction action = object instanceof AnAction ? ((AnAction)object) : ((GotoActionModel.ActionWrapper)object).getAction();
|
||||
if (isEnabled(action)) {
|
||||
result.add(object);
|
||||
}
|
||||
}
|
||||
return result.size() <= max;
|
||||
}
|
||||
@@ -1905,19 +1912,9 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
public void run() {
|
||||
if (isCanceled()) return;
|
||||
|
||||
|
||||
for (Object element : new ArrayList(elements)) {
|
||||
if (element instanceof AnAction) {
|
||||
final AnAction action = (AnAction)element;
|
||||
final AnActionEvent e = new AnActionEvent(myActionEvent.getInputEvent(),
|
||||
myActionEvent.getDataContext(),
|
||||
myActionEvent.getPlace(),
|
||||
action.getTemplatePresentation(),
|
||||
myActionEvent.getActionManager(),
|
||||
myActionEvent.getModifiers());
|
||||
ActionUtil.performDumbAwareUpdate(action, e, false);
|
||||
final Presentation presentation = e.getPresentation();
|
||||
if (!presentation.isEnabled() || !presentation.isVisible() || StringUtil.isEmpty(presentation.getText())) {
|
||||
if (!isEnabled((AnAction)element)) {
|
||||
elements.remove(element);
|
||||
}
|
||||
if (isCanceled()) return;
|
||||
@@ -1933,6 +1930,29 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isEnabled(final AnAction action) {
|
||||
if (myDisabledActions.contains(action)) return false;
|
||||
final AnActionEvent e = new AnActionEvent(myActionEvent.getInputEvent(),
|
||||
myActionEvent.getDataContext(),
|
||||
myActionEvent.getPlace(),
|
||||
action.getTemplatePresentation(),
|
||||
myActionEvent.getActionManager(),
|
||||
myActionEvent.getModifiers());
|
||||
|
||||
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ActionUtil.performDumbAwareUpdate(action, e, false);
|
||||
}
|
||||
});
|
||||
final Presentation presentation = e.getPresentation();
|
||||
final boolean enabled = presentation.isEnabled() && presentation.isVisible() && !StringUtil.isEmpty(presentation.getText());
|
||||
if (!enabled) {
|
||||
myDisabledActions.add(action);
|
||||
}
|
||||
return enabled;
|
||||
}
|
||||
|
||||
private synchronized void checkModelsUpToDate() {
|
||||
if (myClassModel == null) {
|
||||
myClassModel = new GotoClassModel2(project);
|
||||
@@ -2165,6 +2185,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
myEditor = null;
|
||||
myFileEditor = null;
|
||||
myStructureModel = null;
|
||||
myDisabledActions.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -41,6 +41,7 @@ import com.intellij.ui.components.JBLabel;
|
||||
import com.intellij.ui.components.OnOffButton;
|
||||
import com.intellij.ui.speedSearch.SpeedSearchUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.ContainerUtilRt;
|
||||
import com.intellij.util.ui.EmptyIcon;
|
||||
@@ -144,7 +145,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C
|
||||
@NotNull public final Comparable value;
|
||||
@NotNull final String pattern;
|
||||
|
||||
MatchedValue(@NotNull Comparable value, @NotNull String pattern) {
|
||||
public MatchedValue(@NotNull Comparable value, @NotNull String pattern) {
|
||||
this.value = value;
|
||||
this.pattern = pattern;
|
||||
}
|
||||
@@ -208,121 +209,12 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C
|
||||
|
||||
@Override
|
||||
public ListCellRenderer getListCellRenderer() {
|
||||
return new DefaultListCellRenderer() {
|
||||
return new GotoActionListCellRenderer(new Function<OptionDescription, String>() {
|
||||
@Override
|
||||
public Component getListCellRendererComponent(@NotNull final JList list,
|
||||
final Object matchedValue,
|
||||
final int index, final boolean isSelected, final boolean cellHasFocus) {
|
||||
final JPanel panel = new JPanel(new BorderLayout());
|
||||
panel.setBorder(IdeBorderFactory.createEmptyBorder(2));
|
||||
panel.setOpaque(true);
|
||||
Color bg = UIUtil.getListBackground(isSelected);
|
||||
panel.setBackground(bg);
|
||||
|
||||
if (matchedValue instanceof String) { //...
|
||||
final JBLabel label = new JBLabel((String)matchedValue);
|
||||
label.setIcon(EMPTY_ICON);
|
||||
panel.add(label, BorderLayout.WEST);
|
||||
return panel;
|
||||
}
|
||||
|
||||
Color groupFg = isSelected ? UIUtil.getListSelectionForeground() : UIUtil.getLabelDisabledForeground();
|
||||
|
||||
final Object value = ((MatchedValue) matchedValue).value;
|
||||
String pattern = ((MatchedValue)matchedValue).pattern;
|
||||
|
||||
SimpleColoredComponent nameComponent = new SimpleColoredComponent();
|
||||
nameComponent.setBackground(bg);
|
||||
panel.add(nameComponent, BorderLayout.CENTER);
|
||||
|
||||
if (value instanceof ActionWrapper) {
|
||||
final ActionWrapper actionWithParentGroup = (ActionWrapper)value;
|
||||
final AnAction anAction = actionWithParentGroup.getAction();
|
||||
final Presentation presentation = anAction.getTemplatePresentation();
|
||||
boolean toggle = anAction instanceof ToggleAction;
|
||||
String groupName = actionWithParentGroup.getAction() instanceof ApplyIntentionAction ? null : actionWithParentGroup.getGroupName();
|
||||
final Color fg = defaultActionForeground(isSelected, actionWithParentGroup.getPresentation());
|
||||
panel.add(createIconLabel(presentation.getIcon()), BorderLayout.WEST);
|
||||
appendWithColoredMatches(nameComponent, getName(presentation.getText(), groupName, toggle), pattern, fg, isSelected);
|
||||
|
||||
final Shortcut shortcut = preferKeyboardShortcut(KeymapManager.getInstance().getActiveKeymap().getShortcuts(getActionId(anAction)));
|
||||
if (shortcut != null) {
|
||||
nameComponent.append(" (" + KeymapUtil.getShortcutText(shortcut) + ")", new SimpleTextAttributes(STYLE_PLAIN, groupFg));
|
||||
}
|
||||
|
||||
if (toggle) {
|
||||
final OnOffButton button = new OnOffButton();
|
||||
AnActionEvent event = new AnActionEvent(null, ((ActionWrapper)value).myDataContext,
|
||||
ActionPlaces.UNKNOWN, new Presentation(), ActionManager.getInstance(),
|
||||
0);
|
||||
button.setSelected(((ToggleAction)anAction).isSelected(event));
|
||||
panel.add(button, BorderLayout.EAST);
|
||||
panel.setBorder(IdeBorderFactory.createEmptyBorder());
|
||||
}
|
||||
else {
|
||||
if (groupName != null) {
|
||||
final JLabel groupLabel = new JLabel(groupName);
|
||||
groupLabel.setBackground(bg);
|
||||
groupLabel.setForeground(groupFg);
|
||||
panel.add(groupLabel, BorderLayout.EAST);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (value instanceof OptionDescription) {
|
||||
if (!isSelected && !(value instanceof BooleanOptionDescription)) {
|
||||
Color descriptorBg = UIUtil.isUnderDarcula() ? ColorUtil.brighter(UIUtil.getListBackground(), 1) : LightColors.SLIGHTLY_GRAY;
|
||||
panel.setBackground(descriptorBg);
|
||||
nameComponent.setBackground(descriptorBg);
|
||||
}
|
||||
String hit = ((OptionDescription)value).getHit();
|
||||
if (hit == null) {
|
||||
hit = ((OptionDescription)value).getOption();
|
||||
}
|
||||
hit = StringUtil.unescapeXml(hit);
|
||||
hit = hit.replace(" ", " "); // avoid extra spaces from mnemonics and xml conversion
|
||||
String fullHit = hit;
|
||||
hit = StringUtil.first(hit, 45, true);
|
||||
|
||||
final Color fg = UIUtil.getListForeground(isSelected);
|
||||
|
||||
appendWithColoredMatches(nameComponent, hit.trim(), pattern, fg, isSelected);
|
||||
|
||||
panel.add(new JLabel(EMPTY_ICON), BorderLayout.WEST);
|
||||
panel.setToolTipText(fullHit);
|
||||
|
||||
if (value instanceof BooleanOptionDescription) {
|
||||
final OnOffButton button = new OnOffButton();
|
||||
button.setSelected(((BooleanOptionDescription)value).isOptionEnabled());
|
||||
panel.add(button, BorderLayout.EAST);
|
||||
panel.setBorder(IdeBorderFactory.createEmptyBorder());
|
||||
}
|
||||
else {
|
||||
final JLabel settingsLabel = new JLabel(getGroupName((OptionDescription)value));
|
||||
settingsLabel.setForeground(groupFg);
|
||||
settingsLabel.setBackground(bg);
|
||||
panel.add(settingsLabel, BorderLayout.EAST);
|
||||
}
|
||||
}
|
||||
return panel;
|
||||
public String fun(OptionDescription description) {
|
||||
return getGroupName(description);
|
||||
}
|
||||
|
||||
public String getName(String text, String groupName, boolean toggle) {
|
||||
return toggle && StringUtil.isNotEmpty(groupName)? groupName + ": "+ text : text;
|
||||
}
|
||||
|
||||
private void appendWithColoredMatches(SimpleColoredComponent nameComponent, String name, String pattern, Color fg, boolean selected) {
|
||||
final SimpleTextAttributes plain = new SimpleTextAttributes(STYLE_PLAIN, fg);
|
||||
final SimpleTextAttributes highlighted = new SimpleTextAttributes(null, fg, null, STYLE_SEARCH_MATCH);
|
||||
List<TextRange> fragments = ContainerUtil.newArrayList();
|
||||
if (selected) {
|
||||
int matchStart = StringUtil.indexOfIgnoreCase(name, pattern, 0);
|
||||
if (matchStart >= 0) {
|
||||
fragments.add(TextRange.from(matchStart, pattern.length()));
|
||||
}
|
||||
}
|
||||
SpeedSearchUtil.appendColoredFragments(nameComponent, name, fragments, plain, highlighted);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
protected String getActionId(@NotNull final AnAction anAction) {
|
||||
@@ -721,4 +613,130 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C
|
||||
return myAction.getTemplatePresentation().getText().hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public static class GotoActionListCellRenderer extends DefaultListCellRenderer {
|
||||
private final Function<OptionDescription, String> myGroupNamer;
|
||||
|
||||
public GotoActionListCellRenderer(Function<OptionDescription, String> groupNamer) {
|
||||
myGroupNamer = groupNamer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getListCellRendererComponent(@NotNull final JList list,
|
||||
final Object matchedValue,
|
||||
final int index, final boolean isSelected, final boolean cellHasFocus) {
|
||||
final JPanel panel = new JPanel(new BorderLayout());
|
||||
panel.setBorder(IdeBorderFactory.createEmptyBorder(2));
|
||||
panel.setOpaque(true);
|
||||
Color bg = UIUtil.getListBackground(isSelected);
|
||||
panel.setBackground(bg);
|
||||
|
||||
if (matchedValue instanceof String) { //...
|
||||
final JBLabel label = new JBLabel((String)matchedValue);
|
||||
label.setIcon(EMPTY_ICON);
|
||||
panel.add(label, BorderLayout.WEST);
|
||||
return panel;
|
||||
}
|
||||
|
||||
Color groupFg = isSelected ? UIUtil.getListSelectionForeground() : UIUtil.getLabelDisabledForeground();
|
||||
|
||||
final Object value = ((MatchedValue) matchedValue).value;
|
||||
String pattern = ((MatchedValue)matchedValue).pattern;
|
||||
|
||||
SimpleColoredComponent nameComponent = new SimpleColoredComponent();
|
||||
nameComponent.setBackground(bg);
|
||||
panel.add(nameComponent, BorderLayout.CENTER);
|
||||
|
||||
if (value instanceof ActionWrapper) {
|
||||
final ActionWrapper actionWithParentGroup = (ActionWrapper)value;
|
||||
final AnAction anAction = actionWithParentGroup.getAction();
|
||||
final Presentation presentation = anAction.getTemplatePresentation();
|
||||
boolean toggle = anAction instanceof ToggleAction;
|
||||
String groupName = actionWithParentGroup.getAction() instanceof ApplyIntentionAction ? null : actionWithParentGroup.getGroupName();
|
||||
final Color fg = defaultActionForeground(isSelected, actionWithParentGroup.getPresentation());
|
||||
panel.add(createIconLabel(presentation.getIcon()), BorderLayout.WEST);
|
||||
appendWithColoredMatches(nameComponent, getName(presentation.getText(), groupName, toggle), pattern, fg, isSelected);
|
||||
|
||||
final Shortcut shortcut = preferKeyboardShortcut(KeymapManager.getInstance().getActiveKeymap().getShortcuts(ActionManager.getInstance().getId(anAction)));
|
||||
if (shortcut != null) {
|
||||
nameComponent.append(" (" + KeymapUtil.getShortcutText(shortcut) + ")", new SimpleTextAttributes(STYLE_PLAIN, groupFg));
|
||||
}
|
||||
|
||||
if (toggle) {
|
||||
final OnOffButton button = new OnOffButton();
|
||||
AnActionEvent event = new AnActionEvent(null, ((ActionWrapper)value).myDataContext,
|
||||
ActionPlaces.UNKNOWN, new Presentation(), ActionManager.getInstance(),
|
||||
0);
|
||||
button.setSelected(((ToggleAction)anAction).isSelected(event));
|
||||
panel.add(button, BorderLayout.EAST);
|
||||
panel.setBorder(IdeBorderFactory.createEmptyBorder());
|
||||
}
|
||||
else {
|
||||
if (groupName != null) {
|
||||
final JLabel groupLabel = new JLabel(groupName);
|
||||
groupLabel.setBackground(bg);
|
||||
groupLabel.setForeground(groupFg);
|
||||
panel.add(groupLabel, BorderLayout.EAST);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (value instanceof OptionDescription) {
|
||||
if (!isSelected && !(value instanceof BooleanOptionDescription)) {
|
||||
Color descriptorBg = UIUtil.isUnderDarcula() ? ColorUtil.brighter(UIUtil.getListBackground(), 1) : LightColors.SLIGHTLY_GRAY;
|
||||
panel.setBackground(descriptorBg);
|
||||
nameComponent.setBackground(descriptorBg);
|
||||
}
|
||||
String hit = ((OptionDescription)value).getHit();
|
||||
if (hit == null) {
|
||||
hit = ((OptionDescription)value).getOption();
|
||||
}
|
||||
hit = StringUtil.unescapeXml(hit);
|
||||
hit = hit.replace(" ", " "); // avoid extra spaces from mnemonics and xml conversion
|
||||
String fullHit = hit;
|
||||
hit = StringUtil.first(hit, 45, true);
|
||||
|
||||
final Color fg = UIUtil.getListForeground(isSelected);
|
||||
|
||||
appendWithColoredMatches(nameComponent, hit.trim(), pattern, fg, isSelected);
|
||||
|
||||
panel.add(new JLabel(EMPTY_ICON), BorderLayout.WEST);
|
||||
panel.setToolTipText(fullHit);
|
||||
|
||||
if (value instanceof BooleanOptionDescription) {
|
||||
final OnOffButton button = new OnOffButton();
|
||||
button.setSelected(((BooleanOptionDescription)value).isOptionEnabled());
|
||||
panel.add(button, BorderLayout.EAST);
|
||||
panel.setBorder(IdeBorderFactory.createEmptyBorder());
|
||||
}
|
||||
else {
|
||||
final JLabel settingsLabel = new JLabel(myGroupNamer.fun((OptionDescription)value));
|
||||
settingsLabel.setForeground(groupFg);
|
||||
settingsLabel.setBackground(bg);
|
||||
panel.add(settingsLabel, BorderLayout.EAST);
|
||||
}
|
||||
}
|
||||
return panel;
|
||||
}
|
||||
|
||||
public String getName(String text, String groupName, boolean toggle) {
|
||||
return toggle && StringUtil.isNotEmpty(groupName)? groupName + ": "+ text : text;
|
||||
}
|
||||
|
||||
private static void appendWithColoredMatches(SimpleColoredComponent nameComponent,
|
||||
String name,
|
||||
String pattern,
|
||||
Color fg,
|
||||
boolean selected) {
|
||||
final SimpleTextAttributes plain = new SimpleTextAttributes(STYLE_PLAIN, fg);
|
||||
final SimpleTextAttributes highlighted = new SimpleTextAttributes(null, fg, null, STYLE_SEARCH_MATCH);
|
||||
List<TextRange> fragments = ContainerUtil.newArrayList();
|
||||
if (selected) {
|
||||
int matchStart = StringUtil.indexOfIgnoreCase(name, pattern, 0);
|
||||
if (matchStart >= 0) {
|
||||
fragments.add(TextRange.from(matchStart, pattern.length()));
|
||||
}
|
||||
}
|
||||
SpeedSearchUtil.appendColoredFragments(nameComponent, name, fragments, plain, highlighted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-1
@@ -20,6 +20,7 @@ import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
|
||||
import com.intellij.codeInsight.editorActions.CopyPastePostProcessor;
|
||||
import com.intellij.codeInsight.editorActions.CopyPastePreProcessor;
|
||||
import com.intellij.ide.highlighter.HighlighterFactory;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.*;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
@@ -45,6 +46,7 @@ import com.intellij.openapi.editor.richcopy.view.RtfTransferableData;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.TokenType;
|
||||
@@ -271,7 +273,17 @@ public class TextWithMarkupProcessor extends CopyPastePostProcessor<RawTextWithM
|
||||
myText = charSequence;
|
||||
myDefaultForeground = scheme.getDefaultForeground();
|
||||
myDefaultBackground = scheme.getDefaultBackground();
|
||||
builder = new SyntaxInfo.Builder(myDefaultForeground, myDefaultBackground, scheme.getEditorFontSize());
|
||||
|
||||
// Java assumes screen resolution of 72dpi when calculating font size in pixels. External applications are supposedly using correct
|
||||
// resolution, so we need to adjust font size for copied text to look the same in them.
|
||||
// (See https://docs.oracle.com/javase/7/docs/webnotes/tsg/TSG-Desktop/html/java2d.html#gdlwn)
|
||||
// Java on Mac is not affected by this issue.
|
||||
int javaFontSize = scheme.getEditorFontSize();
|
||||
float fontSize = SystemInfo.isMac || ApplicationManager.getApplication().isHeadlessEnvironment() ?
|
||||
javaFontSize :
|
||||
javaFontSize * 72f / Toolkit.getDefaultToolkit().getScreenResolution();
|
||||
|
||||
builder = new SyntaxInfo.Builder(myDefaultForeground, myDefaultBackground, fontSize);
|
||||
myIndentSymbolsToStrip = indentSymbolsToStrip;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,13 +34,13 @@ public class SyntaxInfo {
|
||||
|
||||
private final int myDefaultForeground;
|
||||
private final int myDefaultBackground;
|
||||
private final int myFontSize;
|
||||
private final float myFontSize;
|
||||
|
||||
private SyntaxInfo(int outputInfoCount,
|
||||
byte[] outputInfosSerialized,
|
||||
int defaultForeground,
|
||||
int defaultBackground,
|
||||
int fontSize,
|
||||
float fontSize,
|
||||
@NotNull FontNameRegistry fontNameRegistry,
|
||||
@NotNull ColorRegistry colorRegistry)
|
||||
{
|
||||
@@ -71,7 +71,7 @@ public class SyntaxInfo {
|
||||
return myDefaultBackground;
|
||||
}
|
||||
|
||||
public int getFontSize() {
|
||||
public float getFontSize() {
|
||||
return myFontSize;
|
||||
}
|
||||
|
||||
@@ -146,12 +146,12 @@ public class SyntaxInfo {
|
||||
private final FontNameRegistry myFontNameRegistry = new FontNameRegistry();
|
||||
private final int myDefaultForeground;
|
||||
private final int myDefaultBackground;
|
||||
private final int myFontSize;
|
||||
private final float myFontSize;
|
||||
private final ByteArrayOutputStream myStream = new ByteArrayOutputStream();
|
||||
private final OutputInfoSerializer.OutputStream myOutputInfoStream;
|
||||
private int myOutputInfoCount;
|
||||
|
||||
public Builder(Color defaultForeground, Color defaultBackground, int fontSize) {
|
||||
public Builder(Color defaultForeground, Color defaultBackground, float fontSize) {
|
||||
myDefaultForeground = myColorRegistry.getId(defaultForeground);
|
||||
myDefaultBackground = myColorRegistry.getId(defaultBackground);
|
||||
myFontSize = fontSize;
|
||||
|
||||
+1
-1
@@ -83,7 +83,7 @@ public class HtmlTransferableData extends AbstractSyntaxAwareReaderTransferableD
|
||||
else {
|
||||
myFontFamily = myDefaultFontFamily = -1;
|
||||
}
|
||||
myResultBuffer.append("font-size:").append(mySyntaxInfo.getFontSize()).append("pt;\">");
|
||||
myResultBuffer.append(String.format("font-size:%.1fpt;\">", mySyntaxInfo.getFontSize()));
|
||||
|
||||
mySyntaxInfo.processOutputInfo(this);
|
||||
|
||||
|
||||
+3
-3
@@ -77,8 +77,8 @@ public class RtfTransferableData extends AbstractSyntaxAwareInputStreamTransfera
|
||||
return "US-ASCII";
|
||||
}
|
||||
|
||||
private static void addFontSize(StringBuilder buffer, int fontSize) {
|
||||
buffer.append("\\fs").append(fontSize * 2);
|
||||
private static void addFontSize(StringBuilder buffer, float fontSize) {
|
||||
buffer.append("\\fs").append(Math.round(fontSize * 2));
|
||||
}
|
||||
|
||||
private static class MyVisitor implements MarkupHandler {
|
||||
@@ -88,7 +88,7 @@ public class RtfTransferableData extends AbstractSyntaxAwareInputStreamTransfera
|
||||
private final int myMaxLength;
|
||||
|
||||
private final int myDefaultBackgroundId;
|
||||
private final int myFontSize;
|
||||
private final float myFontSize;
|
||||
private int myForegroundId = -1;
|
||||
private int myFontNameId = -1;
|
||||
private int myFontStyle = -1;
|
||||
|
||||
+33
-32
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -32,7 +32,6 @@ import com.intellij.openapi.project.DumbModeTask;
|
||||
import com.intellij.openapi.project.DumbServiceImpl;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.*;
|
||||
import com.intellij.openapi.roots.libraries.Library;
|
||||
import com.intellij.openapi.startup.StartupManager;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.vfs.*;
|
||||
@@ -59,15 +58,17 @@ import java.util.Set;
|
||||
*/
|
||||
public class ProjectRootManagerComponent extends ProjectRootManagerImpl {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.roots.impl.ProjectManagerComponent");
|
||||
private static final boolean ourScheduleCacheUpdateInDumbMode = SystemProperties.getBooleanProperty(
|
||||
"idea.schedule.cache.update.in.dumb.mode", true);
|
||||
|
||||
private static final boolean ourScheduleCacheUpdateInDumbMode =
|
||||
SystemProperties.getBooleanProperty("idea.schedule.cache.update.in.dumb.mode", true);
|
||||
|
||||
private boolean myPointerChangesDetected = false;
|
||||
private int myInsideRefresh = 0;
|
||||
private final BatchUpdateListener myHandler;
|
||||
private final MessageBusConnection myConnection;
|
||||
|
||||
protected final List<CacheUpdater> myRootsChangeUpdaters = new ArrayList<CacheUpdater>();
|
||||
protected final List<CacheUpdater> myRefreshCacheUpdaters = new ArrayList<CacheUpdater>();
|
||||
@SuppressWarnings("deprecation") protected final List<CacheUpdater> myRootsChangeUpdaters = new ArrayList<CacheUpdater>();
|
||||
@SuppressWarnings("deprecation") protected final List<CacheUpdater> myRefreshCacheUpdaters = new ArrayList<CacheUpdater>();
|
||||
|
||||
private Set<LocalFileSystem.WatchRequest> myRootsToWatch = new THashSet<LocalFileSystem.WatchRequest>();
|
||||
private final boolean myDoLogCachesUpdate;
|
||||
@@ -120,19 +121,23 @@ public class ProjectRootManagerComponent extends ProjectRootManagerImpl {
|
||||
myDoLogCachesUpdate = ApplicationManager.getApplication().isInternal() && !ApplicationManager.getApplication().isUnitTestMode();
|
||||
}
|
||||
|
||||
@SuppressWarnings({"deprecation", "unused"})
|
||||
public void registerRootsChangeUpdater(CacheUpdater updater) {
|
||||
myRootsChangeUpdaters.add(updater);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"deprecation", "unused"})
|
||||
public void unregisterRootsChangeUpdater(CacheUpdater updater) {
|
||||
boolean removed = myRootsChangeUpdaters.remove(updater);
|
||||
LOG.assertTrue(removed);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"deprecation", "unused"})
|
||||
public void registerRefreshUpdater(CacheUpdater updater) {
|
||||
myRefreshCacheUpdaters.add(updater);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"deprecation", "unused"})
|
||||
public void unregisterRefreshUpdater(CacheUpdater updater) {
|
||||
boolean removed = myRefreshCacheUpdaters.remove(updater);
|
||||
LOG.assertTrue(removed);
|
||||
@@ -273,27 +278,22 @@ public class ProjectRootManagerComponent extends ProjectRootManagerImpl {
|
||||
|
||||
final Module[] modules = ModuleManager.getInstance(myProject).getModules();
|
||||
for (Module module : modules) {
|
||||
flat.add(module.getModuleFilePath());
|
||||
|
||||
final ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module);
|
||||
|
||||
addRootsToTrack(moduleRootManager.getContentRootUrls(), recursive, flat);
|
||||
|
||||
if (includeSourceRoots) {
|
||||
addRootsToTrack(moduleRootManager.getSourceRootUrls(), recursive, flat);
|
||||
}
|
||||
flat.add(module.getModuleFilePath());
|
||||
|
||||
final OrderEntry[] orderEntries = moduleRootManager.getOrderEntries();
|
||||
for (OrderEntry entry : orderEntries) {
|
||||
if (entry instanceof LibraryOrderEntry) {
|
||||
final Library library = ((LibraryOrderEntry)entry).getLibrary();
|
||||
if (library != null) {
|
||||
for (OrderRootType orderRootType : OrderRootType.getAllTypes()) {
|
||||
addRootsToTrack(library.getUrls(orderRootType), recursive, flat);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (entry instanceof JdkOrderEntry) {
|
||||
if (entry instanceof LibraryOrSdkOrderEntry) {
|
||||
final LibraryOrSdkOrderEntry libSdkEntry = (LibraryOrSdkOrderEntry)entry;
|
||||
for (OrderRootType orderRootType : OrderRootType.getAllTypes()) {
|
||||
addRootsToTrack(((JdkOrderEntry)entry).getRootUrls(orderRootType), recursive, flat);
|
||||
addRootsToTrack(libSdkEntry.getRootUrls(orderRootType), recursive, flat);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -302,6 +302,20 @@ public class ProjectRootManagerComponent extends ProjectRootManagerImpl {
|
||||
return Pair.create(recursive, flat);
|
||||
}
|
||||
|
||||
private static void addRootsToTrack(final String[] urls, final Collection<String> recursive, final Collection<String> flat) {
|
||||
for (String url : urls) {
|
||||
if (url != null) {
|
||||
final String protocol = VirtualFileManager.extractProtocol(url);
|
||||
if (protocol == null || LocalFileSystem.PROTOCOL.equals(protocol)) {
|
||||
recursive.add(extractLocalPath(url));
|
||||
}
|
||||
else if (JarFileSystem.PROTOCOL.equals(protocol)) {
|
||||
flat.add(extractLocalPath(url));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doSynchronizeRoots() {
|
||||
if (!myStartupActivityPerformed) return;
|
||||
@@ -315,22 +329,9 @@ public class ProjectRootManagerComponent extends ProjectRootManagerImpl {
|
||||
|
||||
if (ourScheduleCacheUpdateInDumbMode) {
|
||||
dumbService.queueCacheUpdateInDumbMode(myRootsChangeUpdaters);
|
||||
} else {
|
||||
dumbService.queueCacheUpdate(myRootsChangeUpdaters);
|
||||
}
|
||||
}
|
||||
|
||||
private static void addRootsToTrack(final String[] urls, final Collection<String> recursive, final Collection<String> flat) {
|
||||
for (String url : urls) {
|
||||
if (url != null) {
|
||||
final String protocol = VirtualFileManager.extractProtocol(url);
|
||||
if (protocol == null || LocalFileSystem.PROTOCOL.equals(protocol)) {
|
||||
recursive.add(extractLocalPath(url));
|
||||
}
|
||||
else if (JarFileSystem.PROTOCOL.equals(protocol)) {
|
||||
flat.add(extractLocalPath(url));
|
||||
}
|
||||
}
|
||||
else {
|
||||
dumbService.queueCacheUpdate(myRootsChangeUpdaters);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -84,9 +84,21 @@ public final class MapIndexStorage<Key, Value> implements IndexStorage<Key, Valu
|
||||
initMapAndCache();
|
||||
}
|
||||
|
||||
private static final PersistentHashMapValueStorage.ExceptionalIOCancellationCallback ourProgressManagerCheckCancelledIOCanceller =
|
||||
new PersistentHashMapValueStorage.ExceptionalIOCancellationCallback() {
|
||||
@Override
|
||||
public void checkCancellation() {
|
||||
ProgressManager.checkCanceled();
|
||||
}
|
||||
};
|
||||
private void initMapAndCache() throws IOException {
|
||||
final ValueContainerMap<Key, Value> map = new ValueContainerMap<Key, Value>(myStorageFile, myKeyDescriptor, myDataExternalizer,
|
||||
myKeyIsUniqueForIndexedFile);
|
||||
final ValueContainerMap<Key, Value> map;
|
||||
PersistentHashMapValueStorage.CreationTimeOptions.EXCEPTIONAL_IO_CANCELLATION.set(ourProgressManagerCheckCancelledIOCanceller);
|
||||
try {
|
||||
map = new ValueContainerMap<Key, Value>(myStorageFile, myKeyDescriptor, myDataExternalizer, myKeyIsUniqueForIndexedFile);
|
||||
} finally {
|
||||
PersistentHashMapValueStorage.CreationTimeOptions.EXCEPTIONAL_IO_CANCELLATION.set(null);
|
||||
}
|
||||
myCache = new SLRUCache<Key, ChangeTrackingValueContainer<Value>>(myCacheSize, (int)(Math.ceil(myCacheSize * 0.25)) /* 25% from the main cache size*/) {
|
||||
@Override
|
||||
@NotNull
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.intellij.openapi;
|
||||
|
||||
import com.intellij.ide.ui.UISettings;
|
||||
import com.intellij.openapi.actionSystem.CustomShortcutSet;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
@@ -26,7 +25,6 @@ import com.intellij.util.ui.DialogUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.text.JTextComponent;
|
||||
import java.awt.*;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
@@ -80,7 +78,7 @@ public class MnemonicHelper extends ComponentTreeWatcher {
|
||||
}
|
||||
|
||||
private static void fixMacMnemonicKeyStroke(JComponent component, String type) {
|
||||
if (SystemInfo.isMac) {
|
||||
if (SystemInfo.isMac && Registry.is("ide.mac.alt.mnemonic.without.ctrl")) {
|
||||
// hack to make component's mnemonic work for ALT+KEY_CODE on Macs.
|
||||
// Default implementation uses ALT+CTRL+KEY_CODE (see BasicLabelUI).
|
||||
InputMap inputMap = component.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||
|
||||
@@ -0,0 +1,322 @@
|
||||
/*
|
||||
* 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.openapi;
|
||||
|
||||
import com.intellij.ide.ui.UISettings;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.Component;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* @author Sergey.Malenkov
|
||||
*/
|
||||
abstract class MnemonicWrapper<T extends Component> implements Runnable, PropertyChangeListener {
|
||||
public static MnemonicWrapper getWrapper(Component component) {
|
||||
for (PropertyChangeListener listener : component.getPropertyChangeListeners()) {
|
||||
if (listener instanceof MnemonicWrapper) {
|
||||
MnemonicWrapper wrapper = (MnemonicWrapper)listener;
|
||||
wrapper.run(); // update mnemonics immediately
|
||||
return wrapper;
|
||||
}
|
||||
}
|
||||
if (component instanceof JMenuItem) {
|
||||
return null; // TODO: new MenuWrapper((JMenuItem)component);
|
||||
}
|
||||
if (component instanceof AbstractButton) {
|
||||
return new ButtonWrapper((AbstractButton)component);
|
||||
}
|
||||
if (component instanceof JLabel) {
|
||||
return new LabelWrapper((JLabel)component);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
final T myComponent; // direct access from inner classes
|
||||
private final String myTextProperty;
|
||||
private final String myCodeProperty;
|
||||
private final String myIndexProperty;
|
||||
private int myCode;
|
||||
private int myIndex;
|
||||
private boolean myFocusable;
|
||||
private boolean myEvent;
|
||||
private Runnable myRunnable;
|
||||
|
||||
private MnemonicWrapper(T component, String text, String code, String index) {
|
||||
myComponent = component;
|
||||
myTextProperty = text;
|
||||
myCodeProperty = code;
|
||||
myIndexProperty = index;
|
||||
if (!updateText()) {
|
||||
// assume that it is already set
|
||||
myCode = getMnemonicCode();
|
||||
myIndex = getMnemonicIndex();
|
||||
}
|
||||
myFocusable = isFocusable();
|
||||
myComponent.addPropertyChangeListener(this);
|
||||
run(); // update mnemonics immediately
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void run() {
|
||||
boolean disabled = isDisabled();
|
||||
try {
|
||||
myEvent = true;
|
||||
setMnemonicCode(disabled ? KeyEvent.VK_UNDEFINED : myCode);
|
||||
setMnemonicIndex(disabled ? -1 : myIndex);
|
||||
Component component = getFocusableComponent();
|
||||
if (component != null) {
|
||||
component.setFocusable(disabled || myFocusable);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
myEvent = false;
|
||||
myRunnable = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void propertyChange(PropertyChangeEvent event) {
|
||||
if (!myEvent) {
|
||||
String property = event.getPropertyName();
|
||||
if (myTextProperty.equals(property)) {
|
||||
if (updateText()) {
|
||||
updateRequest();
|
||||
}
|
||||
}
|
||||
else if (myCodeProperty.equals(property)) {
|
||||
myCode = getMnemonicCode();
|
||||
updateRequest();
|
||||
}
|
||||
else if (myIndexProperty.equals(property)) {
|
||||
myIndex = getMnemonicIndex();
|
||||
updateRequest();
|
||||
}
|
||||
else if ("focusable".equals(property) || "labelFor".equals(property)) {
|
||||
myFocusable = isFocusable();
|
||||
updateRequest();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean updateText() {
|
||||
String text = getText();
|
||||
if (text != null) {
|
||||
int code = KeyEvent.VK_UNDEFINED;
|
||||
int index = -1;
|
||||
int length = text.length();
|
||||
StringBuilder sb = new StringBuilder(length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
char ch = text.charAt(i);
|
||||
if (ch != UIUtil.MNEMONIC) {
|
||||
sb.append(ch);
|
||||
}
|
||||
else if (i + 1 < length) {
|
||||
code = getExtendedKeyCodeForChar(text.charAt(i + 1));
|
||||
index = sb.length();
|
||||
}
|
||||
}
|
||||
if (code != KeyEvent.VK_UNDEFINED) {
|
||||
try {
|
||||
myEvent = true;
|
||||
setText(sb.toString());
|
||||
}
|
||||
finally {
|
||||
myEvent = false;
|
||||
}
|
||||
myCode = code;
|
||||
myIndex = index;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void updateRequest() {
|
||||
if (myRunnable == null) {
|
||||
myRunnable = this; // run once
|
||||
SwingUtilities.invokeLater(this);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isFocusable() {
|
||||
Component component = getFocusableComponent();
|
||||
return component == null || component.isFocusable();
|
||||
}
|
||||
|
||||
Component getFocusableComponent() {
|
||||
return myComponent;
|
||||
}
|
||||
|
||||
boolean isDisabled() {
|
||||
return UISettings.getShadowInstance().DISABLE_MNEMONICS_IN_CONTROLS;
|
||||
}
|
||||
|
||||
abstract String getText();
|
||||
|
||||
abstract void setText(String text);
|
||||
|
||||
abstract int getMnemonicCode();
|
||||
|
||||
abstract void setMnemonicCode(int code);
|
||||
|
||||
abstract int getMnemonicIndex();
|
||||
|
||||
abstract void setMnemonicIndex(int index);
|
||||
|
||||
static KeyStroke fixMacKeyStroke(KeyStroke stroke, InputMap map, int code, boolean onKeyRelease, String action) {
|
||||
if (stroke != null && code != stroke.getKeyCode()) {
|
||||
map.remove(stroke);
|
||||
stroke = null;
|
||||
}
|
||||
if (stroke == null && code != KeyEvent.VK_UNDEFINED) {
|
||||
stroke = KeyStroke.getKeyStroke(code, InputEvent.ALT_MASK | InputEvent.ALT_DOWN_MASK, onKeyRelease);
|
||||
map.put(stroke, action);
|
||||
}
|
||||
return stroke;
|
||||
}
|
||||
|
||||
// TODO: HACK because of Java7 required:
|
||||
// replace later with KeyEvent.getExtendedKeyCodeForChar(ch)
|
||||
private static int getExtendedKeyCodeForChar(int ch) {
|
||||
try {
|
||||
Method method = KeyEvent.class.getMethod("getExtendedKeyCodeForChar", int.class);
|
||||
if (!method.isAccessible()) {
|
||||
method.setAccessible(true);
|
||||
}
|
||||
return (Integer)method.invoke(KeyEvent.class, ch);
|
||||
}
|
||||
catch (Exception exception) {
|
||||
if (ch >= 'a' && ch <= 'z') {
|
||||
ch -= ('a' - 'A');
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
}
|
||||
|
||||
private static class MenuWrapper extends ButtonWrapper {
|
||||
private MenuWrapper(AbstractButton component) {
|
||||
super(component);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isDisabled() {
|
||||
return UISettings.getShadowInstance().DISABLE_MNEMONICS;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ButtonWrapper extends MnemonicWrapper<AbstractButton> {
|
||||
private KeyStroke myStrokePressed;
|
||||
private KeyStroke myStrokeReleased;
|
||||
|
||||
private ButtonWrapper(AbstractButton component) {
|
||||
super(component, "text", "mnemonic", "displayedMnemonicIndex");
|
||||
}
|
||||
|
||||
@Override
|
||||
String getText() {
|
||||
return myComponent.getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
void setText(String text) {
|
||||
myComponent.setText(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
int getMnemonicCode() {
|
||||
return myComponent.getMnemonic();
|
||||
}
|
||||
|
||||
@Override
|
||||
void setMnemonicCode(int code) {
|
||||
myComponent.setMnemonic(code);
|
||||
if (SystemInfo.isMac && Registry.is("ide.mac.alt.mnemonic.without.ctrl")) {
|
||||
InputMap map = myComponent.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||
if (map != null) {
|
||||
myStrokePressed = fixMacKeyStroke(myStrokePressed, map, code, false, "pressed");
|
||||
myStrokeReleased = fixMacKeyStroke(myStrokeReleased, map, code, true, "released");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
int getMnemonicIndex() {
|
||||
return myComponent.getDisplayedMnemonicIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
void setMnemonicIndex(int index) {
|
||||
myComponent.setDisplayedMnemonicIndex(index);
|
||||
}
|
||||
}
|
||||
|
||||
private static class LabelWrapper extends MnemonicWrapper<JLabel> {
|
||||
private KeyStroke myStrokeRelease;
|
||||
|
||||
private LabelWrapper(JLabel component) {
|
||||
super(component, "text", "displayedMnemonic", "displayedMnemonicIndex");
|
||||
}
|
||||
|
||||
@Override
|
||||
String getText() {
|
||||
return myComponent.getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
void setText(String text) {
|
||||
myComponent.setText(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
int getMnemonicCode() {
|
||||
return myComponent.getDisplayedMnemonic();
|
||||
}
|
||||
|
||||
@Override
|
||||
void setMnemonicCode(int code) {
|
||||
myComponent.setDisplayedMnemonic(code);
|
||||
if (SystemInfo.isMac && Registry.is("ide.mac.alt.mnemonic.without.ctrl")) {
|
||||
InputMap map = myComponent.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||
if (map != null) {
|
||||
myStrokeRelease = fixMacKeyStroke(myStrokeRelease, map, code, true, "release");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
int getMnemonicIndex() {
|
||||
return myComponent.getDisplayedMnemonicIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
void setMnemonicIndex(int index) {
|
||||
myComponent.setDisplayedMnemonicIndex(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
Component getFocusableComponent() {
|
||||
return myComponent.getLabelFor();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,6 +40,8 @@ public interface IdeActions {
|
||||
@NonNls String ACTION_EDITOR_BACKSPACE = "EditorBackSpace";
|
||||
@NonNls String ACTION_EDITOR_MOVE_CARET_LEFT_WITH_SELECTION = "EditorLeftWithSelection";
|
||||
@NonNls String ACTION_EDITOR_MOVE_CARET_RIGHT_WITH_SELECTION = "EditorRightWithSelection";
|
||||
@NonNls String ACTION_EDITOR_MOVE_CARET_UP_WITH_SELECTION = "EditorUpWithSelection";
|
||||
@NonNls String ACTION_EDITOR_MOVE_CARET_DOWN_WITH_SELECTION = "EditorDownWithSelection";
|
||||
@NonNls String ACTION_EDITOR_MOVE_CARET_UP = "EditorUp";
|
||||
@NonNls String ACTION_EDITOR_MOVE_CARET_LEFT = "EditorLeft";
|
||||
@NonNls String ACTION_EDITOR_MOVE_CARET_DOWN = "EditorDown";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -406,7 +406,6 @@ public class VfsUtil extends VfsUtilCore {
|
||||
* @return the relative path, or null if the files have no common ancestor.
|
||||
* @since 5.0.2
|
||||
*/
|
||||
|
||||
@Nullable
|
||||
public static String getPath(@NotNull VirtualFile src, @NotNull VirtualFile dst, char separatorChar) {
|
||||
final VirtualFile commonAncestor = getCommonAncestor(src, dst);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -41,7 +41,9 @@ public abstract class ArchiveFileSystem extends NewVirtualFileSystem {
|
||||
* or null if the file does not host this file system.
|
||||
*/
|
||||
@Nullable
|
||||
public abstract VirtualFile getRootByLocal(@NotNull VirtualFile file);
|
||||
public VirtualFile getRootByLocal(@NotNull VirtualFile file) {
|
||||
return findFileByPath(composeRootPath(file.getPath()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a root entry of an archive which hosts a given entry file
|
||||
@@ -73,8 +75,11 @@ public abstract class ArchiveFileSystem extends NewVirtualFileSystem {
|
||||
@NotNull
|
||||
protected abstract String extractLocalPath(@NotNull String rootPath);
|
||||
|
||||
/**
|
||||
* A reverse to {@link #extractLocalPath(String)} - i.e. dresses a local file path to make it a suitable root path for this filesystem.
|
||||
*/
|
||||
@NotNull
|
||||
protected abstract String convertLocalToRootPath(@NotNull String localPath);
|
||||
protected abstract String composeRootPath(@NotNull String localPath);
|
||||
|
||||
@NotNull
|
||||
protected abstract ArchiveHandler getHandler(@NotNull VirtualFile entryFile);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -50,8 +50,7 @@ import java.util.zip.GZIPInputStream;
|
||||
* }</pre>
|
||||
*/
|
||||
public final class HttpRequests {
|
||||
private HttpRequests() {
|
||||
}
|
||||
private HttpRequests() { }
|
||||
|
||||
public interface Request {
|
||||
@NotNull
|
||||
|
||||
+1
-1
@@ -117,7 +117,7 @@ public class DarculaRadioButtonUI extends MetalRadioButtonUI {
|
||||
if (b.isSelected()) {
|
||||
final boolean enabled = b.isEnabled();
|
||||
g.setColor(UIManager.getColor(enabled ? "RadioButton.darcula.selectionEnabledShadowColor" : "RadioButton.darcula.selectionDisabledShadowColor"));// ? Gray._30 : Gray._60);
|
||||
final int yOff = UIUtil.isUnderDarcula() ? 2 : JBUI.scale(1);
|
||||
final int yOff = 2;
|
||||
g.fillOval(w/2 - rad/2, h/2 - rad/2 + yOff , rad, rad);
|
||||
g.setColor(UIManager.getColor(enabled ? "RadioButton.darcula.selectionEnabledColor" : "RadioButton.darcula.selectionDisabledColor")); //Gray._170 : Gray._120);
|
||||
g.fillOval(w/2 - rad/2, h/2 - rad/2 -1 + yOff, rad, rad);
|
||||
|
||||
@@ -106,8 +106,9 @@ public class EventLog {
|
||||
Map<RangeMarker, HyperlinkInfo> links = new LinkedHashMap<RangeMarker, HyperlinkInfo>();
|
||||
List<RangeMarker> lineSeparators = new ArrayList<RangeMarker>();
|
||||
|
||||
String title = notification.getTitle();
|
||||
String content = notification.getContent();
|
||||
String title = truncateLongString(showMore, notification.getTitle());
|
||||
String content = truncateLongString(showMore, notification.getContent());
|
||||
|
||||
RangeMarker afterTitle = null;
|
||||
boolean hasHtml = parseHtmlContent(title, notification, logDoc, showMore, links, lineSeparators);
|
||||
if (StringUtil.isNotEmpty(title)) {
|
||||
@@ -144,6 +145,15 @@ public class EventLog {
|
||||
return new LogEntry(logDoc.getText(), status, list);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String truncateLongString(AtomicBoolean showMore, String title) {
|
||||
if (title.length() > 1000) {
|
||||
showMore.set(true);
|
||||
return title.substring(0, 1000) + "...";
|
||||
}
|
||||
return title;
|
||||
}
|
||||
|
||||
private static void indentNewLines(DocumentImpl logDoc, List<RangeMarker> lineSeparators, RangeMarker afterTitle, boolean hasHtml, String indent) {
|
||||
if (!hasHtml) {
|
||||
int i = -1;
|
||||
|
||||
@@ -248,6 +248,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
|
||||
myEditor.getCaretModel().doWithCaretMerging(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int oldOffset = myOffset;
|
||||
final int leadSelectionOffset = getLeadSelectionOffset();
|
||||
final VisualPosition leadSelectionPosition = getLeadSelectionPosition();
|
||||
EditorSettings editorSettings = myEditor.getSettings();
|
||||
@@ -370,7 +371,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
|
||||
else {
|
||||
int selectionStartToUse = leadSelectionOffset;
|
||||
VisualPosition selectionStartPositionToUse = leadSelectionPosition;
|
||||
if (isUnknownDirection()) {
|
||||
if (isUnknownDirection() || oldOffset > getSelectionStart() && oldOffset < getSelectionEnd()) {
|
||||
if (getOffset() > leadSelectionOffset ^ getSelectionStart() < getSelectionEnd()) {
|
||||
selectionStartToUse = getSelectionEnd();
|
||||
selectionStartPositionToUse = getSelectionEndPosition();
|
||||
|
||||
+2
-2
@@ -22,7 +22,7 @@
|
||||
</constraints>
|
||||
<properties>
|
||||
<selected value="true"/>
|
||||
<text value="Unlock files"/>
|
||||
<text value="I want to edit these files anyway"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="592c9" class="javax.swing.JRadioButton" binding="myUnlockAllButton" default-binding="true">
|
||||
@@ -30,7 +30,7 @@
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Unlock all non-project files in current session"/>
|
||||
<text value="I want to edit any non-project file in the current session"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
|
||||
+5
-1
@@ -38,9 +38,13 @@ public class NonProjectFileWritingAccessDialog extends DialogWrapper {
|
||||
myFileList.setCellRenderer(new FileListRenderer());
|
||||
myFileList.setModel(new CollectionListModel<VirtualFile>(nonProjectFiles));
|
||||
|
||||
getOKAction().putValue(DEFAULT_ACTION, null);
|
||||
getCancelAction().putValue(DEFAULT_ACTION, true);
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected JComponent createCenterPanel() {
|
||||
@@ -54,6 +58,6 @@ public class NonProjectFileWritingAccessDialog extends DialogWrapper {
|
||||
}
|
||||
|
||||
protected String getHelpId() {
|
||||
return "readOnlyHandler.nonProjectFilesDialog";
|
||||
return "Non-Project_Files_Access_Dialog";
|
||||
}
|
||||
}
|
||||
|
||||
+5
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -105,27 +105,21 @@ public class JarFileSystemImpl extends JarFileSystem {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected String convertLocalToRootPath(@NotNull String localPath) {
|
||||
protected String composeRootPath(@NotNull String localPath) {
|
||||
return localPath + JAR_SEPARATOR;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected JarHandler getHandler(@NotNull VirtualFile entryFile) {
|
||||
return VfsImplUtil.getHandler(entryFile, this, new Function<String, JarHandler>() {
|
||||
return VfsImplUtil.getHandler(this, entryFile, new Function<String, JarHandler>() {
|
||||
@Override
|
||||
public JarHandler fun(String rootPath) {
|
||||
return new JarHandler(extractLocalPath(rootPath));
|
||||
public JarHandler fun(String localPath) {
|
||||
return new JarHandler(localPath);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public VirtualFile getRootByLocal(@NotNull VirtualFile file) {
|
||||
return findFileByPath(convertLocalToRootPath(file.getPath()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public VirtualFile findFileByPath(@NotNull String path) {
|
||||
return VfsImplUtil.findFileByPath(this, path);
|
||||
|
||||
+7
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -53,11 +53,11 @@ public final class LocalFileSystemImpl extends LocalFileSystemBase implements Ap
|
||||
private final FileWatcher myWatcher;
|
||||
|
||||
private static class WatchRequestImpl implements WatchRequest {
|
||||
private final boolean myToWatchRecursively;
|
||||
private String myFSRootPath;
|
||||
private final String myFSRootPath;
|
||||
private final boolean myWatchRecursively;
|
||||
private boolean myDominated;
|
||||
|
||||
public WatchRequestImpl(String rootPath, boolean toWatchRecursively) throws FileNotFoundException {
|
||||
public WatchRequestImpl(String rootPath, boolean watchRecursively) throws FileNotFoundException {
|
||||
int index = rootPath.indexOf(JarFileSystem.JAR_SEPARATOR);
|
||||
if (index >= 0) rootPath = rootPath.substring(0, index);
|
||||
|
||||
@@ -73,7 +73,7 @@ public final class LocalFileSystemImpl extends LocalFileSystemBase implements Ap
|
||||
}
|
||||
|
||||
myFSRootPath = rootFile.getAbsolutePath();
|
||||
myToWatchRecursively = toWatchRecursively;
|
||||
myWatchRecursively = watchRecursively;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -84,7 +84,7 @@ public final class LocalFileSystemImpl extends LocalFileSystemBase implements Ap
|
||||
|
||||
@Override
|
||||
public boolean isToWatchRecursively() {
|
||||
return myToWatchRecursively;
|
||||
return myWatchRecursively;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -112,8 +112,7 @@ public final class LocalFileSystemImpl extends LocalFileSystemBase implements Ap
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initComponent() {
|
||||
}
|
||||
public void initComponent() { }
|
||||
|
||||
@Override
|
||||
public void disposeComponent() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.openapi.vfs.newvfs;
|
||||
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
@@ -22,10 +23,7 @@ import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.io.ZipFileCache;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VFileProperty;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.openapi.vfs.*;
|
||||
import com.intellij.openapi.vfs.impl.ArchiveHandler;
|
||||
import com.intellij.openapi.vfs.newvfs.events.VFileCreateEvent;
|
||||
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
|
||||
@@ -34,22 +32,26 @@ import com.intellij.openapi.vfs.newvfs.events.VFilePropertyChangeEvent;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.messages.MessageBus;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import static com.intellij.util.containers.ContainerUtil.newTroveMap;
|
||||
|
||||
public class VfsImplUtil {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.newvfs.VfsImplUtil");
|
||||
|
||||
private static final String FILE_SEPARATORS = "/" + File.separator;
|
||||
|
||||
private VfsImplUtil() { }
|
||||
private VfsImplUtil() {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static NewVirtualFile findFileByPath(@NotNull NewVirtualFileSystem vfs, @NotNull @NonNls String path) {
|
||||
@@ -176,34 +178,40 @@ public class VfsImplUtil {
|
||||
|
||||
private static final AtomicBoolean ourSubscribed = new AtomicBoolean(false);
|
||||
private static final Object ourLock = new Object();
|
||||
private static final Map<String, Pair<ArchiveFileSystem, ArchiveHandler>> ourHandlers = ContainerUtil.newTroveMap(FileUtil.PATH_HASHING_STRATEGY);
|
||||
private static final Map<String, Set<String>> ourDominatorsMap = ContainerUtil.newTroveMap(FileUtil.PATH_HASHING_STRATEGY);
|
||||
private static final Map<String, Pair<ArchiveFileSystem, ArchiveHandler>> ourHandlers = newTroveMap(FileUtil.PATH_HASHING_STRATEGY);
|
||||
private static final Map<String, Set<String>> ourDominatorsMap = newTroveMap(FileUtil.PATH_HASHING_STRATEGY);
|
||||
|
||||
@NotNull
|
||||
public static <T extends ArchiveHandler> T getHandler(@NotNull VirtualFile entryFile,
|
||||
@NotNull ArchiveFileSystem vfs,
|
||||
public static <T extends ArchiveHandler> T getHandler(@NotNull ArchiveFileSystem vfs,
|
||||
@NotNull VirtualFile entryFile,
|
||||
@NotNull Function<String, T> producer) {
|
||||
String localPath = vfs.extractLocalPath(vfs.extractRootPath(entryFile.getPath()));
|
||||
return getHandler(vfs, localPath, producer);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <T extends ArchiveHandler> T getHandler(@NotNull ArchiveFileSystem vfs,
|
||||
@NotNull String localPath,
|
||||
@NotNull Function<String, T> producer) {
|
||||
checkSubscription();
|
||||
|
||||
String rootPath = vfs.extractRootPath(entryFile.getPath());
|
||||
rootPath = vfs.extractLocalPath(rootPath);
|
||||
ArchiveHandler handler;
|
||||
boolean refresh = false;
|
||||
|
||||
synchronized (ourLock) {
|
||||
Pair<ArchiveFileSystem, ArchiveHandler> record = ourHandlers.get(rootPath);
|
||||
Pair<ArchiveFileSystem, ArchiveHandler> record = ourHandlers.get(localPath);
|
||||
if (record == null) {
|
||||
handler = producer.fun(rootPath);
|
||||
handler = producer.fun(localPath);
|
||||
record = Pair.create(vfs, handler);
|
||||
ourHandlers.put(rootPath, record);
|
||||
ourHandlers.put(localPath, record);
|
||||
|
||||
final String finalRootPath = rootPath;
|
||||
forEachDirectoryComponent(rootPath, new Processor<String>() {
|
||||
final String finalRootPath = localPath;
|
||||
forEachDirectoryComponent(localPath, new Processor<String>() {
|
||||
@Override
|
||||
public boolean process(String containingDirectoryPath) {
|
||||
Set<String> handlers = ourDominatorsMap.get(containingDirectoryPath);
|
||||
if (handlers == null) {
|
||||
ourDominatorsMap.put(containingDirectoryPath, handlers = new THashSet<String>());
|
||||
ourDominatorsMap.put(containingDirectoryPath, handlers = ContainerUtil.newTroveSet());
|
||||
}
|
||||
handlers.add(finalRootPath);
|
||||
return true;
|
||||
@@ -230,7 +238,7 @@ public class VfsImplUtil {
|
||||
|
||||
private static void forEachDirectoryComponent(String rootPath, Processor<String> processor) {
|
||||
int index = rootPath.lastIndexOf('/');
|
||||
while(index > 0) {
|
||||
while (index > 0) {
|
||||
String containingDirectoryPath = rootPath.substring(0, index);
|
||||
if (!processor.process(containingDirectoryPath)) return;
|
||||
index = rootPath.lastIndexOf('/', index - 1);
|
||||
@@ -240,8 +248,8 @@ public class VfsImplUtil {
|
||||
private static void checkSubscription() {
|
||||
if (ourSubscribed.getAndSet(true)) return;
|
||||
|
||||
MessageBus bus = ApplicationManager.getApplication().getMessageBus();
|
||||
bus.connect().subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener.Adapter() {
|
||||
Application app = ApplicationManager.getApplication();
|
||||
app.getMessageBus().connect(app).subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener.Adapter() {
|
||||
@Override
|
||||
public void after(@NotNull List<? extends VFileEvent> events) {
|
||||
InvalidationState state = null;
|
||||
@@ -257,22 +265,25 @@ public class VfsImplUtil {
|
||||
continue;
|
||||
}
|
||||
|
||||
VirtualFile file = event.getFile();
|
||||
String path = event.getPath();
|
||||
if (event instanceof VFilePropertyChangeEvent) {
|
||||
path = ((VFilePropertyChangeEvent)event).getOldPath();
|
||||
} else if (event instanceof VFileMoveEvent) {
|
||||
}
|
||||
else if (event instanceof VFileMoveEvent) {
|
||||
path = ((VFileMoveEvent)event).getOldPath();
|
||||
}
|
||||
|
||||
VirtualFile file = event.getFile();
|
||||
if (file == null || !file.isDirectory()) {
|
||||
if (state == null) state = new InvalidationState();
|
||||
state.invalidateHandlerForPath(path);
|
||||
} else {
|
||||
state = InvalidationState.invalidate(state, path);
|
||||
}
|
||||
else {
|
||||
Collection<String> affectedPaths = ourDominatorsMap.get(path);
|
||||
if (affectedPaths != null) {
|
||||
affectedPaths = new ArrayList<String>(affectedPaths); // defensive copying, we will modify original during invalidate
|
||||
if (state == null) state = new InvalidationState();
|
||||
for (String affectedPath : affectedPaths) state.invalidateHandlerForPath(affectedPath);
|
||||
affectedPaths = ContainerUtil.newArrayList(affectedPaths); // defensive copying; original may be updated on invalidation
|
||||
for (String affectedPath : affectedPaths) {
|
||||
state = InvalidationState.invalidate(state, affectedPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -286,38 +297,39 @@ public class VfsImplUtil {
|
||||
private static class InvalidationState {
|
||||
private Map<String, VirtualFile> rootsToRefresh;
|
||||
|
||||
boolean invalidateHandlerForPath(final String path) {
|
||||
@Nullable
|
||||
public static InvalidationState invalidate(@Nullable InvalidationState state, final String path) {
|
||||
Pair<ArchiveFileSystem, ArchiveHandler> handlerPair = ourHandlers.remove(path);
|
||||
if (handlerPair != null) {
|
||||
forEachDirectoryComponent(path, new Processor<String>() {
|
||||
@Override
|
||||
public boolean process(String containingDirectoryPath) {
|
||||
Set<String> handlers = ourDominatorsMap.get(containingDirectoryPath);
|
||||
if (handlers != null) {
|
||||
if(handlers.remove(path) && handlers.size() == 0) {
|
||||
ourDominatorsMap.remove(containingDirectoryPath);
|
||||
}
|
||||
if (handlers != null && handlers.remove(path) && handlers.size() == 0) {
|
||||
ourDominatorsMap.remove(containingDirectoryPath);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
registerPathToRefresh(handlerPair, path);
|
||||
|
||||
if (state == null) state = new InvalidationState();
|
||||
state.registerPathToRefresh(path, handlerPair.first);
|
||||
}
|
||||
return handlerPair != null;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
private void registerPathToRefresh(Pair<ArchiveFileSystem, ArchiveHandler> handlerPair, String path) {
|
||||
String rootPath = handlerPair.first.convertLocalToRootPath(path);
|
||||
NewVirtualFile root = ManagingFS.getInstance().findRoot(rootPath, handlerPair.first);
|
||||
private void registerPathToRefresh(String path, ArchiveFileSystem vfs) {
|
||||
NewVirtualFile root = ManagingFS.getInstance().findRoot(vfs.composeRootPath(path), vfs);
|
||||
if (root != null) {
|
||||
if (rootsToRefresh == null) rootsToRefresh = ContainerUtil.newHashMap();
|
||||
rootsToRefresh.put(path, root);
|
||||
}
|
||||
}
|
||||
|
||||
void scheduleRefresh() {
|
||||
public void scheduleRefresh() {
|
||||
if (rootsToRefresh != null) {
|
||||
for(VirtualFile root:rootsToRefresh.values()) {
|
||||
for (VirtualFile root : rootsToRefresh.values()) {
|
||||
((NewVirtualFile)root).markDirtyRecursively();
|
||||
}
|
||||
ZipFileCache.reset(rootsToRefresh.keySet());
|
||||
|
||||
@@ -31,7 +31,7 @@ completion.no.suggestions=No suggestions
|
||||
completion.quick.javadoc.ad=Did you know that Quick Documentation View ({0}) works in completion lookups as well?
|
||||
completion.quick.implementations.ad=Did you know that Quick Definition View ({0}) works in completion lookups as well?
|
||||
completion.dot.etc.ad=Dot, space and some other keys will also close this lookup and be inserted into editor
|
||||
completion.smart.enter.ad=Use {0} to syntactically correct your code after completing (balance parentheses etc.)
|
||||
completion.smart.enter.ad=Use {0} to syntactically correct your code after completing (balance parentheses etc.)
|
||||
|
||||
xml.terms.tag=tag
|
||||
xml.terms.entity=entity
|
||||
@@ -52,3 +52,8 @@ template.data.language.override.warning.text=There are template data languages s
|
||||
template.data.language.override.warning.title=Override Subdirectory Template Data Languages
|
||||
quickfix.change.template.data.language.text=Change {0} template data language to...
|
||||
incorrect.name=Incorrect name
|
||||
|
||||
jrt.node.short=[JRT]
|
||||
jrt.node.long=[Java Run-time Modules]
|
||||
jrt.not.available.message=You need to run IDEA on Java 8 to be able to use modular JDK. Sorry.
|
||||
jrt.not.available.title=Unsupported JDK ''{0}'' detected
|
||||
|
||||
+20
@@ -167,4 +167,24 @@ public class EditorActionTest extends AbstractEditorTest {
|
||||
executeAction(IdeActions.ACTION_EDITOR_DELETE_TO_WORD_END);
|
||||
checkResultByText("class Foo { String s = \"a\\<caret>b\"; }");
|
||||
}
|
||||
|
||||
public void testUpWithSelectionOnCaretInsideSelection() throws Exception {
|
||||
initText("blah blah\n" +
|
||||
"blah <selection>bl<caret>ah</selection>\n" +
|
||||
"blah blah");
|
||||
executeAction(IdeActions.ACTION_EDITOR_MOVE_CARET_UP_WITH_SELECTION);
|
||||
checkResultByText("blah bl<selection><caret>ah\n" +
|
||||
"blah blah</selection>\n" +
|
||||
"blah blah");
|
||||
}
|
||||
|
||||
public void testDownWithSelectionOnCaretInsideSelection() throws Exception {
|
||||
initText("blah blah\n" +
|
||||
"blah <selection>bl<caret>ah</selection>\n" +
|
||||
"blah blah");
|
||||
executeAction(IdeActions.ACTION_EDITOR_MOVE_CARET_DOWN_WITH_SELECTION);
|
||||
checkResultByText("blah blah\n" +
|
||||
"blah <selection>blah\n" +
|
||||
"blah bl<caret></selection>ah");
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -305,7 +305,7 @@ public class SyntaxInfoConstructionTest extends LightPlatformCodeInsightFixtureT
|
||||
final ColorRegistry colorRegistry = syntaxInfo.getColorRegistry();
|
||||
assertEquals(JBColor.BLACK, colorRegistry.dataById(syntaxInfo.getDefaultForeground()));
|
||||
assertEquals(JBColor.WHITE, colorRegistry.dataById(syntaxInfo.getDefaultBackground()));
|
||||
assertEquals(getFontSize(), syntaxInfo.getFontSize());
|
||||
assertEquals((float)getFontSize(), syntaxInfo.getFontSize(), 0.01f);
|
||||
syntaxInfo.processOutputInfo(new MarkupHandler() {
|
||||
@Override
|
||||
public void handleText(int startOffset, int endOffset) throws Exception {
|
||||
|
||||
@@ -154,6 +154,7 @@ skip.untitled.windows.for.mac.messages=false
|
||||
skip.untitled.windows.for.mac.messages.description=Temporary key to test a fix for MacMessages
|
||||
ide.mac.mountain.lion.notifications.enabled=true
|
||||
ide.mac.inplaceDialogMnemonicsFix=false
|
||||
ide.mac.alt.mnemonic.without.ctrl=true
|
||||
ide.mac.fix.dialog.showing=false
|
||||
ide.mac.hide.cursor.when.typing=true
|
||||
ide.mac.show.native.help=true
|
||||
|
||||
@@ -38,11 +38,20 @@ public class PersistentHashMapValueStorage {
|
||||
private volatile long mySize;
|
||||
private final File myFile;
|
||||
private final String myPath;
|
||||
private final ExceptionalIOCancellationCallback myExceptionalIOCancellationCallback;
|
||||
private boolean myCompactionMode = false;
|
||||
|
||||
private static final int CACHE_PROTECTED_QUEUE_SIZE = 10;
|
||||
private static final int CACHE_PROBATIONAL_QUEUE_SIZE = 20;
|
||||
|
||||
public static class CreationTimeOptions {
|
||||
public static final ThreadLocal<ExceptionalIOCancellationCallback> EXCEPTIONAL_IO_CANCELLATION = new ThreadLocal<ExceptionalIOCancellationCallback>();
|
||||
}
|
||||
|
||||
public interface ExceptionalIOCancellationCallback {
|
||||
void checkCancellation();
|
||||
}
|
||||
|
||||
// cache size is twice larger than constants because (when used) it replaces two caches
|
||||
private static final FileAccessorCache<RandomAccessFileWithLengthAndSizeTracking> ourRandomAccessFileCache = new FileAccessorCache<RandomAccessFileWithLengthAndSizeTracking>(
|
||||
2*CACHE_PROTECTED_QUEUE_SIZE, 2*CACHE_PROBATIONAL_QUEUE_SIZE) {
|
||||
@@ -93,6 +102,7 @@ public class PersistentHashMapValueStorage {
|
||||
};
|
||||
|
||||
public PersistentHashMapValueStorage(String path) throws IOException {
|
||||
myExceptionalIOCancellationCallback = CreationTimeOptions.EXCEPTIONAL_IO_CANCELLATION.get();
|
||||
myPath = path;
|
||||
myFile = new File(path);
|
||||
mySize = myFile.length(); // volatile write
|
||||
@@ -322,6 +332,7 @@ public class PersistentHashMapValueStorage {
|
||||
public ReadResult readBytes(long tailChunkAddress) throws IOException {
|
||||
force();
|
||||
|
||||
checkCancellation();
|
||||
long chunk = tailChunkAddress;
|
||||
int chunkCount = 0;
|
||||
|
||||
@@ -362,6 +373,8 @@ public class PersistentHashMapValueStorage {
|
||||
|
||||
chunk = prevChunkAddress;
|
||||
chunkCount++;
|
||||
|
||||
if (prevChunkAddress != 0) checkCancellation();
|
||||
if (result.length > mySize) {
|
||||
throw new PersistentEnumeratorBase.CorruptedException(myFile);
|
||||
}
|
||||
@@ -377,6 +390,7 @@ public class PersistentHashMapValueStorage {
|
||||
}
|
||||
|
||||
if (chunkCount > 1 && !myCompactionMode) {
|
||||
checkCancellation();
|
||||
long l = appendBytes(new ByteSequence(result), 0);
|
||||
return new ReadResult(l, result);
|
||||
}
|
||||
@@ -384,6 +398,11 @@ public class PersistentHashMapValueStorage {
|
||||
return new ReadResult(tailChunkAddress, result);
|
||||
}
|
||||
|
||||
// hook for exceptional termination of long io operation
|
||||
protected void checkCancellation() {
|
||||
if (myExceptionalIOCancellationCallback != null) myExceptionalIOCancellationCallback.checkCancellation();
|
||||
}
|
||||
|
||||
private long readPrevChunkAddress(long chunk) throws IOException {
|
||||
final long prevOffsetDiff = DataInputOutputUtil.readLONG(myBufferDataStreamWrapper);
|
||||
assert prevOffsetDiff < chunk:chunk + "," + prevOffsetDiff + "," + mySize;
|
||||
|
||||
@@ -116,6 +116,7 @@ public class ListTableModel<Item> extends TableViewModel<Item> implements Editab
|
||||
if (rowIndex < myItems.size()) {
|
||||
myColumnInfos[columnIndex].setValue(getItem(rowIndex), aValue);
|
||||
}
|
||||
fireTableCellUpdated(rowIndex, columnIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3215,6 +3215,10 @@ public class UIUtil {
|
||||
textComponent.getActionMap().put("redoKeystroke", REDO_ACTION);
|
||||
}
|
||||
|
||||
public static void adjustRows(JTextArea area, int minRows, int maxRows) {
|
||||
area.setRows(Math.max(minRows, Math.min(maxRows, area.getText().split("\n").length)));
|
||||
}
|
||||
|
||||
public static void playSoundFromResource(final String resourceName) {
|
||||
final Class callerClass = ReflectionUtil.getGrandCallerClass();
|
||||
if (callerClass == null) return;
|
||||
|
||||
@@ -98,7 +98,8 @@ public abstract class FileAnnotation {
|
||||
public abstract VcsRevisionNumber getCurrentRevision();
|
||||
|
||||
/**
|
||||
* Get all revisions that are mentioned in the annotations
|
||||
* Get all revisions that are mentioned in the annotations.
|
||||
* order: from newest to oldest
|
||||
*
|
||||
* @return the list of revisions that are mentioned in annotations. Or null
|
||||
* if before/after popups cannot be suported by the VCS system.
|
||||
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package com.intellij.openapi.vcs.actions;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.vcs.AbstractVcs;
|
||||
import com.intellij.openapi.vcs.annotate.FileAnnotation;
|
||||
import com.intellij.openapi.vcs.history.VcsFileRevision;
|
||||
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
class AnnotateCurrentRevisionAction extends AnnotateRevisionAction {
|
||||
@NotNull private final List<VcsFileRevision> myRevisions;
|
||||
|
||||
public AnnotateCurrentRevisionAction(@NotNull FileAnnotation annotation, @NotNull AbstractVcs vcs) {
|
||||
super("Annotate Revision", "Annotate selected revision in new tab", AllIcons.Actions.Annotate,
|
||||
annotation, vcs);
|
||||
Map<VcsRevisionNumber, VcsFileRevision> map = new HashMap<VcsRevisionNumber, VcsFileRevision>();
|
||||
List<VcsFileRevision> revisions = annotation.getRevisions();
|
||||
if (revisions != null) {
|
||||
for (VcsFileRevision revision : revisions) {
|
||||
map.put(revision.getRevisionNumber(), revision);
|
||||
}
|
||||
}
|
||||
|
||||
myRevisions = new ArrayList<VcsFileRevision>(annotation.getLineCount());
|
||||
for (int i = 0; i < annotation.getLineCount(); i++) {
|
||||
myRevisions.add(map.get(annotation.getLineRevisionNumber(i)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<VcsFileRevision> getRevisions() {
|
||||
return myRevisions;
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
package com.intellij.openapi.vcs.actions;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.vcs.AbstractVcs;
|
||||
import com.intellij.openapi.vcs.annotate.FileAnnotation;
|
||||
import com.intellij.openapi.vcs.history.VcsFileRevision;
|
||||
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
class AnnotatePreviousRevisionAction extends AnnotateRevisionAction {
|
||||
@NotNull private final List<VcsFileRevision> myRevisions;
|
||||
|
||||
public AnnotatePreviousRevisionAction(@NotNull FileAnnotation annotation, @NotNull AbstractVcs vcs) {
|
||||
super("Annotate Previous Revision", "Annotate successor of selected revision in new tab", AllIcons.Actions.Annotate,
|
||||
annotation, vcs);
|
||||
Map<VcsRevisionNumber, VcsFileRevision> map = new HashMap<VcsRevisionNumber, VcsFileRevision>();
|
||||
List<VcsFileRevision> revisions = annotation.getRevisions();
|
||||
if (revisions != null) {
|
||||
for (int i = 0; i < revisions.size(); i++) {
|
||||
VcsFileRevision revision = revisions.get(i);
|
||||
VcsFileRevision previousRevision = i + 1 < revisions.size() ? revisions.get(i + 1) : null;
|
||||
map.put(revision.getRevisionNumber(), previousRevision);
|
||||
}
|
||||
}
|
||||
|
||||
myRevisions = new ArrayList<VcsFileRevision>(annotation.getLineCount());
|
||||
for (int i = 0; i < annotation.getLineCount(); i++) {
|
||||
myRevisions.add(map.get(annotation.getLineRevisionNumber(i)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<VcsFileRevision> getRevisions() {
|
||||
return myRevisions;
|
||||
}
|
||||
}
|
||||
+12
-25
@@ -1,6 +1,5 @@
|
||||
package com.intellij.openapi.vcs.actions;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.vcs.AbstractVcs;
|
||||
@@ -10,45 +9,31 @@ import com.intellij.openapi.vcs.annotate.FileAnnotation;
|
||||
import com.intellij.openapi.vcs.annotate.LineNumberListener;
|
||||
import com.intellij.openapi.vcs.history.VcsFileRevision;
|
||||
import com.intellij.openapi.vcs.history.VcsFileRevisionEx;
|
||||
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
|
||||
import com.intellij.openapi.vcs.vfs.VcsFileSystem;
|
||||
import com.intellij.openapi.vcs.vfs.VcsVirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import javax.swing.*;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
class AnnotateRevisionAction extends AnnotateRevisionActionBase implements DumbAware, LineNumberListener {
|
||||
abstract class AnnotateRevisionAction extends AnnotateRevisionActionBase implements DumbAware, LineNumberListener {
|
||||
@NotNull private final FileAnnotation myAnnotation;
|
||||
@NotNull private final AbstractVcs myVcs;
|
||||
|
||||
@NotNull private final List<VcsFileRevision> myRevisions;
|
||||
|
||||
private int currentLine;
|
||||
|
||||
public AnnotateRevisionAction(@NotNull FileAnnotation annotation, @NotNull AbstractVcs vcs) {
|
||||
super("Annotate revision", "Annotate selected revision in new tab", AllIcons.Actions.Annotate);
|
||||
public AnnotateRevisionAction(@Nullable String text, @Nullable String description, @Nullable Icon icon,
|
||||
@NotNull FileAnnotation annotation, @NotNull AbstractVcs vcs) {
|
||||
super(text, description, icon);
|
||||
myAnnotation = annotation;
|
||||
myVcs = vcs;
|
||||
|
||||
Map<VcsRevisionNumber, VcsFileRevision> map = new HashMap<VcsRevisionNumber, VcsFileRevision>();
|
||||
List<VcsFileRevision> revisions = myAnnotation.getRevisions();
|
||||
if (revisions != null) {
|
||||
for (VcsFileRevision revision : revisions) {
|
||||
map.put(revision.getRevisionNumber(), revision);
|
||||
}
|
||||
}
|
||||
|
||||
myRevisions = new ArrayList<VcsFileRevision>(myAnnotation.getLineCount());
|
||||
for (int i = 0; i < myAnnotation.getLineCount(); i++) {
|
||||
myRevisions.add(map.get(myAnnotation.getLineRevisionNumber(i)));
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected abstract List<VcsFileRevision> getRevisions();
|
||||
|
||||
@Nullable
|
||||
protected AbstractVcs getVcs(@NotNull AnActionEvent e) {
|
||||
return myVcs;
|
||||
@@ -68,8 +53,10 @@ class AnnotateRevisionAction extends AnnotateRevisionActionBase implements DumbA
|
||||
@Nullable
|
||||
@Override
|
||||
protected VcsFileRevision getFileRevision(@NotNull AnActionEvent e) {
|
||||
if (currentLine < 0 || currentLine >= myRevisions.size()) return null;
|
||||
return myRevisions.get(currentLine);
|
||||
List<VcsFileRevision> revisions = getRevisions();
|
||||
|
||||
if (currentLine < 0 || currentLine >= revisions.size()) return null;
|
||||
return revisions.get(currentLine);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -299,7 +299,8 @@ public class AnnotateToggleAction extends ToggleAction implements DumbAware, Ann
|
||||
gutters.add(new ExtraFieldGutter(fileAnnotation, editor, presentation, bgColorMap, actionGroup));
|
||||
|
||||
presentation.addAction(new ShowHideAdditionalInfoAction(gutters, editorGutter, actionGroup));
|
||||
presentation.addAction(new AnnotateRevisionAction(fileAnnotation, vcs));
|
||||
presentation.addAction(new AnnotateCurrentRevisionAction(fileAnnotation, vcs));
|
||||
presentation.addAction(new AnnotatePreviousRevisionAction(fileAnnotation, vcs));
|
||||
addActionsFromExtensions(presentation, fileAnnotation);
|
||||
|
||||
for (AnAction action : presentation.getActions()) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user