Merge remote-tracking branch 'origin/master'

This commit is contained in:
Roman Shevchenko
2015-07-03 16:09:44 +03:00
108 changed files with 670 additions and 1702 deletions
+1 -1
View File
@@ -21,7 +21,7 @@
<intentionAction>
<className>org.intellij.lang.regexp.intention.CheckRegExpIntentionAction</className>
<category>Declaration</category>
<category>RegExp/Declaration</category>
</intentionAction>
</extensions>
</idea-plugin>
@@ -27,6 +27,7 @@ import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.ide.CopyPasteManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.util.IncorrectOperationException;
@@ -128,7 +129,8 @@ public class JavaFilePasteProvider implements PasteProvider {
private static PsiJavaFile createJavaFileFromClipboardContent(final Project project) {
String text = CopyPasteManager.getInstance().getContents(DataFlavor.stringFlavor);
if (text == null) return null;
PsiFile psiFile = PsiFileFactory.getInstance(project).createFileFromText("A.java", JavaLanguage.INSTANCE, text);
PsiFile psiFile = PsiFileFactory.getInstance(project).createFileFromText("A.java", JavaLanguage.INSTANCE,
StringUtil.convertLineSeparators(text));
return psiFile instanceof PsiJavaFile ? (PsiJavaFile)psiFile : null;
}
}
@@ -72,7 +72,6 @@ public class JavaLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSett
}
else if (settingsType == SettingsType.WRAPPING_AND_BRACES_SETTINGS) {
consumer.showStandardOptions("RIGHT_MARGIN",
"WRAP_ON_TYPING",
"KEEP_CONTROL_STATEMENT_IN_ONE_LINE",
"LINE_COMMENT_AT_FIRST_COLUMN",
"BLOCK_COMMENT_AT_FIRST_COLUMN",
@@ -412,7 +412,7 @@ public class ImportHelper{
useOnDemand = false;
}
// name of class we try to import is the same as of the class defined in this file
if (curRefClass != null) {
if (containsInCurrentFile(file, curRefClass)) {
useOnDemand = true;
}
// check conflicts
@@ -428,10 +428,9 @@ public class ImportHelper{
}
if (useOnDemand &&
curRefClass != null &&
refClass.getContainingClass() != null &&
mySettings.INSERT_INNER_CLASS_IMPORTS &&
"java.lang".equals(StringUtil.getPackageName(curRefClass.getQualifiedName()))) {
containsInCurrentFile(file, curRefClass)) {
return false;
}
@@ -465,6 +464,17 @@ public class ImportHelper{
return true;
}
private static boolean containsInCurrentFile(@NotNull PsiJavaFile file, PsiClass curRefClass) {
if (curRefClass != null) {
final String curRefClassQualifiedName = curRefClass.getQualifiedName();
if (curRefClassQualifiedName != null &&
ArrayUtil.find(file.getImplicitlyImportedPackages(), StringUtil.getPackageName(curRefClassQualifiedName)) < 0) {
return true;
}
}
return false;
}
private static void calcClassesToReimport(PsiJavaFile file, JavaPsiFacade facade, PsiResolveHelper helper, String packageName, List<PsiClass> classesToReimport,
Collection<String> onDemandRefs) {
if (onDemandRefs.isEmpty()) {
@@ -81,7 +81,7 @@ public class AllClassesSearchExecutor implements QueryExecutor<PsiClass, AllClas
final PsiShortNamesCache cache = PsiShortNamesCache.getInstance(project);
for (final String name : names) {
ProgressIndicatorProvider.checkCanceled();
final PsiClass[] classes = ApplicationManager.getApplication().runReadAction(new Computable<PsiClass[]>() {
final PsiClass[] classes = MethodUsagesSearcher.resolveInReadAction(project, new Computable<PsiClass[]>() {
@Override
public PsiClass[] compute() {
return cache.getClassesByName(name, scope);
@@ -97,21 +97,27 @@ public class AllClassesSearchExecutor implements QueryExecutor<PsiClass, AllClas
return true;
}
public static Project processClassNames(Project project, GlobalSearchScope scope, final Consumer<String> consumer) {
public static Project processClassNames(final Project project, final GlobalSearchScope scope, final Consumer<String> consumer) {
final ProgressIndicator indicator = ProgressIndicatorProvider.getGlobalProgressIndicator();
PsiShortNamesCache.getInstance(project).processAllClassNames(new Processor<String>() {
int i = 0;
MethodUsagesSearcher.resolveInReadAction(project, new Computable<Void>() {
@Override
public boolean process(String s) {
if (indicator != null && i++ % 512 == 0) {
indicator.checkCanceled();
}
consumer.consume(s);
return true;
public Void compute() {
PsiShortNamesCache.getInstance(project).processAllClassNames(new Processor<String>() {
int i = 0;
@Override
public boolean process(String s) {
if (indicator != null && i++ % 512 == 0) {
indicator.checkCanceled();
}
consumer.consume(s);
return true;
}
}, scope, IdFilter.getProjectIdFilter(project, true));
return null;
}
}, scope, IdFilter.getProjectIdFilter(project, true));
});
if (indicator != null) {
indicator.checkCanceled();
@@ -1262,13 +1262,12 @@ class ControlFlowAnalyzer extends JavaElementVisitor {
myStartStatementStack.pushStatement(expression.getRExpression() == null ? expression : expression.getRExpression(), false);
myEndStatementStack.pushStatement(expression.getRExpression() == null ? expression : expression.getRExpression(), false);
PsiExpression rExpr = expression.getRExpression();
if (rExpr != null) {
rExpr.accept(this);
}
PsiExpression lExpr = PsiUtil.skipParenthesizedExprDown(expression.getLExpression());
if (lExpr instanceof PsiReferenceExpression) {
PsiExpression rExpr = expression.getRExpression();
if (rExpr != null) {
rExpr.accept(this);
}
final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)lExpr;
PsiExpression qualifierExpression = referenceExpression.getQualifierExpression();
PsiVariable variable = getUsedVariable(referenceExpression);
@@ -1293,6 +1292,10 @@ class ControlFlowAnalyzer extends JavaElementVisitor {
}
else if (lExpr != null) {
lExpr.accept(this);
PsiExpression rExpr = expression.getRExpression();
if (rExpr != null) {
rExpr.accept(this);
}
}
myStartStatementStack.popStatement();
@@ -0,0 +1,7 @@
class Test {
public static void main(String[] args) {
int i;
int[] iA = {10,20};
iA[<error descr="Variable 'i' might not have been initialized">i</error>] = i = 30;
}
}
@@ -63,4 +63,8 @@ public class LightAdvHighlightingJdk6Test extends LightDaemonAnalyzerTestCase {
public void testAgentPremain() {
doTest(false, false);
}
public void testInitializedBeforeUsed() throws Exception {
doTest(false, false);
}
}
@@ -17,8 +17,11 @@ package com.intellij.codeInsight.intention
import com.intellij.lang.java.JavaLanguage;
import com.intellij.pom.java.LanguageLevel
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiFile
import com.intellij.psi.codeStyle.CodeStyleSettings
import com.intellij.psi.codeStyle.CodeStyleSettingsManager
import com.intellij.psi.impl.source.codeStyle.ImportHelper
import com.intellij.testFramework.IdeaTestUtil
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
@@ -74,7 +77,7 @@ public class Foo {
}
'''
importClass()
myFixture.checkResult '''import foo.*;
myFixture.checkResult '''import foo.StringValue;
public class Foo {
String<caret>Value sv;
@@ -462,25 +462,7 @@ public class FindManagerTest extends DaemonAnalyzerTestCase {
}
public void testReplaceWithRegExp() {
FindModel findModel = new FindModel();
findModel.setStringToFind("(?<!^) ");
findModel.setStringToReplace(" ");
findModel.setWholeWordsOnly(false);
findModel.setRegularExpressions(true);
findModel.setFromCursor(false);
findModel.setGlobal(true);
findModel.setMultipleFiles(false);
findModel.setProjectScope(false);
findModel.setPromptOnReplace(false);
myFindManager.setFindNextModel(null);
myFindManager.getFindInFileModel().copyFrom(findModel);
String text = "# Base";
configureByText(PlainTextFileType.INSTANCE, text);
assertTrue(FindUtil.replace(getProject(), getEditor(), 0, findModel));
assertEquals("# Base", getEditor().getDocument().getText());
doTestRegexpReplace("# Base", "(?<!^) ", " ", "# Base");
}
private void initProject(String folderName, final String... sourceDirs) {
@@ -9,15 +9,15 @@
<conversion.rule implementation="com.intellij.refactoring.typeMigration.rules.ThreadLocalConversionRule"/>
<intentionAction>
<className>com.intellij.refactoring.typeMigration.intentions.ConvertFieldToAtomicIntention</className>
<category>Concurrency</category>
<category>Java/Concurrency</category>
</intentionAction>
<intentionAction>
<className>com.intellij.refactoring.typeMigration.intentions.ConvertFieldToThreadLocalIntention</className>
<category>Concurrency</category>
<category>Java/Concurrency</category>
</intentionAction>
<intentionAction>
<className>com.intellij.refactoring.typeMigration.intentions.ChangeClassParametersIntention</className>
<category>Declaration</category>
<category>Java/Declaration</category>
</intentionAction>
</extensions>
</idea-plugin>
@@ -37,29 +37,14 @@ public class FileTypeAssocTable<T> {
private final Map<CharSequence, T> myExtensionMappings;
private final Map<CharSequence, T> myExactFileNameMappings;
private final Map<CharSequence, T> myExactFileNameAnyCaseMappings;
private boolean myHasAnyCaseExactMappings;
private final List<Pair<FileNameMatcher, T>> myMatchingMappings;
private FileTypeAssocTable(Map<CharSequence, T> extensionMappings, Map<CharSequence, T> exactFileNameMappings, Map<CharSequence, T> exactFileNameAnyCaseMappings, List<Pair<FileNameMatcher, T>> matchingMappings) {
private FileTypeAssocTable(@NotNull Map<CharSequence, T> extensionMappings, @NotNull Map<CharSequence, T> exactFileNameMappings, @NotNull Map<CharSequence, T> exactFileNameAnyCaseMappings, List<Pair<FileNameMatcher, T>> matchingMappings) {
myExtensionMappings = new THashMap<CharSequence, T>(extensionMappings, CharSequenceHashingStrategy.CASE_INSENSITIVE);
myExactFileNameMappings = new THashMap<CharSequence, T>(exactFileNameMappings, CharSequenceHashingStrategy.CASE_SENSITIVE);
myExactFileNameAnyCaseMappings = new THashMap<CharSequence, T>(exactFileNameAnyCaseMappings, CharSequenceHashingStrategy.CASE_INSENSITIVE) {
@Override
public T remove(Object key) {
T removed = super.remove(key);
myHasAnyCaseExactMappings = size() > 0;
return removed;
}
myExactFileNameAnyCaseMappings = new THashMap<CharSequence, T>(exactFileNameAnyCaseMappings, CharSequenceHashingStrategy.CASE_INSENSITIVE);
@Override
public T put(CharSequence key, T value) {
T result = super.put(key, value);
myHasAnyCaseExactMappings = true;
return result;
}
};
myMatchingMappings = new ArrayList<Pair<FileNameMatcher, T>>(matchingMappings);
}
@@ -67,7 +52,7 @@ public class FileTypeAssocTable<T> {
this(Collections.<CharSequence, T>emptyMap(), Collections.<CharSequence, T>emptyMap(), Collections.<CharSequence, T>emptyMap(), Collections.<Pair<FileNameMatcher, T>>emptyList());
}
public boolean isAssociatedWith(T type, FileNameMatcher matcher) {
public boolean isAssociatedWith(@NotNull T type, @NotNull FileNameMatcher matcher) {
if (matcher instanceof ExtensionFileNameMatcher || matcher instanceof ExactFileNameMatcher) {
return findAssociatedFileType(matcher) == type;
}
@@ -86,17 +71,15 @@ public class FileTypeAssocTable<T> {
else if (matcher instanceof ExactFileNameMatcher) {
final ExactFileNameMatcher exactFileNameMatcher = (ExactFileNameMatcher)matcher;
if (exactFileNameMatcher.isIgnoreCase()) {
myExactFileNameAnyCaseMappings.put(exactFileNameMatcher.getFileName(), type);
} else {
myExactFileNameMappings.put(exactFileNameMatcher.getFileName(), type);
}
} else {
Map<CharSequence, T> mapToUse = exactFileNameMatcher.isIgnoreCase() ? myExactFileNameAnyCaseMappings : myExactFileNameMappings;
mapToUse.put(exactFileNameMatcher.getFileName(), type);
}
else {
myMatchingMappings.add(Pair.create(matcher, type));
}
}
public boolean removeAssociation(FileNameMatcher matcher, T type) {
boolean removeAssociation(@NotNull FileNameMatcher matcher, @NotNull T type) {
if (matcher instanceof ExtensionFileNameMatcher) {
String extension = ((ExtensionFileNameMatcher)matcher).getExtension();
if (myExtensionMappings.get(extension) == type) {
@@ -108,14 +91,9 @@ public class FileTypeAssocTable<T> {
if (matcher instanceof ExactFileNameMatcher) {
final ExactFileNameMatcher exactFileNameMatcher = (ExactFileNameMatcher)matcher;
final Map<CharSequence, T> mapToUse;
String fileName = exactFileNameMatcher.getFileName();
if (exactFileNameMatcher.isIgnoreCase()) {
mapToUse = myExactFileNameAnyCaseMappings;
} else {
mapToUse = myExactFileNameMappings;
}
final Map<CharSequence, T> mapToUse = exactFileNameMatcher.isIgnoreCase() ? myExactFileNameAnyCaseMappings : myExactFileNameMappings;
if(mapToUse.get(fileName) == type) {
mapToUse.remove(fileName);
return true;
@@ -134,7 +112,7 @@ public class FileTypeAssocTable<T> {
return false;
}
public boolean removeAllAssociations(T type) {
boolean removeAllAssociations(@NotNull T type) {
boolean changed = removeAssociationsFromMap(myExtensionMappings, type, false);
changed = removeAssociationsFromMap(myExactFileNameAnyCaseMappings, type, changed);
@@ -151,7 +129,7 @@ public class FileTypeAssocTable<T> {
return changed;
}
private boolean removeAssociationsFromMap(Map<CharSequence, T> extensionMappings, T type, boolean changed) {
private boolean removeAssociationsFromMap(@NotNull Map<CharSequence, T> extensionMappings, @NotNull T type, boolean changed) {
Set<CharSequence> exts = extensionMappings.keySet();
CharSequence[] extsStrings = exts.toArray(new CharSequence[exts.size()]);
for (CharSequence s : extsStrings) {
@@ -165,16 +143,18 @@ public class FileTypeAssocTable<T> {
@Nullable
public T findAssociatedFileType(@NotNull @NonNls CharSequence fileName) {
T t = myExactFileNameMappings.get(fileName);
if (t != null) return t;
if (!myExactFileNameMappings.isEmpty()) {
T t = myExactFileNameMappings.get(fileName);
if (t != null) return t;
}
if (myHasAnyCaseExactMappings) { // even hash lookup with case insensitive hasher is costly for isIgnored checks during compile
t = myExactFileNameAnyCaseMappings.get(fileName);
if (!myExactFileNameAnyCaseMappings.isEmpty()) { // even hash lookup with case insensitive hasher is costly for isIgnored checks during compile
T t = myExactFileNameAnyCaseMappings.get(fileName);
if (t != null) return t;
}
//noinspection ForLoopReplaceableByForEach
for (int i = 0, n = myMatchingMappings.size(); i < n; i++) {
for (int i = 0; i < myMatchingMappings.size(); i++) {
final Pair<FileNameMatcher, T> mapping = myMatchingMappings.get(i);
if (FileNameMatcherEx.acceptsCharSequence(mapping.getFirst(), fileName)) return mapping.getSecond();
}
@@ -183,7 +163,7 @@ public class FileTypeAssocTable<T> {
}
@Nullable
public T findAssociatedFileType(final FileNameMatcher matcher) {
public T findAssociatedFileType(@NotNull FileNameMatcher matcher) {
if (matcher instanceof ExtensionFileNameMatcher) {
return myExtensionMappings.get(((ExtensionFileNameMatcher)matcher).getExtension());
}
@@ -191,11 +171,8 @@ public class FileTypeAssocTable<T> {
if (matcher instanceof ExactFileNameMatcher) {
final ExactFileNameMatcher exactFileNameMatcher = (ExactFileNameMatcher)matcher;
if (exactFileNameMatcher.isIgnoreCase()) {
return myExactFileNameAnyCaseMappings.get(exactFileNameMatcher.getFileName());
} else {
return myExactFileNameMappings.get(exactFileNameMatcher.getFileName());
}
Map<CharSequence, T> mapToUse = exactFileNameMatcher.isIgnoreCase() ? myExactFileNameAnyCaseMappings : myExactFileNameMappings;
return mapToUse.get(exactFileNameMatcher.getFileName());
}
for (Pair<FileNameMatcher, T> mapping : myMatchingMappings) {
@@ -207,13 +184,13 @@ public class FileTypeAssocTable<T> {
@Deprecated
@NotNull
public String[] getAssociatedExtensions(T type) {
public String[] getAssociatedExtensions(@NotNull T type) {
Map<CharSequence, T> extMap = myExtensionMappings;
List<String> exts = new ArrayList<String>();
for (CharSequence ext : extMap.keySet()) {
if (extMap.get(ext) == type) {
exts.add(ext.toString());
for (Map.Entry<CharSequence, T> entry : extMap.entrySet()) {
if (entry.getValue() == type) {
exts.add(entry.getKey().toString());
}
}
return ArrayUtil.toStringArray(exts);
@@ -284,8 +261,7 @@ public class FileTypeAssocTable<T> {
}
public int hashCode() {
int result;
result = myExtensionMappings.hashCode();
int result = myExtensionMappings.hashCode();
result = 31 * result + myMatchingMappings.hashCode();
result = 31 * result + myExactFileNameMappings.hashCode();
result = 31 * result + myExactFileNameAnyCaseMappings.hashCode();
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,6 +31,7 @@ public class IgnoredPatternSet {
private final Set<String> myMasks = new LinkedHashSet<String>();
private final FileTypeAssocTable<Boolean> myIgnorePatterns = new FileTypeAssocTable<Boolean>().copy();
@NotNull
Set<String> getIgnoreMasks() {
return Collections.unmodifiableSet(myMasks);
}
@@ -41,9 +42,7 @@ public class IgnoredPatternSet {
StringTokenizer tokenizer = new StringTokenizer(list, ";");
while (tokenizer.hasMoreTokens()) {
String ignoredFile = tokenizer.nextToken();
if (ignoredFile != null) {
addIgnoreMask(ignoredFile);
}
addIgnoreMask(ignoredFile);
}
}
@@ -64,7 +63,7 @@ public class IgnoredPatternSet {
return fileName.endsWith(FileUtil.ASYNC_DELETE_EXTENSION);
}
public void clearPatterns() {
void clearPatterns() {
myMasks.clear();
myIgnorePatterns.removeAllAssociations(Boolean.TRUE);
}
@@ -1,5 +1,6 @@
package org.jetbrains.ide
import com.intellij.testFramework.FixtureRule
import com.intellij.util.Consumer
import com.intellij.util.concurrency.Semaphore
import com.intellij.util.net.NetUtils
@@ -17,7 +18,6 @@ import org.jetbrains.io.ChannelExceptionHandler
import org.jetbrains.io.Decoder
import org.jetbrains.io.MessageDecoder
import org.jetbrains.io.NettyUtil
import org.jetbrains.testFramework.FixtureRule
import org.junit.Rule
import org.junit.Test
import org.junit.rules.RuleChain
@@ -2,10 +2,10 @@ package org.jetbrains.ide
import com.google.gson.stream.JsonWriter
import com.intellij.openapi.vfs.CharsetToolkit
import com.intellij.testFramework.FixtureRule
import io.netty.handler.codec.http.HttpResponseStatus
import org.hamcrest.CoreMatchers.equalTo
import org.jetbrains.ide.TestManager.TestDescriptor
import org.jetbrains.testFramework.FixtureRule
import org.junit.Assert.assertThat
import org.junit.Rule
import org.junit.Test
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,7 +29,7 @@ import org.jetbrains.annotations.Nullable;
public abstract class FileTypeRegistry {
public static Getter<FileTypeRegistry> ourInstanceGetter;
public abstract boolean isFileIgnored(@NonNls @NotNull VirtualFile file);
public abstract boolean isFileIgnored(@NotNull VirtualFile file);
public static FileTypeRegistry getInstance() {
return ourInstanceGetter.get();
@@ -86,7 +86,7 @@ public abstract class FileTypeRegistry {
* Finds a file type with the specified name.
*/
@Nullable
public abstract FileType findFileTypeByName(String fileTypeName);
public abstract FileType findFileTypeByName(@NotNull String fileTypeName);
/**
* Pluggable file type detector by content
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -70,7 +70,8 @@ public class PsiFileStubImpl<T extends PsiFile> extends StubBase<T> implements P
@NotNull
@Override
public PsiFileStub[] getStubRoots() {
return myStubRoots != null ? myStubRoots : new PsiFileStub[]{this};
PsiFileStub[] roots = myStubRoots;
return roots == null ? new PsiFileStub[]{this} : roots;
}
public void setStubRoots(@NotNull PsiFileStub[] roots) {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -43,7 +43,7 @@ public class CoreFileTypeRegistry extends FileTypeRegistry {
}
@Override
public boolean isFileIgnored(@NonNls @NotNull VirtualFile file) {
public boolean isFileIgnored(@NotNull VirtualFile file) {
return false;
}
@@ -93,7 +93,7 @@ public class CoreFileTypeRegistry extends FileTypeRegistry {
@Nullable
@Override
public FileType findFileTypeByName(String fileTypeName) {
public FileType findFileTypeByName(@NotNull String fileTypeName) {
for (FileType type : myAllFileTypes) {
if (type.getName().equals(fileTypeName)) {
return type;
@@ -1,705 +0,0 @@
/*
* 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.openapi.editor.impl;
import com.intellij.diagnostic.Dumpable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.impl.ApplicationInfoImpl;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.LocalTimeCounter;
import com.intellij.util.text.CharArrayCharSequence;
import com.intellij.util.text.CharArrayUtil;
import com.intellij.util.text.CharSequenceBackedByArray;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author cdr
*/
abstract class CharArray implements CharSequenceBackedByArray, Dumpable {
private static final boolean CHECK_DOCUMENT_CONSISTENCY = ApplicationManager.getApplication() != null && ApplicationManager.getApplication().isUnitTestMode();
private static final Logger LOG = Logger.getInstance("#" + CharArray.class.getName());
@SuppressWarnings("UseOfArchaicSystemPropertyAccessors")
private static final boolean DISABLE_DEFERRED_PROCESSING = Boolean.getBoolean("idea.document.deny.deferred.changes");
@SuppressWarnings("UseOfArchaicSystemPropertyAccessors")
private static final boolean DEBUG_DEFERRED_PROCESSING = LOG.isDebugEnabled() || Boolean.getBoolean("idea.document.debug.bulk.processing");
/**
* We can't exclude possibility of situation when <code>'defer changes'</code> state is {@link #setDeferredChangeMode(boolean) entered}
* but not exited, hence, we want to perform automatic flushing if necessary in order to avoid memory leaks. This constant holds
* a value that defines that 'automatic flushing' criteria, i.e. every time number of stored deferred changes exceeds this value,
* they are automatically flushed.
*/
private static final int MAX_DEFERRED_CHANGES_NUMBER = 10000;
private final TextChangesStorage myDeferredChangesStorage;
private volatile int myStart; // start offset in myArray (used as an optimization when call substring())
private volatile int myCount;
private volatile CharSequence myOriginalSequence;
private volatile char[] myArray;
private volatile Reference<String> myStringRef; // buffers String value - for not to generate it every time
private volatile int myBufferSize;
private volatile int myDeferredShift;
private volatile boolean myDeferredChangeMode;
private volatile boolean myHasDeferredChanges;
// this lock is for mutual exclusion during read action access
// (some fields are changed in read action too)
private final Object lock = new String("myOriginalSequence");
// We had a problems with bulk document text processing, hence, debug facilities were introduced. The fields group below work with them.
// The main idea is to hold all history of bulk processing iteration in order to be able to retrieve it from client and reproduce the
// problem.
private final boolean myDebug = isDebug();
boolean isDebug() {
return DEBUG_DEFERRED_PROCESSING || CHECK_DOCUMENT_CONSISTENCY && !ApplicationInfoImpl.isInPerformanceTest();
}
/**
* Duplicate instance of the current char array that is used during debug processing as follows - apply every text change
* from the bulk changes group to this instance immediately in order to be able to check if the current 'deferred change-aware'
* instance functionally behaves at the same way as 'straightforward' one.
*/
private CharArray myDebugArray;
/**
* Holds deferred changes create during the current bulk processing iteration.
*/
private List<TextChangeImpl> myDebugDeferredChanges;
/**
* Document text on bulk processing start.
*/
private String myDebugTextOnBatchUpdateStart;
// bufferSize == 0 means unbounded
CharArray(final int bufferSize, @NotNull char[] data, int length) {
myBufferSize = bufferSize;
myDeferredChangesStorage = new TextChangesStorage();
myArray = Arrays.copyOf(data, length);
myCount = length;
if (myDebug) {
myDebugArray = new CharArray(bufferSize, data, length) {
@NotNull
@Override
protected DocumentEvent beforeChangedUpdate(int offset,
CharSequence oldString,
CharSequence newString,
boolean wholeTextReplaced) {
return CharArray.this.beforeChangedUpdate(offset, oldString, newString, wholeTextReplaced);
}
@Override
protected void afterChangedUpdate(@NotNull DocumentEvent event, long newModificationStamp) {
}
@Override
protected void assertWriteAccess() {
}
@Override
protected void assertReadAccess() {
}
@Override
boolean isDebug() {
return false;
}
};
myDebugDeferredChanges = new ArrayList<TextChangeImpl>();
}
assertConsistency();
}
public void setBufferSize(int bufferSize) {
assert bufferSize >= 0 : bufferSize;
myBufferSize = bufferSize;
assertConsistency();
}
private DocumentEvent startChange(int offset,
@Nullable CharSequence oldString,
@Nullable CharSequence newString,
boolean wholeTextReplaced) {
assert myStart == 0; // can't change substring
assertWriteAccess();
assertConsistency();
return beforeChangedUpdate(offset, oldString, newString, wholeTextReplaced);
}
@NotNull
protected abstract DocumentEvent beforeChangedUpdate(int offset,
@Nullable CharSequence oldString,
@Nullable CharSequence newString,
boolean wholeTextReplaced);
protected abstract void afterChangedUpdate(@NotNull DocumentEvent event, long newModificationStamp);
protected abstract void assertWriteAccess();
protected abstract void assertReadAccess();
private void setText(@NotNull CharSequence chars) {
assertConsistency();
myOriginalSequence = chars.toString();
myArray = null;
myStringRef = null;
myCount = chars.length();
assert myStart == 0; // can't change substring
myDeferredChangesStorage.clear();
myHasDeferredChanges = false;
trimToSize();
if (myDebug) {
myDebugArray.setText(chars);
myDebugDeferredChanges.clear();
}
assertConsistency();
}
private void assertConsistency() {
if (isDeferredChangeMode()) {
assert myOriginalSequence == null;
}
CharSequence originalSequence = myOriginalSequence;
int origLen = originalSequence == null ? -1 : originalSequence.length();
String string = com.intellij.reference.SoftReference.dereference(myStringRef);
int stringLen = string == null ? -1 : string.length();
assert origLen == stringLen || origLen==-1 || stringLen==-1;
int count = myCount + myDeferredShift;
assert count == origLen || origLen==-1;
assert count == stringLen || stringLen==-1;
if (!myDebug) return;
final CharSequence seqFromCharArray;
if (myArray != null) {
assert myCount <= myArray.length;
seqFromCharArray = new CharArrayCharSequence(myArray, myStart, myCount);
}
else {
seqFromCharArray = null;
}
if (seqFromCharArray != null && originalSequence != null) {
assert StringUtil.equals(seqFromCharArray, originalSequence);
}
if (!isDeferredChangeMode() && seqFromCharArray != null && string != null) {
assert StringUtil.equals(seqFromCharArray, string);
}
if (originalSequence != null && string != null) {
assert string.equals(originalSequence.toString());
}
myDebugArray.assertConsistency();
CharSequence str = com.intellij.reference.SoftReference.dereference(myStringRef);
if (str == null) {
if (myHasDeferredChanges) {
str = doSubString(0, myCount + myDeferredShift).toString();
}
else if (myOriginalSequence != null) {
str = myOriginalSequence.toString();
}
else {
str = seqFromCharArray;
}
}
assert count == str.length();
if (isDeferredChangeMode()) {
String expected = myDebugArray.toString();
checkStrings("toString()", expected, str);
}
}
public void replace(int startOffset,
int endOffset,
@NotNull CharSequence toDelete,
@NotNull CharSequence newString,
long newModificationStamp,
boolean wholeTextReplaced) {
final DocumentEvent event = startChange(startOffset, toDelete, newString, wholeTextReplaced);
startOffset += myStart;
endOffset += myStart;
doReplace(startOffset, endOffset, newString);
afterChangedUpdate(event, newModificationStamp);
assertConsistency();
}
private void doReplace(int startOffset, int endOffset, @NotNull CharSequence newString) {
prepareForModification();
if (isDeferredChangeMode()) {
storeChange(new TextChangeImpl(newString, startOffset, endOffset));
if (myDebug) {
myDebugArray.doReplace(startOffset, endOffset, newString);
}
}
else {
int newLength = newString.length();
int oldLength = endOffset - startOffset;
CharArrayUtil.getChars(newString, myArray, startOffset, Math.min(newLength, oldLength));
myStringRef = null;
if (newLength > oldLength) {
doInsert(newString.subSequence(oldLength, newLength), endOffset);
}
else if (newLength < oldLength) {
doRemove(startOffset + newLength, startOffset + oldLength);
}
}
}
public void remove(int startIndex, int endIndex, @NotNull CharSequence toDelete) {
DocumentEvent event = startChange(startIndex, toDelete, null, false);
startIndex += myStart;
endIndex += myStart;
doRemove(startIndex, endIndex);
afterChangedUpdate(event, LocalTimeCounter.currentTime());
assertConsistency();
}
private void doRemove(int startIndex, int endIndex) {
if (startIndex == endIndex) {
return;
}
prepareForModification();
if (isDeferredChangeMode()) {
storeChange(new TextChangeImpl("", startIndex, endIndex));
if (myDebug) {
myDebugArray.doRemove(startIndex, endIndex);
}
}
else {
if (endIndex < myCount) {
System.arraycopy(myArray, endIndex, myArray, startIndex, myCount - endIndex);
myStringRef = null;
}
myCount -= endIndex - startIndex;
}
}
public void insert(@NotNull CharSequence s, int startIndex) {
DocumentEvent event = startChange(startIndex, null, s, false);
startIndex += myStart;
doInsert(s, startIndex);
afterChangedUpdate(event, LocalTimeCounter.currentTime());
trimToSize();
assertConsistency();
}
private void doInsert(@NotNull CharSequence s, final int startIndex) {
prepareForModification();
if (isDeferredChangeMode()) {
storeChange(new TextChangeImpl(s, startIndex));
if (myDebug) {
myDebugArray.doInsert(s, startIndex);
}
}
else {
int insertLength = s.length();
myArray = resizeArray(myArray, myCount + insertLength);
if (startIndex < myCount) {
System.arraycopy(myArray, startIndex, myArray, startIndex + insertLength, myCount - startIndex);
}
CharArrayUtil.getChars(s, myArray, startIndex);
myCount += insertLength;
myStringRef = null;
}
}
/**
* Stores given change at collection of deferred changes (merging it with others if necessary) and updates current object
* state ({@link #length() length} etc).
*
* @param change new change to store
*/
private void storeChange(@NotNull TextChangeImpl change) {
if (!change.isWithinBounds(length())) {
LOG.error(
"Invalid change attempt detected - given change bounds are not within the current char array. Change: " +
change.getText().length()+":" + change.getStart()+"-" + change.getEnd(), dumpState());
return;
}
if (myDeferredChangesStorage.size() >= MAX_DEFERRED_CHANGES_NUMBER) {
flushDeferredChanged();
}
myDeferredChangesStorage.store(change);
myHasDeferredChanges = true;
myDeferredShift += change.getDiff();
if (myDebug) {
myDebugDeferredChanges.add(change);
}
}
private void prepareForModification() {
if (myOriginalSequence != null) {
myArray = new char[myOriginalSequence.length()];
CharArrayUtil.getChars(myOriginalSequence, myArray, 0);
myCount = myArray.length;
myOriginalSequence = null;
myStart = 0;
}
myStringRef = null;
assertConsistency();
}
@NotNull
public CharSequence getCharArray() {
assertConsistency();
CharSequence originalSequence = myOriginalSequence;
return originalSequence == null ? this : originalSequence;
}
@Override
@NotNull
public String toString() {
assertConsistency();
String str = com.intellij.reference.SoftReference.dereference(myStringRef);
if (str == null) {
if (myHasDeferredChanges) {
str = substring(0, length()).toString();
}
else {
str = myOriginalSequence == null ? new String(myArray, myStart, myCount) : myOriginalSequence.toString();
}
myStringRef = new SoftReference<String>(str);
}
return str;
}
@Override
public final int length() {
final int result = myCount + myDeferredShift;
if (myDebug && isDeferredChangeMode()) {
int expected = myDebugArray.length();
if (expected != result) {
dumpDebugInfo("Incorrect length() processing. Expected: '" + expected + "', actual: '" + result + "'");
}
}
return result;
}
@Override
public final char charAt(int i) {
if (i < 0 || i >= length()) {
throw new IndexOutOfBoundsException("Wrong offset: " + i + "; count:" + length());
}
i += myStart;
final char result;
if (!myHasDeferredChanges) {
if (myOriginalSequence != null) {
result = myOriginalSequence.charAt(i);
}
else {
result = myArray[i];
}
}
else {
result = myDeferredChangesStorage.charAt(myArray, i);
}
if (myDebug && isDeferredChangeMode()) {
char expected = myDebugArray.charAt(i);
if (expected != result) {
dumpDebugInfo("Incorrect charAt() processing for index " + i + ". Expected: '" + expected + "', actual: '" + result + "'");
}
}
return result;
}
@Override
@NotNull
public CharSequence subSequence(final int start, final int end) {
assertReadAccess();
assertConsistency();
if (start == 0 && end == length()) return this;
if (myOriginalSequence != null) {
return myOriginalSequence.subSequence(start, end);
}
flushDeferredChanged();
return new CharArrayCharSequence(myArray, start, end);
}
@Override
@NotNull
public char[] getChars() {
assertReadAccess();
assertConsistency();
char[] array = myArray;
CharSequence originalSequence = myOriginalSequence;
if (myHasDeferredChanges || originalSequence != null && array == null) {
// slow track
synchronized (lock) {
flushDeferredChanged();
array = myArray;
originalSequence = myOriginalSequence;
if (originalSequence != null && array == null) {
myArray = array = CharArrayUtil.fromSequence(originalSequence);
myStringRef = null;
}
}
assertConsistency();
}
return array;
}
@Override
public void getChars(@NotNull final char[] dst, final int dstOffset) {
assertReadAccess();
assertConsistency();
flushDeferredChanged();
if (myOriginalSequence == null) {
System.arraycopy(myArray, myStart, dst, dstOffset, length());
}
else {
CharArrayUtil.getChars(myOriginalSequence, dst, dstOffset);
}
if (myDebug && isDeferredChangeMode()) {
char[] expected = new char[dst.length];
myDebugArray.getChars(expected, dstOffset);
for (int i = dstOffset, j = myStart; i < dst.length && j < myArray.length; i++, j++) {
if (expected[i] != myArray[j]) {
dumpDebugInfo("getChars(char[], int). Given array of length " + dst.length + ", offset " + dstOffset + ". Found char '" + myArray[j] +
"' at index " + i + ", expected to find '" + expected[i] + "'");
break;
}
}
}
}
@NotNull
public CharSequence substring(final int start, final int end) {
assertReadAccess();
final CharSequence result = doSubString(start, end);
assertConsistency();
return result;
}
private CharSequence doSubString(int start, int end) {
if (start == end) return "";
final CharSequence result;
if (myOriginalSequence == null) {
result = myDeferredChangesStorage.substring(myArray, start + myStart, end + myStart);
}
else {
result = myOriginalSequence.subSequence(start, end);
}
return result;
}
@NotNull
private static char[] resizeArray(@NotNull char[] array, int newSize) {
if (newSize < array.length) {
return array;
}
int newArraySize = array.length;
if (newArraySize == 0) {
newArraySize = 16;
}
while (newArraySize <= newSize) {
newArraySize = newArraySize * 12 / 10 + 1;
}
char[] newArray = new char[newArraySize];
System.arraycopy(array, 0, newArray, 0, array.length);
return newArray;
}
private void trimToSize() {
if (myBufferSize != 0 && length() > myBufferSize) {
flushDeferredChanged();
// make a copy
int endIndex = myCount - myBufferSize;
String toDelete = getCharArray().subSequence(0, endIndex).toString();
remove(0, endIndex, toDelete);
}
}
/**
* @return <code>true</code> if this object is in the defer changes mode, see {@link #setDeferredChangeMode(boolean)};
*/
public boolean isDeferredChangeMode() {
return myDeferredChangeMode;
}
public boolean hasDeferredChanges() {
return myHasDeferredChanges;
}
/**
* There is a possible case that client of this class wants to perform great number of modifications in a short amount of time
* (e.g. end-user performs formatting of the document backed by the object of the current class). It may result in significant
* performance degradation is the changes are performed one by one (every time the change is applied tail content is shifted to
* the left or right). So, we may want to optimize that by avoiding actual array modification until information about
* all target changes is provided and perform array data moves only after that.
* <p/>
* This method allows to define that <code>'defer changes'</code> mode usages, i.e. expected usage pattern is as follows:
* <pre>
* <ol>
* <li>
* Client of this class enters <code>'defer changes'</code> mode (calls this method with <code>'true'</code> argument).
* That means that all subsequent changes will not actually modify backed array data and will be stored separately;
* </li>
* <li>
* Number of target changes are applied to the current object via standard API
* ({@link #insert(CharSequence, int) insert},
* {@link #remove(int, int, CharSequence) remove} and
* {@link #replace(int, int, java.lang.CharSequence, java.lang.CharSequence, long, boolean)});
* </li>
* <li>
* Client of this class indicates that <code>'massive change time'</code> is over by calling this method with <code>'false'</code>
* argument. That flushes all deferred changes (if any) to the backed data array and makes every subsequent change to
* be immediate flushed to the backed array;
* </li>
* </ol>
* </pre>
* <p/>
* <b>Note:</b> we can't exclude possibility that <code>'defer changes'</code> mode is started but inadvertently not ended
* (due to programming error, unexpected exception etc). Hence, this class is free to automatically end
* <code>'defer changes'</code> mode when necessary in order to avoid memory leak with infinite deferred changes storing.
*
* @param deferredChangeMode flag that defines if <code>'defer changes'</code> mode should be used by the current object
*/
public void setDeferredChangeMode(boolean deferredChangeMode) {
if (!DISABLE_DEFERRED_PROCESSING) {
if (deferredChangeMode) {
if (myDebug) {
myDebugArray.setText(myDebugTextOnBatchUpdateStart = toString());
myDebugDeferredChanges.clear();
}
prepareForModification();
}
else {
flushDeferredChanged();
}
myDeferredChangeMode = deferredChangeMode;
}
assertConsistency();
}
private void flushDeferredChanged() {
List<TextChangeImpl> changes = myDeferredChangesStorage.getChanges();
if (changes.isEmpty()) {
return;
}
synchronized (lock) {
char[] beforeMerge = null;
if (myDebug) {
beforeMerge = new char[myArray.length];
System.arraycopy(myArray, 0, beforeMerge, 0, myArray.length);
}
BulkChangesMerger changesMerger = BulkChangesMerger.INSTANCE;
final boolean inPlace;
if (myArray.length < length()) {
myArray = changesMerger.mergeToCharArray(myArray, myCount, changes);
inPlace = false;
}
else {
changesMerger.mergeInPlace(myArray, myCount, changes);
inPlace = true;
}
myCount += myDeferredShift;
myDeferredShift = 0;
myDeferredChangesStorage.clear();
myHasDeferredChanges = false;
myDeferredChangeMode = false;
myStringRef = null;
if (myDebug) {
for (int i = 0, max = length(); i < max; i++) {
if (myArray[i] != myDebugArray.myArray[i]) {
dumpDebugInfo("flushDeferredChanged(). Index " + i + ", expected: '" + myDebugArray.myArray[i]+"', actual '" +
myArray[i]+"'. Text before merge: '" + Arrays.toString(beforeMerge)+"', merge inplace: "+inPlace);
break;
}
}
}
}
assertConsistency();
}
@Override
@NonNls
@NotNull
public String dumpState() {
return "deferred changes mode: " + isDeferredChangeMode()+", length: " + length()+" (data array length: " + myCount+
", deferred shift: " + myDeferredShift+"); view offsets: [" + myStart+"; "+myCount+"]; deferred changes: "+myDeferredChangesStorage;
}
private void checkStrings(@NonNls @NotNull String operation, @NotNull String expected, @NotNull CharSequence actual) {
if (StringUtil.equals(expected, actual)) {
return;
}
for (int i = 0, max = Math.min(expected.length(), actual.length()); i < max; i++) {
if (actual.charAt(i) != expected.charAt(i)) {
dumpDebugInfo(
"Incorrect " +
operation+" processing. Expected length: " +
expected.length()+", actual length: " +
actual.length()+". Unmatched symbol at " +
i+" - expected: '" +
expected.charAt(i)+"', " +
"actual: '" +
actual.charAt(i)+"', expected document: '" +
expected+"', actual document: '" +
actual+"'"
);
return;
}
}
dumpDebugInfo("Incorrect " + operation+" processing. Expected length: " + expected.length()+", actual length: " +
actual.length()+", expected: '" + expected+"', actual: '" + actual+"'");
}
private void dumpDebugInfo(@NonNls @NotNull String problem) {
LOG.error(
"Incorrect CharArray processing detected: " + problem +
". Start: " + myStart
+ ", count: " + myCount + ", text on batch update start: " +
myDebugTextOnBatchUpdateStart + ", deferred changes history: " +
myDebugDeferredChanges + ", current deferred changes: " + myDeferredChangesStorage
);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -68,7 +68,7 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF
protected IElementType myContentElementType;
private long myModificationStamp;
protected PsiFile myOriginalFile = null;
protected PsiFile myOriginalFile;
private final FileViewProvider myViewProvider;
private volatile Reference<StubTree> myStub;
private boolean myInvalidated;
@@ -555,7 +555,7 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF
}
private static final Comparator<PsiFile> FILE_BY_LANGUAGE_ID = new Comparator<PsiFile>() {
@Override
public int compare(PsiFile o1, PsiFile o2) {
public int compare(@NotNull PsiFile o1, @NotNull PsiFile o2) {
return o1.getLanguage().getID().compareTo(o2.getLanguage().getID());
}
};
@@ -944,14 +944,18 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF
return this == another;
}
private static final Key<SoftReference<StubTree>> STUB_TREE_IN_PARSED_TREE = Key.create("STUB_TREE_IN_PARSED_TREE");
private static final Key<Reference<StubTree>> STUB_TREE_IN_PARSED_TREE = Key.create("STUB_TREE_IN_PARSED_TREE");
private final Object myStubFromTreeLock = new Object();
@NotNull
public StubTree calcStubTree() {
FileElement fileElement = calcTreeElement();
StubTree tree = SoftReference.dereference(fileElement.getUserData(STUB_TREE_IN_PARSED_TREE));
if (tree != null) {
return tree;
}
synchronized (myStubFromTreeLock) {
SoftReference<StubTree> ref = fileElement.getUserData(STUB_TREE_IN_PARSED_TREE);
StubTree tree = SoftReference.dereference(ref);
tree = SoftReference.dereference(fileElement.getUserData(STUB_TREE_IN_PARSED_TREE));
if (tree == null) {
ApplicationManager.getApplication().assertReadAccessAllowed();
@@ -346,8 +346,8 @@ public class UnifiedDiffViewer extends ListenerDiffViewerBase {
EditorHighlighter highlighter2 = DiffUtil.initEditorHighlighter(project, content2, text2);
if (highlighter1 == null && highlighter2 == null) return null;
if (highlighter1 == null) highlighter1 = DiffUtil.initEmptyEditorHighlighter(project, text1);
if (highlighter2 == null) highlighter2 = DiffUtil.initEmptyEditorHighlighter(project, text2);
if (highlighter1 == null) highlighter1 = DiffUtil.initEmptyEditorHighlighter(text1);
if (highlighter2 == null) highlighter2 = DiffUtil.initEmptyEditorHighlighter(text2);
return new UnifiedEditorHighlighter(myDocument, highlighter1, highlighter2, ranges, textLength);
}
@@ -107,7 +107,7 @@ public class DiffUtil {
}
@NotNull
public static EditorHighlighter initEmptyEditorHighlighter(@Nullable Project project, @NotNull CharSequence text) {
public static EditorHighlighter initEmptyEditorHighlighter(@NotNull CharSequence text) {
EditorHighlighter highlighter = createEmptyEditorHighlighter();
highlighter.setText(text);
return highlighter;
@@ -216,10 +216,6 @@ public class DiffUtil {
scrollToCaret(editor, animated);
}
public static void scrollToPoint(@Nullable Editor editor, @NotNull Point point) {
scrollToPoint(editor, point, false);
}
public static void scrollToPoint(@Nullable Editor editor, @NotNull Point point, boolean animated) {
if (editor == null) return;
if (!animated) editor.getScrollingModel().disableAnimation();
@@ -876,14 +872,6 @@ public class DiffUtil {
return holder;
}
public static <T> UserDataHolderBase createUserDataHolder(@NotNull Key<T> key1, @Nullable T value1,
@NotNull Key<T> key2, @Nullable T value2) {
UserDataHolderBase holder = new UserDataHolderBase();
holder.putUserData(key1, value1);
holder.putUserData(key2, value2);
return holder;
}
public static boolean isUserDataFlagSet(@NotNull Key<Boolean> key, UserDataHolder... holders) {
for (UserDataHolder holder : holders) {
if (holder == null) continue;
@@ -1039,9 +1027,5 @@ public class DiffUtil {
this(ignorePolicy.getComparisonPolicy(), highlightPolicy.isFineFragments(), highlightPolicy.isShouldSquash(),
ignorePolicy.isShouldTrimChunks());
}
public DiffConfig() {
this(IgnorePolicy.DEFAULT, HighlightPolicy.BY_LINE);
}
}
}
@@ -161,6 +161,20 @@ public interface RunnerAndConfigurationSettings {
*/
boolean isEditBeforeRun();
/**
* Sets the "Before launch: Activate tool window" flag (for activation tool window Run/Debug etc.)
*
* @param b if true, the tool window will be activated before launching this configuration.
*/
void setActivateToolWindowBeforeRun(boolean activate);
/**
* Returns the "Before launch: Activate tool window" flag (for activation tool window Run/Debug etc.)
*
* @return if true (it's default value), the tool window will be activated before launching this configuration.
*/
boolean isActivateToolWindowBeforeRun();
/**
* Sets the "Single instance only" flag (meaning that only one instance of this run configuration can be run at the same time).
*
@@ -16,10 +16,7 @@
package com.intellij.execution.runners;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.ExecutionResult;
import com.intellij.execution.Executor;
import com.intellij.execution.RunManager;
import com.intellij.execution.*;
import com.intellij.execution.configurations.*;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.openapi.options.SettingsEditor;
@@ -72,6 +69,10 @@ abstract class BaseProgramRunner<Settings extends RunnerSettings> implements Pro
static RunContentDescriptor postProcess(@NotNull ExecutionEnvironment environment, @Nullable RunContentDescriptor descriptor, @Nullable Callback callback) {
if (descriptor != null) {
descriptor.setExecutionId(environment.getExecutionId());
RunnerAndConfigurationSettings settings = environment.getRunnerAndConfigurationSettings();
if (settings != null) {
descriptor.setActivateToolWindowWhenAdded(settings.isActivateToolWindowBeforeRun());
}
}
if (callback != null) {
callback.processStarted(descriptor);
@@ -266,11 +266,6 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
*/
@Deprecated
public int RIGHT_MARGIN = 120;
/**
* @deprecated Use isWrapOnTyping(Language) instead or setWrapOnTyping(Language,boolean) for testing purposes.
* @see #isWrapOnTyping(Language)
* @see #setWrapOnTyping(Language, boolean)
*/
public boolean WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN = false;
@@ -962,35 +957,4 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
public void setDefaultRightMargin(int rightMargin) {
RIGHT_MARGIN = rightMargin;
}
/**
* Defines whether or not wrapping should occur when typing reaches right margin.
* @param language The language to check the option for or null for a global option.
* @return True if wrapping on right margin is enabled.
*/
public boolean isWrapOnTyping(@Nullable Language language) {
if (language != null) {
CommonCodeStyleSettings langSettings = getCommonSettings(language);
if (langSettings != null) {
if (langSettings.WRAP_ON_TYPING != WrapOnTyping.UNDEFINED.intValue) {
return langSettings.WRAP_ON_TYPING == WrapOnTyping.WRAP.intValue;
}
}
}
//noinspection deprecation
return WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN;
}
@TestOnly
public void setWrapOnTyping(@Nullable Language language, boolean wrapOnTyping) {
if (language != null) {
CommonCodeStyleSettings langSettings = getCommonSettings(language);
if (langSettings != null) {
langSettings.WRAP_ON_TYPING = wrapOnTyping ? WrapOnTyping.WRAP.intValue : WrapOnTyping.NO_WRAP.intValue;
return;
}
}
//noinspection deprecation
WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN = wrapOnTyping;
}
}
@@ -113,7 +113,6 @@ public interface CodeStyleSettingsCustomizable {
enum WrappingOrBraceOption {
RIGHT_MARGIN,
WRAP_ON_TYPING,
KEEP_CONTROL_STATEMENT_IN_ONE_LINE,
LINE_COMMENT_AT_FIRST_COLUMN,
BLOCK_COMMENT_AT_FIRST_COLUMN,
@@ -890,24 +890,6 @@ public class CommonCodeStyleSettings {
public int FORCE_REARRANGE_MODE = REARRANGE_ACCORDIND_TO_DIALOG;
public enum WrapOnTyping {
UNDEFINED (-1),
NO_WRAP (0),
WRAP (1);
public int intValue;
WrapOnTyping(int i) {
this.intValue = i;
}
}
/**
* Defines if wrapping should occur when typing reaches right margin. <b>Do not refer to this field directly, use
* <code>CodeStyleSettings.isWrapOnTyping(Language)</code> method instead</b>.
* @see CodeStyleSettings#isWrapOnTyping(Language)
*/
public int WRAP_ON_TYPING = WrapOnTyping.UNDEFINED.intValue;
//-------------------------Indent options-------------------------------------------------
public static class IndentOptions implements JDOMExternalizable, Cloneable {
@@ -158,7 +158,6 @@ public class GeneralCodeStylePanel extends CodeStyleAbstractPanel {
settings.LINE_SEPARATOR = getSelectedLineSeparator();
settings.setDefaultRightMargin(((Number) myRightMarginSpinner.getValue()).intValue());
//noinspection deprecation
settings.WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN = myCbWrapWhenTypingReachesRightMargin.isSelected();
myIndentOptionsEditor.setEnabled(true);
myIndentOptionsEditor.apply(settings, settings.OTHER_INDENT_OPTIONS);
@@ -224,7 +223,6 @@ public class GeneralCodeStylePanel extends CodeStyleAbstractPanel {
return true;
}
//noinspection deprecation
if (settings.WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN ^ myCbWrapWhenTypingReachesRightMargin.isSelected()) {
return true;
}
@@ -281,7 +279,6 @@ public class GeneralCodeStylePanel extends CodeStyleAbstractPanel {
}
myRightMarginSpinner.setValue(settings.getDefaultRightMargin());
//noinspection deprecation
myCbWrapWhenTypingReachesRightMargin.setSelected(settings.WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN);
myIndentOptionsEditor.reset(settings, settings.OTHER_INDENT_OPTIONS);
myIndentOptionsEditor.setEnabled(true);
@@ -31,7 +31,6 @@ import com.intellij.ui.treeStructure.treetable.TreeTableModel;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.AbstractTableCellEditor;
import com.intellij.util.ui.ColumnInfo;
import com.intellij.util.ui.ThreeStateCheckBox;
import com.intellij.util.ui.UIUtil;
import gnu.trove.THashMap;
import gnu.trove.THashSet;
@@ -352,11 +351,6 @@ public abstract class OptionTableWithPreviewPanel extends CustomizableLanguageCo
myOptions.add(new BooleanOption(null, fieldName, title, groupName, null, null));
}
protected void addOption(
@NotNull String filedName, @NotNull String title, @Nullable String groupName, int undefinedValue, int falseValue, int trueValue) {
myOptions.add(new TriStateOption(null, filedName, title, groupName, null, null, undefinedValue, falseValue, trueValue));
}
protected void addOption(@NotNull String fieldName, @NotNull String title, @Nullable String groupName,
@NotNull String[] options, @NotNull int[] values) {
myOptions.add(new SelectionOption(null, fieldName, title, groupName, null, null, options, values));
@@ -437,61 +431,6 @@ public abstract class OptionTableWithPreviewPanel extends CustomizableLanguageCo
}
}
private class TriStateOption extends Option {
private int myUndefinedValue;
private int myFalseValue;
private int myTrueValue;
public TriStateOption(@Nullable Class<? extends CustomCodeStyleSettings> clazz,
@NotNull String fieldName,
@NotNull String title,
@Nullable String groupName,
@Nullable OptionAnchor anchor,
@Nullable String anchorFiledName,
int undefinedValue,
int falseValue,
int trueValue) {
super(clazz, fieldName, title, groupName, anchor, anchorFiledName);
myUndefinedValue = undefinedValue;
myFalseValue = falseValue;
myTrueValue = trueValue;
}
@Override
public Object getValue(CodeStyleSettings settings) {
try {
int value = field.getInt(getSettings(settings));
return getState(value);
}
catch (IllegalAccessException e) {
return null;
}
}
@Override
public void setValue(Object value, CodeStyleSettings settings) {
try {
int intValue =
ThreeStateCheckBox.State.DONT_CARE.equals(value) ? myUndefinedValue :
ThreeStateCheckBox.State.SELECTED.equals(value) ? myTrueValue : myFalseValue;
field.setInt(getSettings(settings), intValue);
}
catch (IllegalAccessException ignored) {
}
}
public ThreeStateCheckBox.State getState(Object value) {
if (value instanceof Integer) {
if (value.equals(myTrueValue)) return ThreeStateCheckBox.State.SELECTED;
if (value.equals(myFalseValue)) return ThreeStateCheckBox.State.NOT_SELECTED;
}
return ThreeStateCheckBox.State.DONT_CARE;
}
}
private class SelectionOption extends Option {
@NotNull final String[] options;
@NotNull final int[] values;
@@ -746,7 +685,6 @@ public abstract class OptionTableWithPreviewPanel extends CustomizableLanguageCo
private final JCheckBox myCheckBox = new JBCheckBox();
private final JPanel myEmptyLabel = new JPanel();
private final JLabel myIntLabel = new JLabel();
private final ThreeStateCheckBox myTriStateCheckBox = new ThreeStateCheckBox();
@NotNull
@Override
@@ -787,10 +725,6 @@ public abstract class OptionTableWithPreviewPanel extends CustomizableLanguageCo
myIntLabel.setText(value.toString());
return myIntLabel;
}
else if (value instanceof ThreeStateCheckBox.State) {
myTriStateCheckBox.setState((ThreeStateCheckBox.State)value);
return myTriStateCheckBox;
}
myCheckBox.putClientProperty("JComponent.sizeVariant", "small");
myComboBox.putClientProperty("JComponent.sizeVariant", "small");
@@ -849,7 +783,6 @@ public abstract class OptionTableWithPreviewPanel extends CustomizableLanguageCo
private final JCheckBox myBooleanEditor = new JBCheckBox();
private JBComboBoxTableCellEditorComponent myOptionsEditor = new JBComboBoxTableCellEditorComponent();
private MyIntOptionEditor myIntOptionsEditor = new MyIntOptionEditor();
private ThreeStateCheckBox myTriStateOptionsEditor = new ThreeStateCheckBox();
private Component myCurrentEditor = null;
private MyTreeNode myCurrentNode = null;
@@ -865,7 +798,6 @@ public abstract class OptionTableWithPreviewPanel extends CustomizableLanguageCo
};
myBooleanEditor.addActionListener(itemChoosen);
myOptionsEditor.addActionListener(itemChoosen);
myTriStateOptionsEditor.addActionListener(itemChoosen);
myBooleanEditor.putClientProperty("JComponent.sizeVariant", "small");
myOptionsEditor.putClientProperty("JComponent.sizeVariant", "small");
}
@@ -887,9 +819,6 @@ public abstract class OptionTableWithPreviewPanel extends CustomizableLanguageCo
else if (myCurrentEditor == myIntOptionsEditor) {
return myIntOptionsEditor.getPresentableValue();
}
else if (myCurrentEditor == myTriStateOptionsEditor) {
return myTriStateOptionsEditor.getState();
}
return null;
}
@@ -917,11 +846,6 @@ public abstract class OptionTableWithPreviewPanel extends CustomizableLanguageCo
myIntOptionsEditor.setDefaultValue(intOption.getDefaultValue());
myIntOptionsEditor.setDefaultValueText(intOption.getDefaultValueText());
}
else if (node.getKey() instanceof TriStateOption) {
TriStateOption triStateOption = (TriStateOption)node.getKey();
myCurrentEditor = myTriStateOptionsEditor;
myTriStateOptionsEditor.setState(triStateOption.getState(node.getValue()));
}
else {
myCurrentEditor = myOptionsEditor;
myOptionsEditor.setCell(table, row, column);
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.application.options.codeStyle.RightMarginForm">
<grid id="27dc6" binding="myTopPanel" layout-manager="GridLayoutManager" row-count="3" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="10" left="0" bottom="10" right="10"/>
<grid id="27dc6" binding="myTopPanel" layout-manager="GridLayoutManager" row-count="2" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="10" left="10" bottom="10" right="10"/>
<constraints>
<xy x="20" y="20" width="500" height="400"/>
</constraints>
@@ -18,7 +18,7 @@
</component>
<vspacer id="1265c">
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<component id="78fe" class="javax.swing.JTextField" binding="myRightMarginField">
@@ -39,14 +39,6 @@
<text resource-bundle="messages/ApplicationBundle" key="settings.code.style.default.general"/>
</properties>
</component>
<component id="7701d" class="javax.swing.JCheckBox" binding="myWrapOnTypingCheckBox" custom-create="true" default-binding="true">
<constraints>
<grid row="1" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Wrap on typing"/>
</properties>
</component>
</children>
</grid>
</form>
@@ -16,10 +16,8 @@
package com.intellij.application.options.codeStyle;
import com.intellij.lang.Language;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.util.ui.ThreeStateCheckBox;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -45,7 +43,6 @@ public class RightMarginForm {
private JTextField myRightMarginField;
private JCheckBox myDefaultGeneralCheckBox;
private JPanel myTopPanel;
private JCheckBox myWrapOnTypingCheckBox;
private final Language myLanguage;
private final int myDefaultRightMargin;
@@ -80,22 +77,6 @@ public class RightMarginForm {
myRightMarginField.setEnabled(false);
}
}
if (langSettings != settings) {
if (CommonCodeStyleSettings.WrapOnTyping.WRAP.intValue == langSettings.WRAP_ON_TYPING) {
((ThreeStateCheckBox)myWrapOnTypingCheckBox).setState(ThreeStateCheckBox.State.SELECTED);
}
else if (CommonCodeStyleSettings.WrapOnTyping.NO_WRAP.intValue == langSettings.WRAP_ON_TYPING) {
((ThreeStateCheckBox)myWrapOnTypingCheckBox).setState(ThreeStateCheckBox.State.NOT_SELECTED);
}
else {
((ThreeStateCheckBox)myWrapOnTypingCheckBox).setState(ThreeStateCheckBox.State.DONT_CARE);
}
}
else {
((ThreeStateCheckBox)myWrapOnTypingCheckBox)
.setState(settings.isWrapOnTyping(myLanguage) ? ThreeStateCheckBox.State.SELECTED : ThreeStateCheckBox.State.NOT_SELECTED);
myWrapOnTypingCheckBox.setEnabled(false);
}
}
public void apply(@NotNull CodeStyleSettings settings) {
@@ -107,26 +88,17 @@ public class RightMarginForm {
else {
langSettings.RIGHT_MARGIN = getFieldRightMargin(settings.getDefaultRightMargin());
}
langSettings.WRAP_ON_TYPING = getWrapOnTypingIntValue();
}
}
public boolean isModified(@NotNull CodeStyleSettings settings) {
CommonCodeStyleSettings langSettings = settings.getCommonSettings(myLanguage);
boolean isRightMarginChanged =
myDefaultGeneralCheckBox.isSelected() ?
langSettings.RIGHT_MARGIN >= 0 :
langSettings.RIGHT_MARGIN != getFieldRightMargin(settings.getDefaultRightMargin());
return isRightMarginChanged || getWrapOnTypingIntValue() != langSettings.WRAP_ON_TYPING;
}
private int getWrapOnTypingIntValue() {
ThreeStateCheckBox.State state = ((ThreeStateCheckBox)myWrapOnTypingCheckBox).getState();
return
ThreeStateCheckBox.State.SELECTED.equals(state) ? CommonCodeStyleSettings.WrapOnTyping.WRAP.intValue :
ThreeStateCheckBox.State.NOT_SELECTED.equals(state) ? CommonCodeStyleSettings.WrapOnTyping.NO_WRAP.intValue :
CommonCodeStyleSettings.WrapOnTyping.UNDEFINED.intValue;
if (myDefaultGeneralCheckBox.isSelected()) {
return langSettings.RIGHT_MARGIN >= 0;
}
else {
return langSettings.RIGHT_MARGIN != getFieldRightMargin(settings.getDefaultRightMargin());
}
}
private int getFieldRightMargin(int fallBackValue) {
@@ -145,8 +117,4 @@ public class RightMarginForm {
public JPanel getTopPanel() {
return myTopPanel;
}
private void createUIComponents() {
myWrapOnTypingCheckBox = new ThreeStateCheckBox(ApplicationBundle.message("wrapping.wrap.on.typing"));
}
}
@@ -17,7 +17,6 @@ package com.intellij.application.options.codeStyle;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
@@ -59,27 +58,9 @@ public class WrappingAndBracesPanel extends OptionTableWithPreviewPanel {
}
}
@Override
protected void addOption(@NotNull String fieldName,
@NotNull String title,
@Nullable String groupName,
int minValue,
int maxValue,
int defaultValue,
String defaultValueText) {
super.addOption(fieldName, title, groupName, minValue, maxValue, defaultValue, defaultValueText);
if (groupName != null) {
myGroupToFields.putValue(groupName, fieldName);
}
}
@Override
protected void initTables() {
addOption("RIGHT_MARGIN", ApplicationBundle.message("editbox.right.margin.columns"), null, 0, 999, -1, ApplicationBundle.message("settings.code.style.default.general"));
addOption("WRAP_ON_TYPING", ApplicationBundle.message("wrapping.wrap.on.typing"), null,
CommonCodeStyleSettings.WrapOnTyping.UNDEFINED.intValue,
CommonCodeStyleSettings.WrapOnTyping.NO_WRAP.intValue,
CommonCodeStyleSettings.WrapOnTyping.WRAP.intValue);
addOption("KEEP_LINE_BREAKS", ApplicationBundle.message("wrapping.keep.line.breaks"), WRAPPING_KEEP);
addOption("KEEP_FIRST_COLUMN_COMMENT", ApplicationBundle.message("wrapping.keep.comment.at.first.column"), WRAPPING_KEEP);
@@ -17,7 +17,6 @@ package com.intellij.codeInsight.editorActions;
import com.intellij.codeInsight.template.TemplateManager;
import com.intellij.formatting.FormatConstants;
import com.intellij.lang.Language;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.formatter.WhiteSpaceFormattingStrategy;
import com.intellij.ide.DataManager;
@@ -48,7 +47,7 @@ public class AutoHardWrapHandler {
/**
* This key is used as a flag that indicates if <code>'auto wrap line on typing'</code> activity is performed now.
*
* @see CodeStyleSettings#isWrapOnTyping(Language)
* @see CodeStyleSettings#WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN
*/
public static final Key<Boolean> AUTO_WRAP_LINE_IN_PROGRESS_KEY = new Key<Boolean>("AUTO_WRAP_LINE_IN_PROGRESS");
@@ -43,6 +43,7 @@ import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl;
import com.intellij.openapi.fileTypes.SyntaxHighlighter;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
@@ -550,7 +551,12 @@ public class LanguageConsoleImpl extends ConsoleViewImpl implements LanguageCons
@NotNull
public PsiFile getFile() {
return PsiUtilCore.getPsiFile(project, virtualFile);
return ApplicationManager.getApplication().runReadAction(new Computable<PsiFile>() {
@Override
public PsiFile compute() {
return PsiUtilCore.getPsiFile(project, virtualFile);
}
});
}
@NotNull
@@ -35,6 +35,7 @@ import com.intellij.openapi.util.SystemInfo;
import com.intellij.ui.*;
import com.intellij.ui.components.JBList;
import com.intellij.util.containers.hash.HashSet;
import com.intellij.util.ui.JBUI;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -52,6 +53,7 @@ import java.util.List;
class BeforeRunStepsPanel extends JPanel {
private final JCheckBox myShowSettingsBeforeRunCheckBox;
private final JCheckBox myActivateToolWindowBeforeRunCheckBox;
private final JBList myList;
private final CollectionListModel<BeforeRunTask> myModel;
private RunConfiguration myRunConfiguration;
@@ -138,12 +140,22 @@ class BeforeRunStepsPanel extends JPanel {
updateText();
}
});
myActivateToolWindowBeforeRunCheckBox = new JCheckBox(ExecutionBundle.message("configuration.activate.toolwindow.before.run"));
myActivateToolWindowBeforeRunCheckBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
updateText();
}
});
myPanel = myDecorator.createPanel();
setLayout(new BorderLayout());
add(myPanel, BorderLayout.CENTER);
add(myShowSettingsBeforeRunCheckBox, BorderLayout.SOUTH);
JPanel checkboxPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, JBUI.scale(5), JBUI.scale(5)));
checkboxPanel.add(myShowSettingsBeforeRunCheckBox);
checkboxPanel.add(myActivateToolWindowBeforeRunCheckBox);
add(checkboxPanel, BorderLayout.SOUTH);
}
@Nullable
@@ -165,7 +177,9 @@ class BeforeRunStepsPanel extends JPanel {
originalTasks.addAll(runManager.getBeforeRunTasks(myRunConfiguration));
myModel.replaceAll(originalTasks);
myShowSettingsBeforeRunCheckBox.setSelected(settings.isEditBeforeRun());
myShowSettingsBeforeRunCheckBox.setEnabled(!(isUnknown()));
myShowSettingsBeforeRunCheckBox.setEnabled(!isUnknown());
myActivateToolWindowBeforeRunCheckBox.setSelected(settings.isActivateToolWindowBeforeRun());
myActivateToolWindowBeforeRunCheckBox.setEnabled(!isUnknown());
myPanel.setVisible(checkBeforeRunTasksAbility(false));
updateText();
}
@@ -209,6 +223,9 @@ class BeforeRunStepsPanel extends JPanel {
}
}
}
if (myActivateToolWindowBeforeRunCheckBox.isSelected()) {
sb.append(sb.length() > 0 ? ", " : "").append(ExecutionBundle.message("configuration.activate.toolwindow.before.run"));
}
if (sb.length() > 0) {
sb.insert(0, ": ");
}
@@ -228,6 +245,10 @@ class BeforeRunStepsPanel extends JPanel {
return myShowSettingsBeforeRunCheckBox.isSelected();
}
public boolean needActivateToolWindowBeforeRun() {
return myActivateToolWindowBeforeRunCheckBox.isSelected();
}
private boolean checkBeforeRunTasksAbility(boolean checkOnlyAddAction) {
if (isUnknown()) {
return false;
@@ -130,8 +130,10 @@ public class ConfigurationSettingsEditorWrapper extends SettingsEditor<RunnerAnd
RunnerAndConfigurationSettings runManagerSettings = runManager.getSettings(runConfiguration);
if (runManagerSettings != null) {
runManagerSettings.setEditBeforeRun(myBeforeRunStepsPanel.needEditBeforeRun());
runManagerSettings.setActivateToolWindowBeforeRun(myBeforeRunStepsPanel.needActivateToolWindowBeforeRun());
} else {
settings.setEditBeforeRun(myBeforeRunStepsPanel.needEditBeforeRun());
settings.setActivateToolWindowBeforeRun(myBeforeRunStepsPanel.needActivateToolWindowBeforeRun());
}
}
@@ -388,6 +388,7 @@ class RunConfigurable extends BaseConfigurable {
JComponent configurableComponent = configurable.createComponent();
final JBScrollPane scrollPane = new JBScrollPane(configurableComponent);
scrollPane.getVerticalScrollBar().setUnitIncrement(10);
scrollPane.setBorder(null);
myRightPanel.add(scrollPane, BorderLayout.CENTER);
if (configurable instanceof SingleConfigurationConfigurable) {
@@ -72,6 +72,8 @@ public class RunnerAndConfigurationSettingsImpl implements JDOMExternalizable, C
@NonNls
private static final String EDIT_BEFORE_RUN = "editBeforeRun";
@NonNls
private static final String ACTIVATE_TOOLWINDOW_BEFORE_RUN = "activateToolWindowBeforeRun";
@NonNls
public static final String SINGLETON = "singleton";
/** for compatibility */
@@ -98,6 +100,7 @@ public class RunnerAndConfigurationSettingsImpl implements JDOMExternalizable, C
private boolean myTemporary;
private boolean myEditBeforeRun;
private boolean myActivateToolWindowBeforeRun = true;
private boolean mySingleton;
private boolean myWasSingletonSpecifiedExplicitly;
private String myFolderName;
@@ -305,6 +308,16 @@ public class RunnerAndConfigurationSettingsImpl implements JDOMExternalizable, C
return myEditBeforeRun;
}
@Override
public void setActivateToolWindowBeforeRun(boolean activate) {
myActivateToolWindowBeforeRun = activate;
}
@Override
public boolean isActivateToolWindowBeforeRun() {
return myActivateToolWindowBeforeRun;
}
@Override
public void setSingleton(boolean singleton) {
mySingleton = singleton;
@@ -338,6 +351,8 @@ public class RunnerAndConfigurationSettingsImpl implements JDOMExternalizable, C
myIsTemplate = Boolean.valueOf(element.getAttributeValue(TEMPLATE_FLAG_ATTRIBUTE)).booleanValue();
myTemporary = Boolean.valueOf(element.getAttributeValue(TEMPORARY_ATTRIBUTE)).booleanValue() || TEMP_CONFIGURATION.equals(element.getName());
myEditBeforeRun = Boolean.valueOf(element.getAttributeValue(EDIT_BEFORE_RUN)).booleanValue();
String value = element.getAttributeValue(ACTIVATE_TOOLWINDOW_BEFORE_RUN);
myActivateToolWindowBeforeRun = value == null || Boolean.valueOf(value).booleanValue();
myFolderName = element.getAttributeValue(FOLDER_NAME);
//assert myID == null: "myId must be null at readExternal() stage";
//myID = element.getAttributeValue(UNIQUE_ID, UUID.randomUUID().toString());
@@ -391,6 +406,9 @@ public class RunnerAndConfigurationSettingsImpl implements JDOMExternalizable, C
if (isEditBeforeRun()) {
element.setAttribute(EDIT_BEFORE_RUN, String.valueOf(true));
}
if (!isActivateToolWindowBeforeRun()) {
element.setAttribute(ACTIVATE_TOOLWINDOW_BEFORE_RUN, String.valueOf(false));
}
if (myWasSingletonSpecifiedExplicitly || mySingleton != factory.isConfigurationSingletonByDefault()) {
element.setAttribute(SINGLETON, String.valueOf(mySingleton));
}
@@ -469,6 +487,7 @@ public class RunnerAndConfigurationSettingsImpl implements JDOMExternalizable, C
setSingleton(template.isSingleton());
setEditBeforeRun(template.isEditBeforeRun());
setActivateToolWindowBeforeRun(template.isActivateToolWindowBeforeRun());
}
@SuppressWarnings("deprecation")
@@ -203,6 +203,9 @@ class InitialInfoBuilder {
if (rootBlock instanceof ReadOnlyBlockInformationProvider) {
myReadOnlyBlockInformationProvider = (ReadOnlyBlockInformationProvider)rootBlock;
}
if (!isInsideFormattingRanges && !myCollectAlignmentsInsideFormattingRange) {
return processSimpleBlock(rootBlock, parent, true, index, parentBlock);
}
final List<Block> subBlocks = rootBlock.getSubBlocks();
if (subBlocks.isEmpty() || myReadOnlyBlockInformationProvider != null
@@ -237,10 +240,11 @@ class InitialInfoBuilder {
}
boolean blocksMayBeOfInterest = false;
if (myPositionOfInterest != -1) {
if (myPositionOfInterest != -1 && rootBlock.getTextRange().contains(myPositionOfInterest)) {
myResult.put(wrappedRootBlock, rootBlock);
blocksMayBeOfInterest = true;
}
final boolean blocksAreReadOnly = rootBlock instanceof ReadOnlyBlockContainer || blocksMayBeOfInterest;
State state = new State(rootBlock, wrappedRootBlock, currentWrapParent, blocksAreReadOnly, rootBlockIsRightBlock);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,7 +31,6 @@ import javax.swing.*;
* @author Rustam Vishnyakov
*/
public class EnforcedPlainTextFileTypeFactory extends FileTypeFactory {
public static final LayeredIcon ENFORCED_PLAIN_TEXT_ICON = new LayeredIcon(2);
public static final String ENFORCED_PLAIN_TEXT = "Enforced Plain Text";
@@ -40,15 +39,10 @@ public class EnforcedPlainTextFileTypeFactory extends FileTypeFactory {
ENFORCED_PLAIN_TEXT_ICON.setIcon(PlatformIcons.EXCLUDED_FROM_COMPILE_ICON, 1);
}
private final FileTypeIdentifiableByVirtualFile myFileType;
public EnforcedPlainTextFileTypeFactory() {
myFileType = new FileTypeIdentifiableByVirtualFile() {
public EnforcedPlainTextFileTypeFactory() {
myFileType = new FileTypeIdentifiableByVirtualFile() {
@Override
public boolean isMyFileType(@NotNull VirtualFile file) {
return isMarkedAsPlainText(file);
@@ -95,14 +89,12 @@ public class EnforcedPlainTextFileTypeFactory extends FileTypeFactory {
}
@Override
public void createFileTypes(final @NotNull FileTypeConsumer consumer) {
public void createFileTypes(@NotNull final FileTypeConsumer consumer) {
consumer.consume(myFileType, "");
}
private static boolean isMarkedAsPlainText(VirtualFile file) {
private static boolean isMarkedAsPlainText(@NotNull VirtualFile file) {
EnforcedPlainTextFileTypeManager typeManager = EnforcedPlainTextFileTypeManager.getInstance();
if (typeManager == null) return false;
return typeManager.isMarkedAsPlainText(file);
return typeManager != null && typeManager.isMarkedAsPlainText(file);
}
}
@@ -48,7 +48,7 @@ public class EnforcedPlainTextFileTypeManager implements ProjectManagerListener
ProjectManager.getInstance().addProjectManagerListener(this);
}
public boolean isMarkedAsPlainText(VirtualFile file) {
public boolean isMarkedAsPlainText(@NotNull VirtualFile file) {
if (!(file instanceof VirtualFileWithId) || file.isDirectory()) return false;
if (!mySetsInitialized) {
synchronized (LOCK) {
@@ -77,15 +77,15 @@ public class EnforcedPlainTextFileTypeManager implements ProjectManagerListener
return !originalType.isBinary() && originalType != FileTypes.PLAIN_TEXT && originalType != StdFileTypes.JAVA;
}
public void markAsPlainText(@NotNull Project project, VirtualFile... files) {
public void markAsPlainText(@NotNull Project project, @NotNull VirtualFile... files) {
setPlainTextStatus(project, true, files);
}
public void resetOriginalFileType(@NotNull Project project, VirtualFile... files) {
public void resetOriginalFileType(@NotNull Project project, @NotNull VirtualFile... files) {
setPlainTextStatus(project, false, files);
}
private void setPlainTextStatus(@NotNull final Project project, final boolean isAdded, final VirtualFile... files) {
private void setPlainTextStatus(@NotNull final Project project, final boolean isAdded, @NotNull final VirtualFile... files) {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@ import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.VirtualFileWithId;
import com.intellij.util.containers.HashSet;
import gnu.trove.THashSet;
import org.jdom.Attribute;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
@@ -30,23 +30,23 @@ import java.util.*;
/**
* @author Rustam Vishnyakov
*/
public class PersistentFileSetManager implements PersistentStateComponent<Element> {
class PersistentFileSetManager implements PersistentStateComponent<Element> {
private static final String FILE_ELEMENT = "file";
private static final String PATH_ATTR = "url";
private final Set<VirtualFile> myFiles = new HashSet<VirtualFile>();
private final Set<VirtualFile> myFiles = new THashSet<VirtualFile>();
protected boolean addFile(VirtualFile file) {
protected boolean addFile(@NotNull VirtualFile file) {
if (!(file instanceof VirtualFileWithId) || file.isDirectory()) return false;
myFiles.add(file);
return true;
}
protected boolean containsFile(VirtualFile file) {
protected boolean containsFile(@NotNull VirtualFile file) {
return myFiles.contains(file);
}
protected boolean removeFile(VirtualFile file) {
protected boolean removeFile(@NotNull VirtualFile file) {
if (!myFiles.contains(file)) return false;
myFiles.remove(file);
return true;
@@ -56,8 +56,9 @@ public class PersistentFileSetManager implements PersistentStateComponent<Elemen
public Collection<VirtualFile> getFiles() {
return myFiles;
}
public Collection<VirtualFile> getSortedFiles() {
@NotNull
private Collection<VirtualFile> getSortedFiles() {
List<VirtualFile> sortedFiles = new ArrayList<VirtualFile>();
sortedFiles.addAll(myFiles);
Collections.sort(sortedFiles, new Comparator<VirtualFile>() {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@ import com.intellij.openapi.components.StoragePathMacros;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
/**
* @author Rustam Vishnyakov
@@ -34,7 +35,7 @@ public class ProjectPlainTextFileTypeManager extends PersistentFileSetManager {
myIndex = projectFileIndex;
}
public boolean hasProjectContaining(VirtualFile file) {
boolean hasProjectContaining(@NotNull VirtualFile file) {
return myIndex.isInContent(file);
}
@@ -74,17 +74,10 @@ public class CodeStyleFacadeImpl extends CodeStyleFacade {
}
@Override
@Deprecated
public boolean isWrapWhenTypingReachesRightMargin() {
//noinspection deprecation
return CodeStyleSettingsManager.getSettings(myProject).WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN;
}
@Override
public boolean isWrapOnTyping(@Nullable Language language) {
return CodeStyleSettingsManager.getSettings(myProject).isWrapOnTyping(language);
}
@Override
public int getTabSize(final FileType fileType) {
return CodeStyleSettingsManager.getSettings(myProject).getTabSize(fileType);
@@ -56,17 +56,8 @@ public abstract class CodeStyleFacade {
public abstract int getRightMargin(Language language);
/**
* @return True if wrap on typing is enabled
* @deprecated Use isWrapOnTyping(language) instead
*/
public abstract boolean isWrapWhenTypingReachesRightMargin();
@SuppressWarnings("deprecation")
public boolean isWrapOnTyping(@Nullable Language language) {
return isWrapWhenTypingReachesRightMargin();
}
public abstract int getTabSize(final FileType fileType);
public abstract boolean useTabCharacter(final FileType fileType);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -65,7 +65,7 @@ public class MockFileTypeManager extends FileTypeManager {
}
@Override
public boolean isFileIgnored(@NonNls @NotNull VirtualFile file) {
public boolean isFileIgnored(@NotNull VirtualFile file) {
return false;
}
@@ -123,6 +123,7 @@ public class MockFileTypeManager extends FileTypeManager {
return MockLanguageFileType.INSTANCE;
}
@Override
public boolean isFileOfType(@NotNull VirtualFile file, @NotNull FileType type) {
return false;
}
@@ -135,7 +136,7 @@ public class MockFileTypeManager extends FileTypeManager {
@Nullable
@Override
public FileType findFileTypeByName(String fileTypeName) {
public FileType findFileTypeByName(@NotNull String fileTypeName) {
return null;
}
}
@@ -22,10 +22,14 @@ import com.intellij.openapi.ui.ComponentWithBrowseButton;
import com.intellij.openapi.ui.TextComponentAccessor;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
/**
* User: anna
*/
public class TextFieldWithHistoryWithBrowseButton extends ComponentWithBrowseButton<TextFieldWithHistory> {
private String myText;
public TextFieldWithHistoryWithBrowseButton() {
super(new TextFieldWithHistory(), null);
}
@@ -54,4 +58,10 @@ public class TextFieldWithHistoryWithBrowseButton extends ComponentWithBrowseBut
public String getText() {
return getChildComponent().getText();
}
public void setText(String text) {
final ComboBoxModel model = getChildComponent().getModel();
model.setSelectedItem(text);
myText = text;
}
}
@@ -501,20 +501,9 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
}
if (myErrorStripeRenderer != null) {
if (isMirrored() && g instanceof Graphics2D) {
Graphics2D g2d = (Graphics2D)g;
AffineTransform old = g2d.getTransform();
AffineTransform tx = AffineTransform.getScaleInstance(-1, 1);
tx.translate(-getErrorIconWidth(), 0);
g2d.transform(tx);
myErrorStripeRenderer.paint(this, g2d, new Rectangle(0, 0, getErrorIconWidth(), getErrorIconHeight()));
g2d.setTransform(old);
}
else {
int x = getThinGap() + myMinMarkHeight;
final Rectangle b = new Rectangle(x, 0, getErrorIconWidth(), getErrorIconHeight());
myErrorStripeRenderer.paint(this, g, b);
}
int x = isMirrored() ? 0 : (getThinGap() + myMinMarkHeight);
final Rectangle b = new Rectangle(x, 0, getErrorIconWidth(), getErrorIconHeight());
myErrorStripeRenderer.paint(this, g, b);
}
}
finally {
@@ -213,7 +213,7 @@ public class SettingsImpl implements EditorSettings {
public boolean isWrapWhenTypingReachesRightMargin(Project project) {
return myWrapWhenTypingReachesRightMargin != null ?
myWrapWhenTypingReachesRightMargin.booleanValue() :
CodeStyleFacade.getInstance(project).isWrapOnTyping(myLanguage);
CodeStyleFacade.getInstance(project).isWrapWhenTypingReachesRightMargin();
}
@Override
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -144,7 +144,7 @@ public class FileTypeChooser extends DialogWrapper {
}
FileType type = file.getFileType();
if (type == FileTypes.UNKNOWN) {
type = getKnownFileTypeOrAssociate(file.getName());
type = getKnownFileTypeOrAssociate(file.getName());
}
return type;
}
@@ -594,7 +594,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent
}
@Override
public FileType findFileTypeByName(String fileTypeName) {
public FileType findFileTypeByName(@NotNull String fileTypeName) {
FileType type = getStdFileType(fileTypeName);
// TODO: Abstract file types are not std one, so need to be restored specially,
// currently there are 6 of them and restoration does not happen very often so just iteration is enough
@@ -738,7 +738,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent
});
}
private void unregisterFileTypeWithoutNotification(FileType fileType) {
private void unregisterFileTypeWithoutNotification(@NotNull FileType fileType) {
myPatternsTable.removeAllAssociations(fileType);
mySchemesManager.removeScheme(fileType);
if (fileType instanceof FileTypeIdentifiableByVirtualFile) {
@@ -793,14 +793,14 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent
}
@Override
public boolean isFileIgnored(@NonNls @NotNull VirtualFile file) {
public boolean isFileIgnored(@NotNull VirtualFile file) {
return myIgnoredFileCache.isFileIgnored(file);
}
@Override
@SuppressWarnings({"deprecation"})
@NotNull
public String[] getAssociatedExtensions(@NotNull FileType type) {
//noinspection deprecation
return myPatternsTable.getAssociatedExtensions(type);
}
@@ -1033,7 +1033,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent
FileNameMatcher[] unresolvedMappingKeys = myUnresolvedMappings.keySet().toArray(new FileNameMatcher[myUnresolvedMappings.size()]);
Arrays.sort(unresolvedMappingKeys, new Comparator<FileNameMatcher>() {
@Override
public int compare(FileNameMatcher o1, FileNameMatcher o2) {
public int compare(@NotNull FileNameMatcher o1, @NotNull FileNameMatcher o2) {
return o1.getPresentableString().compareTo(o2.getPresentableString());
}
});
@@ -1080,7 +1080,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent
}
}
private boolean isApproved(FileNameMatcher matcher) {
private boolean isApproved(@NotNull FileNameMatcher matcher) {
Pair<FileType, Boolean> pair = myRemovedMappings.get(matcher);
return pair != null && pair.getSecond();
}
@@ -1234,7 +1234,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent
}
}
private static boolean shouldSave(FileType fileType) {
private static boolean shouldSave(@NotNull FileType fileType) {
return fileType != FileTypes.UNKNOWN && !fileType.isReadOnly();
}
@@ -1248,6 +1248,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent
return getFileTypeComponentName();
}
@NotNull
public static String getFileTypeComponentName() {
return PlatformUtils.isIdeaCommunity() ? "CommunityFileTypes" : "FileTypeManager";
}
@@ -1274,7 +1275,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent
fireFileTypesChanged();
}
public void associate(FileType fileType, FileNameMatcher matcher, boolean fireChange) {
public void associate(@NotNull FileType fileType, @NotNull FileNameMatcher matcher, boolean fireChange) {
if (!myPatternsTable.isAssociatedWith(fileType, matcher)) {
if (fireChange) {
fireBeforeFileTypesChanged();
@@ -1286,7 +1287,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent
}
}
public void removeAssociation(FileType fileType, FileNameMatcher matcher, boolean fireChange) {
public void removeAssociation(@NotNull FileType fileType, @NotNull FileNameMatcher matcher, boolean fireChange) {
if (myPatternsTable.isAssociatedWith(fileType, matcher)) {
if (fireChange) {
fireBeforeFileTypesChanged();
@@ -1311,7 +1312,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent
return FileTypeChooser.getKnownFileTypeOrAssociate(file, project);
}
private void registerReDetectedMappings(StandardFileType pair) {
private void registerReDetectedMappings(@NotNull StandardFileType pair) {
FileType fileType = pair.fileType;
if (fileType == PlainTextFileType.INSTANCE) return;
for (FileNameMatcher matcher : pair.matchers) {
@@ -1333,6 +1334,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent
}
}
@NotNull
Map<FileNameMatcher, Pair<FileType, Boolean>> getRemovedMappings() {
return myRemovedMappings;
}
@@ -217,7 +217,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements PersistentSt
}
public static int TEST_PROJECTS_CREATED;
private static final boolean LOG_PROJECT_LEAKAGE_IN_TESTS = false;
private static final boolean LOG_PROJECT_LEAKAGE_IN_TESTS = true;
private static final int MAX_LEAKY_PROJECTS = 42;
@SuppressWarnings("FieldCanBeLocal") private final Map<Project, String> myProjects = new WeakHashMap<Project, String>();
@@ -1053,6 +1053,32 @@ public class FSRecords implements Forceable {
}
}
// returns id, parent(id), parent(parent(id)), ... rootId
@NotNull
public static TIntArrayList getParents(int id) {
TIntArrayList result = new TIntArrayList(10);
r.lock();
try {
int parentId;
do {
result.add(id);
parentId = getRecordInt(id, PARENT_OFFSET);
if (parentId == id || result.size() % 128 == 0 && result.contains(parentId)) {
LOG.error("Cyclic parent child relations in the database. id = " + parentId);
return result;
}
id = parentId;
} while (parentId != 0);
}
catch (Throwable e) {
throw DbConnection.handleError(e);
}
finally {
r.unlock();
}
return result;
}
public static void setParent(int id, int parent) {
if (id == parent) {
LOG.error("Cyclic parent/child relations");
@@ -61,7 +61,7 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone
private final ReadWriteLock myRootsLock = new ReentrantReadWriteLock();
private final Map<String, VirtualFileSystemEntry> myRoots = ContainerUtil.newTroveMap(FileUtil.PATH_HASHING_STRATEGY);
private final TIntObjectHashMap<VirtualFileSystemEntry> myRootsById = new TIntObjectHashMap<VirtualFileSystemEntry>();
private final ConcurrentIntObjectMap<VirtualFileSystemEntry> myRootsById = ContainerUtil.createConcurrentIntObjectMap();
private final ConcurrentIntObjectMap<VirtualFileSystemEntry> myIdToDirCache = ContainerUtil.createConcurrentIntObjectMap();
private final Object myInputLock = new Object();
@@ -199,7 +199,7 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone
return nameIds.toArray(new FSRecords.NameId[nameIds.size()]);
}
public static void setChildrenCached(int id) {
private static void setChildrenCached(int id) {
int flags = FSRecords.getFlags(id);
FSRecords.setFlags(id, flags | CHILDREN_CACHED_FLAG, true);
}
@@ -311,11 +311,6 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone
return isDirectory(getFileAttributes(getFileId(file)));
}
private static int getParent(final int id) {
assert id > 0;
return FSRecords.getParent(id);
}
private static boolean namesEqual(@NotNull VirtualFileSystem fs, @NotNull CharSequence n1, CharSequence n2) {
return Comparing.equal(n1, n2, fs.isCaseSensitive());
}
@@ -912,9 +907,8 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone
return null;
}
boolean mark = false;
myRootsLock.writeLock().lock();
boolean mark = false;
try {
VirtualFileSystemEntry root = myRoots.get(rootUrl);
if (root != null) return root;
@@ -962,59 +956,31 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone
myIdToDirCache.clear();
}
private static final int DEPTH_LIMIT = 75;
@Override
@Nullable
public NewVirtualFile findFileById(final int id) {
return findFileById(id, false, null, 0);
return findFileById(id, false);
}
@Override
public NewVirtualFile findFileByIdIfCached(final int id) {
return findFileById(id, true, null, 0);
return findFileById(id, true);
}
@Nullable
private VirtualFileSystemEntry findFileById(int id, boolean cachedOnly, TIntArrayList visited, int mask) {
private VirtualFileSystemEntry findFileById(int id, boolean cachedOnly) {
VirtualFileSystemEntry cached = myIdToDirCache.get(id);
if (cached != null) return cached;
if (visited != null && (visited.size() >= DEPTH_LIMIT || (mask & id) == id && visited.contains(id))) {
@NonNls String sb = "Dead loop detected in persistent FS (id=" + id + " cached-only=" + cachedOnly + "):";
for (int i = 0; i < visited.size(); i++) {
int _id = visited.get(i);
sb += "\n " + _id + " '" + getName(_id) + "' " +
String.format("%02x", getFileAttributes(_id)) + ' ' + myIdToDirCache.containsKey(_id);
}
LOG.error(sb);
return null;
}
int parentId = getParent(id);
if (parentId >= id) {
if (visited == null) visited = new TIntArrayList(DEPTH_LIMIT);
}
if (visited != null) visited.add(id);
VirtualFileSystemEntry result;
if (parentId == 0) {
myRootsLock.readLock().lock();
try {
result = myRootsById.get(id);
}
finally {
myRootsLock.readLock().unlock();
}
}
else {
VirtualFileSystemEntry parentFile = findFileById(parentId, cachedOnly, visited, mask | id);
if (parentFile instanceof VirtualDirectoryImpl) {
result = ((VirtualDirectoryImpl)parentFile).findChildById(id, cachedOnly);
}
else {
result = null;
TIntArrayList parents = FSRecords.getParents(id);
int rootId = parents.get(parents.size() - 1);
VirtualFileSystemEntry result = myRootsById.get(rootId);
for (int i=parents.size() - 2; i>=0; i--) {
if (result == null) {
break;
}
int parentId = parents.get(i);
result = ((VirtualDirectoryImpl)result).findChildById(parentId, cachedOnly);
}
if (result != null && result.isDirectory()) {
@@ -985,7 +985,11 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
@Override
public void run() {
if (ApplicationManager.getApplication().isActive()) {
window.toFront();
if (window instanceof JFrame && ((JFrame)window).getState() == Frame.ICONIFIED) {
((JFrame)window).setState(Frame.NORMAL);
} else {
window.toFront();
}
}
}
});
@@ -1094,7 +1098,7 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
if (mgr.getFocusOwner() == null) {
Component c = getComponent(myLastFocusedAtDeactivation, ideFrame);
if (c == null || !c.isShowing()) {
c = getComponent(myLastFocused, ideFrame);
c = getComponent(myLastFocusedAtDeactivation, ideFrame);
}
final boolean mouseEventAhead = IdeEventQueue.isMouseEventAhead(null);
@@ -223,7 +223,6 @@ wrapping.long.lines=Ensure right margin is not exceeded
wrapping.comments=Comments
wrapping.comments.wrap.at.right.margin=Wrap at right margin
wrapping.annotation.parameters=Annotation parameters
wrapping.wrap.on.typing=Wrap on typing
checkbox.align.multiline.chained.methods=Chained methods
checkbox.align.multiline.method.parameters=Method parameters
@@ -351,6 +351,7 @@ export.test.results.footer=Generated by {0} on {1}
export.test.results.file.exists.message=File ''{0}'' already exists.\nDo you want to overwrite it?
export.test.results.file.exists.title=Export Test Results
configuration.edit.before.run=Show this page
configuration.activate.toolwindow.before.run=Activate tool window
configuration.singleton=Check no other instances are running
failed.to.create.output.file=Failed to create output file ''{0}''
@@ -1,243 +0,0 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.openapi.editor.impl;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.impl.event.DocumentEventImpl;
import com.intellij.openapi.util.Pair;
import com.intellij.util.LocalTimeCounter;
import com.intellij.util.containers.Stack;
import com.intellij.util.text.CharSequenceBackedByArray;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.api.Invocation;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.jmock.lib.action.CustomAction;
import org.jmock.lib.legacy.ClassImposteriser;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import static org.junit.Assert.*;
/**
* @author Denis Zhdanov
* @since 03/01/2011
*/
public class CharArrayTest {
@Rule
public TestWatcher configReader = new TestWatcher() {
@Override
protected void starting(Description description) {
Config config = description.getAnnotation(Config.class);
if (config != null) {
myConfig = config;
}
}
};
private CharArray myArray;
private Config myConfig;
private Mockery myMockery;
private DocumentImpl myDocument;
@Before
public void setUp() {
myMockery = new JUnit4Mockery() {{
setImposteriser(ClassImposteriser.INSTANCE);
}};
myDocument = myMockery.mock(DocumentImpl.class);
myMockery.checking(new Expectations() {{
allowing(myDocument).getTextLength(); will(new CustomAction("getTextLength") {
@Override
public Object invoke(Invocation invocation) throws Throwable {
return myArray.length();
}
});
}});
init(10);
if (myConfig != null) {
myArray.insert(myConfig.text(), 0);
myArray.setDeferredChangeMode(myConfig.deferred());
}
}
@After
public void checkExpectations() {
myMockery.assertIsSatisfied();
}
@Config(text = "1234", deferred = true)
@Test
public void deferredReplace() {
replace(1, 3, "abc");
assertTrue(myArray.hasDeferredChanges());
checkText("1abc4");
replace(2, 3, "XY");
checkText("1aXYc4");
replace(3, 6, "ABC");
checkText("1aXABC");
myArray.setDeferredChangeMode(false);
checkText("1aXABC");
}
@Config(text = "01234567", deferred = true)
@Test
public void subSequenceWithDeferredChangeBeforeIt() {
replace(0, 2, "abc");
CharSequenceBackedByArray subsSequence = (CharSequenceBackedByArray)myArray.subSequence(5, 6);
assertArrayEquals("4".toCharArray(), subsSequence.getChars());
}
@Config(text = "01234567", deferred = true)
@Test
public void subSequenceWithDeferredChangeIntersectingFromLeft() {
replace(0, 2, "abc");
CharSequenceBackedByArray subsSequence = (CharSequenceBackedByArray)myArray.subSequence(2, 4);
assertArrayEquals("c2".toCharArray(), subsSequence.getChars());
}
@Config(text = "01234567", deferred = true)
@Test
public void subSequenceWithDeferredChangeIntersectingFromRight() {
replace(4, 6, "abc");
CharSequenceBackedByArray subsSequence = (CharSequenceBackedByArray)myArray.subSequence(3, 5);
assertArrayEquals("3a".toCharArray(), subsSequence.getChars());
}
@Config(text = "01234567", deferred = true)
@Test
public void subSequenceWithDeferredChangeAfterIt() {
replace(6, 8, "abc");
CharSequenceBackedByArray subsSequence = (CharSequenceBackedByArray)myArray.subSequence(1, 2);
assertArrayEquals("1".toCharArray(), subsSequence.getChars());
}
private void init(int size) {
myArray = new CharArray(size, new char[0], 0) {
@NotNull
@Override
protected DocumentEvent beforeChangedUpdate(int offset, CharSequence oldString, CharSequence newString,
boolean wholeTextReplaced) {
return new DocumentEventImpl(myDocument, offset, oldString, newString, LocalTimeCounter.currentTime(), wholeTextReplaced);
}
@Override
protected void afterChangedUpdate(@NotNull DocumentEvent event, long newModificationStamp) {
}
@Override
protected void assertWriteAccess() {
}
@Override
protected void assertReadAccess() {
}
};
}
private void checkText(@NonNls @NotNull String expected) {
// Test as a whole.
assertEquals(expected, myArray.toString());
assertEquals(expected.length(), myArray.length());
// Test 'charAt()'.
for (int i = 0; i < expected.length(); i++) {
if (expected.charAt(i) != myArray.charAt(i)) {
fail(String.format(
"Detected incorrect 'charAt()' processing for deferred changes. Text: '%1$s'. Expected to get symbol '%2$c' "
+ "(numeric value %2$d) at index %3$d but actual symbol is '%4$c' (numeric value %4$d)",
expected, (int)expected.charAt(i), i, (int)myArray.charAt(i)));
}
assertEquals(expected.charAt(i), myArray.charAt(i));
}
// Test 'substring()'.
for (int start = 0; start < myArray.length() - 1; start++) {
for (int end = start; end < myArray.length(); end++) {
if (!expected.substring(start, end).equals(myArray.substring(start, end).toString())) {
fail(String.format(
"Detected incorrect 'substring()' processing for deferred changes. Text: '%s', expected to get substring '%s' for "
+ "interval [%d; %d) but got '%s'", expected, expected.substring(start, end), start, end, myArray.substring(start, end)
));
}
}
}
// Test subSequence().
checkSubSequence(expected, myArray, new Stack<Pair<Integer, Integer>>());
}
private void checkSubSequence(@NotNull String expected, @NotNull CharSequence actual,
@NotNull Stack<Pair<Integer, Integer>> history) {
assertEquals(expected.length(), actual.length());
for (int i = 0; i < expected.length(); i++) {
char expectedChar = expected.charAt(i);
char actualChar = actual.charAt(i);
if (expectedChar != actualChar) {
fail(String.format(
"Detected incorrect charAt() processing for result of subSequence() with deferred changes. Original text: '%s', "
+ "actual subSequence text: '%s', index: %d, expected symbol: '%c', actual symbol: '%c', subSequence history: %s",
myArray.toString(), expected, i, expectedChar, actualChar, history
));
}
}
if (!expected.equals(actual.toString())) {
fail(String.format(
"Detected incorrect toString() processing for result of subSequence() with deferred changes. Original text: '%s', "
+ "expected subSequence text: '%s', actual subSequence text: '%s', subSequence history: %s",
myArray.toString(), expected, actual.toString(), history
));
}
assertEquals(expected, actual.toString());
for (int start = 0; start < expected.length(); start++) {
for (int end = start; end < expected.length(); end++) {
history.push(new Pair<Integer, Integer>(start, end));
checkSubSequence(expected.substring(start, end), actual.subSequence(start, end), history);
history.pop();
}
}
}
private void replace(int startOffset, int endOffset, @NonNls String newText) {
myArray.replace(
startOffset, endOffset, myArray.substring(startOffset, endOffset), newText, LocalTimeCounter.currentTime(),
startOffset == 0 && endOffset == myArray.length()
);
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
private @interface Config {
String text() default "";
boolean deferred() default false;
}
}
@@ -1,3 +1,18 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.options
import com.intellij.openapi.application.invokeAndWaitIfNeed
@@ -9,7 +24,10 @@ import com.intellij.openapi.util.JDOMUtil
import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.text.StringUtil
import com.intellij.testFramework.FixtureRule
import com.intellij.testFramework.PlatformTestUtil
import com.intellij.testFramework.TemporaryDirectory
import com.intellij.testFramework.exists
import com.intellij.util.SmartList
import com.intellij.util.lang.CompoundRuntimeException
import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters
@@ -25,9 +43,6 @@ import org.hamcrest.CoreMatchers.sameInstance
import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.collection.IsMapContaining.hasKey
import org.jdom.Element
import org.jetbrains.testFramework.FixtureRule
import org.jetbrains.testFramework.TemporaryDirectory
import org.jetbrains.testFramework.exists
import org.junit.Rule
import org.junit.Test
import java.io.File
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -106,7 +106,7 @@ public class MockFileTypeManager extends FileTypeManagerEx {
}
@Override
public boolean isFileIgnored(@NonNls @NotNull VirtualFile file) {
public boolean isFileIgnored(@NotNull VirtualFile file) {
return false;
}
@@ -191,7 +191,7 @@ public class MockFileTypeManager extends FileTypeManagerEx {
@Nullable
@Override
public FileType findFileTypeByName(String fileTypeName) {
public FileType findFileTypeByName(@NotNull String fileTypeName) {
return null;
}
}
@@ -13,10 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.testFramework
package com.intellij.testFramework
import com.intellij.openapi.application.invokeAndWaitIfNeed
import com.intellij.testFramework.UsefulTestCase
import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory
import org.junit.rules.ExternalResource
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.testFramework
package com.intellij.testFramework
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.io.FileUtilRt
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.testFramework
package com.intellij.testFramework
import org.hamcrest.Description
import org.hamcrest.Factory
@@ -144,7 +144,7 @@ editor.soft.wrap.force.limit.description=If document contains lines longer than
editor.navigation.history.stack.size=25
editor.navigation.history.stack.size.description=Stack size limit for back/forward and last/next edit location navigation
editor.mac.smooth.scrolling=true
editor.mac.smooth.scrolling=false
editor.mac.smooth.scrolling.description=Enable precise (with sub-line resolution) scrolling on Mac with mouse or trackpad
ide.showIndexRebuildMessage=false
@@ -15,7 +15,6 @@
*/
package com.intellij.util.text;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
public class ByteArrayCharSequence implements CharSequence {
@@ -40,11 +39,6 @@ public class ByteArrayCharSequence implements CharSequence {
return h;
}
@Override
public boolean equals(Object obj) {
return obj instanceof CharSequence && StringUtil.equals(this, (CharSequence)obj);
}
@Override
public final int length() {
return myChars.length;
@@ -233,13 +233,15 @@ public class FileUtilHeavyTest {
public void testToCanonicalPathSymLinksAware() throws Exception {
assumeTrue(SystemInfo.areSymLinksSupported);
File root = IoTestUtil.createTestDir(myTempDirectory, "root");
assertTrue(new File(root, "dir1/dir2/dir3/dir4").mkdirs());
File rootDir = IoTestUtil.createTestDir(myTempDirectory, "root");
assertTrue(new File(rootDir, "dir1/dir2/dir3/dir4").mkdirs());
String root = FileUtil.toSystemIndependentName(FileUtil.resolveShortWindowsName(rootDir.getPath()));
// non-recursive link
IoTestUtil.createSymLink(new File(root, "dir1/dir2").getPath(), new File(root, "dir1/dir2_link").getPath());
IoTestUtil.createSymLink(new File(rootDir, "dir1/dir2").getPath(), new File(rootDir, "dir1/dir2_link").getPath());
// recursive links to a parent dir
IoTestUtil.createSymLink(new File(root, "dir1").getPath(), new File(root, "dir1/dir1_link").getPath());
IoTestUtil.createSymLink(new File(rootDir, "dir1").getPath(), new File(rootDir, "dir1/dir1_link").getPath());
// I) links should NOT be resolved when ../ stays inside the linked path
// I.I) non-recursive links
@@ -266,13 +268,25 @@ public class FileUtilHeavyTest {
assertEquals(root + "/dir1/dir2", FileUtil.toCanonicalPath(root + "/dir1/dir2_link/dir3/../../../dir1/dir2", true));
assertEquals(root + "/dir1/dir2", FileUtil.toCanonicalPath(root + "/dir1/../dir1/dir2_link/../dir2", true));
// II.I) recursive links
assertEquals(root.getPath(), FileUtil.toCanonicalPath(root + "/dir1/dir1_link/../", true));
assertEquals(root + "/dir1", FileUtil.toCanonicalPath(root + "/dir1/dir1_link/../dir1", true));
assertEquals(root + "/dir1", FileUtil.toCanonicalPath(root + "/dir1/dir1_link/../../root/dir1", true));
assertEquals(root + "/dir1", FileUtil.toCanonicalPath(root + "/dir1/dir1_link/dir3/../../dir1", true));
assertEquals(root + "/dir1", FileUtil.toCanonicalPath(root + "/dir1/dir1_link/dir3/../../../root/dir1", true));
assertEquals(root + "/dir1", FileUtil.toCanonicalPath(root + "/dir1/../dir1/dir1_link/../dir1", true));
// II.I) recursive links
// the rules seems to be different when ../ goes over recursive link:
// * on Windows ../ goes to link's parent
// * on Unix ../ goes to target's parent
if (SystemInfo.isWindows) {
assertEquals(root + "/dir1", FileUtil.toCanonicalPath(root + "/dir1/dir1_link/../", true));
assertEquals(root + "/dir1/dir2", FileUtil.toCanonicalPath(root + "/dir1/dir1_link/../dir2", true));
assertEquals(root + "/dir1/dir2", FileUtil.toCanonicalPath(root + "/dir1/dir1_link/../../dir1/dir2", true));
assertEquals(root + "/dir1/dir2", FileUtil.toCanonicalPath(root + "/dir1/dir1_link/dir2/../../dir2", true));
assertEquals(root + "/dir1/dir2", FileUtil.toCanonicalPath(root + "/dir1/dir1_link/dir2/../../../dir1/dir2", true));
assertEquals(root + "/dir1/dir2", FileUtil.toCanonicalPath(root + "/dir1/../dir1/dir1_link/../dir2", true));
} else {
assertEquals(root, FileUtil.toCanonicalPath(root + "/dir1/dir1_link/../", true));
assertEquals(root + "/dir1", FileUtil.toCanonicalPath(root + "/dir1/dir1_link/../dir1", true));
assertEquals(root + "/dir1", FileUtil.toCanonicalPath(root + "/dir1/dir1_link/../../root/dir1", true));
assertEquals(root + "/dir1", FileUtil.toCanonicalPath(root + "/dir1/dir1_link/dir2/../../dir1", true));
assertEquals(root + "/dir1", FileUtil.toCanonicalPath(root + "/dir1/dir1_link/dir2/../../../root/dir1", true));
assertEquals(root + "/dir1", FileUtil.toCanonicalPath(root + "/dir1/../dir1/dir1_link/../dir1", true));
}
// some corner cases, behavior should be the same as the default FileUtil.toCanonicalPath
assertEquals(FileUtil.toCanonicalPath("..", false), FileUtil.toCanonicalPath("..", true));
@@ -279,9 +279,9 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
vcsManager.addVcsListener(myVcsListener);
}
});
}
myConflictTracker.startTracking();
myConflictTracker.startTracking();
}
}
private void broadcastStateAfterLoad() {
@@ -225,20 +225,20 @@ postfix.prefix.intention.name=Replace with ''{0}''
#categories
intention.category.annotations=Annotations
intention.category.numbers=Numbers
intention.category.boolean=Boolean
intention.category.conditional.operator=Conditional Operator
intention.category.shift.operation=Shift Operation
intention.category.junit=JUnit
intention.category.declaration=Declaration
intention.category.imports=Imports
intention.category.comments=Comments
intention.category.control.flow=Control Flow
intention.category.strings=Strings
intention.category.modifiers=Modifiers
intention.category.try.statements=Try Statements
intention.category.other=Other
intention.category.annotations=Java/Annotations
intention.category.numbers=Java/Numbers
intention.category.boolean=Java/Boolean
intention.category.conditional.operator=Java/Conditional Operator
intention.category.shift.operation=Java/Shift Operation
intention.category.junit=Java/JUnit
intention.category.declaration=Java/Declaration
intention.category.imports=Java/Imports
intention.category.comments=Java/Comments
intention.category.control.flow=Java/Control Flow
intention.category.strings=Java/Strings
intention.category.modifiers=Java/Modifiers
intention.category.try.statements=Java/Try Statements
intention.category.other=Java/Other
#warnings
0.is.declared.in.1.but.when.public.should.be.declared.in.a.file.named.2={0} is declared in {1} but when public should be declared in a file named {2}
@@ -251,21 +251,7 @@ public class JavaCoverageViewExtension extends CoverageViewExtension {
}
});
for (final PsiFile file : childFiles) {
if (file instanceof PsiJavaFile) {
PsiClass[] classes = ApplicationManager.getApplication().runReadAction(new Computable<PsiClass[]>() {
public PsiClass[] compute() {
return file.isValid() ? ((PsiJavaFile) file).getClasses() : PsiClass.EMPTY_ARRAY;
}
});
if (classes.length > 0) {
PsiClass aClass = classes[0];
if (!(node instanceof CoverageListRootNode) && getClassCoverageInfo(aClass) == null) continue;
children.add(new CoverageListNode(myProject, aClass, mySuitesBundle, myStateBean));
}
}
else if (file instanceof PsiClassOwner) {
children.add(new CoverageListNode(myProject, file, mySuitesBundle, myStateBean));
}
collectFileChildren(file, node, children);
}
}
else if (!myStateBean.myFlattenPackages) {
@@ -287,6 +273,20 @@ public class JavaCoverageViewExtension extends CoverageViewExtension {
return children;
}
protected void collectFileChildren(final PsiFile file, AbstractTreeNode node, List<AbstractTreeNode> children) {
if (file instanceof PsiClassOwner) {
PsiClass[] classes = ApplicationManager.getApplication().runReadAction(new Computable<PsiClass[]>() {
public PsiClass[] compute() {
return file.isValid() ? ((PsiClassOwner) file).getClasses() : PsiClass.EMPTY_ARRAY;
}
});
for (PsiClass aClass : classes) {
if (!(node instanceof CoverageListRootNode) && getClassCoverageInfo(aClass) == null) continue;
children.add(new CoverageListNode(myProject, aClass, mySuitesBundle, myStateBean));
}
}
}
@Nullable
private PackageAnnotator.ClassCoverageInfo getClassCoverageInfo(final PsiClass aClass) {
return myAnnotator.getClassCoverageInfo(ApplicationManager.getApplication().runReadAction(new NullableComputable<String>() {
+1 -1
View File
@@ -142,7 +142,7 @@
<stacktrace.fold substring="at com.intellij.openapi.application.impl.ApplicationImpl.runWriteAction("/>
<stacktrace.fold substring="at com.intellij.openapi.application.impl.ApplicationImpl.runReadAction("/>
<stacktrace.fold substring="at com.intellij.openapi.application.RunResult.run("/>
<stacktrace.fold substring="at com.intellij.openapi.command.impl.CommandProcessorImpl.executeCommand("/>
<stacktrace.fold substring="at com.intellij.openapi.command.impl.CoreCommandProcessor.executeCommand("/>
<codeInsight.lineMarkerProvider language="JAVA"
implementationClass="org.jetbrains.idea.devkit.navigation.DescriptionTypeRelatedItemLineMarkerProvider"/>
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
+1 -1
View File
@@ -63,7 +63,7 @@
<intentionAction>
<className>com.intellij.codeInspection.capitalization.AnnotateCapitalizationIntention</className>
<category>I18N</category>
<category>Java/I18N</category>
</intentionAction>
</extensions>
@@ -266,6 +266,11 @@ private layoutFull(Map args, String target, Set usedJars) {
fileset(file: it)
}
fileset(dir: "$ch/build/kotlinc/lib") {
include(name: "kotlin-runtime.jar")
include(name: "kotlin-reflect.jar")
}
dir("libpty") {
fileset(dir: "$ch/lib/libpty") {
exclude(name: "*.txt")
+5
View File
@@ -303,6 +303,11 @@ private layoutFull(Map args, String target, Set usedJars) {
fileset(file: it)
}
fileset(dir: "$ch/build/kotlinc/lib") {
include(name: "kotlin-runtime.jar")
include(name: "kotlin-reflect.jar")
}
dir("libpty") {
fileset(dir: "$ch/lib/libpty") {
exclude(name: "*.txt")
+12 -5
View File
@@ -4,7 +4,7 @@ import pstats
from prof_util import statsToResponse
from _prof_imports import TSerialization
from _prof_imports import TJSONProtocol
from _prof_imports import TBinaryProtocol
from _prof_imports import ProfilerResponse
from _prof_imports import IS_PY3K
@@ -19,13 +19,20 @@ if __name__ == '__main__':
statsToResponse(stats.stats, m)
data = TSerialization.serialize(m, TJSONProtocol.TJSONProtocolFactory())
data = TSerialization.serialize(m, TBinaryProtocol.TBinaryProtocolFactory())
# setup stdout to write binary data to it
if IS_PY3K:
data = data.decode("utf-8")
out = sys.stdout.buffer
elif sys.platform == 'win32':
import os, msvcrt
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
out = sys.stdout
else:
out = sys.stdout
sys.stdout.write(data)
sys.stdout.flush()
out.write(data)
out.flush()
+3 -3
View File
@@ -1,7 +1,7 @@
import traceback
from _prof_imports import TSerialization
from _prof_imports import TJSONProtocol
from _prof_imports import TBinaryProtocol
from _prof_imports import ProfilerRequest
from _prof_imports import IS_PY3K
@@ -15,7 +15,7 @@ def send_message(sock, message):
to a socket, prepended by its length packed in 4
bytes (big endian).
"""
s = TSerialization.serialize(message, TJSONProtocol.TJSONProtocolFactory())
s = TSerialization.serialize(message, TBinaryProtocol.TBinaryProtocolFactory())
packed_len = struct.pack('>L', len(s))
sock.sendall(packed_len + s)
@@ -29,7 +29,7 @@ def get_message(sock, msgtype):
msg_buf = socket_read_n(sock, msg_len)
msg = msgtype()
TSerialization.deserialize(msg, msg_buf, TJSONProtocol.TJSONProtocolFactory())
TSerialization.deserialize(msg, msg_buf, TBinaryProtocol.TBinaryProtocolFactory())
return msg
+1 -2
View File
@@ -15,8 +15,7 @@ The Python plug-in provides smart editing for Python scripts. The feature set of
<a href="https://youtrack.jetbrains.com/issues/PY">Issue tracker</a><br>
]]></description>
<!-- <PyCharm version> <Build number> -->
<version>@@PYCHARM_VERSION@@ @@BUILD_NUMBER@@</version>
<version>@@PYCHARM_VERSION@@</version>
<depends>com.intellij.modules.java</depends>
@@ -23,6 +23,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.QualifiedName;
import com.intellij.util.containers.ContainerUtil;
@@ -58,7 +59,6 @@ public class PyPsiUtils {
/**
* Finds the closest comma after the element skipping any whitespaces in-between.
* @param element
*/
@Nullable
public static PsiElement getPrevComma(@NotNull PsiElement element) {
@@ -66,13 +66,36 @@ public class PyPsiUtils {
return prevNode != null && prevNode.getNode().getElementType() == PyTokenTypes.COMMA ? prevNode : null;
}
/**
* Finds first non-whitespace sibling before given PSI element.
*/
@Nullable
public static PsiElement getPrevNonWhitespaceSibling(@NotNull PsiElement element) {
public static PsiElement getPrevNonWhitespaceSibling(@Nullable PsiElement element) {
return PsiTreeUtil.skipSiblingsBackward(element, PsiWhiteSpace.class);
}
/**
* Finds the closest comma before the element skipping any whitespaces in-between.
* Finds first non-whitespace sibling before given AST node.
*/
@Nullable
public static ASTNode getPrevNonWhitespaceSibling(@NotNull ASTNode node) {
return skipSiblingsBackward(node, TokenSet.create(TokenType.WHITE_SPACE));
}
/**
* Finds first sibling that is neither comment, nor whitespace before given element.
* @param strict prohibit returning element itself
*/
@Nullable
public static PsiElement getPrevNonCommentSibling(@Nullable PsiElement start, boolean strict) {
if (!strict && !(start instanceof PsiWhiteSpace || start instanceof PsiComment)) {
return start;
}
return PsiTreeUtil.skipSiblingsBackward(start, PsiWhiteSpace.class, PsiComment.class);
}
/**
* Finds the closest comma after the element skipping any whitespaces in-between.
*/
@Nullable
public static PsiElement getNextComma(@NotNull PsiElement element) {
@@ -80,11 +103,58 @@ public class PyPsiUtils {
return nextNode != null && nextNode.getNode().getElementType() == PyTokenTypes.COMMA ? nextNode : null;
}
/**
* Finds first non-whitespace sibling after given PSI element.
*/
@Nullable
public static PsiElement getNextNonWhitespaceSibling(@NotNull PsiElement element) {
public static PsiElement getNextNonWhitespaceSibling(@Nullable PsiElement element) {
return PsiTreeUtil.skipSiblingsForward(element, PsiWhiteSpace.class);
}
/**
* Finds first non-whitespace sibling after given AST node.
*/
@Nullable
public static ASTNode getNextNonWhitespaceSibling(@NotNull ASTNode after) {
return skipSiblingsForward(after, TokenSet.create(TokenType.WHITE_SPACE));
}
/**
* Finds first sibling that is neither comment, nor whitespace after given element.
* @param strict prohibit returning element itself
*/
@Nullable
public static PsiElement getNextNonCommentSibling(@Nullable PsiElement start, boolean strict) {
if (!strict && !(start instanceof PsiWhiteSpace || start instanceof PsiComment)) {
return start;
}
return PsiTreeUtil.skipSiblingsForward(start, PsiWhiteSpace.class, PsiComment.class);
}
/**
* Finds first token after given element that doesn't consist solely of spaces and is not empty (e.g. error marker).
* @param ignoreComments ignore commentaries as well
*/
@Nullable
public static PsiElement getNextSignificantLeaf(@Nullable PsiElement element, boolean ignoreComments) {
while (element != null && StringUtil.isEmptyOrSpaces(element.getText()) || ignoreComments && element instanceof PsiComment) {
element = PsiTreeUtil.nextLeaf(element);
}
return element;
}
/**
* Finds first token before given element that doesn't consist solely of spaces and is not empty (e.g. error marker).
* @param ignoreComments ignore commentaries as well
*/
@Nullable
public static PsiElement getPrevSignificantLeaf(@Nullable PsiElement element, boolean ignoreComments) {
while (element != null && StringUtil.isEmptyOrSpaces(element.getText()) || ignoreComments && element instanceof PsiComment) {
element = PsiTreeUtil.prevLeaf(element);
}
return element;
}
/**
* Finds the closest comma looking for the next comma first and then for the preceding one.
*/
@@ -94,6 +164,70 @@ public class PyPsiUtils {
return nextComma != null ? nextComma : getPrevComma(element);
}
/**
* Works similarly to {@link PsiTreeUtil#skipSiblingsForward(PsiElement, Class[])}, but for AST nodes.
*/
@Nullable
public static ASTNode skipSiblingsForward(@Nullable ASTNode node, @NotNull TokenSet types) {
if (node == null) {
return null;
}
for (ASTNode next = node.getTreeNext(); next != null; next = next.getTreeNext()) {
if (!types.contains(next.getElementType())) {
return next;
}
}
return null;
}
/**
* Works similarly to {@link PsiTreeUtil#skipSiblingsBackward(PsiElement, Class[])}, but for AST nodes.
*/
@Nullable
public static ASTNode skipSiblingsBackward(@Nullable ASTNode node, @NotNull TokenSet types) {
if (node == null) {
return null;
}
for (ASTNode prev = node.getTreePrev(); prev != null; prev = prev.getTreePrev()) {
if (!types.contains(prev.getElementType())) {
return prev;
}
}
return null;
}
/**
* Returns first child psi element with specified element type or {@code null} if no such element exists.
* Semantically it's the same as {@code getChildByFilter(element, TokenSet.create(type), 0)}.
*
* @param element tree parent node
* @param type element type expected
* @return child element described
*/
@Nullable
public static PsiElement getFirstChildOfType(@NotNull final PsiElement element, @NotNull PyElementType type) {
final ASTNode child = element.getNode().findChildByType(type);
return child != null ? child.getPsi() : null;
}
/**
* Returns child element in the psi tree
*
* @param filter Types of expected child
* @param number number
* @param element tree parent node
* @return PsiElement - child psiElement
*/
@Nullable
public static PsiElement getChildByFilter(@NotNull PsiElement element, @NotNull TokenSet filter, int number) {
final ASTNode node = element.getNode();
if (node != null) {
final ASTNode[] children = node.getChildren(filter);
return (0 <= number && number < children.length) ? children[number].getPsi() : null;
}
return null;
}
public static void addBeforeInParent(@NotNull final PsiElement anchor, @NotNull final PsiElement... newElements) {
final ASTNode anchorNode = anchor.getNode();
LOG.assertTrue(anchorNode != null);
@@ -326,22 +460,6 @@ public class PyPsiUtils {
return result;
}
@Nullable
public static PsiElement getSignificantToTheRight(PsiElement element, final boolean ignoreComments) {
while (element != null && StringUtil.isEmptyOrSpaces(element.getText()) || ignoreComments && element instanceof PsiComment) {
element = PsiTreeUtil.nextLeaf(element);
}
return element;
}
@Nullable
public static PsiElement getSignificantToTheLeft(PsiElement element, final boolean ignoreComments) {
while (element != null && StringUtil.isEmptyOrSpaces(element.getText()) || ignoreComments && element instanceof PsiComment) {
element = PsiTreeUtil.prevLeaf(element);
}
return element;
}
public static int findArgumentIndex(PyCallExpression call, PsiElement argument) {
final PyExpression[] args = call.getArguments();
for (int i = 0; i < args.length; i++) {
@@ -31,6 +31,7 @@ import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.PythonFileType;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.psi.PyUtil;
import com.jetbrains.python.psi.impl.PyPsiUtils;
/**
* Adds appropriate first parameter to a freshly-typed method declaration.
@@ -55,7 +56,7 @@ public class PyMethodNameTypedHandler extends TypedHandlerDelegate {
final ASTNode token_node = token.getNode();
if (token_node != null && token_node.getElementType() == PyTokenTypes.IDENTIFIER) {
PsiElement maybe_def = PyUtil.getFirstNonCommentBefore(token.getPrevSibling());
PsiElement maybe_def = PyPsiUtils.getPrevNonCommentSibling(token.getPrevSibling(), false);
if (maybe_def != null) {
ASTNode def_node = maybe_def.getNode();
if (def_node != null && def_node.getElementType() == PyTokenTypes.DEF_KEYWORD) {
@@ -24,7 +24,7 @@ import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterPro
import com.jetbrains.python.psi.PyArgumentList;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyDecorator;
import com.jetbrains.python.psi.PyUtil;
import com.jetbrains.python.psi.impl.PyPsiUtils;
import org.jetbrains.annotations.NotNull;
/**
@@ -37,9 +37,9 @@ public class PyArgumentListFixer extends PyFixer<PyArgumentList> {
@Override
public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyArgumentList arguments) throws IncorrectOperationException {
final PsiElement rBrace = PyUtil.getChildByFilter(arguments, PyTokenTypes.CLOSE_BRACES, 0);
final PsiElement rBrace = PyPsiUtils.getChildByFilter(arguments, PyTokenTypes.CLOSE_BRACES, 0);
if (arguments.getParent() instanceof PyClass || arguments.getParent() instanceof PyDecorator) {
final PsiElement lBrace = PyUtil.getChildByFilter(arguments, PyTokenTypes.OPEN_BRACES, 0);
final PsiElement lBrace = PyPsiUtils.getChildByFilter(arguments, PyTokenTypes.OPEN_BRACES, 0);
if (lBrace != null && rBrace == null) {
final Document document = editor.getDocument();
document.insertString(arguments.getTextRange().getEndOffset(), ")");
@@ -23,7 +23,7 @@ import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
import com.jetbrains.python.psi.PyArgumentList;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyUtil;
import com.jetbrains.python.psi.impl.PyPsiUtils;
import org.jetbrains.annotations.NotNull;
import static com.jetbrains.python.psi.PyUtil.sure;
@@ -40,7 +40,7 @@ public class PyClassFixer extends PyFixer<PyClass> {
}
public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyClass pyClass) throws IncorrectOperationException {
final PsiElement colon = PyUtil.getFirstChildOfType(pyClass, PyTokenTypes.COLON);
final PsiElement colon = PyPsiUtils.getFirstChildOfType(pyClass, PyTokenTypes.COLON);
if (colon == null) {
final PyArgumentList argList = PsiTreeUtil.getChildOfType(pyClass, PyArgumentList.class);
final int colonOffset = sure(argList).getTextRange().getEndOffset();
@@ -24,7 +24,7 @@ import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
import com.jetbrains.python.psi.PyConditionalStatementPart;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.PyUtil;
import com.jetbrains.python.psi.impl.PyPsiUtils;
import org.jetbrains.annotations.NotNull;
import static com.jetbrains.python.psi.PyUtil.sure;
@@ -45,18 +45,18 @@ public class PyConditionalStatementPartFixer extends PyFixer<PyConditionalStatem
throws IncorrectOperationException {
final PyExpression condition = statementPart.getCondition();
final Document document = editor.getDocument();
final PsiElement colon = PyUtil.getFirstChildOfType(statementPart, PyTokenTypes.COLON);
final PsiElement colon = PyPsiUtils.getFirstChildOfType(statementPart, PyTokenTypes.COLON);
if (colon == null) {
if (condition != null) {
final PsiElement firstNonComment = PyUtil.getFirstNonCommentAfter(condition.getNextSibling());
final PsiElement firstNonComment = PyPsiUtils.getNextNonCommentSibling(condition.getNextSibling(), false);
if (firstNonComment != null && !":".equals(firstNonComment.getNode().getText())) {
document.insertString(firstNonComment.getTextRange().getEndOffset(), ":");
}
}
else {
final TokenSet keywords = TokenSet.create(PyTokenTypes.IF_KEYWORD, PyTokenTypes.ELIF_KEYWORD, PyTokenTypes.WHILE_KEYWORD);
final PsiElement keywordToken = PyUtil.getChildByFilter(statementPart,
keywords, 0);
final PsiElement keywordToken = PyPsiUtils.getChildByFilter(statementPart,
keywords, 0);
final int offset = sure(keywordToken).getTextRange().getEndOffset();
document.insertString(offset, " :");
processor.registerUnresolvedError(offset + 1);
@@ -22,7 +22,7 @@ import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
import com.jetbrains.python.psi.PyExceptPart;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.PyUtil;
import com.jetbrains.python.psi.impl.PyPsiUtils;
import org.jetbrains.annotations.NotNull;
import static com.jetbrains.python.psi.PyUtil.sure;
@@ -40,9 +40,9 @@ public class PyExceptFixer extends PyFixer<PyExceptPart> {
@Override
public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyExceptPart exceptPart) throws IncorrectOperationException {
final PsiElement colon = PyUtil.getFirstChildOfType(exceptPart, PyTokenTypes.COLON);
final PsiElement colon = PyPsiUtils.getFirstChildOfType(exceptPart, PyTokenTypes.COLON);
if (colon == null) {
final PsiElement exceptToken = PyUtil.getFirstChildOfType(exceptPart, PyTokenTypes.EXCEPT_KEYWORD);
final PsiElement exceptToken = PyPsiUtils.getFirstChildOfType(exceptPart, PyTokenTypes.EXCEPT_KEYWORD);
int offset = sure(exceptToken).getTextRange().getEndOffset();
final PyExpression exceptClass = exceptPart.getExceptClass();
if (exceptClass != null) {
@@ -21,7 +21,7 @@ import com.intellij.psi.PsiElement;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
import com.jetbrains.python.psi.PyForPart;
import com.jetbrains.python.psi.PyUtil;
import com.jetbrains.python.psi.impl.PyPsiUtils;
import org.jetbrains.annotations.NotNull;
import static com.jetbrains.python.psi.PyUtil.sure;
@@ -39,16 +39,16 @@ public class PyForPartFixer extends PyFixer<PyForPart> {
@Override
public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyForPart forPart) {
final PsiElement colon = PyUtil.getFirstChildOfType(forPart, PyTokenTypes.COLON);
final PsiElement colon = PyPsiUtils.getFirstChildOfType(forPart, PyTokenTypes.COLON);
final Document document = editor.getDocument();
final PsiElement forToken = PyUtil.getFirstChildOfType(forPart, PyTokenTypes.FOR_KEYWORD);
final PsiElement forToken = PyPsiUtils.getFirstChildOfType(forPart, PyTokenTypes.FOR_KEYWORD);
if (colon == null) {
String textToInsert = ":";
PsiElement sourceOrTarget = forPart.getSource();
PsiElement positionToInsert = sourceOrTarget;
if (sourceOrTarget == null) {
sourceOrTarget = forPart.getTarget();
final PsiElement inToken = PyUtil.getFirstChildOfType(forPart, PyTokenTypes.IN_KEYWORD);
final PsiElement inToken = PyPsiUtils.getFirstChildOfType(forPart, PyTokenTypes.IN_KEYWORD);
if (inToken == null) {
if (sourceOrTarget == null) {
positionToInsert = sure(forToken);
@@ -22,7 +22,7 @@ import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.psi.PyParameterList;
import com.jetbrains.python.psi.PyUtil;
import com.jetbrains.python.psi.impl.PyPsiUtils;
import org.jetbrains.annotations.NotNull;
/**
@@ -39,7 +39,7 @@ public class PyFunctionFixer extends PyFixer<PyFunction> {
@Override
public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyFunction function)
throws IncorrectOperationException {
final PsiElement colon = PyUtil.getFirstChildOfType(function, PyTokenTypes.COLON);
final PsiElement colon = PyPsiUtils.getFirstChildOfType(function, PyTokenTypes.COLON);
if (!isFakeFunction(function) && colon == null) {
final PyParameterList parameterList = function.getParameterList();
if (function.getNameNode() == null) {
@@ -20,6 +20,7 @@ import com.intellij.psi.PsiElement;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyPsiUtils;
import org.jetbrains.annotations.NotNull;
/**
@@ -37,7 +38,7 @@ public class PyMissingBracesFixer extends PyFixer<PyElement> {
public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyElement psiElement)
throws IncorrectOperationException {
if (psiElement instanceof PySetLiteralExpression || psiElement instanceof PyDictLiteralExpression) {
final PsiElement lastChild = PyUtil.getFirstNonCommentBefore(psiElement.getLastChild());
final PsiElement lastChild = PyPsiUtils.getPrevNonCommentSibling(psiElement.getLastChild(), false);
if (lastChild != null && !"}".equals(lastChild.getText())) {
editor.getDocument().insertString(lastChild.getTextRange().getEndOffset(), "}");
}
@@ -45,7 +46,7 @@ public class PyMissingBracesFixer extends PyFixer<PyElement> {
else if (psiElement instanceof PyListLiteralExpression ||
psiElement instanceof PySliceExpression ||
psiElement instanceof PySubscriptionExpression) {
final PsiElement lastChild = PyUtil.getFirstNonCommentBefore(psiElement.getLastChild());
final PsiElement lastChild = PyPsiUtils.getPrevNonCommentSibling(psiElement.getLastChild(), false);
if (lastChild != null && !"]".equals(lastChild.getText())) {
editor.getDocument().insertString(lastChild.getTextRange().getEndOffset(), "]");
}
@@ -23,7 +23,7 @@ import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.psi.PyParameterList;
import com.jetbrains.python.psi.PyUtil;
import com.jetbrains.python.psi.impl.PyPsiUtils;
import org.jetbrains.annotations.NotNull;
import static com.jetbrains.python.psi.PyUtil.as;
@@ -42,8 +42,8 @@ public class PyParameterListFixer extends PyFixer<PyParameterList> {
@Override
public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyParameterList parameters)
throws IncorrectOperationException {
final PsiElement lBrace = PyUtil.getChildByFilter(parameters, PyTokenTypes.OPEN_BRACES, 0);
final PsiElement rBrace = PyUtil.getChildByFilter(parameters, PyTokenTypes.CLOSE_BRACES, 0);
final PsiElement lBrace = PyPsiUtils.getChildByFilter(parameters, PyTokenTypes.OPEN_BRACES, 0);
final PsiElement rBrace = PyPsiUtils.getChildByFilter(parameters, PyTokenTypes.CLOSE_BRACES, 0);
final PyFunction pyFunction = as(parameters.getParent(), PyFunction.class);
if (pyFunction != null && !PyFunctionFixer.isFakeFunction(pyFunction) && (lBrace == null || rBrace == null)) {
final Document document = editor.getDocument();
@@ -22,6 +22,7 @@ import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyPsiUtils;
import org.jetbrains.annotations.NotNull;
import static com.jetbrains.python.psi.PyUtil.sure;
@@ -41,10 +42,10 @@ public class PyUnconditionalStatementPartFixer extends PyFixer<PyElement> {
public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyElement psiElement)
throws IncorrectOperationException {
if (PyUtil.instanceOf(psiElement, PyElsePart.class, PyTryPart.class, PyFinallyPart.class)) {
final PsiElement colon = PyUtil.getFirstChildOfType(psiElement, PyTokenTypes.COLON);
final PsiElement colon = PyPsiUtils.getFirstChildOfType(psiElement, PyTokenTypes.COLON);
if (colon == null) {
final TokenSet keywords = TokenSet.create(PyTokenTypes.ELSE_KEYWORD, PyTokenTypes.TRY_KEYWORD, PyTokenTypes.FINALLY_KEYWORD);
final PsiElement keywordToken = PyUtil.getChildByFilter(psiElement, keywords, 0);
final PsiElement keywordToken = PyPsiUtils.getChildByFilter(psiElement, keywords, 0);
editor.getDocument().insertString(sure(keywordToken).getTextRange().getEndOffset(), ":");
}
}
@@ -23,9 +23,9 @@ import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.PyUtil;
import com.jetbrains.python.psi.PyWithItem;
import com.jetbrains.python.psi.PyWithStatement;
import com.jetbrains.python.psi.impl.PyPsiUtils;
import org.jetbrains.annotations.NotNull;
/**
@@ -38,8 +38,8 @@ public class PyWithFixer extends PyFixer<PyWithStatement> {
@Override
public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyWithStatement withStatement) throws IncorrectOperationException {
final PsiElement colonToken = PyUtil.getFirstChildOfType(withStatement, PyTokenTypes.COLON);
final PsiElement withToken = PyUtil.getFirstChildOfType(withStatement, PyTokenTypes.WITH_KEYWORD);
final PsiElement colonToken = PyPsiUtils.getFirstChildOfType(withStatement, PyTokenTypes.COLON);
final PsiElement withToken = PyPsiUtils.getFirstChildOfType(withStatement, PyTokenTypes.WITH_KEYWORD);
final Document document = editor.getDocument();
if (colonToken == null && withToken != null) {
int insertAt = withToken.getTextRange().getEndOffset();
@@ -52,7 +52,7 @@ public class PyWithFixer extends PyFixer<PyWithStatement> {
else {
final PyExpression expression = lastItem.getExpression();
insertAt = expression.getTextRange().getEndOffset();
final PsiElement asToken = PyUtil.getFirstChildOfType(lastItem, PyTokenTypes.AS_KEYWORD);
final PsiElement asToken = PyPsiUtils.getFirstChildOfType(lastItem, PyTokenTypes.AS_KEYWORD);
if (asToken != null) {
insertAt = asToken.getTextRange().getEndOffset();
final PyExpression target = lastItem.getTarget();
@@ -26,6 +26,7 @@ import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyPsiUtils;
import org.jetbrains.annotations.NotNull;
/**
@@ -54,11 +55,11 @@ public class PySplitIfIntention extends BaseIntentionAction {
final IElementType elementType = elementAtOffset.getNode().getElementType();
if (elementType == PyTokenTypes.COLON) {
elementAtOffset = elementAtOffset.getPrevSibling();
elementAtOffset = PyUtil.getFirstNonCommentBefore(elementAtOffset);
elementAtOffset = PyPsiUtils.getPrevNonCommentSibling(elementAtOffset, false);
}
else if (elementType == PyTokenTypes.IF_KEYWORD) {
elementAtOffset = elementAtOffset.getNextSibling();
elementAtOffset = PyUtil.getFirstNonCommentAfter(elementAtOffset);
elementAtOffset = PyPsiUtils.getNextNonCommentSibling(elementAtOffset, false);
}
PsiElement element = PsiTreeUtil.getParentOfType(elementAtOffset, PyBinaryExpression.class, false);
@@ -87,11 +88,11 @@ public class PySplitIfIntention extends BaseIntentionAction {
final IElementType elementType = elementAtOffset.getNode().getElementType();
if (elementType == PyTokenTypes.COLON) {
elementAtOffset = elementAtOffset.getPrevSibling();
elementAtOffset = PyUtil.getFirstNonCommentBefore(elementAtOffset);
elementAtOffset = PyPsiUtils.getPrevNonCommentSibling(elementAtOffset, false);
}
else if (elementType == PyTokenTypes.IF_KEYWORD) {
elementAtOffset = elementAtOffset.getNextSibling();
elementAtOffset = PyUtil.getFirstNonCommentAfter(elementAtOffset);
elementAtOffset = PyPsiUtils.getNextNonCommentSibling(elementAtOffset, false);
}
PyBinaryExpression element = PsiTreeUtil.getParentOfType(elementAtOffset, PyBinaryExpression.class, false);
@@ -64,8 +64,8 @@ public class DocStringUtil {
@Nullable
public static PyStringLiteralExpression findDocStringExpression(@Nullable PyElement parent) {
if (parent != null) {
PsiElement seeker = PyUtil.getFirstNonCommentAfter(parent.getFirstChild());
if (seeker instanceof PyExpressionStatement) seeker = PyUtil.getFirstNonCommentAfter(seeker.getFirstChild());
PsiElement seeker = PyPsiUtils.getNextNonCommentSibling(parent.getFirstChild(), false);
if (seeker instanceof PyExpressionStatement) seeker = PyPsiUtils.getNextNonCommentSibling(seeker.getFirstChild(), false);
if (seeker instanceof PyStringLiteralExpression) return (PyStringLiteralExpression)seeker;
}
return null;
@@ -51,7 +51,6 @@ import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings.IndentOptions;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.tree.TokenSet;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.QualifiedName;
import com.intellij.ui.awt.RelativePoint;
@@ -100,44 +99,6 @@ public class PyUtil {
private PyUtil() {
}
public static ASTNode getNextNonWhitespace(ASTNode after) {
ASTNode node = after;
do {
node = node.getTreeNext();
}
while (isWhitespace(node));
return node;
}
public static ASTNode getPreviousNonWhitespace(ASTNode after) {
ASTNode node = after;
do {
node = node.getTreePrev();
}
while (isWhitespace(node));
return node;
}
private static boolean isWhitespace(ASTNode node) {
return node != null && node.getElementType().equals(TokenType.WHITE_SPACE);
}
@Nullable
public static PsiElement getFirstNonCommentAfter(PsiElement start) {
PsiElement seeker = start;
while (seeker instanceof PsiWhiteSpace || seeker instanceof PsiComment) seeker = seeker.getNextSibling();
return seeker;
}
@Nullable
public static PsiElement getFirstNonCommentBefore(PsiElement start) {
PsiElement seeker = start;
while (seeker instanceof PsiWhiteSpace || seeker instanceof PsiComment) {
seeker = seeker.getPrevSibling();
}
return seeker;
}
@NotNull
public static <T extends PyElement> T[] getAllChildrenOfType(@NotNull PsiElement element, @NotNull Class<T> aClass) {
List<T> result = new SmartList<T>();
@@ -917,38 +878,6 @@ public class PyUtil {
}
}
/**
* Returns child element in the psi tree
*
* @param filter Types of expected child
* @param number number
* @param element tree parent node
* @return PsiElement - child psiElement
*/
@Nullable
public static PsiElement getChildByFilter(@NotNull final PsiElement element, final @NotNull TokenSet filter, final int number) {
final ASTNode node = element.getNode();
if (node != null) {
final ASTNode[] children = node.getChildren(filter);
return (0 <= number && number < children.length) ? children[number].getPsi() : null;
}
return null;
}
/**
* Returns first child psi element with specified element type or {@code null} if no such element exists.
* Semantically it's the same as {@code getChildByFilter(element, TokenSet.create(type), 0)}.
*
* @param element tree parent node
* @param type element type expected
* @return child element described
*/
@Nullable
public static PsiElement getFirstChildOfType(@NotNull final PsiElement element, @NotNull PyElementType type) {
final ASTNode child = element.getNode().findChildByType(type);
return child != null ? child.getPsi() : null;
}
/**
* If argument is a PsiDirectory, turn it into a PsiFile that points to __init__.py in that directory.
* If there's no __init__.py there, null is returned, there's no point to resolve to a dir which is not a package.
@@ -157,7 +157,7 @@ public class PyArgumentListImpl extends PyElementImpl implements PyArgumentList
}
}
else {
ASTNode before = PyUtil.getNextNonWhitespace(pars[0]);
ASTNode before = PyPsiUtils.getNextNonWhitespaceSibling(pars[0]);
ASTNode anchorBefore;
if (before != null && elementPrecedesElementsOfType(before, PythonDialectsTokenSetProvider.INSTANCE.getExpressionTokens())) {
ASTNode comma = createComma();
@@ -265,7 +265,7 @@ public class PyArgumentListImpl extends PyElementImpl implements PyArgumentList
break;
}
else if (type == PyTokenTypes.COMMA) {
ASTNode next = PyUtil.getNextNonWhitespace(node);
ASTNode next = PyPsiUtils.getNextNonWhitespaceSibling(node);
if (next == null) {
addArgumentLastWithoutComma(argument);
}
@@ -19,11 +19,10 @@ import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.PythonDialectsTokenSetProvider;
import com.jetbrains.python.psi.PyUtil;
import org.jetbrains.annotations.NotNull;
import com.jetbrains.python.psi.PyAugAssignmentStatement;
import com.jetbrains.python.psi.PyElementVisitor;
import com.jetbrains.python.psi.PyExpression;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
@@ -55,6 +54,6 @@ public class PyAugAssignmentStatementImpl extends PyElementImpl implements PyAug
@Nullable
public PsiElement getOperation() {
return PyUtil.getChildByFilter(this, PyTokenTypes.AUG_ASSIGN_OPERATIONS, 0);
return PyPsiUtils.getChildByFilter(this, PyTokenTypes.AUG_ASSIGN_OPERATIONS, 0);
}
}

Some files were not shown because too many files have changed in this diff Show More