Merge remote-tracking branch 'origin/master'

This commit is contained in:
Daniil Ovchinnikov
2015-01-14 20:59:03 +03:00
294 changed files with 3725 additions and 1593 deletions
@@ -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);
}
}
@@ -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) {
@@ -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();
@@ -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);
}
@@ -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;
}
}
@@ -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);
}
}
}
}
}
@@ -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;
}
}
@@ -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)) {
@@ -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);
}
}
@@ -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);
}
@@ -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();
@@ -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;
}
@@ -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);
}
}
}
@@ -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) {
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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) {}
}
}
@@ -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) {}
}
@@ -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) {}
}
}
@@ -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) {}
}
@@ -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);
}
}
}
@@ -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]) ;
}
}
@@ -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>
@@ -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"); }
@@ -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;
}
}'''
}
}
@@ -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();
}
}
@@ -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();
}
}
@@ -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;
}
}
@@ -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;
}
@@ -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);
}
}
}
@@ -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;
@@ -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);
@@ -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;
@@ -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
@@ -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();
@@ -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>
@@ -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";
}
}
@@ -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);
@@ -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
@@ -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");
}
}
@@ -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.
@@ -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;
}
}
@@ -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;
}
}
@@ -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