mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
introduce VirtualFile.getNameSequence() to avoid too many String instantiations
This commit is contained in:
@@ -1266,7 +1266,7 @@ public class BuildManager implements ApplicationComponent{
|
||||
@Override
|
||||
public String getValue() {
|
||||
if (myPath.length == 1) {
|
||||
final String name = FileNameCache.getVFileName(myPath[0]);
|
||||
final String name = FileNameCache.getVFileName(myPath[0]).toString();
|
||||
// handle case of windows drive letter
|
||||
return name.length() == 2 && name.endsWith(":")? name + "/" : name;
|
||||
}
|
||||
|
||||
@@ -18,13 +18,14 @@ package com.intellij.spi;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.lang.spi.SPILanguage;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.fileTypes.*;
|
||||
import com.intellij.openapi.fileTypes.FileTypeRegistry;
|
||||
import com.intellij.openapi.fileTypes.FileTypes;
|
||||
import com.intellij.openapi.fileTypes.LanguageFileType;
|
||||
import com.intellij.openapi.fileTypes.ex.FileTypeIdentifiableByVirtualFile;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -43,9 +44,9 @@ public class SPIFileType extends LanguageFileType implements FileTypeIdentifiabl
|
||||
@Override
|
||||
public boolean isMyFileType(VirtualFile file) {
|
||||
VirtualFile parent = file.getParent();
|
||||
if (parent != null && "services".equals(parent.getName())) {
|
||||
if (parent != null && Comparing.equal("services", parent.getNameSequence())) {
|
||||
final VirtualFile gParent = parent.getParent();
|
||||
if (gParent != null && "META-INF".equals(gParent.getName())) {
|
||||
if (gParent != null && Comparing.equal("META-INF", gParent.getNameSequence())) {
|
||||
final String fileName = file.getName();
|
||||
for (Object condition : Extensions.getExtensions("com.intellij.vetoSPICondition")) {
|
||||
if (((Condition<String>)condition).value(fileName)) return false;
|
||||
|
||||
@@ -742,4 +742,9 @@ public abstract class VirtualFile extends UserDataHolderBase implements Modifica
|
||||
public void setDetectedLineSeparator(@Nullable String separator) {
|
||||
putUserData(DETECTED_LINE_SEPARATOR_KEY, separator);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CharSequence getNameSequence() {
|
||||
return getName();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,8 +63,7 @@ public class IdeaGateway {
|
||||
public boolean isVersioned(@NotNull VirtualFile f, boolean shouldBeInContent) {
|
||||
if (!f.isInLocalFileSystem()) return false;
|
||||
|
||||
String fileName = f.getName();
|
||||
if (!f.isDirectory() && fileName.endsWith(".class")) return false;
|
||||
if (!f.isDirectory() && StringUtil.endsWith(f.getNameSequence(), ".class")) return false;
|
||||
|
||||
Project[] openProjects = ProjectManager.getInstance().getOpenProjects();
|
||||
boolean isInContent = false;
|
||||
|
||||
@@ -67,6 +67,9 @@ public abstract class NewVirtualFile extends VirtualFile implements VirtualFileW
|
||||
|
||||
|
||||
public abstract void setTimeStamp(final long time) throws IOException;
|
||||
|
||||
@NotNull
|
||||
public abstract CharSequence getNameSequence();
|
||||
|
||||
@Override
|
||||
public abstract int getId();
|
||||
|
||||
+24
-71
@@ -16,13 +16,12 @@
|
||||
package com.intellij.openapi.vfs.newvfs.impl;
|
||||
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.newvfs.persistent.FSRecords;
|
||||
import com.intellij.util.containers.IntObjectLinkedMap;
|
||||
import com.intellij.util.IntSLRUCache;
|
||||
import com.intellij.util.containers.IntObjectLinkedMap;
|
||||
import com.intellij.util.io.IOUtil;
|
||||
import com.intellij.util.io.PersistentStringEnumerator;
|
||||
import com.intellij.util.text.StringFactory;
|
||||
import com.intellij.util.text.ByteArrayCharSequence;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -31,12 +30,12 @@ import org.jetbrains.annotations.Nullable;
|
||||
*/
|
||||
public class FileNameCache {
|
||||
private static final PersistentStringEnumerator ourNames = FSRecords.getNames();
|
||||
@SuppressWarnings("unchecked") private static final IntSLRUCache<IntObjectLinkedMap.MapEntry<Object>>[] ourNameCache = new IntSLRUCache[16];
|
||||
@SuppressWarnings("unchecked") private static final IntSLRUCache<IntObjectLinkedMap.MapEntry<CharSequence>>[] ourNameCache = new IntSLRUCache[16];
|
||||
static {
|
||||
final int protectedSize = 40000 / ourNameCache.length;
|
||||
final int probationalSize = 20000 / ourNameCache.length;
|
||||
for(int i = 0; i < ourNameCache.length; ++i) {
|
||||
ourNameCache[i] = new IntSLRUCache<IntObjectLinkedMap.MapEntry<Object>>(protectedSize, probationalSize);
|
||||
ourNameCache[i] = new IntSLRUCache<IntObjectLinkedMap.MapEntry<CharSequence>>(protectedSize, probationalSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,15 +46,16 @@ public class FileNameCache {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static IntObjectLinkedMap.MapEntry<Object> cacheData(String name, int id, int stripe) {
|
||||
private static IntObjectLinkedMap.MapEntry<CharSequence> cacheData(String name, int id, int stripe) {
|
||||
if (name == null) {
|
||||
ourNames.markCorrupted();
|
||||
throw new RuntimeException("VFS name enumerator corrupted");
|
||||
}
|
||||
|
||||
Object rawName = convertToBytesIfAsciiString(name);
|
||||
IntObjectLinkedMap.MapEntry<Object> entry = new IntObjectLinkedMap.MapEntry<Object>(id, rawName);
|
||||
IntSLRUCache<IntObjectLinkedMap.MapEntry<Object>> cache = ourNameCache[stripe];
|
||||
CharSequence rawName = convertToBytesIfAsciiString(name);
|
||||
IntObjectLinkedMap.MapEntry<CharSequence> entry = new IntObjectLinkedMap.MapEntry<CharSequence>(id, rawName);
|
||||
IntSLRUCache<IntObjectLinkedMap.MapEntry<CharSequence>> cache = ourNameCache[stripe];
|
||||
//noinspection SynchronizationOnLocalVariableOrMethodParameter
|
||||
synchronized (cache) {
|
||||
return cache.cacheEntry(entry);
|
||||
}
|
||||
@@ -74,7 +74,7 @@ public class FileNameCache {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Object convertToBytesIfAsciiString(@NotNull String name) {
|
||||
private static CharSequence convertToBytesIfAsciiString(@NotNull String name) {
|
||||
int length = name.length();
|
||||
if (length == 0) return "";
|
||||
|
||||
@@ -86,15 +86,16 @@ public class FileNameCache {
|
||||
for (int i = 0; i < length; i++) {
|
||||
bytes[i] = (byte)name.charAt(i);
|
||||
}
|
||||
return bytes;
|
||||
return new ByteArrayCharSequence(bytes);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static IntObjectLinkedMap.MapEntry<Object> getEntry(int id) {
|
||||
private static IntObjectLinkedMap.MapEntry<CharSequence> getEntry(int id) {
|
||||
final int stripe = calcStripeIdFromNameId(id);
|
||||
IntSLRUCache<IntObjectLinkedMap.MapEntry<Object>> cache = ourNameCache[stripe];
|
||||
IntSLRUCache<IntObjectLinkedMap.MapEntry<CharSequence>> cache = ourNameCache[stripe];
|
||||
//noinspection SynchronizationOnLocalVariableOrMethodParameter
|
||||
synchronized (cache) {
|
||||
IntObjectLinkedMap.MapEntry<Object> entry = cache.getCachedEntry(id);
|
||||
IntObjectLinkedMap.MapEntry<CharSequence> entry = cache.getCachedEntry(id);
|
||||
if (entry != null) {
|
||||
return entry;
|
||||
}
|
||||
@@ -104,57 +105,20 @@ public class FileNameCache {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getVFileName(int nameId) {
|
||||
IntObjectLinkedMap.MapEntry<Object> entry = getEntry(nameId);
|
||||
Object name = entry.value;
|
||||
if (name instanceof String) {
|
||||
//noinspection StringEquality
|
||||
return (String)name;
|
||||
}
|
||||
|
||||
byte[] bytes = (byte[])name;
|
||||
int length = bytes.length;
|
||||
char[] chars = new char[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
chars[i] = (char)bytes[i];
|
||||
}
|
||||
return StringFactory.createShared(chars);
|
||||
public static CharSequence getVFileName(int nameId) {
|
||||
return getEntry(nameId).value;
|
||||
}
|
||||
|
||||
static int compareNameTo(int nameId, @NotNull String name, boolean ignoreCase) {
|
||||
IntObjectLinkedMap.MapEntry<Object> entry = getEntry(nameId);
|
||||
Object rawName = entry.value;
|
||||
if (rawName instanceof String) {
|
||||
String thisName = (String)rawName;
|
||||
return VirtualFileSystemEntry.compareNames(thisName, name, ignoreCase);
|
||||
}
|
||||
|
||||
byte[] bytes = (byte[])rawName;
|
||||
int bytesLength = bytes.length;
|
||||
|
||||
int d = bytesLength - name.length();
|
||||
if (d != 0) return d;
|
||||
|
||||
return compareBytes(bytes, name, bytesLength, ignoreCase);
|
||||
}
|
||||
|
||||
private static int compareBytes(@NotNull byte[] name1, @NotNull String name2, int len, boolean ignoreCase) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
char c1 = (char)name1[i];
|
||||
char c2 = name2.charAt(i);
|
||||
int d = StringUtil.compare(c1, c2, ignoreCase);
|
||||
if (d != 0) return d;
|
||||
}
|
||||
return 0;
|
||||
static int compareNameTo(int nameId, @NotNull CharSequence name, boolean ignoreCase) {
|
||||
return VirtualFileSystemEntry.compareNames(getEntry(nameId).value, name, ignoreCase);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
static char[] appendPathOnFileSystem(int nameId, @Nullable VirtualFileSystemEntry parent, int accumulatedPathLength, @NotNull int[] positionRef) {
|
||||
IntObjectLinkedMap.MapEntry<Object> entry = getEntry(nameId);
|
||||
Object o = entry.value;
|
||||
int nameLength = o instanceof String ? ((String)o).length() : ((byte[])o).length;
|
||||
boolean appendSlash = SystemInfo.isWindows && parent == null && nameLength == 2 &&
|
||||
(o instanceof String ? ((String)o).charAt(1) : (char)((byte[])o)[1]) == ':';
|
||||
IntObjectLinkedMap.MapEntry<CharSequence> entry = getEntry(nameId);
|
||||
CharSequence o = entry.value;
|
||||
int nameLength = o.length();
|
||||
boolean appendSlash = SystemInfo.isWindows && parent == null && nameLength == 2 && o.charAt(1) == ':';
|
||||
|
||||
char[] chars;
|
||||
if (parent != null) {
|
||||
@@ -169,18 +133,7 @@ public class FileNameCache {
|
||||
chars = new char[rootPathLength];
|
||||
}
|
||||
|
||||
if (o instanceof String) {
|
||||
positionRef[0] = VirtualFileSystemEntry.copyString(chars, positionRef[0], (String)o);
|
||||
}
|
||||
else {
|
||||
byte[] bytes = (byte[])o;
|
||||
int pos = positionRef[0];
|
||||
//noinspection ForLoopReplaceableByForEach
|
||||
for (int i = 0, len = bytes.length; i < len; i++) {
|
||||
chars[pos++] = (char)bytes[i];
|
||||
}
|
||||
positionRef[0] = pos;
|
||||
}
|
||||
positionRef[0] = VirtualFileSystemEntry.copyString(chars, positionRef[0], o);
|
||||
|
||||
if (appendSlash) {
|
||||
chars[positionRef[0]++] = '/';
|
||||
|
||||
+4
-4
@@ -151,7 +151,7 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
public CharSequence getNameSequence() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareNameTo(@NotNull String name, boolean ignoreCase) {
|
||||
public int compareNameTo(@NotNull CharSequence name, boolean ignoreCase) {
|
||||
return compareNames(myName, name, ignoreCase);
|
||||
}
|
||||
|
||||
@@ -548,8 +548,8 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry {
|
||||
Arrays.sort(childrenIds, new java.util.Comparator<FSRecords.NameId>() {
|
||||
@Override
|
||||
public int compare(FSRecords.NameId o1, FSRecords.NameId o2) {
|
||||
String name1 = o1.name;
|
||||
String name2 = o2.name;
|
||||
CharSequence name1 = o1.name;
|
||||
CharSequence name2 = o2.name;
|
||||
int cmp = compareNames(name1, name2, ignoreCase);
|
||||
if (cmp == 0 && name1 != name2) {
|
||||
LOG.error(ourPersistence + " returned duplicate file names("+name1+","+name2+")" +
|
||||
|
||||
+12
-5
@@ -32,6 +32,7 @@ import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
|
||||
import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS;
|
||||
import com.intellij.psi.SingleRootFileViewProvider;
|
||||
import com.intellij.util.LocalTimeCounter;
|
||||
import com.intellij.util.text.CharArrayUtil;
|
||||
import com.intellij.util.text.StringFactory;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -103,18 +104,24 @@ public abstract class VirtualFileSystemEntry extends NewVirtualFile {
|
||||
@Override
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return getNameSequence().toString();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public CharSequence getNameSequence() {
|
||||
return FileNameCache.getVFileName(myNameId);
|
||||
}
|
||||
|
||||
public int compareNameTo(@NotNull String name, boolean ignoreCase) {
|
||||
public int compareNameTo(@NotNull CharSequence name, boolean ignoreCase) {
|
||||
return FileNameCache.compareNameTo(myNameId, name, ignoreCase);
|
||||
}
|
||||
|
||||
protected static int compareNames(@NotNull String name1, @NotNull String name2, boolean ignoreCase) {
|
||||
protected static int compareNames(@NotNull CharSequence name1, @NotNull CharSequence name2, boolean ignoreCase) {
|
||||
return compareNames(name1, name2, ignoreCase, 0);
|
||||
}
|
||||
|
||||
static int compareNames(@NotNull String name1, @NotNull String name2, boolean ignoreCase, int offset2) {
|
||||
static int compareNames(@NotNull CharSequence name1, @NotNull CharSequence name2, boolean ignoreCase, int offset2) {
|
||||
int d = name1.length() - name2.length() + offset2;
|
||||
if (d != 0) return d;
|
||||
for (int i=0; i<name1.length(); i++) {
|
||||
@@ -197,9 +204,9 @@ public abstract class VirtualFileSystemEntry extends NewVirtualFile {
|
||||
return FileNameCache.appendPathOnFileSystem(myNameId, myParent, accumulatedPathLength, positionRef);
|
||||
}
|
||||
|
||||
protected static int copyString(@NotNull char[] chars, int pos, @NotNull String s) {
|
||||
protected static int copyString(@NotNull char[] chars, int pos, @NotNull CharSequence s) {
|
||||
int length = s.length();
|
||||
s.getChars(0, length, chars, pos);
|
||||
CharArrayUtil.getChars(s, chars, 0, pos, length);
|
||||
return pos + length;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -879,10 +879,10 @@ public class FSRecords implements Forceable {
|
||||
public static class NameId {
|
||||
public static final NameId[] EMPTY_ARRAY = new NameId[0];
|
||||
public final int id;
|
||||
public final String name;
|
||||
public final CharSequence name;
|
||||
public final int nameId;
|
||||
|
||||
public NameId(int id, int nameId, @NotNull String name) {
|
||||
public NameId(int id, int nameId, @NotNull CharSequence name) {
|
||||
this.id = id;
|
||||
this.nameId = nameId;
|
||||
this.name = name;
|
||||
|
||||
+6
-6
@@ -141,7 +141,7 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone
|
||||
return ContainerUtil.map2Array(nameIds, String.class, new Function<FSRecords.NameId, String>() {
|
||||
@Override
|
||||
public String fun(FSRecords.NameId id) {
|
||||
return id.name;
|
||||
return id.name.toString();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -172,7 +172,7 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone
|
||||
|
||||
Set<String> toAdd = ContainerUtil.newHashSet(delegateNames);
|
||||
for (FSRecords.NameId nameId : current) {
|
||||
toAdd.remove(nameId.name);
|
||||
toAdd.remove(nameId.name.toString());
|
||||
}
|
||||
|
||||
final TIntArrayList childrenIds = new TIntArrayList(current.length + toAdd.size());
|
||||
@@ -1276,10 +1276,10 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public abstract String getName();
|
||||
public abstract CharSequence getNameSequence();
|
||||
|
||||
@Override
|
||||
public int compareNameTo(@NotNull String name, boolean ignoreCase) {
|
||||
public int compareNameTo(@NotNull CharSequence name, boolean ignoreCase) {
|
||||
return VirtualFileSystemEntry.compareNames(getName(), name, ignoreCase);
|
||||
}
|
||||
|
||||
@@ -1309,7 +1309,7 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
public CharSequence getNameSequence() {
|
||||
return myParentLocalFile.getName();
|
||||
}
|
||||
|
||||
@@ -1332,7 +1332,7 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
public CharSequence getNameSequence() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.util.text;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ByteArrayCharSequence implements CharSequence {
|
||||
private final byte[] myChars;
|
||||
|
||||
public ByteArrayCharSequence(@NotNull byte... chars) {
|
||||
myChars = chars;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int length() {
|
||||
return myChars.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final char charAt(int index) {
|
||||
return (char)myChars[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence subSequence(int start, int end) {
|
||||
return start == 0 && end == length() ? this : new CharSequenceSubSequence(this, start, end);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String toString() {
|
||||
return StringFactory.createShared(CharArrayUtil.fromSequence(this, 0, length()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -32,10 +32,8 @@ import com.intellij.openapi.util.ModificationTracker;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Trinity;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileAdapter;
|
||||
import com.intellij.openapi.vfs.VirtualFileEvent;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.*;
|
||||
import com.intellij.openapi.vfs.newvfs.FileAttribute;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiModificationTrackerImpl;
|
||||
@@ -516,8 +514,8 @@ public class GroovyDslFileIndex extends ScalarIndexExtension<String> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptInput(@NotNull final VirtualFile file) {
|
||||
return "gdsl".equals(file.getExtension());
|
||||
public boolean acceptInput(final VirtualFile file) {
|
||||
return StringUtil.endsWith(file.getNameSequence(), ".gdsl");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user