Merge remote-tracking branch 'origin/master' into test2

This commit is contained in:
Ilya.Kazakevich
2014-12-04 21:50:31 +03:00
35 changed files with 516 additions and 44 deletions
@@ -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;
}
@@ -0,0 +1,9 @@
public class Foo {
void m() {
methodCall(.assert<caret>
}
boolean methodCall(String s) {
return null;
}
}
@@ -0,0 +1,9 @@
public class Foo {
void m() {
methodCall(.assert <caret>
}
boolean methodCall(String s) {
return null;
}
}
@@ -1,8 +1,8 @@
public class Foo {
void m() {
assert is();<caret>
is();.assert <caret>
}
boolean is() {
return false;
}
@@ -0,0 +1,9 @@
public class Foo {
void m() {
methodCall(.if<caret>
}
boolean methodCall(String s) {
return null;
}
}
@@ -0,0 +1,9 @@
public class Foo {
void m() {
methodCall(.if <caret>
}
boolean methodCall(String s) {
return null;
}
}
@@ -1,10 +1,8 @@
public class Foo {
void m() {
if (is()) {
<caret>
}
is();.if <caret>
}
boolean is() {
return false;
}
@@ -0,0 +1,5 @@
public class Foo {
Object m() {
new Object(.return<caret>
}
}
@@ -0,0 +1,5 @@
public class Foo {
Object m() {
new Object(.return <caret>
}
}
@@ -0,0 +1,9 @@
public class Foo {
String m() {
methodCall(.return<caret>
}
String methodCall(String s) {
return null;
}
}
@@ -0,0 +1,9 @@
public class Foo {
String m() {
methodCall("string".return<caret>
}
String methodCall(String s) {
return null;
}
}
@@ -0,0 +1,9 @@
public class Foo {
String m() {
methodCall("string".return <caret>
}
String methodCall(String s) {
return null;
}
}
@@ -0,0 +1,9 @@
public class Foo {
String m() {
methodCall(.return <caret>
}
String methodCall(String s) {
return null;
}
}
@@ -0,0 +1,9 @@
public class Foo {
String m() {
(methodCall("").return<caret>
}
String methodCall(String s) {
return null;
}
}
@@ -0,0 +1,9 @@
public class Foo {
String m() {
(methodCall("").return <caret>
}
String methodCall(String s) {
return null;
}
}
@@ -0,0 +1,9 @@
public class Foo {
void m() {
methodCall(.sout<caret>
}
String methodCall(String s) {
return null;
}
}
@@ -0,0 +1,9 @@
public class Foo {
void m() {
methodCall(.sout <caret>
}
String methodCall(String s) {
return null;
}
}
@@ -0,0 +1,11 @@
import java.lang.Exception;
public class Foo {
void m() {
methodCall(.throw<caret>
}
Exception methodCall(String s) {
return null;
}
}
@@ -0,0 +1,11 @@
import java.lang.Exception;
public class Foo {
void m() {
methodCall(.throw <caret>
}
Exception methodCall(String s) {
return null;
}
}
@@ -2,6 +2,6 @@ import java.lang.RuntimeException;
public class Foo {
void m() {
throw new RuntimeException("error");
new RuntimeException("error");.throw <caret>
}
}
@@ -0,0 +1,9 @@
public class Foo {
void m() {
methodCall(.while<caret>
}
boolean methodCall(String s) {
return null;
}
}
@@ -0,0 +1,9 @@
public class Foo {
void m() {
methodCall(.while <caret>
}
boolean methodCall(String s) {
return null;
}
}
@@ -71,5 +71,9 @@ public class AssertStatementPostfixTemplateTest extends PostfixTemplateTestCase
public void testSimpleWithSemicolon() {
doTest();
}
public void testIncompleteExpression() {
doTest();
}
}
@@ -69,5 +69,7 @@ public class IfStatementPostfixTemplateTest extends PostfixTemplateTestCase {
doTest();
}
public void testIncompleteExpression() {
doTest();
}
}
@@ -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();
}
}
@@ -31,4 +31,8 @@ public class SoutPostfixTemplateTest extends PostfixTemplateTestCase {
public void testVoid() {
doTest();
}
public void testIncompleteExpression() {
doTest();
}
}
@@ -37,4 +37,7 @@ public class ThrowStatementPostfixTemplateTest extends PostfixTemplateTestCase {
public void testSimpleWithSemicolon() {
doTest();
}
public void testIncompleteExpression() {
doTest();
}
}
@@ -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) {
@@ -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());
}
}
@@ -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();
}
});
}
});
}