mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master' into test2
This commit is contained in:
@@ -16,8 +16,6 @@
|
||||
package com.intellij.psi.formatter.java;
|
||||
|
||||
import com.intellij.formatting.*;
|
||||
import com.intellij.formatting.alignment.AlignmentInColumnsConfig;
|
||||
import com.intellij.formatting.alignment.AlignmentInColumnsHelper;
|
||||
import com.intellij.formatting.alignment.AlignmentStrategy;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
@@ -38,7 +36,6 @@ import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
|
||||
import com.intellij.psi.impl.source.tree.java.ClassElement;
|
||||
import com.intellij.psi.jsp.JspElementType;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.text.CharArrayUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -378,24 +375,15 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected Alignment createChildAlignment2(@Nullable Alignment base) {
|
||||
final IElementType nodeType = myNode.getElementType();
|
||||
if (nodeType == JavaElementType.CONDITIONAL_EXPRESSION) {
|
||||
return base == null ? createAlignment(mySettings.ALIGN_MULTILINE_TERNARY_OPERATION, null) : createAlignment(base, mySettings.ALIGN_MULTILINE_TERNARY_OPERATION, null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected Alignment chooseAlignment(@Nullable Alignment alignment, @Nullable Alignment alignment2, @NotNull ASTNode child) {
|
||||
if (preferSlaveAlignment(child)) {
|
||||
if (isTernaryOperatorToken(child)) {
|
||||
return alignment2;
|
||||
}
|
||||
return alignment;
|
||||
}
|
||||
|
||||
private boolean preferSlaveAlignment(@NotNull final ASTNode child) {
|
||||
private boolean isTernaryOperatorToken(@NotNull final ASTNode child) {
|
||||
final IElementType nodeType = myNode.getElementType();
|
||||
|
||||
if (nodeType == JavaElementType.CONDITIONAL_EXPRESSION) {
|
||||
@@ -775,7 +763,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Alignment createAlignment(Alignment base, final boolean alignOption, @Nullable final Alignment defaultAlignment) {
|
||||
public static Alignment createAlignment(Alignment base, final boolean alignOption, @Nullable final Alignment defaultAlignment) {
|
||||
return alignOption ? createAlignmentOrDefault(base, defaultAlignment) : defaultAlignment;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.intellij.psi.impl.source.tree.StdTokenSets;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -71,11 +72,20 @@ public class SimpleJavaBlock extends AbstractJavaBlock {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected Alignment createChildAlignment2(@Nullable Alignment base) {
|
||||
final IElementType nodeType = myNode.getElementType();
|
||||
if (nodeType == JavaElementType.CONDITIONAL_EXPRESSION) {
|
||||
return base == null ? createAlignment(mySettings.ALIGN_MULTILINE_TERNARY_OPERATION, null) : createAlignment(base, mySettings.ALIGN_MULTILINE_TERNARY_OPERATION, null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void processRemainingChildren(List<Block> result, Wrap childWrap) {
|
||||
while (myCurrentChild != null) {
|
||||
if (isNotEmptyNode(myCurrentChild)) {
|
||||
final ASTNode astNode = myCurrentChild;
|
||||
AlignmentStrategy alignmentStrategyToUse = getAlignmentStrategy(myCurrentChild);
|
||||
AlignmentStrategy alignmentStrategyToUse = AlignmentStrategy.wrap(chooseAlignment(myReservedAlignment, myReservedAlignment2, myCurrentChild));
|
||||
myCurrentChild = processChild(result, astNode, alignmentStrategyToUse, childWrap, myCurrentIndent, myCurrentOffset);
|
||||
if (astNode != myCurrentChild && myCurrentChild != null) {
|
||||
myCurrentOffset = myCurrentChild.getTextRange().getStartOffset();
|
||||
@@ -114,12 +124,6 @@ public class SimpleJavaBlock extends AbstractJavaBlock {
|
||||
}
|
||||
}
|
||||
|
||||
private AlignmentStrategy getAlignmentStrategy(ASTNode child) {
|
||||
return JavaElementType.FIELD == myNode.getElementType()
|
||||
? myAlignmentStrategy
|
||||
: AlignmentStrategy.wrap(chooseAlignment(myReservedAlignment, myReservedAlignment2, child));
|
||||
}
|
||||
|
||||
private boolean isNotEmptyNode(@NotNull ASTNode child) {
|
||||
return !FormatterUtil.containsWhiteSpacesOnly(child) && child.getTextLength() > 0;
|
||||
}
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
public class Foo {
|
||||
void m() {
|
||||
methodCall(.assert<caret>
|
||||
}
|
||||
|
||||
boolean methodCall(String s) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
public class Foo {
|
||||
void m() {
|
||||
methodCall(.assert <caret>
|
||||
}
|
||||
|
||||
boolean methodCall(String s) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
public class Foo {
|
||||
void m() {
|
||||
assert is();<caret>
|
||||
is();.assert <caret>
|
||||
}
|
||||
|
||||
|
||||
boolean is() {
|
||||
return false;
|
||||
}
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
public class Foo {
|
||||
void m() {
|
||||
methodCall(.if<caret>
|
||||
}
|
||||
|
||||
boolean methodCall(String s) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
public class Foo {
|
||||
void m() {
|
||||
methodCall(.if <caret>
|
||||
}
|
||||
|
||||
boolean methodCall(String s) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+2
-4
@@ -1,10 +1,8 @@
|
||||
public class Foo {
|
||||
void m() {
|
||||
if (is()) {
|
||||
<caret>
|
||||
}
|
||||
is();.if <caret>
|
||||
}
|
||||
|
||||
|
||||
boolean is() {
|
||||
return false;
|
||||
}
|
||||
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
public class Foo {
|
||||
Object m() {
|
||||
new Object(.return<caret>
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
public class Foo {
|
||||
Object m() {
|
||||
new Object(.return <caret>
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
public class Foo {
|
||||
String m() {
|
||||
methodCall(.return<caret>
|
||||
}
|
||||
|
||||
String methodCall(String s) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
public class Foo {
|
||||
String m() {
|
||||
methodCall("string".return<caret>
|
||||
}
|
||||
|
||||
String methodCall(String s) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
public class Foo {
|
||||
String m() {
|
||||
methodCall("string".return <caret>
|
||||
}
|
||||
|
||||
String methodCall(String s) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
public class Foo {
|
||||
String m() {
|
||||
methodCall(.return <caret>
|
||||
}
|
||||
|
||||
String methodCall(String s) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
public class Foo {
|
||||
String m() {
|
||||
(methodCall("").return<caret>
|
||||
}
|
||||
|
||||
String methodCall(String s) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
public class Foo {
|
||||
String m() {
|
||||
(methodCall("").return <caret>
|
||||
}
|
||||
|
||||
String methodCall(String s) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
public class Foo {
|
||||
void m() {
|
||||
methodCall(.sout<caret>
|
||||
}
|
||||
|
||||
String methodCall(String s) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
public class Foo {
|
||||
void m() {
|
||||
methodCall(.sout <caret>
|
||||
}
|
||||
|
||||
String methodCall(String s) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import java.lang.Exception;
|
||||
|
||||
public class Foo {
|
||||
void m() {
|
||||
methodCall(.throw<caret>
|
||||
}
|
||||
|
||||
Exception methodCall(String s) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import java.lang.Exception;
|
||||
|
||||
public class Foo {
|
||||
void m() {
|
||||
methodCall(.throw <caret>
|
||||
}
|
||||
|
||||
Exception methodCall(String s) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -2,6 +2,6 @@ import java.lang.RuntimeException;
|
||||
|
||||
public class Foo {
|
||||
void m() {
|
||||
throw new RuntimeException("error");
|
||||
new RuntimeException("error");.throw <caret>
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
public class Foo {
|
||||
void m() {
|
||||
methodCall(.while<caret>
|
||||
}
|
||||
|
||||
boolean methodCall(String s) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
public class Foo {
|
||||
void m() {
|
||||
methodCall(.while <caret>
|
||||
}
|
||||
|
||||
boolean methodCall(String s) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+4
@@ -71,5 +71,9 @@ public class AssertStatementPostfixTemplateTest extends PostfixTemplateTestCase
|
||||
public void testSimpleWithSemicolon() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testIncompleteExpression() {
|
||||
doTest();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -69,5 +69,7 @@ public class IfStatementPostfixTemplateTest extends PostfixTemplateTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
|
||||
public void testIncompleteExpression() {
|
||||
doTest();
|
||||
}
|
||||
}
|
||||
|
||||
+16
@@ -38,4 +38,20 @@ public class ReturnPostfixTemplateTest extends PostfixTemplateTestCase {
|
||||
public void testComposite2() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testIncompleteExpression() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testIncompleteConstructor() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testIncompleteExpressionWithParam() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testIncompleteParentheses() {
|
||||
doTest();
|
||||
}
|
||||
}
|
||||
+4
@@ -31,4 +31,8 @@ public class SoutPostfixTemplateTest extends PostfixTemplateTestCase {
|
||||
public void testVoid() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testIncompleteExpression() {
|
||||
doTest();
|
||||
}
|
||||
}
|
||||
+3
@@ -37,4 +37,7 @@ public class ThrowStatementPostfixTemplateTest extends PostfixTemplateTestCase {
|
||||
public void testSimpleWithSemicolon() {
|
||||
doTest();
|
||||
}
|
||||
public void testIncompleteExpression() {
|
||||
doTest();
|
||||
}
|
||||
}
|
||||
|
||||
+4
@@ -34,6 +34,10 @@ public class WhileStatementPostfixTemplateTest extends PostfixTemplateTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testIncompleteExpression() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected String getSuffix() {
|
||||
|
||||
@@ -109,8 +109,7 @@ public class IndexTest extends JavaCodeInsightFixtureTestCase {
|
||||
assertDataEquals(index.getFilesByWord("h"));
|
||||
}
|
||||
finally {
|
||||
indexStorage.close();
|
||||
FileUtil.delete(storageFile);
|
||||
index.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,10 @@ public class StringIndex {
|
||||
public void update(final String path, @Nullable String content, @Nullable String oldContent) throws StorageException {
|
||||
myIndex.update(path.hashCode(), toInput(path, content)).compute();
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
myIndex.dispose();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private PathContentPair toInput(@NotNull String path, @Nullable String content) {
|
||||
|
||||
+6
-1
@@ -19,6 +19,7 @@ import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
@@ -41,7 +42,11 @@ public class TopmostExpressionSelector implements PostfixTemplateExpressionSelec
|
||||
@NotNull Document copyDocument,
|
||||
int newOffset) {
|
||||
PsiElement topmostExpression = template.getPsiInfo().getTopmostExpression(context);
|
||||
return topmostExpression != null && myCondition.value(topmostExpression);
|
||||
|
||||
return topmostExpression != null &&
|
||||
topmostExpression.getTextRange().getEndOffset() == newOffset &&
|
||||
!PsiTreeUtil.hasErrorElements(topmostExpression) &&
|
||||
myCondition.value(topmostExpression);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -21,6 +21,7 @@ package com.intellij.util.io;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.io.ByteSequence;
|
||||
import com.intellij.util.SystemProperties;
|
||||
import com.intellij.util.containers.SLRUCache;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -42,14 +43,41 @@ public class PersistentHashMapValueStorage {
|
||||
private static final int CACHE_PROTECTED_QUEUE_SIZE = 10;
|
||||
private static final int CACHE_PROBATIONAL_QUEUE_SIZE = 20;
|
||||
|
||||
// cache size is twice larger than constants because (when used) it replaces two caches
|
||||
private static final FileAccessorCache<RandomAccessFileWrapper> ourRandomAccessFileCache = new FileAccessorCache<RandomAccessFileWrapper>(
|
||||
2*CACHE_PROTECTED_QUEUE_SIZE, 2*CACHE_PROBATIONAL_QUEUE_SIZE) {
|
||||
@Override
|
||||
@NotNull
|
||||
public CacheValue<RandomAccessFileWrapper> createValue(final String path) {
|
||||
try {
|
||||
return new CacheValue<RandomAccessFileWrapper>(new RandomAccessFileWrapper(path)) {
|
||||
@Override
|
||||
protected void disposeAccessor(RandomAccessFileWrapper accessor) {
|
||||
try {
|
||||
accessor.close();
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private static final boolean useSingleFileDescriptor = SystemProperties.getBooleanProperty("idea.use.single.file.descriptor.for.persistent.hash.map", true);
|
||||
|
||||
private static final FileAccessorCache<DataOutputStream> ourAppendersCache = new FileAccessorCache<DataOutputStream>(CACHE_PROTECTED_QUEUE_SIZE, CACHE_PROBATIONAL_QUEUE_SIZE) {
|
||||
@Override
|
||||
@NotNull
|
||||
public CacheValue<DataOutputStream> createValue(String path) {
|
||||
try {
|
||||
return new CachedAppender(new DataOutputStream(new BufferedOutputStream(new FileOutputStream(path, true))));
|
||||
OutputStream out = useSingleFileDescriptor ? new OutputStreamOverRandomAccessFileCache(path):new FileOutputStream(path, true);
|
||||
return new CachedAppender(new DataOutputStream(new BufferedOutputStream(out)));
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
@@ -59,7 +87,8 @@ public class PersistentHashMapValueStorage {
|
||||
@Override
|
||||
@NotNull
|
||||
public CacheValue<RAReader> createValue(String path) {
|
||||
return new CachedReader(new FileReader(new File(path)));
|
||||
RAReader reader = useSingleFileDescriptor ? new ReaderOverRandomAccessFileCache(path) : new FileReader(new File(path));
|
||||
return new CachedReader(reader);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -70,6 +99,7 @@ public class PersistentHashMapValueStorage {
|
||||
|
||||
if (mySize == 0) {
|
||||
appendBytes(new ByteSequence("Header Record For PersistentHashMapValueStorage".getBytes()), 0);
|
||||
|
||||
// avoid corruption issue when disk fails to write first record synchronously, code depends on correct value of mySize (IDEA-106306)
|
||||
CacheValue<DataOutputStream> streamCacheValue = ourAppendersCache.getIfCached(myPath);
|
||||
if (streamCacheValue != null) {
|
||||
@@ -85,8 +115,10 @@ public class PersistentHashMapValueStorage {
|
||||
}
|
||||
|
||||
long currentLength = myFile.length();
|
||||
if (currentLength != mySize) Logger.getInstance(getClass().getName()).info("Avoided PSHM corruption due to write failure");
|
||||
mySize = currentLength; // volatile write
|
||||
if (currentLength > mySize) { // if real file length (unexpectedly) increases
|
||||
Logger.getInstance(getClass().getName()).info("Avoided PSHM corruption due to write failure");
|
||||
mySize = currentLength; // volatile write
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -400,6 +432,8 @@ public class PersistentHashMapValueStorage {
|
||||
ourReadersCache.remove(myPath);
|
||||
ourAppendersCache.remove(myPath);
|
||||
|
||||
ourRandomAccessFileCache.remove(myPath);
|
||||
|
||||
if (myCompactionModeReader != null) {
|
||||
myCompactionModeReader.dispose();
|
||||
myCompactionModeReader = null;
|
||||
@@ -408,6 +442,8 @@ public class PersistentHashMapValueStorage {
|
||||
|
||||
public void switchToCompactionMode() {
|
||||
ourReadersCache.remove(myPath);
|
||||
|
||||
ourRandomAccessFileCache.remove(myPath);
|
||||
// in compaction mode use faster reader
|
||||
myCompactionModeReader = new FileReader(myFile);
|
||||
myCompactionMode = true;
|
||||
@@ -422,6 +458,31 @@ public class PersistentHashMapValueStorage {
|
||||
void dispose();
|
||||
}
|
||||
|
||||
private static class ReaderOverRandomAccessFileCache implements RAReader {
|
||||
private String myPath;
|
||||
|
||||
private ReaderOverRandomAccessFileCache(String path) {
|
||||
myPath = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void get(final long addr, final byte[] dst, final int off, final int len) throws IOException {
|
||||
CacheValue<RandomAccessFileWrapper> fileAccessor = ourRandomAccessFileCache.get(myPath);
|
||||
|
||||
try {
|
||||
RandomAccessFileWrapper file = fileAccessor.get();
|
||||
file.seek(addr);
|
||||
file.read(dst, off, len);
|
||||
} finally {
|
||||
fileAccessor.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
}
|
||||
}
|
||||
|
||||
private static class FileReader implements RAReader {
|
||||
private final RandomAccessFile myFile;
|
||||
|
||||
@@ -542,4 +603,32 @@ public class PersistentHashMapValueStorage {
|
||||
|
||||
protected abstract void disposeAccessor(T accesor);
|
||||
}
|
||||
|
||||
private static class OutputStreamOverRandomAccessFileCache extends OutputStream {
|
||||
private final String myPath;
|
||||
|
||||
public OutputStreamOverRandomAccessFileCache(String path) throws IOException {
|
||||
myPath = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
CacheValue<RandomAccessFileWrapper> fileAccessor = ourRandomAccessFileCache.get(myPath);
|
||||
RandomAccessFileWrapper file = fileAccessor.get();
|
||||
|
||||
try {
|
||||
file.seek(file.length());
|
||||
file.write(b, off, len);
|
||||
}
|
||||
finally {
|
||||
fileAccessor.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
byte[] r = {(byte)(b & 0xFF)};
|
||||
write(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* 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.io;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.util.SystemProperties;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
|
||||
/**
|
||||
* Replacement of RandomAccessFile("rw") with shadow file pointer / size, valid when file manipulations happen in with this class only.
|
||||
* Note that sharing policy is the same as RandomAccessFile
|
||||
*/
|
||||
class RandomAccessFileWrapper extends RandomAccessFile {
|
||||
private static final Logger LOG = Logger.getInstance(RandomAccessFileWrapper.class.getName());
|
||||
private static final boolean doAssertions = SystemProperties.getBooleanProperty("idea.do.random.access.wrapper.assertions", false);
|
||||
|
||||
private final String myPath;
|
||||
private volatile long mySize;
|
||||
private volatile long myPointer;
|
||||
|
||||
public RandomAccessFileWrapper(String name) throws IOException {
|
||||
super(name, "rw");
|
||||
mySize = super.length();
|
||||
myPath = name;
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Inst:" + this + "," + Thread.currentThread() + "," + getClass().getClassLoader());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void seek(long pos) throws IOException {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Seek:" + this + "," + Thread.currentThread() + "," + pos + "," + myPointer + "," + mySize);
|
||||
}
|
||||
if (doAssertions) {
|
||||
checkSizeAndPointerAssertions();
|
||||
}
|
||||
if (myPointer == pos) {
|
||||
return;
|
||||
}
|
||||
super.seek(pos);
|
||||
myPointer = pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long length() throws IOException {
|
||||
if (doAssertions) {
|
||||
checkSizeAndPointerAssertions();
|
||||
}
|
||||
return mySize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
write(new byte[]{ (byte)(b & 0xFF)});
|
||||
}
|
||||
|
||||
private void checkSizeAndPointerAssertions() throws IOException {
|
||||
if (myPointer != super.getFilePointer()) {
|
||||
assert false;
|
||||
}
|
||||
if (mySize != super.length()) {
|
||||
assert false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b) throws IOException {
|
||||
write(b, 0, b.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("write:" + this + "," + Thread.currentThread() + "," + len + "," + myPointer + "," + mySize);
|
||||
}
|
||||
if (doAssertions) {
|
||||
checkSizeAndPointerAssertions();
|
||||
}
|
||||
|
||||
long pointer = myPointer;
|
||||
super.write(b, off, len);
|
||||
|
||||
if (pointer == 0) { // first write can introduce extra bytes, reload the position to avoid position tracking problem, e.g. IDEA-106306
|
||||
pointer = super.getFilePointer();
|
||||
} else {
|
||||
pointer += len;
|
||||
}
|
||||
myPointer = pointer;
|
||||
mySize = Math.max(pointer, mySize);
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("after write:" + this + "," + Thread.currentThread() + "," + myPointer + "," + mySize );
|
||||
}
|
||||
if (doAssertions) {
|
||||
checkSizeAndPointerAssertions();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLength(long newLength) throws IOException {
|
||||
if (doAssertions) {
|
||||
checkSizeAndPointerAssertions();
|
||||
}
|
||||
super.setLength(newLength);
|
||||
mySize = newLength;
|
||||
if (doAssertions) {
|
||||
checkSizeAndPointerAssertions();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("read:" + this + "," + Thread.currentThread() + "," + len + "," + myPointer );
|
||||
}
|
||||
if (doAssertions) {
|
||||
checkSizeAndPointerAssertions();
|
||||
}
|
||||
int read = super.read(b, off, len);
|
||||
if (read != -1) myPointer += read;
|
||||
if (doAssertions) {
|
||||
checkSizeAndPointerAssertions();
|
||||
}
|
||||
return read;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b) throws IOException {
|
||||
return read(b, 0, b.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
int read = super.read();
|
||||
++myPointer;
|
||||
if (doAssertions) {
|
||||
checkSizeAndPointerAssertions();
|
||||
}
|
||||
return read;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getFilePointer() throws IOException {
|
||||
if (doAssertions) {
|
||||
checkSizeAndPointerAssertions();
|
||||
}
|
||||
|
||||
return myPointer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int skipBytes(int n) throws IOException {
|
||||
int i = super.skipBytes(n);
|
||||
if (doAssertions) {
|
||||
checkSizeAndPointerAssertions();
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Closed:" + this + "," + Thread.currentThread() );
|
||||
}
|
||||
super.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return myPath + "@" + Integer.toHexString(hashCode());
|
||||
}
|
||||
}
|
||||
+12
-6
@@ -25,6 +25,7 @@ import com.intellij.cvsSupport2.cvsExecution.ModalityContext;
|
||||
import com.intellij.cvsSupport2.cvshandlers.CommandCvsHandler;
|
||||
import com.intellij.cvsSupport2.cvshandlers.CvsHandler;
|
||||
import com.intellij.cvsSupport2.ui.experts.checkout.CheckoutWizard;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.vcs.CheckoutProvider;
|
||||
@@ -74,14 +75,19 @@ public class CvsCheckoutProvider implements CheckoutProvider {
|
||||
|
||||
public void refreshAfterCheckout(final Listener listener, final CvsElement[] selectedElements, final File checkoutDirectory,
|
||||
final boolean useAlternateCheckoutPath) {
|
||||
|
||||
VirtualFileManager.getInstance().asyncRefresh(new Runnable() {
|
||||
public void run() {
|
||||
// shouldn't hold write action when calling this (IDEADEV-20086)
|
||||
for (CvsElement element : selectedElements) {
|
||||
final File path = useAlternateCheckoutPath ? checkoutDirectory : new File(checkoutDirectory, element.getCheckoutPath());
|
||||
listener.directoryCheckedOut(path, CvsVcs2.getKey());
|
||||
}
|
||||
listener.checkoutCompleted();
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (CvsElement element : selectedElements) {
|
||||
final File path = useAlternateCheckoutPath ? checkoutDirectory : new File(checkoutDirectory, element.getCheckoutPath());
|
||||
listener.directoryCheckedOut(path, CvsVcs2.getKey());
|
||||
}
|
||||
listener.checkoutCompleted();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user