Merge remote-tracking branch 'origin/master'

This commit is contained in:
Roman Shevchenko
2017-05-30 21:51:23 +03:00
21 changed files with 242 additions and 155 deletions
@@ -118,7 +118,7 @@ public class ImageComponentUI extends ComponentUI {
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
}
UIUtil.drawImage(g, renderer, 0, 0, size.width, size.height, ic);
UIUtil.drawImage(g, renderer, new Rectangle(0, 0, size.width, size.height), null, ic);
g2d.setRenderingHints(oldHints);
}
@@ -15,12 +15,14 @@
*/
package com.intellij.psi.impl.search;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.GlobalSearchScopeUtil;
import com.intellij.psi.search.GlobalSearchScopesCore;
import com.intellij.psi.search.searches.MethodReferencesSearch;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.CommonProcessors;
import com.intellij.util.Processor;
import com.intellij.util.indexing.FileBasedIndex;
@@ -32,6 +34,7 @@ import java.util.Collection;
import java.util.Collections;
public class JavaNullMethodArgumentUtil {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.search.JavaNullMethodArgumentUtil");
public static boolean hasNullArgument(@NotNull PsiMethod method, final int argumentIdx) {
final boolean[] result = {false};
@@ -47,35 +50,55 @@ public class JavaNullMethodArgumentUtil {
if (parameter.getType() instanceof PsiEllipsisType) {
return;
}
final GlobalSearchScope scope = findScopeWhereNullArgumentCanPass(method, argumentIdx);
if (scope == null) return;
Collection<VirtualFile> candidateFiles = getFilesWithPotentialNullPassingCalls(method, argumentIdx);
long start = System.currentTimeMillis();
processCallsWithNullArguments(method, argumentIdx, nullArgumentProcessor, candidateFiles);
long duration = System.currentTimeMillis() - start;
if (duration > 200) {
LOG.trace("Long nullable argument search for " + method.getName() + "(" + PsiUtil.getMemberQualifiedName(method) + "): " + duration + "ms, " + candidateFiles.size() + " files");
}
}
private static void processCallsWithNullArguments(@NotNull PsiMethod method,
int argumentIdx,
@NotNull Processor<PsiExpression> nullArgumentProcessor,
Collection<VirtualFile> candidateFiles) {
if (candidateFiles.isEmpty()) return;
GlobalSearchScope scope = GlobalSearchScope.filesScope(method.getProject(), candidateFiles);
MethodReferencesSearch.search(method, scope, true).forEach(ref -> {
final PsiElement psi = ref.getElement();
if (psi != null) {
final PsiElement parent = psi.getParent();
PsiExpressionList argumentList = null;
if (parent instanceof PsiCallExpression) {
argumentList = ((PsiCallExpression)parent).getArgumentList();
}
else if (parent instanceof PsiAnonymousClass) {
argumentList = ((PsiAnonymousClass)parent).getArgumentList();
}
if (argumentList != null) {
final PsiExpression[] arguments = argumentList.getExpressions();
if (argumentIdx < arguments.length) {
final PsiExpression argument = arguments[argumentIdx];
if (argument instanceof PsiLiteralExpression && PsiKeyword.NULL.equals(argument.getText())) {
return nullArgumentProcessor.process(argument);
}
}
}
PsiExpression argument = getCallArgument(ref, argumentIdx);
if (argument instanceof PsiLiteralExpression && argument.textMatches(PsiKeyword.NULL)) {
return nullArgumentProcessor.process(argument);
}
return true;
});
}
@Nullable
private static GlobalSearchScope findScopeWhereNullArgumentCanPass(@NotNull PsiMethod method, int parameterIndex) {
private static PsiExpression getCallArgument(PsiReference ref, int argumentIdx) {
PsiExpressionList argumentList = getCallArgumentList(ref.getElement());
PsiExpression[] arguments = argumentList == null ? PsiExpression.EMPTY_ARRAY : argumentList.getExpressions();
return argumentIdx < arguments.length ? arguments[argumentIdx] : null;
}
@Nullable
private static PsiExpressionList getCallArgumentList(@Nullable PsiElement psi) {
PsiElement parent = psi == null ? null :psi.getParent();
if (parent instanceof PsiCallExpression) {
return ((PsiCallExpression)parent).getArgumentList();
}
else if (parent instanceof PsiAnonymousClass) {
return ((PsiAnonymousClass)parent).getArgumentList();
}
return null;
}
@NotNull
private static Collection<VirtualFile> getFilesWithPotentialNullPassingCalls(@NotNull PsiMethod method, int parameterIndex) {
final FileBasedIndex fileBasedIndex = FileBasedIndex.getInstance();
final CommonProcessors.CollectProcessor<VirtualFile> collector = new CommonProcessors.CollectProcessor<>(new ArrayList<>());
GlobalSearchScope searchScope = GlobalSearchScopeUtil.toGlobalSearchScope(method.getUseScope(), method.getProject());
@@ -84,8 +107,6 @@ public class JavaNullMethodArgumentUtil {
Collections.singleton(new JavaNullMethodArgumentIndex.MethodCallData(method.getName(), parameterIndex)),
collector,
searchScope);
final Collection<VirtualFile> candidateFiles = collector.getResults();
return candidateFiles.isEmpty() ? null : GlobalSearchScope.filesScope(method.getProject(), candidateFiles);
return collector.getResults();
}
}
@@ -462,15 +462,14 @@ public class JavaCompletionUtil {
}), -1);
}
if (containsMember(qualifierType, object)) {
LookupElementRenderer<LookupElementDecorator<LookupElement>> boldRenderer =
new LookupElementRenderer<LookupElementDecorator<LookupElement>>() {
@Override
public void renderElement(LookupElementDecorator<LookupElement> element, LookupElementPresentation presentation) {
element.getDelegate().renderElement(presentation);
presentation.setItemTextBold(true);
}
};
return PrioritizedLookupElement.withExplicitProximity(LookupElementDecorator.withRenderer(item, boldRenderer), 1);
LookupElementDecorator<LookupElement> bold = LookupElementDecorator.withRenderer(item, new LookupElementRenderer<LookupElementDecorator<LookupElement>>() {
@Override
public void renderElement(LookupElementDecorator<LookupElement> element, LookupElementPresentation presentation) {
element.getDelegate().renderElement(presentation);
presentation.setItemTextBold(true);
}
});
return object instanceof PsiField ? bold : PrioritizedLookupElement.withExplicitProximity(bold, 1);
}
return item;
}
@@ -885,7 +884,9 @@ public class JavaCompletionUtil {
String open = escapeXmlIfNeeded(context, "<");
context.getDocument().insertString(offset, open);
context.getEditor().getCaretModel().moveToOffset(offset + open.length());
context.getDocument().insertString(offset + open.length(), escapeXmlIfNeeded(context, ">"));
if (CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET) {
context.getDocument().insertString(offset + open.length(), escapeXmlIfNeeded(context, ">"));
}
if (context.getCompletionChar() != Lookup.COMPLETE_STATEMENT_SELECT_CHAR) {
context.setAddCompletionChar(false);
}
@@ -0,0 +1,6 @@
public class SomeClass {
private void b() {
List<caret>
}
}
@@ -0,0 +1,8 @@
import java.util.List;
public class SomeClass {
private void b() {
List<<caret>
}
}
@@ -111,7 +111,7 @@ class NormalCompletionOrderingTest extends CompletionSortingTestCase {
final String path = getTestName(false) + ".java"
myFixture.configureByFile(path)
myFixture.complete(CompletionType.BASIC, 2)
assertPreferredItems(0, "BOOLEAN", "booleanMethod", "AN_OBJECT", "voidMethod")
assertPreferredItems(0, "booleanMethod", "BOOLEAN", "voidMethod", "AN_OBJECT")
}
void testDispreferDeclared() throws Throwable {
@@ -45,7 +45,7 @@ class NormalCompletionTest extends LightFixtureCompletionTestCase {
void testSimple() throws Exception {
configureByFile("Simple.java")
assertStringItems("_field", "_local1", "_local2", "_baseField", "_method", "_baseMethod")
assertStringItems("_local1", "_local2", "_field", "_baseField", "_method", "_baseMethod")
}
void testCastToPrimitive1() throws Exception {
@@ -222,6 +222,7 @@ class NormalCompletionTest extends LightFixtureCompletionTestCase {
protected void tearDown() throws Exception {
CodeInsightSettings.instance.AUTOCOMPLETE_ON_CODE_COMPLETION = true
CodeInsightSettings.instance.COMPLETION_CASE_SENSITIVE = CodeInsightSettings.FIRST_LETTER
CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET = true
super.tearDown()
}
@@ -361,44 +362,22 @@ class NormalCompletionTest extends LightFixtureCompletionTestCase {
}
void testMethodWithLeftParTailTypeNoPairBrace() throws Exception {
final boolean old = CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET
CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET = false
try {
configureByFile(getTestName(false) + ".java")
type('(')
checkResult()
}
finally {
CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET = old
}
doTest('(')
}
void testMethodWithLeftParTailTypeNoPairBrace2() throws Exception {
final boolean old = CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET
CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET = false
try {
//no tail type should work the normal way
configureByFile("MethodWithLeftParTailTypeNoPairBrace.java")
selectItem(myItems[0])
checkResultByFile("MethodWithLeftParTailTypeNoPairBrace_after2.java")
}
finally {
CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET = old
}
//no tail type should work the normal way
configureByFile("MethodWithLeftParTailTypeNoPairBrace.java")
selectItem(myItems[0])
checkResultByFile("MethodWithLeftParTailTypeNoPairBrace_after2.java")
}
void testMethodNoPairBrace() throws Exception {
final boolean old = CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET
CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET = false
try {
doTest '\n'
}
finally {
CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET = old
}
doTest '\n'
}
void testExcessSpaceInTypeCast() throws Throwable {
@@ -1784,5 +1763,10 @@ class Bar {
myFixture.addClass("package pkg; public class PathUtil { public static String toSystemDependentName() {} }")
doTest('\n')
}
void testPairAngleBracketDisabled() {
CodeInsightSettings.instance.AUTOINSERT_PAIR_BRACKET = false
doTest('<')
}
}
@@ -473,7 +473,7 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase {
public void testNoUninitializedFieldsInConstructor() throws Throwable {
configureByTestName();
assertStringItems("aab", "aac", "hashCode");
assertStringItems("aac", "aab", "hashCode");
}
public void testFieldsSetInAnotherConstructor() throws Throwable { doTest(); }
public void testFieldsSetAbove() throws Throwable { doTest(); }
@@ -56,7 +56,7 @@ class VariablesCompletionTest extends LightFixtureCompletionTestCase {
void testLocals2() throws Exception {
configureByFile(FILE_PREFIX + "locals/" + "TestSource2.java")
myFixture.assertPreferredCompletionItems 0, 'aaa', 'abc'
myFixture.assertPreferredCompletionItems 0, 'abc', 'aaa'
checkResultByFile(FILE_PREFIX + "locals/" + "TestResult2.java")
}
@@ -278,7 +278,7 @@ public class AnalysisScope {
final FileIndex fileIndex = getFileIndex();
accept(file -> {
if (file.isDirectory()) return true;
if (ProjectCoreUtil.isProjectOrWorkspaceFile(file, file.getFileType())) return true;
if (ProjectCoreUtil.isProjectOrWorkspaceFile(file)) return true;
if (fileIndex.isInContent(file) && !isFiltered(file)
&& !GeneratedSourcesFilter.isGeneratedSourceByAnyFilter(file, myProject)) {
return processFile(file, visitor, psiManager, needReadAction, clearResolveCache);
@@ -28,12 +28,14 @@ import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.search.scope.packageSet.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.SmartHashSet;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashSet;
import org.jetbrains.annotations.NotNull;
import java.util.*;
import java.util.Collections;
import java.util.Objects;
import java.util.Set;
public class GlobalSearchScopesCore {
@NotNull
@@ -58,14 +60,12 @@ public class GlobalSearchScopesCore {
@NotNull
public static GlobalSearchScope directoriesScope(@NotNull Project project, boolean withSubdirectories, @NotNull VirtualFile... directories) {
if (directories.length ==1) {
if (directories.length == 1) {
return directoryScope(project, directories[0], withSubdirectories);
}
BitSet withSubdirectoriesBS = new BitSet(directories.length);
if (withSubdirectories) {
withSubdirectoriesBS.set(0, directories.length);
}
return new DirectoriesScope(project, directories, withSubdirectoriesBS);
return new DirectoriesScope(project,
withSubdirectories ? Collections.emptySet() : ContainerUtil.newHashSet(directories),
withSubdirectories ? ContainerUtil.newHashSet(directories) : Collections.emptySet());
}
public static GlobalSearchScope filterScope(@NotNull Project project, @NotNull NamedScope set) {
@@ -220,7 +220,12 @@ public class GlobalSearchScopesCore {
@Override
public boolean contains(@NotNull VirtualFile file) {
return myWithSubdirectories ? VfsUtilCore.isAncestor(myDirectory, file, false) : myDirectory.equals(file.getParent());
VirtualFile parent = file.getParent();
return parent != null && in(parent);
}
private boolean in(@NotNull VirtualFile parent) {
return myWithSubdirectories ? VfsUtilCore.isAncestor(myDirectory, parent, false) : myDirectory.equals(parent);
}
@Override
@@ -262,17 +267,22 @@ public class GlobalSearchScopesCore {
if (equals(scope)) return this;
if (scope instanceof DirectoryScope) {
DirectoryScope other = (DirectoryScope)scope;
VirtualFile otherDirectory = other.myDirectory;
if (myWithSubdirectories && VfsUtilCore.isAncestor(myDirectory, otherDirectory, false)) return this;
if (other.myWithSubdirectories && VfsUtilCore.isAncestor(otherDirectory, myDirectory, false)) return other;
BitSet newWithSubdirectories = new BitSet();
newWithSubdirectories.set(0, myWithSubdirectories);
newWithSubdirectories.set(1, other.myWithSubdirectories);
return new DirectoriesScope(getProject(), new VirtualFile[]{myDirectory,otherDirectory}, newWithSubdirectories);
if (in(other.myDirectory)) return this;
if (other.in(myDirectory)) return other;
return new DirectoriesScope(getProject(),
union(!myWithSubdirectories, myDirectory, !other.myWithSubdirectories, other.myDirectory),
union(myWithSubdirectories, myDirectory, other.myWithSubdirectories, other.myDirectory));
}
return super.uniteWith(scope);
}
private static Set<VirtualFile> union(boolean addDir1, @NotNull VirtualFile dir1, boolean addDir2, @NotNull VirtualFile dir2) {
if (addDir1 && addDir2) return ContainerUtil.newHashSet(dir1, dir2);
if (addDir1) return Collections.singleton(dir1);
if (addDir2) return Collections.singleton(dir2);
return Collections.emptySet();
}
@NotNull
@Override
public Project getProject() {
@@ -288,15 +298,18 @@ public class GlobalSearchScopesCore {
}
static class DirectoriesScope extends GlobalSearchScope {
private final VirtualFile[] myDirectories;
private final BitSet myWithSubdirectories;
private final Set<VirtualFile> myDirectories;
private final Set<VirtualFile> myDirectoriesWithSubdirectories;
private DirectoriesScope(@NotNull Project project, @NotNull VirtualFile[] directories, @NotNull BitSet withSubdirectories) {
private DirectoriesScope(@NotNull Project project,
@NotNull Set<VirtualFile> directories,
@NotNull Set<VirtualFile> directoriesWithSubdirectories) {
super(project);
myWithSubdirectories = withSubdirectories;
myDirectories = directories;
if (directories.length < 2) {
throw new IllegalArgumentException("Expected >1 directories, but got: " + Arrays.asList(directories));
myDirectoriesWithSubdirectories = directoriesWithSubdirectories;
if (directories.size() + directoriesWithSubdirectories.size() < 2) {
throw new IllegalArgumentException("Expected >1 directories, but got: directories " + directories
+ ", directories with subdirectories " + directoriesWithSubdirectories);
}
}
@@ -307,23 +320,10 @@ public class GlobalSearchScopesCore {
}
private boolean in(@NotNull VirtualFile parent) {
Set<VirtualFile> directoriesWithSubdirectories = null;
for (int i = 0; i < myDirectories.length; i++) {
VirtualFile directory = myDirectories[i];
boolean withSubdirectories = myWithSubdirectories.get(i);
if (withSubdirectories) {
if (directory.getFileSystem().equals(parent.getFileSystem())) {
if (directoriesWithSubdirectories == null) {
directoriesWithSubdirectories = new SmartHashSet<>();
}
directoriesWithSubdirectories.add(directory);
}
}
else if (directory.equals(parent)) {
return true;
}
if (myDirectories.contains(parent)) {
return true;
}
return VfsUtilCore.isUnder(parent, directoriesWithSubdirectories);
return VfsUtilCore.isUnder(parent, myDirectoriesWithSubdirectories);
}
@Override
@@ -344,25 +344,21 @@ public class GlobalSearchScopesCore {
@Override
public String toString() {
//noinspection HardCodedStringLiteral
return "Directories scope: " + Arrays.asList(myDirectories);
return "Directories scope: directories " + myDirectories + ", directories with subdirectories " + myDirectoriesWithSubdirectories;
}
@Override
public int hashCode() {
int result = 1;
for (int i = 0; i < myDirectories.length; i++) {
VirtualFile directory = myDirectories[i];
boolean withSubdirectories = myWithSubdirectories.get(i);
result = result*31 + directory.hashCode() *31 + (withSubdirectories?1:0);
}
int result = myDirectories.hashCode();
result = result * 31 + myDirectoriesWithSubdirectories.hashCode();
return result;
}
@Override
public boolean equals(Object obj) {
return obj instanceof DirectoriesScope &&
Arrays.equals(myDirectories, ((DirectoriesScope)obj).myDirectories) &&
myWithSubdirectories.equals(((DirectoriesScope)obj).myWithSubdirectories);
myDirectories.equals(((DirectoriesScope)obj).myDirectories) &&
myDirectoriesWithSubdirectories.equals(((DirectoriesScope)obj).myDirectoriesWithSubdirectories);
}
@NotNull
@@ -372,28 +368,35 @@ public class GlobalSearchScopesCore {
return this;
}
if (scope instanceof DirectoryScope) {
if (in(((DirectoryScope)scope).myDirectory)) {
DirectoryScope other = (DirectoryScope)scope;
if (in(other.myDirectory)) {
return this;
}
VirtualFile[] newDirectories = ArrayUtil.append(myDirectories, ((DirectoryScope)scope).myDirectory, VirtualFile.class);
BitSet newWithSubdirectories = (BitSet)myWithSubdirectories.clone();
newWithSubdirectories.set(myDirectories.length, ((DirectoryScope)scope).myWithSubdirectories);
return new DirectoriesScope(getProject(), newDirectories, newWithSubdirectories);
Set<VirtualFile> directories = myDirectories;
Set<VirtualFile> directoriesWithSubdirectories = myDirectoriesWithSubdirectories;
if (other.myWithSubdirectories) {
directoriesWithSubdirectories = new HashSet<>(directoriesWithSubdirectories);
directoriesWithSubdirectories.add(other.myDirectory);
}
else {
directories = new HashSet<>(directories);
directories.add(other.myDirectory);
}
return new DirectoriesScope(getProject(), directories, directoriesWithSubdirectories);
}
if (scope instanceof DirectoriesScope) {
DirectoriesScope other = (DirectoriesScope)scope;
List<VirtualFile> newDirectories = new ArrayList<>(myDirectories.length + other.myDirectories.length);
newDirectories.addAll(Arrays.asList(myDirectories));
BitSet newWithSubdirectories = (BitSet)myWithSubdirectories.clone();
VirtualFile[] otherDirectories = other.myDirectories;
for (int i = 0; i < otherDirectories.length; i++) {
VirtualFile otherDirectory = otherDirectories[i];
if (!in(otherDirectory)) {
newWithSubdirectories.set(newDirectories.size(), other.myWithSubdirectories.get(i));
newDirectories.add(otherDirectory);
}
Set<VirtualFile> directories = myDirectories;
Set<VirtualFile> directoriesWithSubdirectories = myDirectoriesWithSubdirectories;
if (!other.myDirectories.isEmpty()) {
directories = new HashSet<>(directories);
directories.addAll(other.myDirectories);
}
return new DirectoriesScope(getProject(), newDirectories.toArray(new VirtualFile[newDirectories.size()]), newWithSubdirectories);
if (!other.myDirectoriesWithSubdirectories.isEmpty()) {
directoriesWithSubdirectories = new HashSet<>(directoriesWithSubdirectories);
directoriesWithSubdirectories.addAll(other.myDirectoriesWithSubdirectories);
}
return new DirectoriesScope(getProject(), directories, directoriesWithSubdirectories);
}
return super.uniteWith(scope);
}
@@ -408,11 +411,13 @@ public class GlobalSearchScopesCore {
@NotNull
@Override
public String getDisplayName() {
if (myDirectories.length == 1) {
VirtualFile root = myDirectories[0];
if (myDirectories.size() + myDirectoriesWithSubdirectories.size() == 1) {
Set<VirtualFile> dirs = myDirectories.size() == 1 ? myDirectories : myDirectoriesWithSubdirectories;
VirtualFile root = Objects.requireNonNull(ContainerUtil.getFirstItem(dirs));
return "Directory '" + root.getName() + "'";
}
return "Directories " + StringUtil.join(myDirectories, file -> "'" + file.getName() + "'", ", ");
Iterable<VirtualFile> allDirs = ContainerUtil.concat(myDirectories, myDirectoriesWithSubdirectories);
return "Directories " + StringUtil.join(allDirs, file -> "'" + file.getName() + "'", ", ");
}
}
@@ -29,6 +29,7 @@ import com.intellij.openapi.components.impl.stores.IComponentStore
import com.intellij.openapi.components.impl.stores.IProjectStore
import com.intellij.openapi.components.impl.stores.StoreUtil
import com.intellij.openapi.diagnostic.runAndLogException
import com.intellij.openapi.fileTypes.FileTypeManager
import com.intellij.openapi.module.Module
import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.module.impl.ModuleManagerImpl
@@ -243,7 +244,7 @@ abstract class ProjectStoreBase(override final val project: ProjectImpl) : Compo
}
override fun isProjectFile(file: VirtualFile): Boolean {
if (!file.isInLocalFileSystem || !ProjectCoreUtil.isProjectOrWorkspaceFile(file, file.fileType)) {
if (!file.isInLocalFileSystem || !ProjectCoreUtil.isProjectOrWorkspaceFile(file)) {
return false
}
@@ -141,6 +141,13 @@ public interface Document extends UserDataHolder {
@Contract(pure=true)
int getLineEndOffset(int line);
/**
* @return whether the line with the given index has been modified since the document has been saved
*/
default boolean isLineModified(int line) {
return false;
}
/**
* Inserts the specified text at the specified offset in the document. Line breaks in
* the inserted text must be normalized as \n.
@@ -16,6 +16,7 @@
package com.intellij.openapi.project;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeRegistry;
import com.intellij.openapi.fileTypes.InternalFileType;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.SystemInfoRt;
@@ -26,12 +27,9 @@ import org.jetbrains.annotations.Nullable;
public class ProjectCoreUtil {
public static volatile Project theProject;
/**
* @deprecated Please use ProjectUtil.isProjectOrWorkspaceFile
*/
@Deprecated
public static boolean isProjectOrWorkspaceFile(@NotNull VirtualFile file) {
return isProjectOrWorkspaceFile(file, file.getFileType());
// do not use file.getFileType() to avoid autodetection by content loading for arbitrary files
return isProjectOrWorkspaceFile(file, FileTypeRegistry.getInstance().getFileTypeByFileName(file.getNameSequence()));
}
public static boolean isProjectOrWorkspaceFile(@NotNull VirtualFile file, @Nullable FileType fileType) {
@@ -180,6 +180,12 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
return stripTrailingSpaces(project, inChangedLinesOnly, true, new int[0]);
}
@Override
public boolean isLineModified(int line) {
LineSet lineSet = myLineSet;
return lineSet != null && lineSet.isModified(line);
}
/**
* @return true if stripping was completed successfully, false if the document prevented stripping by e.g. caret(s) being in the way
*/
@@ -518,6 +518,11 @@ public class DocumentWindowImpl extends UserDataHolderBase implements Disposable
}
}
@Override
public boolean isLineModified(int line) {
return myDelegate.isLineModified(injectedToHostLine(line));
}
@Override
@NotNull
public Segment[] getHostRanges() {
@@ -74,7 +74,7 @@ fun guessProjectForFile(file: VirtualFile?): Project? = ProjectLocator.getInstan
* guessProjectForFile works incorrectly - even if file is config (idea config file) first opened project will be returned
*/
@JvmOverloads
fun guessProjectForContentFile(file: VirtualFile, fileType: FileType = file.fileType): Project? {
fun guessProjectForContentFile(file: VirtualFile, fileType: FileType = FileTypeManager.getInstance().getFileTypeByFileName(file.nameSequence)): Project? {
if (ProjectCoreUtil.isProjectOrWorkspaceFile(file, fileType)) {
return null
}
@@ -82,10 +82,7 @@ fun guessProjectForContentFile(file: VirtualFile, fileType: FileType = file.file
return ProjectManager.getInstance().openProjects.firstOrNull { !it.isDefault && it.isInitialized && !it.isDisposed && ProjectRootManager.getInstance(it).fileIndex.isInContent(file) }
}
fun isProjectOrWorkspaceFile(file: VirtualFile): Boolean {
// do not use file.getFileType() to avoid autodetection by content loading for arbitrary files
return ProjectCoreUtil.isProjectOrWorkspaceFile(file, FileTypeManager.getInstance().getFileTypeByFileName(file.name))
}
fun isProjectOrWorkspaceFile(file: VirtualFile): Boolean = ProjectCoreUtil.isProjectOrWorkspaceFile(file)
fun guessCurrentProject(component: JComponent?): Project {
var project: Project? = null
@@ -367,12 +367,13 @@ public class GlassPaneDialogWrapperPeer extends DialogWrapperPeer implements Foc
private void hidePopupsIfNeeded() {
if (!SystemInfo.isMac) return;
StackingPopupDispatcher.getInstance().hidePersistentPopups();
final StackingPopupDispatcher stackingPopupDispatcher = StackingPopupDispatcher.getInstance();
stackingPopupDispatcher.hidePersistentPopups();
Disposer.register(myDialog, new Disposable() {
@Override
public void dispose() {
StackingPopupDispatcher.getInstance().restorePersistentPopups();
stackingPopupDispatcher.restorePersistentPopups();
}
});
}
@@ -16,19 +16,24 @@
package com.intellij.util;
import com.intellij.concurrency.JobLauncher;
import com.intellij.testFramework.PlatformTestCase;
import com.intellij.testFramework.PlatformTestUtil;
import org.junit.Assert;
import java.util.Collections;
import java.util.Random;
import static org.junit.Assume.assumeTrue;
public class StringBuilderSpinAllocatorTest extends PlatformTestCase {
public class StringBuilderSpinAllocatorTester {
public static void main(String[] args) {
testSequentialPerformance();
testConcurrentPerformance();
}
public static final int THREADS = 1000;
public void testSequentialPerformance() {
private static void testSequentialPerformance() {
assumeTrue(!PlatformTestUtil.COVERAGE_ENABLED_BUILD);
for (int i=0; i<10; i++) {
long spinTime = time(count, spinAlloc);
@@ -36,7 +41,7 @@ public class StringBuilderSpinAllocatorTest extends PlatformTestCase {
System.out.println("regular: " + regularTime + "; spin :" +spinTime+"; ratio: "+(10*spinTime/regularTime)/10.0+" times");
}
}
public void testConcurrentPerformance() {
private static void testConcurrentPerformance() {
assumeTrue(!PlatformTestUtil.COVERAGE_ENABLED_BUILD);
for (int i=0; i<10; i++) {
long spinTime = concurrentTime(count/THREADS, spinAlloc);
@@ -53,13 +58,14 @@ public class StringBuilderSpinAllocatorTest extends PlatformTestCase {
return true;
});
assertTrue(ok);
Assert.assertTrue(ok);
});
}
static final int count = 100000;
static final int iter = 1000;
static Runnable spinAlloc = new Runnable() {
@SuppressWarnings("deprecation")
@Override
public void run() {
for (int i = 0; i < iter; ++i) {
@@ -77,6 +83,7 @@ public class StringBuilderSpinAllocatorTest extends PlatformTestCase {
}
};
static Runnable regularAlloc = new Runnable() {
@SuppressWarnings("MismatchedQueryAndUpdateOfStringBuilder")
@Override
public void run() {
for (int i = 0; i < iter; ++i) {
@@ -18,6 +18,7 @@ package com.intellij.util;
/**
* StringBuilderSpinAllocator reuses StringBuilder instances performing non-blocking allocation and dispose.
* @deprecated Simple allocation is faster than this (according to StringBuilderSpinAllocatorTester)
*/
public class StringBuilderSpinAllocator {
@@ -2008,6 +2008,45 @@ public class UIUtil {
drawImage(g, image, x, y, -1, -1, observer);
}
public static void drawImage(Graphics g, Image image, @Nullable Rectangle dstRect, @Nullable Rectangle srcRect, ImageObserver observer) {
Image drawImage = image;
if (image instanceof JBHiDPIScaledImage) {
drawImage = ((JBHiDPIScaledImage)image).getDelegate();
if (drawImage == null) {
drawImage = image;
}
}
int dx = 0;
int dy = 0;
int dw = -1;
int dh = -1;
if (dstRect != null) {
dx = dstRect.x;
dy = dstRect.y;
dw = dstRect.width;
dh = dstRect.height;
}
if (dw == -1 && dh == -1) {
dw = ImageUtil.getUserWidth(image);
dh = ImageUtil.getUserHeight(image);
}
int sx = 0;
int sy = 0;
int sw = -1;
int sh = -1;
if (srcRect != null) {
sx = srcRect.x;
sy = srcRect.y;
sw = srcRect.width;
sh = srcRect.height;
}
if (sw == -1 && sh == -1) {
sw = ImageUtil.getRealWidth(image);
sh = ImageUtil.getRealHeight(image);
}
g.drawImage(drawImage, dx, dy, dx + dw, dy + dh, sx, sy, sx + sw, sy + sh, observer);
}
public static void drawImage(Graphics g, Image image, int x, int y, int width, int height, ImageObserver observer) {
if (image instanceof JBHiDPIScaledImage) {
Image img = ((JBHiDPIScaledImage)image).getDelegate();
@@ -2028,7 +2067,7 @@ public class UIUtil {
g.drawImage(image, x, y, observer);
}
else {
g.drawImage(image, x, y, x + width, y + height, observer);
g.drawImage(image, x, y, x + width, y + height, 0, 0, width, height, observer);
}
}