mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
+15
@@ -31,6 +31,8 @@ import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.controlFlow.*;
|
||||
import com.intellij.psi.search.LocalSearchScope;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.Processor;
|
||||
@@ -75,6 +77,19 @@ public class FieldCanBeLocalInspectionBase extends BaseJavaBatchLocalInspectionT
|
||||
|
||||
for (final PsiField field : candidates) {
|
||||
if (usedFields.contains(field) && !hasImplicitReadOrWriteUsage(field, implicitUsageProviders)) {
|
||||
if (!ReferencesSearch.search(field, new LocalSearchScope(aClass)).forEach(new Processor<PsiReference>() {
|
||||
@Override
|
||||
public boolean process(PsiReference reference) {
|
||||
final PsiElement element = reference.getElement();
|
||||
if (element instanceof PsiReferenceExpression) {
|
||||
final PsiElement qualifier = ((PsiReferenceExpression)element).getQualifier();
|
||||
return qualifier == null || qualifier instanceof PsiThisExpression && ((PsiThisExpression)qualifier).getQualifier() == null;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
})) {
|
||||
continue;
|
||||
}
|
||||
final String message = InspectionsBundle.message("inspection.field.can.be.local.problem.descriptor");
|
||||
final ArrayList<LocalQuickFix> fixes = new ArrayList<LocalQuickFix>();
|
||||
SpecialAnnotationsUtilBase.createAddToSpecialAnnotationFixes(field, new Processor<String>() {
|
||||
|
||||
+2
-1
@@ -158,8 +158,9 @@ public class InvertIfConditionAction extends PsiElementBaseIntentionAction {
|
||||
}
|
||||
|
||||
private static PsiElement findCodeBlock(PsiIfStatement ifStatement) {
|
||||
PsiElement e = PsiTreeUtil.getParentOfType(ifStatement, PsiMethod.class, PsiClassInitializer.class);
|
||||
PsiElement e = PsiTreeUtil.getParentOfType(ifStatement, PsiMethod.class, PsiClassInitializer.class, PsiLambdaExpression.class);
|
||||
if (e instanceof PsiMethod) return ((PsiMethod) e).getBody();
|
||||
if (e instanceof PsiLambdaExpression) return ((PsiLambdaExpression)e).getBody();
|
||||
if (e instanceof PsiClassInitializer) return ((PsiClassInitializer) e).getBody();
|
||||
return null;
|
||||
}
|
||||
|
||||
+2
-17
@@ -15,14 +15,11 @@
|
||||
*/
|
||||
package com.intellij.codeInspection.deadCode;
|
||||
|
||||
import com.intellij.codeInspection.GlobalInspectionContext;
|
||||
import com.intellij.codeInspection.InspectionsBundle;
|
||||
import com.intellij.codeInspection.ex.EntryPointsManager;
|
||||
import com.intellij.codeInspection.ex.EntryPointsManagerImpl;
|
||||
import com.intellij.codeInspection.reference.EntryPoint;
|
||||
import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection;
|
||||
import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspectionBase;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectManager;
|
||||
import com.intellij.ui.components.JBTabbedPane;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
|
||||
@@ -53,17 +50,6 @@ public class UnusedDeclarationInspection extends UnusedDeclarationInspectionBase
|
||||
return tabs;
|
||||
}
|
||||
|
||||
private Project guessProject() {
|
||||
final GlobalInspectionContext context = getContext();
|
||||
Project project = context == null ? null : context.getProject();
|
||||
|
||||
if (project == null) {
|
||||
Project[] openProjects = ProjectManager.getInstance().getOpenProjects();
|
||||
project = openProjects.length == 0 ? ProjectManager.getInstance().getDefaultProject() : openProjects[0];
|
||||
}
|
||||
return project;
|
||||
}
|
||||
|
||||
private class OptionsPanel extends JPanel {
|
||||
private final JCheckBox myMainsCheckbox;
|
||||
private final JCheckBox myAppletToEntries;
|
||||
@@ -141,8 +127,7 @@ public class UnusedDeclarationInspection extends UnusedDeclarationInspectionBase
|
||||
gc.gridy++;
|
||||
add(myNonJavaCheckbox, gc);
|
||||
|
||||
Project project = guessProject();
|
||||
JButton configureAnnotations = EntryPointsManager.getInstance(project).createConfigureAnnotationsBtn();
|
||||
JButton configureAnnotations = EntryPointsManagerImpl.createConfigureAnnotationsButton();
|
||||
gc.fill = GridBagConstraints.NONE;
|
||||
gc.gridy++;
|
||||
gc.insets.top = 10;
|
||||
|
||||
@@ -28,6 +28,7 @@ import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
|
||||
import com.intellij.codeInspection.util.SpecialAnnotationsUtil;
|
||||
import com.intellij.openapi.components.*;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectUtil;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import org.jdom.Element;
|
||||
|
||||
@@ -73,11 +74,15 @@ public class EntryPointsManagerImpl extends EntryPointsManagerBase implements Pe
|
||||
|
||||
@Override
|
||||
public JButton createConfigureAnnotationsBtn() {
|
||||
return createConfigureAnnotationsButton();
|
||||
}
|
||||
|
||||
public static JButton createConfigureAnnotationsButton() {
|
||||
final JButton configureAnnotations = new JButton("Configure annotations...");
|
||||
configureAnnotations.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
configureAnnotations();
|
||||
getInstance(ProjectUtil.guessCurrentProject(configureAnnotations)).configureAnnotations();
|
||||
}
|
||||
});
|
||||
return configureAnnotations;
|
||||
|
||||
+2
-3
@@ -29,10 +29,10 @@ import com.intellij.codeInsight.FileModificationService;
|
||||
import com.intellij.codeInsight.daemon.GroupNames;
|
||||
import com.intellij.codeInspection.*;
|
||||
import com.intellij.codeInspection.ex.EntryPointsManager;
|
||||
import com.intellij.codeInspection.ex.EntryPointsManagerImpl;
|
||||
import com.intellij.codeInspection.reference.*;
|
||||
import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspectionBase;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectUtil;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.PsiReferenceProcessor;
|
||||
@@ -234,8 +234,7 @@ public class UnusedParametersInspection extends GlobalJavaBatchInspectionTool {
|
||||
@Override
|
||||
public JComponent createOptionsPanel() {
|
||||
final JPanel panel = new JPanel(new GridBagLayout());
|
||||
Project project = ProjectUtil.guessCurrentProject(panel);
|
||||
panel.add(EntryPointsManager.getInstance(project).createConfigureAnnotationsBtn(),
|
||||
panel.add(EntryPointsManagerImpl.createConfigureAnnotationsButton(),
|
||||
new GridBagConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE,
|
||||
new Insets(0, 0, 0, 0), 0, 0));
|
||||
return panel;
|
||||
|
||||
@@ -28,6 +28,8 @@ import com.intellij.psi.search.searches.DeepestSuperMethodsSearch;
|
||||
import com.intellij.psi.search.searches.SuperMethodsSearch;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.util.*;
|
||||
import com.intellij.util.containers.ConcurrentFactoryMap;
|
||||
import com.intellij.util.containers.FactoryMap;
|
||||
import gnu.trove.THashMap;
|
||||
import gnu.trove.THashSet;
|
||||
import gnu.trove.TObjectHashingStrategy;
|
||||
@@ -43,7 +45,20 @@ public class PsiSuperMethodImplUtil {
|
||||
@NotNull
|
||||
@Override
|
||||
public Map<MethodSignature, HierarchicalMethodSignature> fun(PsiClass dom) {
|
||||
return buildMethodHierarchy(dom, PsiSubstitutor.EMPTY, true, new THashSet<PsiClass>(), false);
|
||||
return buildMethodHierarchy(dom, null, PsiSubstitutor.EMPTY, true, new THashSet<PsiClass>(), false);
|
||||
}
|
||||
});
|
||||
private static final PsiCacheKey<FactoryMap<String, Map<MethodSignature, HierarchicalMethodSignature>>, PsiClass> SIGNATURES_BY_NAME_KEY = PsiCacheKey
|
||||
.create("SIGNATURES_BY_NAME_KEY", new Function<PsiClass, FactoryMap<String, Map<MethodSignature, HierarchicalMethodSignature>>>() {
|
||||
@Override
|
||||
public FactoryMap<String, Map<MethodSignature, HierarchicalMethodSignature>> fun(final PsiClass psiClass) {
|
||||
return new ConcurrentFactoryMap<String, Map<MethodSignature, HierarchicalMethodSignature>>() {
|
||||
@Nullable
|
||||
@Override
|
||||
protected Map<MethodSignature, HierarchicalMethodSignature> create(String methodName) {
|
||||
return buildMethodHierarchy(psiClass, methodName, PsiSubstitutor.EMPTY, true, new THashSet<PsiClass>(), false);
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
@@ -112,6 +127,7 @@ public class PsiSuperMethodImplUtil {
|
||||
|
||||
@NotNull
|
||||
private static Map<MethodSignature, HierarchicalMethodSignature> buildMethodHierarchy(@NotNull PsiClass aClass,
|
||||
@Nullable String nameHint,
|
||||
@NotNull PsiSubstitutor substitutor,
|
||||
final boolean includePrivates,
|
||||
@NotNull final Set<PsiClass> visited,
|
||||
@@ -144,7 +160,7 @@ public class PsiSuperMethodImplUtil {
|
||||
});
|
||||
|
||||
PsiMethod[] methods = aClass.getMethods();
|
||||
if (aClass instanceof PsiClassImpl) {
|
||||
if ((nameHint == null || "values".equals(nameHint)) && aClass instanceof PsiClassImpl) {
|
||||
final PsiMethod valuesMethod = ((PsiClassImpl)aClass).getValuesMethod();
|
||||
if (valuesMethod != null) {
|
||||
methods = ArrayUtil.append(methods, valuesMethod);
|
||||
@@ -155,6 +171,7 @@ public class PsiSuperMethodImplUtil {
|
||||
if (!method.isValid()) {
|
||||
throw new PsiInvalidElementAccessException(method, "class.valid=" + aClass.isValid() + "; name=" + method.getName());
|
||||
}
|
||||
if (nameHint != null && !nameHint.equals(method.getName())) continue;
|
||||
if (!includePrivates && method.hasModifierProperty(PsiModifier.PRIVATE)) continue;
|
||||
final MethodSignatureBackedByPsiMethod signature = MethodSignatureBackedByPsiMethod.create(method, substitutor, isInRawContext);
|
||||
HierarchicalMethodSignatureImpl newH = new HierarchicalMethodSignatureImpl(signature);
|
||||
@@ -180,7 +197,7 @@ public class PsiSuperMethodImplUtil {
|
||||
PsiSubstitutor finalSubstitutor = obtainFinalSubstitutor(superClass, superSubstitutor, substitutor, isInRawContext);
|
||||
|
||||
final boolean isInRawContextSuper = (isInRawContext || PsiUtil.isRawSubstitutor(superClass, superSubstitutor)) && superClass.getTypeParameters().length != 0;
|
||||
Map<MethodSignature, HierarchicalMethodSignature> superResult = buildMethodHierarchy(superClass, finalSubstitutor, false, visited, isInRawContextSuper);
|
||||
Map<MethodSignature, HierarchicalMethodSignature> superResult = buildMethodHierarchy(superClass, nameHint, finalSubstitutor, false, visited, isInRawContextSuper);
|
||||
visited.remove(superClass);
|
||||
|
||||
List<Pair<MethodSignature, HierarchicalMethodSignature>> flattened = new ArrayList<Pair<MethodSignature, HierarchicalMethodSignature>>();
|
||||
@@ -366,7 +383,7 @@ public class PsiSuperMethodImplUtil {
|
||||
PsiClass aClass = method.getContainingClass();
|
||||
HierarchicalMethodSignature result = null;
|
||||
if (aClass != null) {
|
||||
result = getSignaturesMap(aClass).get(method.getSignature(PsiSubstitutor.EMPTY));
|
||||
result = SIGNATURES_BY_NAME_KEY.getValue(aClass).get(method.getName()).get(method.getSignature(PsiSubstitutor.EMPTY));
|
||||
}
|
||||
if (result == null) {
|
||||
result = new HierarchicalMethodSignatureImpl((MethodSignatureBackedByPsiMethod)method.getSignature(PsiSubstitutor.EMPTY));
|
||||
@@ -395,40 +412,14 @@ public class PsiSuperMethodImplUtil {
|
||||
|
||||
if (!canHaveSuperMethod(method, true, false)) return false;
|
||||
|
||||
Map<MethodSignature, HierarchicalMethodSignature> cachedMap = SIGNATURES_FOR_CLASS_KEY.getCachedValueOrNull(aClass);
|
||||
if (cachedMap != null) {
|
||||
HierarchicalMethodSignature signature = cachedMap.get(method.getSignature(PsiSubstitutor.EMPTY));
|
||||
if (signature != null) {
|
||||
List<HierarchicalMethodSignature> superSignatures = signature.getSuperSignatures();
|
||||
for (HierarchicalMethodSignature superSignature : superSignatures) {
|
||||
if (!superMethodProcessor.process(superSignature.getMethod())) return false;
|
||||
}
|
||||
return true;
|
||||
Map<MethodSignature, HierarchicalMethodSignature> cachedMap = SIGNATURES_BY_NAME_KEY.getValue(aClass).get(method.getName());
|
||||
HierarchicalMethodSignature signature = cachedMap.get(method.getSignature(PsiSubstitutor.EMPTY));
|
||||
if (signature != null) {
|
||||
List<HierarchicalMethodSignature> superSignatures = signature.getSuperSignatures();
|
||||
for (HierarchicalMethodSignature superSignature : superSignatures) {
|
||||
if (!superMethodProcessor.process(superSignature.getMethod())) return false;
|
||||
}
|
||||
}
|
||||
|
||||
PsiClassType[] directSupers = aClass.getSuperTypes();
|
||||
for (PsiClassType directSuper : directSupers) {
|
||||
PsiClassType.ClassResolveResult resolveResult = directSuper.resolveGenerics();
|
||||
if (resolveResult.getSubstitutor() != PsiSubstitutor.EMPTY) {
|
||||
// generics
|
||||
break;
|
||||
}
|
||||
PsiClass directSuperClass = resolveResult.getElement();
|
||||
if (directSuperClass == null) continue;
|
||||
PsiMethod[] candidates = directSuperClass.findMethodsBySignature(method, false);
|
||||
for (PsiMethod candidate : candidates) {
|
||||
if (PsiUtil.canBeOverriden(candidate)) {
|
||||
if (!superMethodProcessor.process(candidate)) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
List<HierarchicalMethodSignature> superSignatures = method.getHierarchicalMethodSignature().getSuperSignatures();
|
||||
for (HierarchicalMethodSignature superSignature : superSignatures) {
|
||||
if (!superMethodProcessor.process(superSignature.getMethod())) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -444,42 +435,10 @@ public class PsiSuperMethodImplUtil {
|
||||
|
||||
if (!canHaveSuperMethod(method, true, false)) return false;
|
||||
|
||||
PsiMethod[] superMethods = null;
|
||||
Map<MethodSignature, HierarchicalMethodSignature> cachedMap = SIGNATURES_FOR_CLASS_KEY.getCachedValueOrNull(aClass);
|
||||
if (cachedMap != null) {
|
||||
HierarchicalMethodSignature signature = cachedMap.get(method.getSignature(PsiSubstitutor.EMPTY));
|
||||
if (signature != null) {
|
||||
superMethods = MethodSignatureUtil.convertMethodSignaturesToMethods(signature.getSuperSignatures());
|
||||
}
|
||||
}
|
||||
if (superMethods == null) {
|
||||
PsiClassType[] directSupers = aClass.getSuperTypes();
|
||||
List<PsiMethod> found = null;
|
||||
boolean canceled = false;
|
||||
for (PsiClassType directSuper : directSupers) {
|
||||
PsiClassType.ClassResolveResult resolveResult = directSuper.resolveGenerics();
|
||||
if (resolveResult.getSubstitutor() != PsiSubstitutor.EMPTY) {
|
||||
// generics
|
||||
canceled = true;
|
||||
break;
|
||||
}
|
||||
PsiClass directSuperClass = resolveResult.getElement();
|
||||
if (directSuperClass == null) continue;
|
||||
PsiMethod[] candidates = directSuperClass.findMethodsBySignature(method, false);
|
||||
if (candidates.length != 0) {
|
||||
if (found == null) found = new ArrayList<PsiMethod>();
|
||||
for (PsiMethod candidate : candidates) {
|
||||
if (PsiUtil.canBeOverriden(candidate)) found.add(candidate);
|
||||
}
|
||||
}
|
||||
}
|
||||
superMethods = canceled ? null : found == null ? PsiMethod.EMPTY_ARRAY : found.toArray(new PsiMethod[found.size()]);
|
||||
}
|
||||
if (superMethods == null) {
|
||||
superMethods = MethodSignatureUtil.convertMethodSignaturesToMethods(method.getHierarchicalMethodSignature().getSuperSignatures());
|
||||
}
|
||||
Map<MethodSignature, HierarchicalMethodSignature> cachedMap = SIGNATURES_BY_NAME_KEY.getValue(aClass).get(method.getName());
|
||||
HierarchicalMethodSignature signature = cachedMap.get(method.getSignature(PsiSubstitutor.EMPTY));
|
||||
|
||||
for (PsiMethod superCandidate : superMethods) {
|
||||
for (PsiMethod superCandidate : MethodSignatureUtil.convertMethodSignaturesToMethods(signature.getSuperSignatures())) {
|
||||
if (superMethod.equals(superCandidate) || isSuperMethodSmart(superCandidate, superMethod)) return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
// "Invert If Condition" "true"
|
||||
class A {
|
||||
public void foo() {
|
||||
Runnable r = () -> {
|
||||
if (System.currentTimeMillis() <= 1) {
|
||||
System.err.println("Elvis lives");
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// "Invert If Condition" "true"
|
||||
class A {
|
||||
public void foo() {
|
||||
Runnable r = () -> {
|
||||
if (System.currentTimeMillis() <caret>> 1) {
|
||||
return;
|
||||
}
|
||||
System.err.println("Elvis lives");
|
||||
};
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems>
|
||||
<problem>
|
||||
<file>Test.java</file>
|
||||
<line>3</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Field can be local</problem_class>
|
||||
<description>Field can be converted to a local variable</description>
|
||||
</problem>
|
||||
</problems>
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
class G {
|
||||
private G foo;
|
||||
private int bar;
|
||||
|
||||
public G(final G gFoo) {
|
||||
foo = gFoo;
|
||||
bar = 1;
|
||||
System.out.println(this.bar);
|
||||
|
||||
G g = this;
|
||||
while (g.foo != null) {
|
||||
g = g.foo;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,7 @@ public class FieldCanBeLocalTest extends InspectionTestCase {
|
||||
public void testFieldWithImmutableType() throws Exception {doTest();}
|
||||
public void testFieldUsedForWritingInLambda() throws Exception {doTest();}
|
||||
public void testStaticQualifiedFieldAccessForWriting() throws Exception {doTest();}
|
||||
public void testFieldReferencedFromAnotherObject() throws Exception {doTest();}
|
||||
public void testIgnoreAnnotated() throws Exception {
|
||||
final FieldCanBeLocalInspection inspection = new FieldCanBeLocalInspection();
|
||||
doTestConfigured(inspection);
|
||||
|
||||
@@ -0,0 +1,305 @@
|
||||
/*
|
||||
* 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.index
|
||||
import com.intellij.openapi.command.WriteCommandAction
|
||||
import com.intellij.openapi.command.impl.CurrentEditorProvider
|
||||
import com.intellij.openapi.command.impl.UndoManagerImpl
|
||||
import com.intellij.openapi.command.undo.UndoManager
|
||||
import com.intellij.openapi.editor.Document
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager
|
||||
import com.intellij.openapi.fileEditor.FileEditor
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager
|
||||
import com.intellij.openapi.fileTypes.PlainTextFileType
|
||||
import com.intellij.openapi.util.Factory
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.vfs.VfsUtil
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.openapi.vfs.newvfs.impl.VirtualFileSystemEntry
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.impl.PsiManagerEx
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.search.PsiSearchHelper
|
||||
import com.intellij.testFramework.PlatformTestUtil
|
||||
import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase
|
||||
import com.intellij.util.indexing.MapIndexStorage
|
||||
import com.intellij.util.indexing.StorageException
|
||||
import com.intellij.util.io.*
|
||||
import org.jetbrains.annotations.NotNull
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: Dec 12, 2007
|
||||
*/
|
||||
public class IndexTest extends JavaCodeInsightFixtureTestCase {
|
||||
@Override
|
||||
protected void invokeTestRunnable(@NotNull Runnable runnable) throws Exception {
|
||||
if ("testUndoToFileContentForUnsavedCommittedDocument".equals(getName())) {
|
||||
super.invokeTestRunnable(runnable);
|
||||
} else {
|
||||
WriteCommandAction.runWriteCommandAction(getProject(), runnable);
|
||||
}
|
||||
}
|
||||
|
||||
public void testUpdate() throws StorageException, IOException {
|
||||
final File storageFile = FileUtil.createTempFile("indextest", "storage");
|
||||
final File metaIndexFile = FileUtil.createTempFile("indextest_inputs", "storage");
|
||||
final MapIndexStorage indexStorage = new MapIndexStorage(storageFile, new EnumeratorStringDescriptor(), new EnumeratorStringDescriptor(), 16 * 1024);
|
||||
final StringIndex index = new StringIndex(indexStorage, new Factory<PersistentHashMap<Integer, Collection<String>>>() {
|
||||
@Override
|
||||
public PersistentHashMap<Integer, Collection<String>> create() {
|
||||
try {
|
||||
return createMetaIndex(metaIndexFile);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
// build index
|
||||
index.update("com/ppp/a.java", "a b c d", null);
|
||||
index.update("com/ppp/b.java", "a b g h", null);
|
||||
index.update("com/ppp/c.java", "a z f", null);
|
||||
index.update("com/ppp/d.java", "a a u y z", null);
|
||||
index.update("com/ppp/e.java", "a n chj e c d", null);
|
||||
|
||||
assertDataEquals(index.getFilesByWord("a"), "com/ppp/a.java", "com/ppp/b.java", "com/ppp/c.java", "com/ppp/d.java", "com/ppp/e.java");
|
||||
assertDataEquals(index.getFilesByWord("b"), "com/ppp/a.java", "com/ppp/b.java");
|
||||
assertDataEquals(index.getFilesByWord("c"), "com/ppp/a.java", "com/ppp/e.java");
|
||||
assertDataEquals(index.getFilesByWord("d"), "com/ppp/a.java", "com/ppp/e.java");
|
||||
assertDataEquals(index.getFilesByWord("g"), "com/ppp/b.java");
|
||||
assertDataEquals(index.getFilesByWord("h"), "com/ppp/b.java");
|
||||
assertDataEquals(index.getFilesByWord("z"), "com/ppp/c.java", "com/ppp/d.java");
|
||||
assertDataEquals(index.getFilesByWord("f"), "com/ppp/c.java");
|
||||
assertDataEquals(index.getFilesByWord("u"), "com/ppp/d.java");
|
||||
assertDataEquals(index.getFilesByWord("y"), "com/ppp/d.java");
|
||||
assertDataEquals(index.getFilesByWord("n"), "com/ppp/e.java");
|
||||
assertDataEquals(index.getFilesByWord("chj"), "com/ppp/e.java");
|
||||
assertDataEquals(index.getFilesByWord("e"), "com/ppp/e.java");
|
||||
|
||||
// update index
|
||||
|
||||
index.update("com/ppp/d.java", "a u y z", "a a u y z");
|
||||
assertDataEquals(index.getFilesByWord("a"), "com/ppp/a.java", "com/ppp/b.java", "com/ppp/c.java", "com/ppp/d.java", "com/ppp/e.java");
|
||||
index.update("com/ppp/d.java", "u y z", "a u y z");
|
||||
assertDataEquals(index.getFilesByWord("a"), "com/ppp/a.java", "com/ppp/b.java", "com/ppp/c.java", "com/ppp/e.java");
|
||||
index.update("com/ppp/d.java", "a a a u y z", "u y z");
|
||||
assertDataEquals(index.getFilesByWord("a"), "com/ppp/a.java", "com/ppp/b.java", "com/ppp/c.java", "com/ppp/d.java", "com/ppp/e.java");
|
||||
|
||||
index.update("com/ppp/e.java", "a n chj e c d z", "a n chj e c d");
|
||||
assertDataEquals(index.getFilesByWord("z"), "com/ppp/c.java", "com/ppp/d.java", "com/ppp/e.java");
|
||||
|
||||
index.update("com/ppp/b.java", null, "a b g h");
|
||||
assertDataEquals(index.getFilesByWord("a"), "com/ppp/a.java", "com/ppp/c.java", "com/ppp/d.java", "com/ppp/e.java");
|
||||
assertDataEquals(index.getFilesByWord("b"), "com/ppp/a.java");
|
||||
assertDataEquals(index.getFilesByWord("g"));
|
||||
assertDataEquals(index.getFilesByWord("h"));
|
||||
}
|
||||
finally {
|
||||
indexStorage.close();
|
||||
FileUtil.delete(storageFile);
|
||||
}
|
||||
}
|
||||
|
||||
private static PersistentHashMap<Integer, Collection<String>> createMetaIndex(File metaIndexFile) throws IOException {
|
||||
return new PersistentHashMap<Integer, Collection<String>>(metaIndexFile, new EnumeratorIntegerDescriptor(), new DataExternalizer<Collection<String>>() {
|
||||
@Override
|
||||
public void save(@NotNull DataOutput out, Collection<String> value) throws IOException {
|
||||
DataInputOutputUtil.writeINT(out, value.size());
|
||||
for (String key : value) {
|
||||
out.writeUTF(key);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> read(@NotNull DataInput _in) throws IOException {
|
||||
final int size = DataInputOutputUtil.readINT(_in);
|
||||
final List<String> list = new ArrayList<String>();
|
||||
for (int idx = 0; idx < size; idx++) {
|
||||
list.add(_in.readUTF());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static <T> void assertDataEquals(List<T> actual, T... expected) {
|
||||
assertTrue(new HashSet<T>(Arrays.asList(expected)).equals(new HashSet<T>(actual)));
|
||||
}
|
||||
|
||||
public void testCollectedPsiWithChangedDocument() throws IOException {
|
||||
final VirtualFile vFile = myFixture.addClass("class Foo {}").getContainingFile().getVirtualFile();
|
||||
|
||||
assertNotNull(findClass("Foo"));
|
||||
PsiFile psiFile = getPsiManager().findFile(vFile);
|
||||
assertNotNull(psiFile);
|
||||
|
||||
Document document = FileDocumentManager.getInstance().getDocument(vFile);
|
||||
document.deleteString(0, document.getTextLength());
|
||||
assertNotNull(findClass("Foo"));
|
||||
|
||||
psiFile = null;
|
||||
PlatformTestUtil.tryGcSoftlyReachableObjects();
|
||||
assertNull(getPsiManager().getFileManager().getCachedPsiFile(vFile));
|
||||
|
||||
PsiClass foo = findClass("Foo");
|
||||
assertNotNull(foo);
|
||||
assertTrue(foo.isValid());
|
||||
assertEquals("class Foo {}", foo.getText());
|
||||
assertTrue(foo.isValid());
|
||||
|
||||
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
|
||||
assertNull(findClass("Foo"));
|
||||
}
|
||||
|
||||
public void testCollectedPsiWithDocumentChangedCommittedAndChangedAgain() throws IOException {
|
||||
final VirtualFile vFile = myFixture.addClass("class Foo {}").getContainingFile().getVirtualFile();
|
||||
|
||||
assertNotNull(findClass("Foo"));
|
||||
PsiFile psiFile = getPsiManager().findFile(vFile);
|
||||
assertNotNull(psiFile);
|
||||
|
||||
Document document = FileDocumentManager.getInstance().getDocument(vFile);
|
||||
document.deleteString(0, document.getTextLength());
|
||||
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
|
||||
document.insertString(0, " ");
|
||||
//assertNotNull(myJavaFacade.findClass("Foo", scope));
|
||||
|
||||
psiFile = null;
|
||||
PlatformTestUtil.tryGcSoftlyReachableObjects();
|
||||
assertNull(getPsiManager().getFileManager().getCachedPsiFile(vFile));
|
||||
|
||||
PsiClass foo = findClass("Foo");
|
||||
assertNull(foo);
|
||||
}
|
||||
|
||||
private PsiClass findClass(String name) {
|
||||
return JavaPsiFacade.getInstance(getProject()).findClass(name, GlobalSearchScope.allScope(getProject()));
|
||||
}
|
||||
|
||||
public void testSavedUncommittedDocument() throws IOException {
|
||||
final VirtualFile vFile = myFixture.addFileToProject("Foo.java", "").getVirtualFile();
|
||||
|
||||
assertNull(findClass("Foo"));
|
||||
PsiFile psiFile = getPsiManager().findFile(vFile);
|
||||
assertNotNull(psiFile);
|
||||
|
||||
long count = getPsiManager().getModificationTracker().getModificationCount();
|
||||
|
||||
Document document = FileDocumentManager.getInstance().getDocument(vFile);
|
||||
document.insertString(0, "class Foo {}");
|
||||
FileDocumentManager.getInstance().saveDocument(document);
|
||||
|
||||
assertTrue(count == getPsiManager().getModificationTracker().getModificationCount());
|
||||
assertNull(findClass("Foo"));
|
||||
|
||||
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
|
||||
assertNotNull(findClass("Foo"));
|
||||
assertNotNull(findClass("Foo").getText());
|
||||
// if Foo exists now, mod count should be different
|
||||
assertTrue(count != getPsiManager().getModificationTracker().getModificationCount());
|
||||
}
|
||||
|
||||
public void testSkipUnknownFileTypes() throws IOException {
|
||||
final VirtualFile vFile = myFixture.addFileToProject("Foo.test", "Foo").getVirtualFile();
|
||||
assertEquals(PlainTextFileType.INSTANCE, vFile.getFileType());
|
||||
final PsiSearchHelper helper = PsiSearchHelper.SERVICE.getInstance(getProject());
|
||||
assertOneElement(helper.findFilesWithPlainTextWords("Foo"));
|
||||
|
||||
final Document document = FileDocumentManager.getInstance().getDocument(vFile);
|
||||
//todo should file type be changed silently without events?
|
||||
//assertEquals(UnknownFileType.INSTANCE, vFile.getFileType());
|
||||
|
||||
final PsiFile file = PsiDocumentManager.getInstance(getProject()).getPsiFile(document);
|
||||
assertInstanceOf(file, PsiPlainTextFile.class);
|
||||
assertEquals("Foo", file.getText());
|
||||
|
||||
assertOneElement(helper.findFilesWithPlainTextWords("Foo"));
|
||||
|
||||
WriteCommandAction.runWriteCommandAction(getProject(), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
document.insertString(0, " ");
|
||||
assertEquals("Foo", file.getText());
|
||||
assertOneElement(helper.findFilesWithPlainTextWords("Foo"));
|
||||
|
||||
FileDocumentManager.getInstance().saveDocument(document);
|
||||
assertEquals("Foo", file.getText());
|
||||
assertOneElement(helper.findFilesWithPlainTextWords("Foo"));
|
||||
|
||||
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
|
||||
assertEquals(" Foo", file.getText());
|
||||
assertOneElement(helper.findFilesWithPlainTextWords("Foo"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void testUndoToFileContentForUnsavedCommittedDocument() throws IOException {
|
||||
final VirtualFile vFile = myFixture.addClass("class Foo {}").getContainingFile().getVirtualFile();
|
||||
((VirtualFileSystemEntry)vFile).setModificationStamp(0); // as unchanged file
|
||||
|
||||
final Document document = FileDocumentManager.getInstance().getDocument(vFile);
|
||||
assertTrue(document != null && document.getModificationStamp() == 0);
|
||||
assertNotNull(findClass("Foo"));
|
||||
|
||||
WriteCommandAction.runWriteCommandAction(getProject(), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
document.insertString(0, "import Bar;\n");
|
||||
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
|
||||
assertNotNull(findClass("Foo"));
|
||||
}
|
||||
});
|
||||
|
||||
final UndoManager undoManager = UndoManager.getInstance(getProject());
|
||||
final FileEditor selectedEditor = FileEditorManager.getInstance(getProject()).openFile(vFile, false)[0];
|
||||
((UndoManagerImpl)undoManager).setEditorProvider(new CurrentEditorProvider() {
|
||||
@Override
|
||||
public FileEditor getCurrentEditor() {
|
||||
return selectedEditor;
|
||||
}
|
||||
});
|
||||
|
||||
assertTrue(undoManager.isUndoAvailable(selectedEditor));
|
||||
FileDocumentManager.getInstance().saveDocument(document);
|
||||
undoManager.undo(selectedEditor);
|
||||
|
||||
assertNotNull(findClass("Foo"));
|
||||
}
|
||||
|
||||
public void "test changing a file without psi makes the document committed and updates index"() {
|
||||
def psiFile = myFixture.addFileToProject("Foo.java", "class Foo {}")
|
||||
def vFile = psiFile.virtualFile
|
||||
def scope = GlobalSearchScope.allScope(project)
|
||||
|
||||
FileDocumentManager.instance.getDocument(vFile).text = "import zoo.Zoo; class Foo1 {}"
|
||||
assert PsiDocumentManager.getInstance(project).uncommittedDocuments
|
||||
psiFile = null
|
||||
|
||||
PlatformTestUtil.tryGcSoftlyReachableObjects()
|
||||
|
||||
assert !((PsiManagerEx) psiManager).fileManager.getCachedPsiFile(vFile)
|
||||
|
||||
FileDocumentManager.instance.saveAllDocuments()
|
||||
|
||||
VfsUtil.saveText(vFile, "class Foo3 {}")
|
||||
|
||||
assert !PsiDocumentManager.getInstance(project).uncommittedDocuments
|
||||
|
||||
assert JavaPsiFacade.getInstance(project).findClass("Foo3", scope)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,388 +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.index;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightTestCase;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.command.impl.CurrentEditorProvider;
|
||||
import com.intellij.openapi.command.impl.UndoManagerImpl;
|
||||
import com.intellij.openapi.command.undo.UndoManager;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.fileEditor.FileEditor;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.fileTypes.PlainTextFileType;
|
||||
import com.intellij.openapi.util.Factory;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.newvfs.impl.VirtualFileSystemEntry;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiManagerEx;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.PsiSearchHelper;
|
||||
import com.intellij.testFramework.PlatformTestUtil;
|
||||
import com.intellij.testFramework.PsiTestUtil;
|
||||
import com.intellij.testFramework.SkipSlowTestLocally;
|
||||
import com.intellij.util.indexing.MapIndexStorage;
|
||||
import com.intellij.util.indexing.StorageException;
|
||||
import com.intellij.util.io.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: Dec 12, 2007
|
||||
*/
|
||||
@SkipSlowTestLocally
|
||||
public class IndexTest extends CodeInsightTestCase {
|
||||
|
||||
public void testUpdate() throws StorageException, IOException {
|
||||
final File storageFile = FileUtil.createTempFile("indextest", "storage");
|
||||
final File metaIndexFile = FileUtil.createTempFile("indextest_inputs", "storage");
|
||||
final MapIndexStorage indexStorage = new MapIndexStorage(storageFile, new EnumeratorStringDescriptor(), new EnumeratorStringDescriptor(), 16 * 1024);
|
||||
final StringIndex index = new StringIndex(indexStorage, new Factory<PersistentHashMap<Integer, Collection<String>>>() {
|
||||
@Override
|
||||
public PersistentHashMap<Integer, Collection<String>> create() {
|
||||
try {
|
||||
return createMetaIndex(metaIndexFile);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
// build index
|
||||
index.update("com/ppp/a.java", "a b c d", null);
|
||||
index.update("com/ppp/b.java", "a b g h", null);
|
||||
index.update("com/ppp/c.java", "a z f", null);
|
||||
index.update("com/ppp/d.java", "a a u y z", null);
|
||||
index.update("com/ppp/e.java", "a n chj e c d", null);
|
||||
|
||||
assertDataEquals(index.getFilesByWord("a"), "com/ppp/a.java", "com/ppp/b.java", "com/ppp/c.java", "com/ppp/d.java", "com/ppp/e.java");
|
||||
assertDataEquals(index.getFilesByWord("b"), "com/ppp/a.java", "com/ppp/b.java");
|
||||
assertDataEquals(index.getFilesByWord("c"), "com/ppp/a.java", "com/ppp/e.java");
|
||||
assertDataEquals(index.getFilesByWord("d"), "com/ppp/a.java", "com/ppp/e.java");
|
||||
assertDataEquals(index.getFilesByWord("g"), "com/ppp/b.java");
|
||||
assertDataEquals(index.getFilesByWord("h"), "com/ppp/b.java");
|
||||
assertDataEquals(index.getFilesByWord("z"), "com/ppp/c.java", "com/ppp/d.java");
|
||||
assertDataEquals(index.getFilesByWord("f"), "com/ppp/c.java");
|
||||
assertDataEquals(index.getFilesByWord("u"), "com/ppp/d.java");
|
||||
assertDataEquals(index.getFilesByWord("y"), "com/ppp/d.java");
|
||||
assertDataEquals(index.getFilesByWord("n"), "com/ppp/e.java");
|
||||
assertDataEquals(index.getFilesByWord("chj"), "com/ppp/e.java");
|
||||
assertDataEquals(index.getFilesByWord("e"), "com/ppp/e.java");
|
||||
|
||||
// update index
|
||||
|
||||
index.update("com/ppp/d.java", "a u y z", "a a u y z");
|
||||
assertDataEquals(index.getFilesByWord("a"), "com/ppp/a.java", "com/ppp/b.java", "com/ppp/c.java", "com/ppp/d.java", "com/ppp/e.java");
|
||||
index.update("com/ppp/d.java", "u y z", "a u y z");
|
||||
assertDataEquals(index.getFilesByWord("a"), "com/ppp/a.java", "com/ppp/b.java", "com/ppp/c.java", "com/ppp/e.java");
|
||||
index.update("com/ppp/d.java", "a a a u y z", "u y z");
|
||||
assertDataEquals(index.getFilesByWord("a"), "com/ppp/a.java", "com/ppp/b.java", "com/ppp/c.java", "com/ppp/d.java", "com/ppp/e.java");
|
||||
|
||||
index.update("com/ppp/e.java", "a n chj e c d z", "a n chj e c d");
|
||||
assertDataEquals(index.getFilesByWord("z"), "com/ppp/c.java", "com/ppp/d.java", "com/ppp/e.java");
|
||||
|
||||
index.update("com/ppp/b.java", null, "a b g h");
|
||||
assertDataEquals(index.getFilesByWord("a"), "com/ppp/a.java", "com/ppp/c.java", "com/ppp/d.java", "com/ppp/e.java");
|
||||
assertDataEquals(index.getFilesByWord("b"), "com/ppp/a.java");
|
||||
assertDataEquals(index.getFilesByWord("g"));
|
||||
assertDataEquals(index.getFilesByWord("h"));
|
||||
}
|
||||
finally {
|
||||
indexStorage.close();
|
||||
FileUtil.delete(storageFile);
|
||||
}
|
||||
}
|
||||
|
||||
private PersistentHashMap<Integer, Collection<String>> createMetaIndex(File metaIndexFile) throws IOException {
|
||||
return new PersistentHashMap<Integer, Collection<String>>(metaIndexFile, new EnumeratorIntegerDescriptor(), new DataExternalizer<Collection<String>>() {
|
||||
@Override
|
||||
public void save(@NotNull DataOutput out, Collection<String> value) throws IOException {
|
||||
DataInputOutputUtil.writeINT(out, value.size());
|
||||
for (String key : value) {
|
||||
out.writeUTF(key);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> read(@NotNull DataInput in) throws IOException {
|
||||
final int size = DataInputOutputUtil.readINT(in);
|
||||
final List<String> list = new ArrayList<String>();
|
||||
for (int idx = 0; idx < size; idx++) {
|
||||
list.add(in.readUTF());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
public void testStubIndexUnsavedDocumentsIndexing() throws IncorrectOperationException, IOException, StorageException {
|
||||
IdeaTestUtil.registerExtension(StubIndexExtension.EP_NAME, new TextStubIndexExtension(), getTestRootDisposable());
|
||||
IdeaTestUtil.registerExtension(StubIndexExtension.EP_NAME, new ClassNameStubIndexExtension(), getTestRootDisposable());
|
||||
FileTypeManager.getInstance().registerFileType(TestFileType.INSTANCE, "fff");
|
||||
final FFFLangParserDefinition parserDefinition = new FFFLangParserDefinition();
|
||||
LanguageParserDefinitions.INSTANCE.addExplicitExtension(FFFLanguage.INSTANCE, parserDefinition);
|
||||
|
||||
final TestStubElementType stubType = new TestStubElementType();
|
||||
SerializationManager.getInstance().registerSerializer(TestStubElement.class, stubType);
|
||||
|
||||
final File fffFile = new File(FileUtil.createTempDirectory("testing", "stubindex"), "MyClass.fff");
|
||||
fffFile.createNewFile();
|
||||
|
||||
final VirtualFile vFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(fffFile);
|
||||
|
||||
assertNotNull(vFile);
|
||||
assertEquals(TestFileType.INSTANCE, vFile.getFileType());
|
||||
|
||||
try {
|
||||
final MockPsiFile psiFile = new MockPsiFile(vFile, MockPsiManager.getInstance(myProject));
|
||||
|
||||
final MockPsiClass cls = new MockPsiClass("com.company.MyClass");
|
||||
psiFile.add(cls);
|
||||
|
||||
final MockPsiMethod aaaMethod = new MockPsiMethod("aaa");
|
||||
cls.addMethod(aaaMethod);
|
||||
final MockPsiMethod bbbMethod = new MockPsiMethod("bbb");
|
||||
cls.addMethod(bbbMethod);
|
||||
|
||||
final PsiFileStubImpl fileStub = new PsiFileStubImpl(psiFile);
|
||||
final TestStubElement clsStub = stubType.createStub(cls, fileStub);
|
||||
stubType.createStub(aaaMethod, clsStub);
|
||||
stubType.createStub(bbbMethod, clsStub);
|
||||
|
||||
final ByteArrayOutputStream arrayStream = new ByteArrayOutputStream();
|
||||
SerializationManager.getInstance().serialize(fileStub, new DataOutputStream(arrayStream));
|
||||
|
||||
final FileBasedIndex fbi = FileBasedIndex.getInstance();
|
||||
final UpdatableIndex<Integer, SerializedStubTree, FileContent> stubUpdatingIndex = fbi.getIndex(StubUpdatingIndex.INDEX_ID);
|
||||
final MemoryIndexStorage storage = (MemoryIndexStorage)((MapReduceIndex)stubUpdatingIndex).getStorage();
|
||||
|
||||
// initial
|
||||
final int fileId = FileBasedIndex.getFileId(vFile);
|
||||
final byte[] bytes = arrayStream.toByteArray();
|
||||
stubUpdatingIndex.update(fileId, new FileContent(vFile, bytes), null);
|
||||
|
||||
final ValueContainer<SerializedStubTree> data = stubUpdatingIndex.getData(fileId);
|
||||
final List<SerializedStubTree> trees = data.toValueList();
|
||||
|
||||
final SerializedStubTree tree = assertOneElement(trees);
|
||||
|
||||
assertTrue(Comparing.equal(bytes, tree.getBytes()));
|
||||
|
||||
final StubElement deserialized = tree.getStub();
|
||||
}
|
||||
finally {
|
||||
LanguageParserDefinitions.INSTANCE.removeExplicitExtension(FFFLanguage.INSTANCE, parserDefinition);
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
private static <T> void assertDataEquals(List<T> actual, T... expected) {
|
||||
assertTrue(new HashSet<T>(Arrays.asList(expected)).equals(new HashSet<T>(actual)));
|
||||
}
|
||||
|
||||
public void testCollectedPsiWithChangedDocument() throws IOException {
|
||||
VirtualFile dir = getVirtualFile(createTempDirectory());
|
||||
PsiTestUtil.addSourceContentToRoots(myModule, dir);
|
||||
|
||||
final VirtualFile vFile = createChildData(dir, "Foo.java");
|
||||
VfsUtil.saveText(vFile, "class Foo {}");
|
||||
|
||||
final GlobalSearchScope scope = GlobalSearchScope.allScope(getProject());
|
||||
assertNotNull(myJavaFacade.findClass("Foo", scope));
|
||||
WriteCommandAction.runWriteCommandAction(null, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
PsiFile psiFile = PsiManager.getInstance(getProject()).findFile(vFile);
|
||||
assertNotNull(psiFile);
|
||||
|
||||
Document document = FileDocumentManager.getInstance().getDocument(vFile);
|
||||
document.deleteString(0, document.getTextLength());
|
||||
assertNotNull(myJavaFacade.findClass("Foo", scope));
|
||||
|
||||
psiFile = null;
|
||||
PlatformTestUtil.tryGcSoftlyReachableObjects();
|
||||
assertNull(((PsiManagerEx)PsiManager.getInstance(getProject())).getFileManager().getCachedPsiFile(vFile));
|
||||
|
||||
PsiClass foo = myJavaFacade.findClass("Foo", scope);
|
||||
assertNotNull(foo);
|
||||
assertTrue(foo.isValid());
|
||||
assertEquals("class Foo {}", foo.getText());
|
||||
assertTrue(foo.isValid());
|
||||
|
||||
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
|
||||
assertNull(myJavaFacade.findClass("Foo", scope));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void _testCollectedPsiWithDocumentChangedCommittedAndChangedAgain() throws IOException {
|
||||
VirtualFile dir = getVirtualFile(createTempDirectory());
|
||||
PsiTestUtil.addSourceContentToRoots(myModule, dir);
|
||||
|
||||
final VirtualFile vFile = createChildData(dir, "Foo.java");
|
||||
VfsUtil.saveText(vFile, "class Foo {}");
|
||||
|
||||
final GlobalSearchScope scope = GlobalSearchScope.allScope(getProject());
|
||||
assertNotNull(myJavaFacade.findClass("Foo", scope));
|
||||
WriteCommandAction.runWriteCommandAction(null, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
PsiFile psiFile = PsiManager.getInstance(getProject()).findFile(vFile);
|
||||
assertNotNull(psiFile);
|
||||
|
||||
Document document = FileDocumentManager.getInstance().getDocument(vFile);
|
||||
document.deleteString(0, document.getTextLength());
|
||||
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
|
||||
document.insertString(0, " ");
|
||||
//assertNotNull(myJavaFacade.findClass("Foo", scope));
|
||||
|
||||
psiFile = null;
|
||||
PlatformTestUtil.tryGcSoftlyReachableObjects();
|
||||
assertNull(((PsiManagerEx)PsiManager.getInstance(getProject())).getFileManager().getCachedPsiFile(vFile));
|
||||
|
||||
PsiClass foo = myJavaFacade.findClass("Foo", scope);
|
||||
assertNotNull(foo);
|
||||
assertTrue(foo.isValid());
|
||||
assertEquals("class Foo {}", foo.getText());
|
||||
assertTrue(foo.isValid());
|
||||
|
||||
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
|
||||
assertNull(myJavaFacade.findClass("Foo", scope));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void testSavedUncommittedDocument() throws IOException {
|
||||
VirtualFile dir = getVirtualFile(createTempDirectory());
|
||||
PsiTestUtil.addSourceContentToRoots(myModule, dir);
|
||||
|
||||
final VirtualFile vFile = createChildData(dir, "Foo.java");
|
||||
VfsUtil.saveText(vFile, "");
|
||||
|
||||
final GlobalSearchScope scope = GlobalSearchScope.allScope(getProject());
|
||||
assertNull(myJavaFacade.findClass("Foo", scope));
|
||||
WriteCommandAction.runWriteCommandAction(null, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
PsiFile psiFile = PsiManager.getInstance(getProject()).findFile(vFile);
|
||||
assertNotNull(psiFile);
|
||||
|
||||
long count = PsiManager.getInstance(myProject).getModificationTracker().getModificationCount();
|
||||
|
||||
Document document = FileDocumentManager.getInstance().getDocument(vFile);
|
||||
document.insertString(0, "class Foo {}");
|
||||
FileDocumentManager.getInstance().saveDocument(document);
|
||||
|
||||
assertTrue(count == PsiManager.getInstance(myProject).getModificationTracker().getModificationCount());
|
||||
assertNull(myJavaFacade.findClass("Foo", scope));
|
||||
|
||||
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
|
||||
assertNotNull(myJavaFacade.findClass("Foo", scope));
|
||||
assertNotNull(myJavaFacade.findClass("Foo", scope).getText());
|
||||
// if Foo exists now, mod count should be different
|
||||
assertTrue(count != PsiManager.getInstance(myProject).getModificationTracker().getModificationCount());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void testSkipUnknownFileTypes() throws IOException {
|
||||
VirtualFile dir = getVirtualFile(createTempDirectory());
|
||||
PsiTestUtil.addSourceContentToRoots(myModule, dir);
|
||||
|
||||
final VirtualFile vFile = createChildData(dir, "Foo.test");
|
||||
VfsUtil.saveText(vFile, "Foo");
|
||||
assertEquals(PlainTextFileType.INSTANCE, vFile.getFileType());
|
||||
assertOneElement(PsiSearchHelper.SERVICE.getInstance(myProject).findFilesWithPlainTextWords("Foo"));
|
||||
|
||||
final Document document = FileDocumentManager.getInstance().getDocument(vFile);
|
||||
//todo should file type be changed silently without events?
|
||||
//assertEquals(UnknownFileType.INSTANCE, vFile.getFileType());
|
||||
|
||||
final PsiFile file = getPsiFile(document);
|
||||
assertInstanceOf(file, PsiPlainTextFile.class);
|
||||
assertEquals("Foo", file.getText());
|
||||
|
||||
assertOneElement(PsiSearchHelper.SERVICE.getInstance(myProject).findFilesWithPlainTextWords("Foo"));
|
||||
|
||||
WriteCommandAction.runWriteCommandAction(myProject, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
document.insertString(0, " ");
|
||||
assertEquals("Foo", file.getText());
|
||||
assertOneElement(PsiSearchHelper.SERVICE.getInstance(myProject).findFilesWithPlainTextWords("Foo"));
|
||||
|
||||
FileDocumentManager.getInstance().saveDocument(document);
|
||||
assertEquals("Foo", file.getText());
|
||||
assertOneElement(PsiSearchHelper.SERVICE.getInstance(myProject).findFilesWithPlainTextWords("Foo"));
|
||||
|
||||
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
|
||||
assertEquals(" Foo", file.getText());
|
||||
assertOneElement(PsiSearchHelper.SERVICE.getInstance(myProject).findFilesWithPlainTextWords("Foo"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void testUndoToFileContentForUnsavedCommittedDocument() throws IOException {
|
||||
VirtualFile dir = getVirtualFile(createTempDirectory());
|
||||
PsiTestUtil.addSourceContentToRoots(myModule, dir);
|
||||
|
||||
final VirtualFile vFile = createChildData(dir, "Foo.java");
|
||||
VfsUtil.saveText(vFile, "class Foo {}");
|
||||
((VirtualFileSystemEntry)vFile).setModificationStamp(0); // as unchanged file
|
||||
|
||||
final Document document = FileDocumentManager.getInstance().getDocument(vFile);
|
||||
assertTrue(document != null && document.getModificationStamp() == 0);
|
||||
final GlobalSearchScope scope = GlobalSearchScope.projectScope(myProject);
|
||||
assertNotNull(myJavaFacade.findClass("Foo", scope));
|
||||
|
||||
WriteCommandAction.runWriteCommandAction(myProject, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
document.insertString(0, "import Bar;\n");
|
||||
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
|
||||
assertNotNull(myJavaFacade.findClass("Foo", scope));
|
||||
}
|
||||
});
|
||||
|
||||
final UndoManager undoManager = UndoManager.getInstance(getProject());
|
||||
final FileEditor selectedEditor = FileEditorManager.getInstance(myProject).openFile(vFile, false)[0];
|
||||
((UndoManagerImpl)undoManager).setEditorProvider(new CurrentEditorProvider() {
|
||||
@Override
|
||||
public FileEditor getCurrentEditor() {
|
||||
return selectedEditor;
|
||||
}
|
||||
});
|
||||
|
||||
assertTrue(undoManager.isUndoAvailable(selectedEditor));
|
||||
FileDocumentManager.getInstance().saveDocument(document);
|
||||
undoManager.undo(selectedEditor);
|
||||
|
||||
assertNotNull(myJavaFacade.findClass("Foo", scope));
|
||||
}
|
||||
}
|
||||
@@ -25,8 +25,11 @@ import org.scalacheck._
|
||||
import scala.collection.JavaConversions._
|
||||
|
||||
/**
|
||||
* Run this class to generate randomized tests for IDEA VFS/document/PSI/index subsystem interaction using ScalaCheck.
|
||||
* When a test fails, a test method code (in Groovy) is printed which should be copied to a normal test class and debugged there.
|
||||
* Run this class to generate randomized tests for IDEA VFS/document/PSI/index subsystem interaction using ScalaCheck.<p/>
|
||||
*
|
||||
* When a test fails, a test method code (in Groovy) is printed which should be copied to a normal test class (IndexTest)
|
||||
* and debugged there.<p/>
|
||||
*
|
||||
* The generated test may contain some excessive declarations and checks that should be corrected manually.
|
||||
* After the fix, that generated test should be renamed according to the underlying issue it found and committed to the repository.
|
||||
*
|
||||
|
||||
+3
-2
@@ -21,6 +21,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.JavaPsiFacade;
|
||||
import com.intellij.psi.PsiElementFactory;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.impl.PsiManagerEx;
|
||||
import com.intellij.testFramework.IdeaTestCase;
|
||||
import com.intellij.testFramework.UsefulTestCase;
|
||||
import com.intellij.testFramework.builders.JavaModuleFixtureBuilder;
|
||||
@@ -105,8 +106,8 @@ public abstract class JavaCodeInsightFixtureTestCase extends UsefulTestCase{
|
||||
return myFixture.getProject();
|
||||
}
|
||||
|
||||
protected PsiManager getPsiManager() {
|
||||
return PsiManager.getInstance(getProject());
|
||||
protected PsiManagerEx getPsiManager() {
|
||||
return (PsiManagerEx)PsiManager.getInstance(getProject());
|
||||
}
|
||||
|
||||
public PsiElementFactory getElementFactory() {
|
||||
|
||||
@@ -29,6 +29,8 @@ import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
public abstract class EntryPointsManager implements Disposable {
|
||||
public static EntryPointsManager getInstance(Project project) {
|
||||
@@ -50,6 +52,10 @@ public abstract class EntryPointsManager implements Disposable {
|
||||
|
||||
public abstract void configureAnnotations();
|
||||
|
||||
/**
|
||||
* {@link com.intellij.codeInspection.ex.EntryPointsManagerImpl#createConfigureAnnotationsButton()} should be used instead
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract JButton createConfigureAnnotationsBtn();
|
||||
|
||||
public abstract boolean isEntryPoint(@NotNull PsiElement element);
|
||||
|
||||
+10
-10
@@ -75,7 +75,7 @@ public class InspectionProfileImpl extends ProfileEx implements ModifiableModel,
|
||||
@TestOnly
|
||||
public static boolean INIT_INSPECTIONS = false;
|
||||
private static Map<String, InspectionElementsMerger> ourMergers = null;
|
||||
final InspectionToolRegistrar myRegistrar;
|
||||
private final InspectionToolRegistrar myRegistrar;
|
||||
@NotNull
|
||||
private final Map<String, Element> myDeinstalledInspectionsSettings;
|
||||
private final ExternalInfo myExternalInfo = new ExternalInfo();
|
||||
@@ -342,9 +342,9 @@ public class InspectionProfileImpl extends ProfileEx implements ModifiableModel,
|
||||
inspectionElement.setAttribute(CLASS_TAG, toolName);
|
||||
toolList.writeExternal(inspectionElement);
|
||||
|
||||
if (areSettingsMerged(toolName, inspectionElement)) continue;
|
||||
|
||||
element.addContent(inspectionElement);
|
||||
if (!areSettingsMerged(toolName, inspectionElement)) {
|
||||
element.addContent(inspectionElement);
|
||||
}
|
||||
}
|
||||
else {
|
||||
element.addContent(toolElement.clone());
|
||||
@@ -378,13 +378,12 @@ public class InspectionProfileImpl extends ProfileEx implements ModifiableModel,
|
||||
if (mainToolId != null) {
|
||||
InspectionToolWrapper dependentEntryWrapper = getInspectionTool(mainToolId, project);
|
||||
|
||||
if (dependentEntryWrapper != null) {
|
||||
if (!dependentEntries.add(dependentEntryWrapper)) {
|
||||
collectDependentInspections(dependentEntryWrapper, dependentEntries, project);
|
||||
}
|
||||
if (dependentEntryWrapper == null) {
|
||||
LOG.error("Can't find main tool: '" + mainToolId+"' which was specified in "+toolWrapper);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
LOG.error("Can't find main tool: " + mainToolId);
|
||||
if (!dependentEntries.add(dependentEntryWrapper)) {
|
||||
collectDependentInspections(dependentEntryWrapper, dependentEntries, project);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1015,6 +1014,7 @@ public class InspectionProfileImpl extends ProfileEx implements ModifiableModel,
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String toString() {
|
||||
return mySource == null ? getName() : getName() + " (copy)";
|
||||
|
||||
@@ -109,6 +109,15 @@ public abstract class PsiDocumentManager {
|
||||
@NotNull
|
||||
public abstract CharSequence getLastCommittedText(@NotNull Document document);
|
||||
|
||||
/**
|
||||
* @return for uncommitted documents, the last stamp before the document change: the same stamp that current PSI should have.
|
||||
* For committed documents, just their stamp.
|
||||
*
|
||||
* @see Document#getModificationStamp()
|
||||
* @see FileViewProvider#getModificationStamp()
|
||||
*/
|
||||
public abstract long getLastCommittedStamp(@NotNull Document document);
|
||||
|
||||
/**
|
||||
* Returns the list of documents which have been modified but not committed.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -32,7 +32,10 @@ import com.intellij.psi.impl.PsiElementBase;
|
||||
import com.intellij.psi.impl.PsiManagerEx;
|
||||
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
|
||||
import com.intellij.psi.impl.source.codeStyle.CodeEditUtil;
|
||||
import com.intellij.psi.impl.source.tree.*;
|
||||
import com.intellij.psi.impl.source.tree.ChangeUtil;
|
||||
import com.intellij.psi.impl.source.tree.CompositeElement;
|
||||
import com.intellij.psi.impl.source.tree.SharedImplUtil;
|
||||
import com.intellij.psi.impl.source.tree.TreeElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
@@ -334,9 +337,9 @@ public abstract class ASTDelegatePsiElement extends PsiElementBase {
|
||||
CheckUtil.checkWritable(this);
|
||||
((ASTDelegatePsiElement)parent).deleteChildInternal(getNode());
|
||||
}
|
||||
else if (parent instanceof CompositePsiElement) {
|
||||
else if (parent instanceof CompositeElement) {
|
||||
CheckUtil.checkWritable(this);
|
||||
((CompositePsiElement)parent).deleteChildInternal(getNode());
|
||||
((CompositeElement)parent).deleteChildInternal(getNode());
|
||||
}
|
||||
else if (parent instanceof PsiFile) {
|
||||
CheckUtil.checkWritable(this);
|
||||
|
||||
+1
-1
@@ -277,7 +277,7 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements
|
||||
MutablePicoContainer container = myPicoContainer;
|
||||
if (container == null || myDisposeCompleted) {
|
||||
ProgressManager.checkCanceled();
|
||||
throw new AssertionError("Already disposed");
|
||||
throw new AssertionError("Already disposed: "+toString());
|
||||
}
|
||||
return container;
|
||||
}
|
||||
|
||||
@@ -165,7 +165,6 @@ public class SingleRootFileViewProvider extends UserDataHolderBase implements Fi
|
||||
|
||||
@Override
|
||||
public void beforeContentsSynchronized() {
|
||||
unsetPsiContent();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -501,7 +500,20 @@ public class SingleRootFileViewProvider extends UserDataHolderBase implements Fi
|
||||
|
||||
@Override
|
||||
public long getModificationStamp() {
|
||||
return getVirtualFile().getModificationStamp();
|
||||
final VirtualFile virtualFile = getVirtualFile();
|
||||
if (virtualFile instanceof LightVirtualFile) {
|
||||
Document doc = getCachedDocument();
|
||||
if (doc != null) return getLastCommittedStamp(doc);
|
||||
return virtualFile.getModificationStamp();
|
||||
}
|
||||
|
||||
final Document document = getDocument();
|
||||
if (document == null) {
|
||||
return virtualFile.getModificationStamp();
|
||||
}
|
||||
else {
|
||||
return getLastCommittedStamp(document);
|
||||
}
|
||||
}
|
||||
|
||||
@NonNls
|
||||
@@ -514,6 +526,9 @@ public class SingleRootFileViewProvider extends UserDataHolderBase implements Fi
|
||||
private CharSequence getLastCommittedText(Document document) {
|
||||
return PsiDocumentManager.getInstance(myManager.getProject()).getLastCommittedText(document);
|
||||
}
|
||||
private long getLastCommittedStamp(Document document) {
|
||||
return PsiDocumentManager.getInstance(myManager.getProject()).getLastCommittedStamp(document);
|
||||
}
|
||||
|
||||
private class DocumentContent implements Content {
|
||||
@NonNls
|
||||
@@ -534,7 +549,7 @@ public class SingleRootFileViewProvider extends UserDataHolderBase implements Fi
|
||||
@Override
|
||||
public long getModificationStamp() {
|
||||
Document document = com.intellij.reference.SoftReference.dereference(myDocument);
|
||||
if (document != null) return document.getModificationStamp();
|
||||
if (document != null) return getLastCommittedStamp(document);
|
||||
return myVirtualFile.getModificationStamp();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.FileIndexFacade;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
@@ -67,7 +68,7 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
|
||||
private final PsiManager myPsiManager;
|
||||
private final DocumentCommitProcessor myDocumentCommitProcessor;
|
||||
protected final Set<Document> myUncommittedDocuments = ContainerUtil.newConcurrentSet();
|
||||
private final Map<Document, CharSequence> myLastCommittedTexts = ContainerUtil.newConcurrentMap();
|
||||
private final Map<Document, Pair<CharSequence, Long>> myLastCommittedTexts = ContainerUtil.newConcurrentMap();
|
||||
|
||||
private volatile boolean myIsCommitInProgress;
|
||||
private final PsiToDocumentSynchronizer mySynchronizer;
|
||||
@@ -558,8 +559,14 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
|
||||
@Override
|
||||
@NotNull
|
||||
public CharSequence getLastCommittedText(@NotNull Document document) {
|
||||
CharSequence text = myLastCommittedTexts.get(document);
|
||||
return text != null ? text : document.getImmutableCharSequence();
|
||||
Pair<CharSequence, Long> pair = myLastCommittedTexts.get(document);
|
||||
return pair != null ? pair.first : document.getImmutableCharSequence();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastCommittedStamp(@NotNull Document document) {
|
||||
Pair<CharSequence, Long> pair = myLastCommittedTexts.get(document);
|
||||
return pair != null ? pair.second : document.getModificationStamp();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -595,7 +602,7 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
|
||||
public void beforeDocumentChange(@NotNull DocumentEvent event) {
|
||||
final Document document = event.getDocument();
|
||||
if (!(document instanceof DocumentWindow) && !myLastCommittedTexts.containsKey(document)) {
|
||||
myLastCommittedTexts.put(document, document.getImmutableCharSequence());
|
||||
myLastCommittedTexts.put(document, Pair.create(document.getImmutableCharSequence(), document.getModificationStamp()));
|
||||
}
|
||||
|
||||
VirtualFile virtualFile = FileDocumentManager.getInstance().getFile(document);
|
||||
@@ -713,14 +720,16 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
|
||||
}
|
||||
|
||||
public void handleCommitWithoutPsi(@NotNull Document document) {
|
||||
final CharSequence prevText = myLastCommittedTexts.remove(document);
|
||||
if (prevText == null) {
|
||||
final Pair<CharSequence, Long> prevPair = myLastCommittedTexts.remove(document);
|
||||
if (prevPair == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!myProject.isInitialized() || myProject.isDisposed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
myUncommittedDocuments.remove(document);
|
||||
|
||||
VirtualFile virtualFile = FileDocumentManager.getInstance().getFile(document);
|
||||
if (virtualFile == null || !FileIndexFacade.getInstance(myProject).isInContent(virtualFile)) {
|
||||
@@ -738,7 +747,7 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
|
||||
public void run() {
|
||||
psiFile.getViewProvider().beforeContentsSynchronized();
|
||||
synchronized (PsiLock.LOCK) {
|
||||
final int oldLength = prevText.length();
|
||||
final int oldLength = prevPair.first.length();
|
||||
PsiManagerImpl manager = (PsiManagerImpl)psiFile.getManager();
|
||||
BlockSupportImpl.sendBeforeChildrenChangeEvent(manager, psiFile, true);
|
||||
BlockSupportImpl.sendBeforeChildrenChangeEvent(manager, psiFile, false);
|
||||
|
||||
@@ -389,6 +389,7 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF
|
||||
DebugUtil.finishPsiModification();
|
||||
}
|
||||
}
|
||||
myViewProvider.contentsSynchronized();
|
||||
}
|
||||
|
||||
private void clearStub(@NotNull String reason) {
|
||||
|
||||
@@ -163,21 +163,28 @@ public class CompositeElement extends TreeElement {
|
||||
startFind:
|
||||
while (true) {
|
||||
TreeElement child = element.getFirstChildNode();
|
||||
TreeElement lastChild = element.getLastChildNode();
|
||||
boolean fwd = lastChild == null || (lastChild.getStartOffset() + lastChild.getTextLength() - child.getStartOffset()) / 2 > offset;
|
||||
if (!fwd) {
|
||||
child = lastChild;
|
||||
offset = element.getTextLength() - offset;
|
||||
}
|
||||
while (child != null) {
|
||||
final int textLength = child.getTextLength();
|
||||
if (textLength > offset) {
|
||||
if (textLength > offset || !fwd && textLength >= offset) {
|
||||
if (child instanceof LeafElement) {
|
||||
if (child instanceof ForeignLeafPsiElement) {
|
||||
child = child.getTreeNext();
|
||||
child = fwd ? child.getTreeNext() : child.getTreePrev();
|
||||
continue;
|
||||
}
|
||||
return (LeafElement)child;
|
||||
}
|
||||
offset = fwd ? offset : child.getTextLength() - offset;
|
||||
element = child;
|
||||
continue startFind;
|
||||
}
|
||||
offset -= textLength;
|
||||
child = child.getTreeNext();
|
||||
child = fwd ? child.getTreeNext() : child.getTreePrev();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
+11
-1
@@ -7,8 +7,11 @@ import com.intellij.dupLocator.iterators.SiblingNodeIterator;
|
||||
import com.intellij.dupLocator.util.DuplocatorUtil;
|
||||
import com.intellij.dupLocator.util.NodeFilter;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.LanguageFileType;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiErrorElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiWhiteSpace;
|
||||
import com.intellij.psi.impl.source.tree.LeafElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
@@ -131,7 +134,14 @@ public class NodeSpecificHasherBase extends NodeSpecificHasher {
|
||||
|
||||
@Override
|
||||
public void visitNode(@NotNull PsiElement node) {
|
||||
final Language language = node.getLanguage();
|
||||
Language language = null;
|
||||
if (node instanceof PsiFile) {
|
||||
FileType fileType = ((PsiFile)node).getFileType();
|
||||
if (fileType instanceof LanguageFileType) {
|
||||
language = ((LanguageFileType)fileType).getLanguage();
|
||||
}
|
||||
}
|
||||
if (language == null) language = node.getLanguage();
|
||||
if ((myForIndexing || mySettings.SELECTED_PROFILES.contains(language.getDisplayName())) &&
|
||||
myDuplicatesProfile.isMyLanguage(language)) {
|
||||
|
||||
|
||||
@@ -115,16 +115,21 @@ public class ProjectUtil {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Project guessCurrentProject(JComponent component) {
|
||||
public static Project guessCurrentProject(@Nullable JComponent component) {
|
||||
Project project = null;
|
||||
Project[] openProjects = ProjectManager.getInstance().getOpenProjects();
|
||||
if (openProjects.length > 0) project = openProjects[0];
|
||||
if (project == null) {
|
||||
DataContext dataContext = component == null ? DataManager.getInstance().getDataContext() : DataManager.getInstance().getDataContext(component);
|
||||
project = CommonDataKeys.PROJECT.getData(dataContext);
|
||||
if (component != null) {
|
||||
project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(component));
|
||||
}
|
||||
if (project == null) {
|
||||
project = ProjectManager.getInstance().getDefaultProject();
|
||||
Project[] openProjects = ProjectManager.getInstance().getOpenProjects();
|
||||
if (openProjects.length > 0) project = openProjects[0];
|
||||
if (project == null) {
|
||||
DataContext dataContext = DataManager.getInstance().getDataContext();
|
||||
project = CommonDataKeys.PROJECT.getData(dataContext);
|
||||
}
|
||||
if (project == null) {
|
||||
project = ProjectManager.getInstance().getDefaultProject();
|
||||
}
|
||||
}
|
||||
return project;
|
||||
}
|
||||
|
||||
+8
-3
@@ -38,9 +38,11 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageManagerImpl;
|
||||
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
|
||||
import com.intellij.psi.impl.source.tree.injected.Place;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.util.CommonProcessors;
|
||||
import com.intellij.util.Processor;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -80,6 +82,7 @@ public class InjectedGeneralHighlightingPass extends GeneralHighlightingPass imp
|
||||
final List<PsiElement> outside = new ArrayList<PsiElement>();
|
||||
List<ProperTextRange> insideRanges = new ArrayList<ProperTextRange>();
|
||||
List<ProperTextRange> outsideRanges = new ArrayList<ProperTextRange>();
|
||||
//TODO: this thing is just called TWICE with same arguments eating CPU on huge files :(
|
||||
Divider.divideInsideAndOutside(myFile, myStartOffset, myEndOffset, myPriorityRange, inside, insideRanges, outside,
|
||||
outsideRanges, false, FILE_FILTER);
|
||||
|
||||
@@ -148,7 +151,7 @@ public class InjectedGeneralHighlightingPass extends GeneralHighlightingPass imp
|
||||
final Set<PsiFile> outInjected = new THashSet<PsiFile>();
|
||||
|
||||
List<DocumentWindow> injected = InjectedLanguageUtil.getCachedInjectedDocuments(myFile);
|
||||
Collection<PsiElement> hosts = new THashSet<PsiElement>(elements1.size() + elements2.size() + injected.size());
|
||||
final Collection<PsiElement> hosts = new THashSet<PsiElement>(elements1.size() + elements2.size() + injected.size());
|
||||
|
||||
//rehighlight all injected PSI regardless the range,
|
||||
//since change in one place can lead to invalidation of injected PSI in (completely) other place.
|
||||
@@ -165,8 +168,10 @@ public class InjectedGeneralHighlightingPass extends GeneralHighlightingPass imp
|
||||
hosts.add(context);
|
||||
}
|
||||
}
|
||||
hosts.addAll(elements1);
|
||||
hosts.addAll(elements2);
|
||||
InjectedLanguageManagerImpl injectedLanguageManager = InjectedLanguageManagerImpl.getInstanceImpl(myProject);
|
||||
Processor<PsiElement> collectInjectableProcessor = new CommonProcessors.CollectProcessor<PsiElement>(hosts);
|
||||
injectedLanguageManager.processInjectableElements(elements1, collectInjectableProcessor);
|
||||
injectedLanguageManager.processInjectableElements(elements2, collectInjectableProcessor);
|
||||
|
||||
final PsiLanguageInjectionHost.InjectedPsiVisitor visitor = new PsiLanguageInjectionHost.InjectedPsiVisitor() {
|
||||
@Override
|
||||
|
||||
@@ -48,9 +48,11 @@ import com.intellij.openapi.project.IndexNotReadyException;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageManagerImpl;
|
||||
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.FunctionUtil;
|
||||
import com.intellij.util.Processor;
|
||||
import gnu.trove.THashSet;
|
||||
import gnu.trove.TIntObjectHashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -201,7 +203,7 @@ public class LineMarkersPass extends TextEditorHighlightingPass implements LineM
|
||||
public static void collectLineMarkersForInjected(@NotNull final List<LineMarkerInfo> result,
|
||||
@NotNull List<PsiElement> elements,
|
||||
@NotNull final LineMarkersProcessor processor,
|
||||
@NotNull PsiFile file,
|
||||
@NotNull final PsiFile file,
|
||||
@NotNull final ProgressIndicator progress) {
|
||||
final InjectedLanguageManager manager = InjectedLanguageManager.getInstance(file.getProject());
|
||||
final List<LineMarkerInfo> injectedMarkers = new ArrayList<LineMarkerInfo>();
|
||||
@@ -213,9 +215,13 @@ public class LineMarkersPass extends TextEditorHighlightingPass implements LineM
|
||||
injectedFiles.add(injectedPsi);
|
||||
}
|
||||
};
|
||||
for (int i = 0, size = elements.size(); i < size; ++i) {
|
||||
InjectedLanguageUtil.enumerate(elements.get(i), file, false, collectingVisitor);
|
||||
}
|
||||
InjectedLanguageManagerImpl.getInstanceImpl(file.getProject()).processInjectableElements(elements, new Processor<PsiElement>() {
|
||||
@Override
|
||||
public boolean process(PsiElement element) {
|
||||
InjectedLanguageUtil.enumerate(element, file, false, collectingVisitor);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
for (PsiFile injectedPsi : injectedFiles) {
|
||||
final Project project = injectedPsi.getProject();
|
||||
Document document = PsiDocumentManager.getInstance(project).getCachedDocument(injectedPsi);
|
||||
|
||||
+9
-4
@@ -60,13 +60,13 @@ import com.intellij.psi.search.LocalSearchScope;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.ui.content.*;
|
||||
import com.intellij.util.ConcurrencyUtil;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.SequentialModalProgressTask;
|
||||
import com.intellij.util.TripleFunction;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import gnu.trove.THashMap;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jdom.Document;
|
||||
import org.jdom.Element;
|
||||
@@ -78,7 +78,9 @@ import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
public class GlobalInspectionContextImpl extends GlobalInspectionContextBase implements GlobalInspectionContext {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.ex.GlobalInspectionContextImpl");
|
||||
@@ -592,7 +594,7 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
|
||||
}
|
||||
}
|
||||
|
||||
private final Map<InspectionToolWrapper, InspectionToolPresentation> myPresentationMap = new THashMap<InspectionToolWrapper, InspectionToolPresentation>();
|
||||
private final ConcurrentMap<InspectionToolWrapper, InspectionToolPresentation> myPresentationMap = ContainerUtil.newConcurrentMap();
|
||||
@NotNull
|
||||
public InspectionToolPresentation getPresentation(@NotNull InspectionToolWrapper toolWrapper) {
|
||||
InspectionToolPresentation presentation = myPresentationMap.get(toolWrapper);
|
||||
@@ -601,12 +603,15 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
|
||||
DefaultInspectionToolPresentation.class.getName());
|
||||
|
||||
try {
|
||||
presentation = (InspectionToolPresentation)Class.forName(presentationClass).getConstructor(InspectionToolWrapper.class, GlobalInspectionContextImpl.class).newInstance(toolWrapper, this);
|
||||
Constructor<?> constructor =
|
||||
Class.forName(presentationClass).getConstructor(InspectionToolWrapper.class, GlobalInspectionContextImpl.class);
|
||||
presentation = (InspectionToolPresentation)constructor.newInstance(toolWrapper, this);
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error(e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
myPresentationMap.put(toolWrapper, presentation);
|
||||
presentation = ConcurrencyUtil.cacheOrGet(myPresentationMap, toolWrapper, presentation);
|
||||
}
|
||||
return presentation;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.VerticalFlowLayout;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.PsiCompiledElement;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
|
||||
import com.intellij.ui.*;
|
||||
@@ -904,8 +906,11 @@ public class MemberChooser<T extends ClassMember> extends DialogWrapper implemen
|
||||
@Override
|
||||
public int compare(ElementNode n1, ElementNode n2) {
|
||||
if (n1.getDelegate() instanceof ClassMemberWithElement && n2.getDelegate() instanceof ClassMemberWithElement) {
|
||||
return ((ClassMemberWithElement)n1.getDelegate()).getElement().getTextOffset() -
|
||||
((ClassMemberWithElement)n2.getDelegate()).getElement().getTextOffset();
|
||||
PsiElement element1 = ((ClassMemberWithElement)n1.getDelegate()).getElement();
|
||||
PsiElement element2 = ((ClassMemberWithElement)n2.getDelegate()).getElement();
|
||||
if (!(element1 instanceof PsiCompiledElement) && !(element2 instanceof PsiCompiledElement)) {
|
||||
return element1.getTextOffset() - element2.getTextOffset();
|
||||
}
|
||||
}
|
||||
return n1.getOrder() - n2.getOrder();
|
||||
}
|
||||
|
||||
+1
-4
@@ -51,10 +51,7 @@ public class EnforcedPlainTextFileTypeFactory extends FileTypeFactory {
|
||||
|
||||
@Override
|
||||
public boolean isMyFileType(@NotNull VirtualFile file) {
|
||||
if (isMarkedAsPlainText(file)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return isMarkedAsPlainText(file);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+8
@@ -228,6 +228,14 @@ public class InjectedLanguageManagerImpl extends InjectedLanguageManager impleme
|
||||
private final Set<MultiHostInjector> myManualInjectors = Collections.synchronizedSet(new LinkedHashSet<MultiHostInjector>());
|
||||
private volatile ClassMapCachingNulls<MultiHostInjector> cachedInjectors;
|
||||
|
||||
public void processInjectableElements(Collection<PsiElement> in, Processor<PsiElement> processor) {
|
||||
ClassMapCachingNulls<MultiHostInjector> map = getInjectorMap();
|
||||
for (PsiElement element : in) {
|
||||
if (map.get(element.getClass()) != null)
|
||||
processor.process(element);
|
||||
}
|
||||
}
|
||||
|
||||
private ClassMapCachingNulls<MultiHostInjector> getInjectorMap() {
|
||||
ClassMapCachingNulls<MultiHostInjector> cached = cachedInjectors;
|
||||
if (cached != null) {
|
||||
|
||||
+1
-1
@@ -307,7 +307,7 @@ public class InjectedLanguageUtil {
|
||||
MultiHostRegistrarImpl registrar = null;
|
||||
PsiElement current = element;
|
||||
nextParent:
|
||||
while (current != null && current != hostPsiFile) {
|
||||
while (current != null && current != hostPsiFile && !(current instanceof PsiDirectory)) {
|
||||
ProgressManager.checkCanceled();
|
||||
if ("EL".equals(current.getLanguage().getID())) break;
|
||||
ParameterizedCachedValue<MultiHostRegistrarImpl, PsiElement> data = current.getUserData(INJECTED_PSI);
|
||||
|
||||
@@ -22,10 +22,15 @@ package com.intellij.ui;
|
||||
import com.intellij.concurrency.Job;
|
||||
import com.intellij.concurrency.JobLauncher;
|
||||
import com.intellij.ide.PowerSaveMode;
|
||||
import com.intellij.openapi.application.ApplicationAdapter;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.application.ex.ApplicationManagerEx;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.progress.util.ProgressIndicatorBase;
|
||||
import com.intellij.openapi.project.IndexNotReadyException;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.ui.tabs.impl.TabLabel;
|
||||
import com.intellij.util.Alarm;
|
||||
@@ -119,18 +124,43 @@ public class DeferredIconImpl<T> implements DeferredIcon {
|
||||
|
||||
final long startTime = System.currentTimeMillis();
|
||||
if (myNeedReadAction) {
|
||||
if (!ApplicationManagerEx.getApplicationEx().tryRunReadAction(new Runnable() {
|
||||
final ProgressIndicatorBase progress = new ProgressIndicatorBase();
|
||||
final ApplicationAdapter listener = new ApplicationAdapter() {
|
||||
@Override
|
||||
public void beforeWriteActionStart(Object action) {
|
||||
progress.cancel();
|
||||
}
|
||||
};
|
||||
ApplicationManager.getApplication().invokeAndWait(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
IconDeferrerImpl.evaluateDeferred(evalRunnable);
|
||||
if (myAutoUpdatable) {
|
||||
myLastCalcTime = System.currentTimeMillis();
|
||||
myLastTimeSpent = myLastCalcTime - startTime;
|
||||
}
|
||||
ApplicationManager.getApplication().addApplicationListener(listener);
|
||||
}
|
||||
})) {
|
||||
myIsScheduled = false;
|
||||
return;
|
||||
}, ModalityState.any());
|
||||
try {
|
||||
final Ref<Boolean> cancelled = new Ref<Boolean>();
|
||||
ProgressManager.getInstance().runProcess(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!ApplicationManagerEx.getApplicationEx().tryRunReadAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
IconDeferrerImpl.evaluateDeferred(evalRunnable);
|
||||
if (myAutoUpdatable) {
|
||||
myLastCalcTime = System.currentTimeMillis();
|
||||
myLastTimeSpent = myLastCalcTime - startTime;
|
||||
}
|
||||
}
|
||||
})) {
|
||||
myIsScheduled = false;
|
||||
cancelled.set(Boolean.TRUE);
|
||||
}
|
||||
}
|
||||
}, progress);
|
||||
if (cancelled.get() == Boolean.TRUE) return;
|
||||
} catch(ProcessCanceledException e) {}
|
||||
finally {
|
||||
ApplicationManager.getApplication().removeApplicationListener(listener);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -1349,9 +1349,6 @@ public class FileBasedIndexImpl extends FileBasedIndex {
|
||||
boolean allDocsProcessed = true;
|
||||
try {
|
||||
for (Document document : documents) {
|
||||
if (psiBasedIndex && project != null && PsiDocumentManager.getInstance(project).isUncommited(document)) {
|
||||
continue;
|
||||
}
|
||||
allDocsProcessed &= indexUnsavedDocument(document, indexId, project, filter, restrictedFile);
|
||||
ProgressManager.checkCanceled();
|
||||
}
|
||||
@@ -1451,7 +1448,7 @@ public class FileBasedIndexImpl extends FileBasedIndex {
|
||||
return false;
|
||||
}
|
||||
|
||||
final PsiFile dominantContentFile = findDominantPsiForDocument(document, project);
|
||||
final PsiFile dominantContentFile = project == null ? null : findLatestKnownPsiForUncomittedDocument(document, project);
|
||||
|
||||
final DocumentContent content;
|
||||
if (dominantContentFile != null && dominantContentFile.getViewProvider().getModificationStamp() != document.getModificationStamp()) {
|
||||
@@ -1461,7 +1458,9 @@ public class FileBasedIndexImpl extends FileBasedIndex {
|
||||
content = new AuthenticContent(document);
|
||||
}
|
||||
|
||||
final long currentDocStamp = content.getModificationStamp();
|
||||
boolean psiBasedIndex = myPsiDependentIndices.contains(requestedIndexId);
|
||||
|
||||
final long currentDocStamp = psiBasedIndex ? PsiDocumentManager.getInstance(project).getLastCommittedStamp(document) : content.getModificationStamp();
|
||||
final long previousDocStamp = myLastIndexedDocStamps.getAndSet(document, requestedIndexId, currentDocStamp);
|
||||
if (currentDocStamp != previousDocStamp) {
|
||||
final CharSequence contentText = content.getText();
|
||||
@@ -1509,14 +1508,6 @@ public class FileBasedIndexImpl extends FileBasedIndex {
|
||||
|
||||
private final TaskQueue myContentlessIndicesUpdateQueue = new TaskQueue(10000);
|
||||
|
||||
@Nullable
|
||||
private PsiFile findDominantPsiForDocument(@NotNull Document document, @Nullable Project project) {
|
||||
PsiFile psiFile = myTransactionMap.get(document);
|
||||
if (psiFile != null) return psiFile;
|
||||
|
||||
return project == null ? null : findLatestKnownPsiForUncomittedDocument(document, project);
|
||||
}
|
||||
|
||||
private final StorageGuard myStorageLock = new StorageGuard();
|
||||
private volatile boolean myPreviousDataBufferingState;
|
||||
private final Object myBufferingStateUpdateLock = new Object();
|
||||
|
||||
@@ -1176,9 +1176,7 @@ public abstract class DialogWrapper {
|
||||
}
|
||||
|
||||
protected void init() {
|
||||
if (!SwingUtilities.isEventDispatchThread()) {
|
||||
LOG.error("Dialog must be init in EDT only: "+Thread.currentThread());
|
||||
}
|
||||
ensureEventDispatchThread();
|
||||
myErrorText = new ErrorText();
|
||||
myErrorText.setVisible(false);
|
||||
|
||||
@@ -1197,7 +1195,7 @@ public abstract class DialogWrapper {
|
||||
final CustomShortcutSet sc = new CustomShortcutSet(SHOW_OPTION_KEYSTROKE);
|
||||
final AnAction toggleShowOptions = new AnAction() {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
expandNextOptionButton();
|
||||
}
|
||||
};
|
||||
@@ -1548,7 +1546,7 @@ public abstract class DialogWrapper {
|
||||
* @throws IllegalStateException if the dialog is invoked not on the event dispatch thread
|
||||
*/
|
||||
public void show() {
|
||||
showAndGetOk();
|
||||
invokeShow();
|
||||
}
|
||||
|
||||
public boolean showAndGet() {
|
||||
@@ -1559,16 +1557,23 @@ public abstract class DialogWrapper {
|
||||
/**
|
||||
* You need this method ONLY for NON-MODAL dialogs. Otherwise, use {@link #show()} or {@link #showAndGet()}.
|
||||
*
|
||||
* @return result callback
|
||||
* @return result callback which set to "Done" on dialog close, and then its {@code getResult()} will contain {@code isOK()}
|
||||
*/
|
||||
@NotNull
|
||||
public AsyncResult<Boolean> showAndGetOk() {
|
||||
if (isModal()) {
|
||||
throw new IllegalStateException("The showAndGetOk() method is for modeless dialogs only");
|
||||
}
|
||||
return invokeShow();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private AsyncResult<Boolean> invokeShow() {
|
||||
final AsyncResult<Boolean> result = new AsyncResult<Boolean>();
|
||||
|
||||
ensureEventDispatchThread();
|
||||
registerKeyboardShortcuts();
|
||||
|
||||
|
||||
final Disposable uiParent = Disposer.get("ui");
|
||||
if (uiParent != null) { // may be null if no app yet (license agreement)
|
||||
Disposer.register(uiParent, myDisposable); // ensure everything is disposed on app quit
|
||||
@@ -1600,7 +1605,6 @@ public abstract class DialogWrapper {
|
||||
}
|
||||
|
||||
private void registerKeyboardShortcuts() {
|
||||
|
||||
final JRootPane rootPane = getRootPane();
|
||||
|
||||
if (rootPane == null) return;
|
||||
@@ -2010,7 +2014,7 @@ public abstract class DialogWrapper {
|
||||
*/
|
||||
private static void ensureEventDispatchThread() {
|
||||
if (!EventQueue.isDispatchThread()) {
|
||||
throw new IllegalStateException("The DialogWrapper can be used only on event dispatch thread.");
|
||||
throw new IllegalStateException("The DialogWrapper can be used only in event dispatch thread. Current thread: "+Thread.currentThread());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2121,7 +2125,7 @@ public abstract class DialogWrapper {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setValidationInfo(@Nullable ValidationInfo info) {
|
||||
private void setValidationInfo(@Nullable ValidationInfo info) {
|
||||
myInfo = info;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,12 +131,13 @@ public class BorderEffect {
|
||||
int startX = startPoint.x;
|
||||
int startY = startPoint.y;
|
||||
int endX = endPoint.x;
|
||||
int lineHeight = editor.getLineHeight();
|
||||
if (height == 0) {
|
||||
int width = endX == startX ? 1 : endX - startX - 1;
|
||||
if (effectType == EffectType.ROUNDED_BOX) {
|
||||
UIUtil.drawRectPickedOut((Graphics2D)g, startX, startY, width, editor.getLineHeight() - 1);
|
||||
UIUtil.drawRectPickedOut((Graphics2D)g, startX, startY, width, lineHeight - 1);
|
||||
} else {
|
||||
g.drawRect(startX, startY, width, editor.getLineHeight() - 1);
|
||||
g.drawRect(startX, startY, width, lineHeight - 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -145,12 +146,12 @@ public class BorderEffect {
|
||||
border.verticalRel(height - 1);
|
||||
border.horizontalTo(endX);
|
||||
if (endX > 0) {
|
||||
border.verticalRel(editor.getLineHeight());
|
||||
border.verticalRel(lineHeight);
|
||||
border.horizontalTo(0);
|
||||
border.verticalRel(-height + 1);
|
||||
}
|
||||
else {
|
||||
border.verticalTo(startY + editor.getLineHeight() - 1);
|
||||
else if (height > lineHeight) {
|
||||
border.verticalRel(-height + lineHeight + 1);
|
||||
}
|
||||
border.horizontalTo(startX);
|
||||
border.verticalTo(startY);
|
||||
|
||||
+48
-8
@@ -77,9 +77,11 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME
|
||||
|
||||
private static final int VERSION = 11;
|
||||
private static final Key<FileType> FILE_TYPE_KEY = Key.create("FILE_TYPE_KEY");
|
||||
// cached auto-detected file type. If the file was auto-detected as plain text or binary
|
||||
// then the value is null and autoDetectedAsText, autoDetectedAsBinary and autoDetectWasRun sets are used instead.
|
||||
private static final Key<FileType> DETECTED_FROM_CONTENT_FILE_TYPE_KEY = Key.create("DETECTED_FROM_CONTENT_FILE_TYPE_KEY");
|
||||
private static final int DETECT_BUFFER_SIZE = 8192; // the number of bytes to read from the file to feed to the file type detector
|
||||
private boolean RE_DETECT_ASYNC = !ApplicationManager.getApplication().isUnitTestMode();
|
||||
private static boolean RE_DETECT_ASYNC = !ApplicationManager.getApplication().isUnitTestMode();
|
||||
private final Set<FileType> myDefaultTypes = new THashSet<FileType>();
|
||||
private final List<FileTypeIdentifiableByVirtualFile> mySpecialFileTypes = new ArrayList<FileTypeIdentifiableByVirtualFile>();
|
||||
|
||||
@@ -257,6 +259,9 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME
|
||||
}
|
||||
});
|
||||
files.remove(null);
|
||||
if (toLog()) {
|
||||
System.out.println("F: VFS events: " + events);
|
||||
}
|
||||
if (!files.isEmpty() && RE_DETECT_ASYNC) {
|
||||
reDetectQueue.offer(files);
|
||||
}
|
||||
@@ -264,6 +269,10 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME
|
||||
});
|
||||
}
|
||||
|
||||
private static boolean toLog() {
|
||||
return RE_DETECT_ASYNC && ApplicationManager.getApplication().isUnitTestMode();
|
||||
}
|
||||
|
||||
private final TransferToPooledThreadQueue<Collection<VirtualFile>> reDetectQueue = new TransferToPooledThreadQueue<Collection<VirtualFile>>("File type re-detect", Conditions.alwaysFalse(), -1, new Processor<Collection<VirtualFile>>() {
|
||||
@Override
|
||||
public boolean process(Collection<VirtualFile> files) {
|
||||
@@ -284,12 +293,20 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME
|
||||
private void reDetect(@NotNull Collection<VirtualFile> files) {
|
||||
final List<VirtualFile> changed = new ArrayList<VirtualFile>();
|
||||
for (VirtualFile file : files) {
|
||||
if (wasAutoDetectedBefore(file) && isDetectable(file)) {
|
||||
boolean shouldRedetect = wasAutoDetectedBefore(file) && isDetectable(file);
|
||||
if (toLog()) {
|
||||
System.out.println("F: Redetect file: " + file.getName() + "; shouldRedetect: " + shouldRedetect);
|
||||
}
|
||||
if (shouldRedetect) {
|
||||
FileType before = file.getFileType();
|
||||
FileType after = detectFromContent(file);
|
||||
if (toLog()) {
|
||||
System.out.println("F: After redetect file: " + file.getName() + "; before: " + before.getName() + "; after: " + after.getName()+"; now getFileType()="+file.getFileType().getName());
|
||||
}
|
||||
|
||||
if (before != after) {
|
||||
changed.add(file);
|
||||
LOG.debug(file+" type was re-detected. Was: "+before+"; now: "+after);
|
||||
LOG.debug(file+" type was re-detected. Was: "+before.getName()+"; now: "+after.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -392,6 +409,9 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME
|
||||
|
||||
public static void cacheFileType(@NotNull VirtualFile file, @Nullable FileType fileType) {
|
||||
file.putUserData(FILE_TYPE_KEY, fileType);
|
||||
if (toLog()) {
|
||||
System.out.println("F: Cached file type for "+file.getName()+" to "+(fileType == null ? null : fileType.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -409,12 +429,20 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME
|
||||
for (int i = 0; i < mySpecialFileTypes.size(); i++) {
|
||||
FileTypeIdentifiableByVirtualFile type = mySpecialFileTypes.get(i);
|
||||
if (type.isMyFileType(file)) {
|
||||
if (toLog()) {
|
||||
System.out.println("F: Special file type for "+file.getName()+"; type: "+type.getName());
|
||||
}
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
fileType = getFileTypeByFileName(file.getNameSequence());
|
||||
if (fileType != UnknownFileType.INSTANCE) return fileType;
|
||||
if (fileType != UnknownFileType.INSTANCE) {
|
||||
if (toLog()) {
|
||||
System.out.println("F: By name file type for "+file.getName()+"; type: "+fileType.getName());
|
||||
}
|
||||
return fileType;
|
||||
}
|
||||
|
||||
if (!(file instanceof StubVirtualFile)) {
|
||||
fileType = getOrDetectFromContent(file);
|
||||
@@ -430,8 +458,13 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME
|
||||
int id = ((VirtualFileWithId)file).getId();
|
||||
if (id < 0) return UnknownFileType.INSTANCE;
|
||||
if (autoDetectWasRun.get(id)) {
|
||||
return autoDetectedAsText.get(id) ? FileTypes.PLAIN_TEXT : autoDetectedAsBinary.get(id) ? UnknownFileType.INSTANCE :
|
||||
ObjectUtils.notNull(file.getUserData(DETECTED_FROM_CONTENT_FILE_TYPE_KEY), FileTypes.PLAIN_TEXT);
|
||||
FileType type = autoDetectedAsText.get(id) ? FileTypes.PLAIN_TEXT :
|
||||
autoDetectedAsBinary.get(id) ? UnknownFileType.INSTANCE :
|
||||
ObjectUtils.notNull(file.getUserData(DETECTED_FROM_CONTENT_FILE_TYPE_KEY), FileTypes.PLAIN_TEXT);
|
||||
if (toLog()) {
|
||||
System.out.println("F: getFileType("+file.getName()+") = "+type.getName());
|
||||
}
|
||||
return type;
|
||||
}
|
||||
boolean wasDetectedAsText = false;
|
||||
boolean wasDetectedAsBinary = false;
|
||||
@@ -465,6 +498,10 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME
|
||||
fileType = detectFromContent(file);
|
||||
}
|
||||
|
||||
if (toLog()) {
|
||||
System.out.println("F: getFileType after detect run("+file.getName()+") = "+fileType.getName());
|
||||
}
|
||||
|
||||
return fileType;
|
||||
}
|
||||
|
||||
@@ -501,6 +538,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME
|
||||
autoDetectedAsText.set(id, wasAutodetectedAsText);
|
||||
autoDetectedAsBinary.set(id, wasAutodetectedAsBinary);
|
||||
if (wasAutodetectedAsText || wasAutodetectedAsBinary) {
|
||||
file.putUserData(DETECTED_FROM_CONTENT_FILE_TYPE_KEY, null);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -535,9 +573,8 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME
|
||||
long start = System.currentTimeMillis();
|
||||
try {
|
||||
final InputStream inputStream = ((FileSystemInterface)file.getFileSystem()).getInputStream(file);
|
||||
final Ref<FileType> result;
|
||||
final Ref<FileType> result = new Ref<FileType>(UnknownFileType.INSTANCE);
|
||||
try {
|
||||
result = new Ref<FileType>(UnknownFileType.INSTANCE);
|
||||
FileUtil.processFirstBytes(inputStream, DETECT_BUFFER_SIZE, new Processor<ByteSequence>() {
|
||||
@Override
|
||||
public boolean process(ByteSequence byteSequence) {
|
||||
@@ -574,6 +611,9 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME
|
||||
inputStream.close();
|
||||
}
|
||||
FileType fileType = result.get();
|
||||
if (toLog()) {
|
||||
System.out.println("F: Redetect run for file: " + file.getName() + "; result: "+fileType.getName());
|
||||
}
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug(file + "; type=" + fileType.getDescription() + "; " + counterAutoDetect);
|
||||
|
||||
+10
-12
@@ -56,7 +56,7 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public class ProgressManagerImpl extends ProgressManager implements Disposable {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.progress.impl.ProgressManagerImpl");
|
||||
public static final int CHECK_CANCELED_DELAY_MILLIS = 10;
|
||||
static final int CHECK_CANCELED_DELAY_MILLIS = 10;
|
||||
private final AtomicInteger myCurrentUnsafeProgressCount = new AtomicInteger(0);
|
||||
private final AtomicInteger myCurrentModalProgressCount = new AtomicInteger(0);
|
||||
|
||||
@@ -321,19 +321,17 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable {
|
||||
Set<Thread> threads = threadsUnderIndicator.get(indicator);
|
||||
if (threads != null) {
|
||||
for (Thread thread : threads) {
|
||||
ProgressIndicator currentIndicator = getCurrentIndicator(thread);
|
||||
boolean underCancelledIndicator = currentIndicator == indicator;
|
||||
|
||||
if (!underCancelledIndicator && currentIndicator instanceof WrappedProgressIndicator) {
|
||||
while(currentIndicator instanceof WrappedProgressIndicator) {
|
||||
ProgressIndicator originalProgressIndicator = ((WrappedProgressIndicator)currentIndicator).getOriginalProgressIndicator();
|
||||
if (originalProgressIndicator == indicator) {
|
||||
underCancelledIndicator = true;
|
||||
break;
|
||||
}
|
||||
currentIndicator = originalProgressIndicator;
|
||||
boolean underCancelledIndicator = false;
|
||||
for (ProgressIndicator currentIndicator = getCurrentIndicator(thread);
|
||||
currentIndicator != null;
|
||||
currentIndicator = currentIndicator instanceof WrappedProgressIndicator ?
|
||||
((WrappedProgressIndicator)currentIndicator).getOriginalProgressIndicator() : null) {
|
||||
if (currentIndicator == indicator) {
|
||||
underCancelledIndicator = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (underCancelledIndicator) {
|
||||
threadsUnderCanceledIndicator.add(thread);
|
||||
}
|
||||
|
||||
@@ -218,6 +218,8 @@ public class FrameWrapper implements Disposable, DataProvider {
|
||||
myStatusBar = null;
|
||||
}
|
||||
|
||||
frame.dispose();
|
||||
|
||||
myDisposed = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.openapi.wm.ex;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.wm.ToolWindowAnchor;
|
||||
@@ -35,6 +36,7 @@ public abstract class ToolWindowManagerEx extends ToolWindowManager {
|
||||
}
|
||||
|
||||
public abstract void addToolWindowManagerListener(@NotNull ToolWindowManagerListener l);
|
||||
public abstract void addToolWindowManagerListener(@NotNull ToolWindowManagerListener l, @NotNull Disposable parentDisposable);
|
||||
public abstract void removeToolWindowManagerListener(@NotNull ToolWindowManagerListener l);
|
||||
|
||||
/**
|
||||
|
||||
+4
@@ -217,6 +217,10 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addToolWindowManagerListener(@NotNull ToolWindowManagerListener l, @NotNull Disposable parentDisposable) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeToolWindowManagerListener(@NotNull ToolWindowManagerListener l) {
|
||||
}
|
||||
|
||||
@@ -566,6 +566,11 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
|
||||
myDispatcher.addListener(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addToolWindowManagerListener(@NotNull ToolWindowManagerListener l, @NotNull Disposable parentDisposable) {
|
||||
myDispatcher.addListener(l, parentDisposable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeToolWindowManagerListener(@NotNull ToolWindowManagerListener l) {
|
||||
myDispatcher.removeListener(l);
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.intellij.ui;
|
||||
import com.intellij.featureStatistics.FeatureUsageTracker;
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.ide.ui.UISettings;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
@@ -25,6 +26,7 @@ import com.intellij.openapi.actionSystem.CustomShortcutSet;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
@@ -65,6 +67,7 @@ public abstract class SpeedSearchBase<Comp extends JComponent> extends SpeedSear
|
||||
private boolean myClearSearchOnNavigateNoMatch = false;
|
||||
|
||||
@NonNls protected static final String ENTERED_PREFIX_PROPERTY_NAME = "enteredPrefix";
|
||||
private Disposable myListenerDisposable;
|
||||
|
||||
public SpeedSearchBase(Comp component) {
|
||||
myComponent = component;
|
||||
@@ -522,10 +525,9 @@ public abstract class SpeedSearchBase<Comp extends JComponent> extends SpeedSear
|
||||
myPopupLayeredPane.validate();
|
||||
myPopupLayeredPane.repaint();
|
||||
myPopupLayeredPane = null;
|
||||
|
||||
if (project != null) {
|
||||
((ToolWindowManagerEx)ToolWindowManager.getInstance(project)).removeToolWindowManagerListener(myWindowManagerListener);
|
||||
}
|
||||
|
||||
Disposer.dispose(myListenerDisposable);
|
||||
myListenerDisposable = null;
|
||||
}
|
||||
else if (searchPopup != null) {
|
||||
FeatureUsageTracker.getInstance().triggerFeatureUsed("ui.tree.speedsearch");
|
||||
@@ -543,7 +545,9 @@ public abstract class SpeedSearchBase<Comp extends JComponent> extends SpeedSear
|
||||
if (mySearchPopup == null || !myComponent.isDisplayable()) return;
|
||||
|
||||
if (project != null) {
|
||||
((ToolWindowManagerEx)ToolWindowManager.getInstance(project)).addToolWindowManagerListener(myWindowManagerListener);
|
||||
myListenerDisposable = Disposer.newDisposable();
|
||||
ToolWindowManagerEx toolWindowManager = (ToolWindowManagerEx)ToolWindowManager.getInstance(project);
|
||||
toolWindowManager.addToolWindowManagerListener(myWindowManagerListener, myListenerDisposable);
|
||||
}
|
||||
JRootPane rootPane = myComponent.getRootPane();
|
||||
if (rootPane != null) {
|
||||
|
||||
@@ -523,8 +523,8 @@ action.ClassNameCompletion.description=Complete class name and add import for it
|
||||
action.InsertLiveTemplate.text=Insert Live _Template...
|
||||
action.InsertLiveTemplate.description=Show popup list of live templates starting with the specified prefix
|
||||
action.ExpandLiveTemplateByTab.text=Expand Live Template by Tab
|
||||
action.ExpandLiveTemplateCustom.text=Expand Live Template
|
||||
action.ExpandLiveTemplateCustom.description=Invoke the live template with the prefix typed in the editor
|
||||
action.ExpandLiveTemplateCustom.text=Expand Live Template / Emmet Abbreviation
|
||||
action.ExpandLiveTemplateCustom.description=Invoke the live template that bound to 'Custom shortcut' with the prefix typed in the editor
|
||||
action.SurroundWithLiveTemplate.text=Surround with Live Tem_plate...
|
||||
action.SurroundWithLiveTemplate.description=Surrounds the selection with one of the template
|
||||
action.CommentByLineComment.text=Comment with _Line Comment
|
||||
|
||||
+2
@@ -19,6 +19,7 @@ import com.intellij.openapi.file.exclude.EnforcedPlainTextFileTypeFactory;
|
||||
import com.intellij.openapi.file.exclude.EnforcedPlainTextFileTypeManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
|
||||
/**
|
||||
* @author Rustam Vishnyakov
|
||||
@@ -30,6 +31,7 @@ public class EnforcedPlaintTextFileTypeManagerTest extends LightPlatformCodeInsi
|
||||
FileType originalType = file.getFileType();
|
||||
assertEquals("JAVA", originalType.getName());
|
||||
manager.markAsPlainText(getProject(), file);
|
||||
UIUtil.dispatchAllInvocationEvents(); // reparseFiles in invokeLater
|
||||
FileType changedType = file.getFileType();
|
||||
assertEquals(EnforcedPlainTextFileTypeFactory.ENFORCED_PLAIN_TEXT, changedType.getName());
|
||||
manager.resetOriginalFileType(getProject(), file);
|
||||
|
||||
+11
-5
@@ -278,14 +278,16 @@ public class FileTypesTest extends PlatformTestCase {
|
||||
}
|
||||
|
||||
public void testReDetectOnContentsChange() throws IOException {
|
||||
FileType fileType = FileTypeRegistry.getInstance().getFileTypeByFileName("x" + ModuleFileType.DOT_DEFAULT_EXTENSION);
|
||||
final FileTypeRegistry fileTypeManager = FileTypeRegistry.getInstance();
|
||||
assertTrue(fileTypeManager.getClass().getName(), fileTypeManager instanceof FileTypeManagerImpl);
|
||||
FileType fileType = fileTypeManager.getFileTypeByFileName("x" + ModuleFileType.DOT_DEFAULT_EXTENSION);
|
||||
assertTrue(fileType.toString(), fileType instanceof ModuleFileType);
|
||||
fileType = FileTypeRegistry.getInstance().getFileTypeByFileName("x" + ProjectFileType.DOT_DEFAULT_EXTENSION);
|
||||
fileType = fileTypeManager.getFileTypeByFileName("x" + ProjectFileType.DOT_DEFAULT_EXTENSION);
|
||||
assertTrue(fileType.toString(), fileType instanceof ProjectFileType);
|
||||
FileType module = FileTypeRegistry.getInstance().findFileTypeByName("IDEA_MODULE");
|
||||
FileType module = fileTypeManager.findFileTypeByName("IDEA_MODULE");
|
||||
assertNotNull(module);
|
||||
assertFalse(module.equals(PlainTextFileType.INSTANCE));
|
||||
FileType project = FileTypeRegistry.getInstance().findFileTypeByName("IDEA_PROJECT");
|
||||
FileType project = fileTypeManager.findFileTypeByName("IDEA_PROJECT");
|
||||
assertNotNull(project);
|
||||
assertFalse(project.equals(PlainTextFileType.INSTANCE));
|
||||
|
||||
@@ -296,7 +298,7 @@ public class FileTypesTest extends PlatformTestCase {
|
||||
public FileType detect(@NotNull VirtualFile file, @NotNull ByteSequence firstBytes, @Nullable CharSequence firstCharsIfText) {
|
||||
detectorCalled.add(file);
|
||||
String text = firstCharsIfText.toString();
|
||||
FileType result = text.startsWith("TYPE:") ? FileTypeRegistry.getInstance().findFileTypeByName(StringUtil.trimStart(text, "TYPE:")) : null;
|
||||
FileType result = text.startsWith("TYPE:") ? fileTypeManager.findFileTypeByName(StringUtil.trimStart(text, "TYPE:")) : null;
|
||||
System.out.println("T: my detector run for "+file.getName()+"; result: "+(result == null ? null : result.getName()));
|
||||
return result;
|
||||
}
|
||||
@@ -308,6 +310,7 @@ public class FileTypesTest extends PlatformTestCase {
|
||||
};
|
||||
Extensions.getRootArea().getExtensionPoint(FileTypeRegistry.FileTypeDetector.EP_NAME).registerExtension(detector);
|
||||
try {
|
||||
System.out.println("T: ------");
|
||||
File d = createTempDirectory();
|
||||
File f = new File(d, "xx.asfdasdfas");
|
||||
FileUtil.writeToFile(f, "akjdhfksdjgf");
|
||||
@@ -315,13 +318,16 @@ public class FileTypesTest extends PlatformTestCase {
|
||||
ensureRedetected(vFile, detectorCalled);
|
||||
assertTrue(vFile.getFileType().toString(), vFile.getFileType() instanceof PlainTextFileType);
|
||||
|
||||
System.out.println("T: ------");
|
||||
VfsUtil.saveText(vFile, "TYPE:IDEA_MODULE");
|
||||
ensureRedetected(vFile, detectorCalled);
|
||||
assertTrue(vFile.getFileType().toString(), vFile.getFileType() instanceof ModuleFileType);
|
||||
|
||||
System.out.println("T: ------");
|
||||
VfsUtil.saveText(vFile, "TYPE:IDEA_PROJECT");
|
||||
ensureRedetected(vFile, detectorCalled);
|
||||
assertTrue(vFile.getFileType().toString(), vFile.getFileType() instanceof ProjectFileType);
|
||||
System.out.println("T: ------");
|
||||
}
|
||||
finally {
|
||||
Extensions.getRootArea().getExtensionPoint(FileTypeRegistry.FileTypeDetector.EP_NAME).unregisterExtension(detector);
|
||||
|
||||
+29
@@ -22,6 +22,7 @@ import com.intellij.openapi.application.ex.ApplicationManagerEx;
|
||||
import com.intellij.openapi.progress.*;
|
||||
import com.intellij.openapi.progress.util.ProgressIndicatorBase;
|
||||
import com.intellij.openapi.progress.util.ProgressIndicatorUtils;
|
||||
import com.intellij.openapi.progress.util.ProgressWrapper;
|
||||
import com.intellij.openapi.progress.util.ReadTask;
|
||||
import com.intellij.openapi.util.EmptyRunnable;
|
||||
import com.intellij.openapi.wm.ex.ProgressIndicatorEx;
|
||||
@@ -373,6 +374,34 @@ public class ProgressIndicatorTest extends LightPlatformTestCase {
|
||||
}).assertTiming();
|
||||
}
|
||||
|
||||
public void testWrapperIndicatorGotCanceledTooWhenInnerIndicatorHas() {
|
||||
final ProgressIndicator progress = new ProgressIndicatorBase(){
|
||||
@Override
|
||||
protected boolean isCancelable() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
try {
|
||||
ProgressManager.getInstance().executeProcessUnderProgress(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
assertFalse(ProgressManagerImpl.threadsUnderCanceledIndicator.contains(Thread.currentThread()));
|
||||
assertTrue(!progress.isCanceled());
|
||||
progress.cancel();
|
||||
assertTrue(ProgressManagerImpl.threadsUnderCanceledIndicator.contains(Thread.currentThread()));
|
||||
assertTrue(progress.isCanceled());
|
||||
while (true) { // wait for PCE
|
||||
ProgressManager.checkCanceled();
|
||||
}
|
||||
}
|
||||
}, ProgressWrapper.wrap(progress));
|
||||
fail("PCE must have been thrown");
|
||||
}
|
||||
catch (ProcessCanceledException ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static class ProgressIndicatorStub implements ProgressIndicatorEx {
|
||||
private volatile boolean myCanceled;
|
||||
|
||||
|
||||
@@ -62,6 +62,11 @@ public class MockPsiDocumentManager extends PsiDocumentManager {
|
||||
return document.getImmutableCharSequence();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastCommittedStamp(@NotNull Document document) {
|
||||
return document.getModificationStamp();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Document[] getUncommittedDocuments() {
|
||||
|
||||
@@ -515,11 +515,7 @@ public class UIUtil {
|
||||
char c = e.getKeyChar();
|
||||
if (c < 0x20 || c == 0x7F) return false;
|
||||
|
||||
if (SystemInfo.isMac) {
|
||||
return !e.isMetaDown() && !e.isControlDown();
|
||||
}
|
||||
|
||||
return !e.isAltDown() && !e.isControlDown();
|
||||
return !e.isMetaDown() && !e.isAltDown() && !e.isControlDown();
|
||||
}
|
||||
|
||||
public static int getStringY(@NotNull final String string, @NotNull final Rectangle bounds, @NotNull final Graphics2D g) {
|
||||
|
||||
@@ -116,7 +116,12 @@ class XmlSerializerImpl {
|
||||
if (binding == null) {
|
||||
binding = _getNonCachedClassBinding(aClass, accessor, originalType);
|
||||
map.put(key, binding);
|
||||
binding.init();
|
||||
try {
|
||||
binding.init();
|
||||
} catch (XmlSerializationException e) {
|
||||
map.remove(key);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
return binding;
|
||||
}
|
||||
|
||||
@@ -15,20 +15,29 @@
|
||||
*/
|
||||
package com.intellij.vcs.log.graph;
|
||||
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.ImmutableList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class GraphCommitImpl<CommitId> implements GraphCommit<CommitId> {
|
||||
public class GraphCommitImpl<CommitId> extends ImmutableList<CommitId> implements GraphCommit<CommitId>{
|
||||
|
||||
@NotNull private final CommitId myId;
|
||||
@NotNull private final List<CommitId> myParents;
|
||||
@NotNull private final Object myParents;
|
||||
private final long myTimestamp;
|
||||
|
||||
public GraphCommitImpl(@NotNull CommitId id, @NotNull List<CommitId> parents, long timestamp) {
|
||||
myId = id;
|
||||
myParents = parents;
|
||||
myTimestamp = timestamp;
|
||||
if (parents.isEmpty()) {
|
||||
myParents = ArrayUtil.EMPTY_OBJECT_ARRAY;
|
||||
} else if (parents.size() == 1) {
|
||||
myParents = parents.get(0);
|
||||
assert !(myParents instanceof Object[]);
|
||||
} else {
|
||||
myParents = parents.toArray();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -40,7 +49,28 @@ public class GraphCommitImpl<CommitId> implements GraphCommit<CommitId> {
|
||||
@NotNull
|
||||
@Override
|
||||
public List<CommitId> getParents() {
|
||||
return myParents;
|
||||
return this;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public CommitId get(int index) {
|
||||
if (myParents instanceof Object[]) {
|
||||
Object[] array = (Object[])myParents;
|
||||
if (index < 0 || index >= array.length) {
|
||||
throw new ArrayIndexOutOfBoundsException(index);
|
||||
}
|
||||
return (CommitId)array[index];
|
||||
}
|
||||
if (index != 0) {
|
||||
throw new ArrayIndexOutOfBoundsException(index);
|
||||
}
|
||||
return (CommitId)myParents;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return myParents instanceof Object[] ? ((Object[])myParents).length : 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -40,6 +40,7 @@ import com.intellij.xdebugger.frame.XStackFrame;
|
||||
import com.intellij.xdebugger.impl.XDebugSessionImpl;
|
||||
import com.intellij.xdebugger.impl.actions.XDebuggerActions;
|
||||
import com.intellij.xdebugger.impl.breakpoints.XExpressionImpl;
|
||||
import com.intellij.xdebugger.impl.frame.actions.XDuplicateWatchAction;
|
||||
import com.intellij.xdebugger.impl.ui.XDebugSessionData;
|
||||
import com.intellij.xdebugger.impl.ui.XDebugSessionTab;
|
||||
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
|
||||
@@ -88,6 +89,8 @@ public class XWatchesViewImpl extends XDebugView implements DnDNativeTarget, XWa
|
||||
CustomShortcutSet f2Shortcut = new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0));
|
||||
actionManager.getAction(XDebuggerActions.XEDIT_WATCH).registerCustomShortcutSet(f2Shortcut, tree);
|
||||
|
||||
new XDuplicateWatchAction().registerCustomShortcutSet(ActionManager.getInstance().getAction(IdeActions.ACTION_EDITOR_DUPLICATE).getShortcutSet(), tree);
|
||||
|
||||
DnDManager.getInstance().registerTarget(this, tree);
|
||||
myRootNode = new WatchesRootNode(tree, this, session.getSessionData().getWatchExpressions());
|
||||
tree.setRoot(myRootNode, false);
|
||||
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.xdebugger.impl.frame.actions;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.xdebugger.impl.frame.XWatchesView;
|
||||
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.WatchNode;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.XDebuggerTreeNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author 1
|
||||
*/
|
||||
public class XDuplicateWatchAction extends XWatchesTreeActionBase {
|
||||
|
||||
protected boolean isEnabled(@NotNull final AnActionEvent e, @NotNull XDebuggerTree tree) {
|
||||
return !getSelectedNodes(tree, WatchNode.class).isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void perform(@NotNull AnActionEvent e, @NotNull XDebuggerTree tree, @NotNull XWatchesView watchesView) {
|
||||
XDebuggerTreeNode root = tree.getRoot();
|
||||
List<? extends WatchNode> nodes = getSelectedNodes(tree, WatchNode.class);
|
||||
for (WatchNode node : nodes) {
|
||||
int index = root.getIndex(node);
|
||||
watchesView.addWatchExpression(node.getExpression(), index + 1, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
@@ -30,6 +30,7 @@ import java.util.List;
|
||||
* @author nik
|
||||
*/
|
||||
public abstract class XWatchesTreeActionBase extends AnAction {
|
||||
@NotNull
|
||||
protected static <T extends TreeNode> List<? extends T> getSelectedNodes(final @NotNull XDebuggerTree tree, Class<T> nodeClass) {
|
||||
List<T> list = new ArrayList<T>();
|
||||
TreePath[] selectionPaths = tree.getSelectionPaths();
|
||||
|
||||
@@ -100,13 +100,13 @@ public class CopyrightManager extends AbstractProjectComponent implements Persis
|
||||
if (module == null) return;
|
||||
if (!newFileTracker.poll(virtualFile)) return;
|
||||
if (!fileTypeUtil.isSupportedFile(virtualFile)) return;
|
||||
final PsiFile file = psiManager.findFile(virtualFile);
|
||||
if (file == null) return;
|
||||
if (psiManager.findFile(virtualFile) == null) return;
|
||||
application.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (myProject.isDisposed()) return;
|
||||
if (file.isValid() && file.isWritable()) {
|
||||
if (!virtualFile.isValid()) return;
|
||||
final PsiFile file = psiManager.findFile(virtualFile);
|
||||
if (file != null && file.isWritable()) {
|
||||
final CopyrightProfile opts = getCopyrightOptions(file);
|
||||
if (opts != null) {
|
||||
new UpdateCopyrightProcessor(myProject, module, file).run();
|
||||
|
||||
@@ -30,6 +30,6 @@
|
||||
<orderEntry type="module" module-name="testRunner" />
|
||||
<orderEntry type="module" module-name="lang-impl" />
|
||||
<orderEntry type="module" module-name="lvcs-api" />
|
||||
<orderEntry type="module" module-name="vcs-api" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
</module>
|
||||
@@ -34,6 +34,13 @@ import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.LineTokenizer;
|
||||
import com.intellij.openapi.vcs.AbstractVcs;
|
||||
import com.intellij.openapi.vcs.FilePath;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.actions.VcsContextFactory;
|
||||
import com.intellij.openapi.vcs.history.VcsFileRevision;
|
||||
import com.intellij.openapi.vcs.history.VcsHistoryProvider;
|
||||
import com.intellij.openapi.vcs.history.VcsHistorySession;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.reference.SoftReference;
|
||||
@@ -46,11 +53,13 @@ import com.intellij.util.Alarm;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.diff.Diff;
|
||||
import com.intellij.util.diff.FilesTooBigForDiffException;
|
||||
import com.intellij.vcsUtil.VcsUtil;
|
||||
import gnu.trove.TIntIntHashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
@@ -194,11 +203,16 @@ public class SrcFileAnnotator implements Disposable {
|
||||
synchronized (LOCK) {
|
||||
if (myOldContent == null) {
|
||||
if (ApplicationManager.getApplication().isDispatchThread()) return null;
|
||||
final byte[] byteContent = LocalHistory.getInstance().getByteContent(f, new FileRevisionTimestampComparator() {
|
||||
final LocalHistory localHistory = LocalHistory.getInstance();
|
||||
byte[] byteContent = localHistory.getByteContent(f, new FileRevisionTimestampComparator() {
|
||||
public boolean isSuitable(long revisionTimestamp) {
|
||||
return revisionTimestamp < date;
|
||||
}
|
||||
});
|
||||
|
||||
if (byteContent == null && f.getTimeStamp() > date) {
|
||||
byteContent = loadFromVersionControl(date, f);
|
||||
}
|
||||
myOldContent = new SoftReference<byte[]>(byteContent);
|
||||
}
|
||||
oldContent = myOldContent.get();
|
||||
@@ -211,7 +225,7 @@ public class SrcFileAnnotator implements Disposable {
|
||||
String[] oldLines = oldToNew ? coveredLines : currentLines;
|
||||
String[] newLines = oldToNew ? currentLines : coveredLines;
|
||||
|
||||
Diff.Change change = null;
|
||||
Diff.Change change;
|
||||
try {
|
||||
change = Diff.buildChanges(oldLines, newLines);
|
||||
}
|
||||
@@ -222,6 +236,41 @@ public class SrcFileAnnotator implements Disposable {
|
||||
return new SoftReference<TIntIntHashMap>(getCoverageVersionToCurrentLineMapping(change, oldLines.length));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private byte[] loadFromVersionControl(long date, VirtualFile f) {
|
||||
try {
|
||||
final AbstractVcs vcs = VcsUtil.getVcsFor(myProject, f);
|
||||
if (vcs == null) return null;
|
||||
|
||||
final VcsHistoryProvider historyProvider = vcs.getVcsHistoryProvider();
|
||||
if (historyProvider == null) return null;
|
||||
|
||||
final FilePath filePath = VcsContextFactory.SERVICE.getInstance().createFilePathOn(f);
|
||||
final VcsHistorySession session = historyProvider.createSessionFor(filePath);
|
||||
if (session == null) return null;
|
||||
|
||||
final List<VcsFileRevision> list = session.getRevisionList();
|
||||
|
||||
if (list != null) {
|
||||
for (VcsFileRevision revision : list) {
|
||||
final Date revisionDate = revision.getRevisionDate();
|
||||
if (revisionDate == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (revisionDate.getTime() < date) {
|
||||
return revision.loadContent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.info(e);
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void showCoverageInformation(final CoverageSuitesBundle suite) {
|
||||
if (myEditor == null || myFile == null) return;
|
||||
final MarkupModel markupModel = DocumentMarkupModel.forDocument(myDocument, myProject, true);
|
||||
|
||||
+31
-50
@@ -16,18 +16,17 @@
|
||||
package org.jetbrains.plugins.groovy.dsl;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ex.ApplicationUtil;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
|
||||
import com.intellij.openapi.progress.EmptyProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectManager;
|
||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.ModificationTracker;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Trinity;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
@@ -44,10 +43,9 @@ import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.reference.SoftReference;
|
||||
import com.intellij.util.ConcurrencyUtil;
|
||||
import com.intellij.util.ExceptionUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.PathUtil;
|
||||
import com.intellij.util.concurrency.Semaphore;
|
||||
import com.intellij.util.containers.ConcurrentMultiMap;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
@@ -68,10 +66,7 @@ import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
@@ -89,10 +84,7 @@ public class GroovyDslFileIndex extends ScalarIndexExtension<String> {
|
||||
private static final MultiMap<String, LinkedBlockingQueue<Pair<VirtualFile, GroovyDslExecutor>>> filesInProcessing =
|
||||
new ConcurrentMultiMap<String, LinkedBlockingQueue<Pair<VirtualFile, GroovyDslExecutor>>>();
|
||||
|
||||
private static final ThreadPoolExecutor ourPool = new ThreadPoolExecutor(0, 1, 10, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), ConcurrencyUtil.newNamedThreadFactory("Groovy DSL File Index Executor"));
|
||||
|
||||
private final EnumeratorStringDescriptor myKeyDescriptor = new EnumeratorStringDescriptor();
|
||||
private static final byte[] ENABLED_FLAG = new byte[]{(byte)239};
|
||||
|
||||
public GroovyDslFileIndex() {
|
||||
VirtualFileManager.getInstance().addVirtualFileListener(new VirtualFileAdapter() {
|
||||
@@ -296,6 +288,7 @@ public class GroovyDslFileIndex extends ScalarIndexExtension<String> {
|
||||
return SoftReference.dereference(ourStandardScripts);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static List<Pair<File, GroovyDslExecutor>> getStandardScripts() {
|
||||
List<Pair<File, GroovyDslExecutor>> result = derefStandardScripts();
|
||||
if (result != null) {
|
||||
@@ -303,28 +296,17 @@ public class GroovyDslFileIndex extends ScalarIndexExtension<String> {
|
||||
}
|
||||
|
||||
final GroovyFrameworkConfigNotification[] extensions = GroovyFrameworkConfigNotification.EP_NAME.getExtensions();
|
||||
|
||||
final Semaphore semaphore = new Semaphore();
|
||||
semaphore.down();
|
||||
final AtomicReference<List<Pair<File, GroovyDslExecutor>>> ref = new AtomicReference<List<Pair<File, GroovyDslExecutor>>>();
|
||||
|
||||
if (ApplicationManager.getApplication().isWriteAccessAllowed()) {
|
||||
// If this method is called with write lock acquired, then the background computation shouldn't acquire read lock.
|
||||
// Otherwise, we'll get a deadlock: this method will wait for the result of the background computation holding the write lock
|
||||
// and the background computation won't finish because of waiting for the read lock.
|
||||
// Dirty workaround: currently the background computation acquires read lock to only initialize GroovyDslExecutor,
|
||||
// so, preventive GroovyDslExecutor initialization should help
|
||||
GroovyDslExecutor.getIdeaVersion();
|
||||
}
|
||||
ourPool.execute(new Runnable() {
|
||||
@SuppressWarnings("AssignmentToStaticFieldFromInstanceMethod")
|
||||
Callable<List<Pair<File, GroovyDslExecutor>>> action = new Callable<List<Pair<File, GroovyDslExecutor>>>() {
|
||||
@Override
|
||||
public void run() {
|
||||
public List<Pair<File, GroovyDslExecutor>> call() throws Exception {
|
||||
if (GdslUtil.ourGdslStopped) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
List<Pair<File, GroovyDslExecutor>> pairs = derefStandardScripts();
|
||||
if (pairs != null) {
|
||||
ref.set(pairs);
|
||||
return;
|
||||
return pairs;
|
||||
}
|
||||
|
||||
Set<Class> classes = new HashSet<Class>(ContainerUtil.map2Set(extensions, new Function<GroovyFrameworkConfigNotification, Class>() {
|
||||
@@ -365,32 +347,31 @@ public class GroovyDslFileIndex extends ScalarIndexExtension<String> {
|
||||
}
|
||||
}
|
||||
}
|
||||
//noinspection AssignmentToStaticFieldFromInstanceMethod
|
||||
ourStandardScripts = new SoftReference<List<Pair<File, GroovyDslExecutor>>>(executors);
|
||||
ref.set(executors);
|
||||
return executors;
|
||||
}
|
||||
catch (Throwable e) {
|
||||
ref.set(new ArrayList<Pair<File, GroovyDslExecutor>>());
|
||||
//noinspection InstanceofCatchParameter
|
||||
if (e instanceof Error) {
|
||||
GdslUtil.stopGdsl();
|
||||
}
|
||||
LOG.error(e);
|
||||
}
|
||||
finally {
|
||||
semaphore.up();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
while (true) {
|
||||
ProgressManager.checkCanceled();
|
||||
|
||||
if (GdslUtil.ourGdslStopped) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
if (ref.get() != null || semaphore.waitFor(20)) {
|
||||
return ref.get();
|
||||
try {
|
||||
if (ApplicationManager.getApplication().isDispatchThread()) {
|
||||
return action.call();
|
||||
}
|
||||
return ApplicationUtil.runWithCheckCanceled(action, new EmptyProgressIndicator());
|
||||
}
|
||||
catch (Exception e) {
|
||||
ExceptionUtil.rethrowUnchecked(e);
|
||||
LOG.error(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -409,9 +390,10 @@ public class GroovyDslFileIndex extends ScalarIndexExtension<String> {
|
||||
List<GroovyDslScript> result = new ArrayList<GroovyDslScript>();
|
||||
|
||||
List<Pair<File, GroovyDslExecutor>> standardScripts = getStandardScripts();
|
||||
assert standardScripts != null;
|
||||
for (Pair<File, GroovyDslExecutor> pair : standardScripts) {
|
||||
result.add(new GroovyDslScript(project, null, pair.second, pair.first.getPath()));
|
||||
if (standardScripts != null) {
|
||||
for (Pair<File, GroovyDslExecutor> pair : standardScripts) {
|
||||
result.add(new GroovyDslScript(project, null, pair.second, pair.first.getPath()));
|
||||
}
|
||||
}
|
||||
|
||||
final LinkedBlockingQueue<Pair<VirtualFile, GroovyDslExecutor>> queue =
|
||||
@@ -521,8 +503,7 @@ public class GroovyDslFileIndex extends ScalarIndexExtension<String> {
|
||||
final boolean isNewRequest = !filesInProcessing.containsKey(fileUrl);
|
||||
filesInProcessing.putValue(fileUrl, queue);
|
||||
if (isNewRequest) {
|
||||
ourPool.execute(parseScript); //todo bring back multi-threading when Groovy team fixes http://jira.codehaus.org/browse/GROOVY-4292
|
||||
//ApplicationManager.getApplication().executeOnPooledThread(parseScript);
|
||||
ApplicationManager.getApplication().executeOnPooledThread(parseScript);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.jetbrains.idea.svn;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.components.*;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.SVNURL;
|
||||
|
||||
@@ -35,7 +36,7 @@ import java.util.List;
|
||||
)}
|
||||
)
|
||||
public class SvnApplicationSettings implements PersistentStateComponent<SvnApplicationSettings.ConfigurationBean> {
|
||||
private SvnFileSystemListenerWrapper myVFSHandler;
|
||||
private SvnFileSystemListener myVFSHandler;
|
||||
private int mySvnProjectCount;
|
||||
private LimitedStringsList myLimitedStringsList;
|
||||
|
||||
@@ -90,8 +91,7 @@ public class SvnApplicationSettings implements PersistentStateComponent<SvnAppli
|
||||
|
||||
public void svnActivated() {
|
||||
if (myVFSHandler == null) {
|
||||
myVFSHandler = new SvnFileSystemListenerWrapper(new SvnFileSystemListener());
|
||||
myVFSHandler.registerSelf();
|
||||
myVFSHandler = new SvnFileSystemListener();
|
||||
}
|
||||
mySvnProjectCount++;
|
||||
}
|
||||
@@ -99,7 +99,7 @@ public class SvnApplicationSettings implements PersistentStateComponent<SvnAppli
|
||||
public void svnDeactivated() {
|
||||
mySvnProjectCount--;
|
||||
if (mySvnProjectCount == 0) {
|
||||
myVFSHandler.unregisterSelf();
|
||||
Disposer.dispose(myVFSHandler);
|
||||
myVFSHandler = null;
|
||||
// todo what should be done instead?
|
||||
//SVNSSHSession.shutdown();
|
||||
|
||||
@@ -17,22 +17,24 @@
|
||||
|
||||
package org.jetbrains.idea.svn;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.CommandAdapter;
|
||||
import com.intellij.openapi.command.CommandEvent;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.command.undo.UndoManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectLocator;
|
||||
import com.intellij.openapi.project.ProjectManager;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Couple;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vcs.*;
|
||||
import com.intellij.openapi.vcs.actions.VcsContextFactory;
|
||||
import com.intellij.openapi.vcs.changes.ChangeListManager;
|
||||
import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
|
||||
import com.intellij.openapi.vfs.LocalFileOperationsHandler;
|
||||
@@ -44,6 +46,7 @@ import com.intellij.util.ThrowableConsumer;
|
||||
import com.intellij.util.containers.Convertor;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import com.intellij.vcsUtil.ActionWithTempFile;
|
||||
import com.intellij.vcsUtil.VcsUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.svn.api.Depth;
|
||||
@@ -61,7 +64,7 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
public class SvnFileSystemListener extends CommandAdapter implements LocalFileOperationsHandler {
|
||||
public class SvnFileSystemListener extends CommandAdapter implements LocalFileOperationsHandler, Disposable {
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.SvnFileSystemListener");
|
||||
private final LocalFileSystem myLfs;
|
||||
|
||||
@@ -100,8 +103,20 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
private final List<Couple<File>> myUndoStorageContents = new ArrayList<Couple<File>>();
|
||||
private boolean myUndoingMove = false;
|
||||
|
||||
private boolean myIsInCommand;
|
||||
@Nullable private Project myGuessedProject;
|
||||
|
||||
public SvnFileSystemListener() {
|
||||
myLfs = LocalFileSystem.getInstance();
|
||||
|
||||
myLfs.registerAuxiliaryFileOperationsHandler(this);
|
||||
CommandProcessor.getInstance().addCommandListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
myLfs.unregisterAuxiliaryFileOperationsHandler(this);
|
||||
CommandProcessor.getInstance().removeCommandListener(this);
|
||||
}
|
||||
|
||||
private void addToMoveExceptions(@NotNull final Project project, @NotNull final Exception e) {
|
||||
@@ -113,12 +128,10 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
exceptionList.add(handleMoveException(e));
|
||||
}
|
||||
|
||||
private VcsException handleMoveException(@NotNull Exception e) {
|
||||
private static VcsException handleMoveException(@NotNull Exception e) {
|
||||
VcsException vcsException;
|
||||
if (e instanceof SVNException && SVNErrorCode.ENTRY_EXISTS.equals(((SVNException)e).getErrorMessage().getErrorCode())) {
|
||||
vcsException = createMoveTargetExistsError(e);
|
||||
}
|
||||
else if (e instanceof SvnBindException && ((SvnBindException)e).contains(SVNErrorCode.ENTRY_EXISTS)) {
|
||||
if (e instanceof SVNException && SVNErrorCode.ENTRY_EXISTS.equals(((SVNException)e).getErrorMessage().getErrorCode()) ||
|
||||
e instanceof SvnBindException && ((SvnBindException)e).contains(SVNErrorCode.ENTRY_EXISTS)) {
|
||||
vcsException = createMoveTargetExistsError(e);
|
||||
}
|
||||
else if (e instanceof VcsException) {
|
||||
@@ -137,6 +150,8 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
|
||||
@Nullable
|
||||
public File copy(final VirtualFile file, final VirtualFile toDir, final String copyName) throws IOException {
|
||||
startOperation(file);
|
||||
|
||||
SvnVcs vcs = getVCS(toDir);
|
||||
if (vcs == null) {
|
||||
vcs = getVCS(file);
|
||||
@@ -220,13 +235,13 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
}
|
||||
|
||||
public boolean move(VirtualFile file, VirtualFile toDir) throws IOException {
|
||||
startOperation(file);
|
||||
|
||||
File srcFile = getIOFile(file);
|
||||
File dstFile = new File(getIOFile(toDir), file.getName());
|
||||
|
||||
final SvnVcs vcs = getVCS(toDir);
|
||||
final SvnVcs sourceVcs = getVCS(file);
|
||||
if (vcs == null && sourceVcs == null) return false;
|
||||
|
||||
if (vcs == null) {
|
||||
return false;
|
||||
}
|
||||
@@ -237,19 +252,19 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
}
|
||||
|
||||
if (isPendingAdd(vcs.getProject(), toDir)) {
|
||||
|
||||
myMovedFiles.add(new MovedFileInfo(sourceVcs.getProject(), srcFile, dstFile));
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
final VirtualFile oldParent = file.getParent();
|
||||
myFilesToRefresh.add(oldParent);
|
||||
myFilesToRefresh.add(file.getParent());
|
||||
myFilesToRefresh.add(toDir);
|
||||
return doMove(sourceVcs, srcFile, dstFile);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean rename(VirtualFile file, String newName) throws IOException {
|
||||
startOperation(file);
|
||||
|
||||
File srcFile = getIOFile(file);
|
||||
File dstFile = new File(srcFile.getParentFile(), newName);
|
||||
SvnVcs vcs = getVCS(file);
|
||||
@@ -272,19 +287,10 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
final boolean is17OrLater = format.isOrGreater(WorkingCopyFormat.ONE_DOT_SEVEN);
|
||||
if (is17OrLater) {
|
||||
Status srcStatus = getFileStatus(vcs, src);
|
||||
final File toDir = dst.getParentFile();
|
||||
Status dstStatus = getFileStatus(vcs, toDir);
|
||||
final boolean srcUnversioned = srcStatus == null || srcStatus.is(StatusType.STATUS_UNVERSIONED);
|
||||
if (srcUnversioned && (dstStatus == null || dstStatus.is(StatusType.STATUS_UNVERSIONED))) {
|
||||
if (isUnversioned(srcStatus) && (isUnversioned(vcs, dst.getParentFile()) || isUnversioned(vcs, dst)) ||
|
||||
for17move(vcs, src, dst, isUndo, srcStatus)) {
|
||||
return false;
|
||||
}
|
||||
if (srcUnversioned) {
|
||||
Status dstWasStatus = getFileStatus(vcs, dst);
|
||||
if (dstWasStatus == null || dstWasStatus.is(StatusType.STATUS_UNVERSIONED)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (for17move(vcs, src, dst, isUndo, srcStatus)) return false;
|
||||
} else {
|
||||
if (for16move(vcs, src, dst, isUndo)) return false;
|
||||
}
|
||||
@@ -301,9 +307,12 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
return true;
|
||||
}
|
||||
|
||||
private final static Set<StatusType> ourStatusesForUndoMove = new HashSet<StatusType>();
|
||||
static {
|
||||
ourStatusesForUndoMove.add(StatusType.STATUS_ADDED);
|
||||
private static boolean isUnversioned(@Nullable Status status) {
|
||||
return status == null || status.is(StatusType.STATUS_UNVERSIONED);
|
||||
}
|
||||
|
||||
private static boolean isUnversioned(@NotNull SvnVcs vcs, @NotNull File file) {
|
||||
return isUnversioned(getFileStatus(vcs, file));
|
||||
}
|
||||
|
||||
private boolean for17move(final SvnVcs vcs, final File src, final File dst, boolean undo, Status srcStatus) throws VcsException {
|
||||
@@ -314,7 +323,7 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
myUndoingMove = true;
|
||||
createRevertAction(vcs, dst, true).execute();
|
||||
copyUnversionedMembersOfDirectory(src, dst);
|
||||
if (srcStatus == null || srcStatus.is(StatusType.STATUS_UNVERSIONED)) {
|
||||
if (isUnversioned(srcStatus)) {
|
||||
FileUtil.delete(src);
|
||||
} else {
|
||||
createRevertAction(vcs, src, true).execute();
|
||||
@@ -323,8 +332,7 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
} else {
|
||||
if (doUsualMove(vcs, src)) return true;
|
||||
// check destination directory
|
||||
final Status dstParentStatus = getFileStatus(vcs, dst.getParentFile());
|
||||
if (dstParentStatus == null || dstParentStatus.is(StatusType.STATUS_UNVERSIONED)) {
|
||||
if (isUnversioned(vcs, dst.getParentFile())) {
|
||||
try {
|
||||
copyFileOrDir(src, dst);
|
||||
}
|
||||
@@ -348,7 +356,7 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
}.execute();
|
||||
}
|
||||
|
||||
private void copyUnversionedMembersOfDirectory(final File src, final File dst) throws SvnBindException {
|
||||
private static void copyUnversionedMembersOfDirectory(final File src, final File dst) throws SvnBindException {
|
||||
if (src.isDirectory()) {
|
||||
final SvnBindException[] exc = new SvnBindException[1];
|
||||
FileUtil.processFilesRecursively(src, new Processor<File>() {
|
||||
@@ -374,7 +382,7 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
}
|
||||
}
|
||||
|
||||
private void copyFileOrDir(File src, File dst) throws IOException {
|
||||
private static void copyFileOrDir(File src, File dst) throws IOException {
|
||||
if (src.isDirectory()) {
|
||||
FileUtil.copyDir(src, dst);
|
||||
} else {
|
||||
@@ -382,45 +390,38 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
}
|
||||
}
|
||||
|
||||
private boolean doUsualMove(SvnVcs vcs, File src) {
|
||||
private static boolean doUsualMove(SvnVcs vcs, File src) {
|
||||
// if src is not under version control, do usual move.
|
||||
Status srcStatus = getFileStatus(vcs, src);
|
||||
return srcStatus == null ||
|
||||
srcStatus.is(StatusType.STATUS_UNVERSIONED, StatusType.STATUS_OBSTRUCTED, StatusType.STATUS_MISSING, StatusType.STATUS_EXTERNAL);
|
||||
}
|
||||
|
||||
private boolean for16move(SvnVcs vcs, final File src, final File dst, boolean undo) throws VcsException {
|
||||
private boolean for16move(SvnVcs vcs, final File src, final File dst, final boolean undo) throws VcsException {
|
||||
final SVNMoveClient mover = vcs.getSvnKitManager().createMoveClient();
|
||||
if (undo) {
|
||||
myUndoingMove = true;
|
||||
restoreFromUndoStorage(dst);
|
||||
new RepeatSvnActionThroughBusy() {
|
||||
@Override
|
||||
protected void executeImpl() throws VcsException {
|
||||
try {
|
||||
}
|
||||
else if (doUsualMove(vcs, src)) return true;
|
||||
|
||||
new RepeatSvnActionThroughBusy() {
|
||||
@Override
|
||||
protected void executeImpl() throws VcsException {
|
||||
try {
|
||||
if (undo) {
|
||||
mover.undoMove(src, dst);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
throw new SvnBindException(e);
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
else {
|
||||
// if src is not under version control, do usual move.
|
||||
if (doUsualMove(vcs, src)) return true;
|
||||
new RepeatSvnActionThroughBusy() {
|
||||
@Override
|
||||
protected void executeImpl() throws VcsException {
|
||||
try {
|
||||
else {
|
||||
mover.doMove(src, dst);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
throw new SvnBindException(e);
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
catch (SVNException e) {
|
||||
throw new SvnBindException(e);
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -451,10 +452,14 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
|
||||
|
||||
public boolean createFile(VirtualFile dir, String name) throws IOException {
|
||||
startOperation(dir);
|
||||
|
||||
return createItem(dir, name, false, false);
|
||||
}
|
||||
|
||||
public boolean createDirectory(VirtualFile dir, String name) throws IOException {
|
||||
startOperation(dir);
|
||||
|
||||
return createItem(dir, name, true, false);
|
||||
}
|
||||
|
||||
@@ -473,6 +478,8 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
* deleted: do nothing, return true (strange)
|
||||
*/
|
||||
public boolean delete(VirtualFile file) throws IOException {
|
||||
startOperation(file);
|
||||
|
||||
final SvnVcs vcs = getVCS(file);
|
||||
if (vcs != null && SvnUtil.isAdminDirectory(file)) {
|
||||
return true;
|
||||
@@ -482,10 +489,7 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
if (VcsShowConfirmationOption.Value.DO_NOTHING_SILENTLY.equals(value)) return false;
|
||||
|
||||
final File ioFile = getIOFile(file);
|
||||
if (! SvnUtil.isSvnVersioned(vcs.getProject(), ioFile.getParentFile())) {
|
||||
return false;
|
||||
}
|
||||
if (SvnUtil.isWorkingCopyRoot(ioFile)) {
|
||||
if (!SvnUtil.isSvnVersioned(vcs, ioFile.getParentFile()) || SvnUtil.isWorkingCopyRoot(ioFile)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -503,7 +507,6 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
if (vcs != null) {
|
||||
if (isAboveSourceOfCopyOrMove(vcs.getProject(), ioFile)) {
|
||||
myDeletedFiles.putValue(vcs.getProject(), ioFile);
|
||||
return true;
|
||||
@@ -521,13 +524,14 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
// packages deleted from disk should not be deleted from svn (IDEADEV-16066)
|
||||
if (file.isDirectory() || isUndo(vcs)) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private RepeatSvnActionThroughBusy createRevertAction(@NotNull final SvnVcs vcs, @NotNull final File file, final boolean recursive) {
|
||||
private static RepeatSvnActionThroughBusy createRevertAction(@NotNull final SvnVcs vcs,
|
||||
@NotNull final File file,
|
||||
final boolean recursive) {
|
||||
return new RepeatSvnActionThroughBusy() {
|
||||
@Override
|
||||
protected void executeImpl() throws VcsException {
|
||||
@@ -537,7 +541,7 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private RepeatSvnActionThroughBusy createDeleteAction(@NotNull final SvnVcs vcs, @NotNull final File file, final boolean force) {
|
||||
private static RepeatSvnActionThroughBusy createDeleteAction(@NotNull final SvnVcs vcs, @NotNull final File file, final boolean force) {
|
||||
return new RepeatSvnActionThroughBusy() {
|
||||
@Override
|
||||
protected void executeImpl() throws VcsException {
|
||||
@@ -597,7 +601,7 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
}
|
||||
File ioDir = getIOFile(dir);
|
||||
boolean pendingAdd = isPendingAdd(vcs.getProject(), dir);
|
||||
if (! SvnUtil.isSvnVersioned(vcs.getProject(), ioDir) && ! pendingAdd) {
|
||||
if (!SvnUtil.isSvnVersioned(vcs, ioDir) && !pendingAdd) {
|
||||
return false;
|
||||
}
|
||||
final File targetFile = new File(ioDir, name);
|
||||
@@ -643,25 +647,29 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
return false;
|
||||
}
|
||||
|
||||
public void commandStarted(CommandEvent event) {
|
||||
@Override
|
||||
public void commandStarted(@NotNull CommandEvent event) {
|
||||
myIsInCommand = true;
|
||||
myUndoingMove = false;
|
||||
final Project project = event.getProject();
|
||||
if (project == null) return;
|
||||
commandStarted(project);
|
||||
}
|
||||
|
||||
void commandStarted(final Project project) {
|
||||
void commandStarted(@NotNull Project project) {
|
||||
myUndoingMove = false;
|
||||
myMoveExceptions.remove(project);
|
||||
}
|
||||
|
||||
public void commandFinished(CommandEvent event) {
|
||||
@Override
|
||||
public void commandFinished(@NotNull CommandEvent event) {
|
||||
myIsInCommand = false;
|
||||
final Project project = event.getProject();
|
||||
if (project == null) return;
|
||||
commandFinished(project);
|
||||
}
|
||||
|
||||
void commandFinished(final Project project) {
|
||||
void commandFinished(@NotNull Project project) {
|
||||
checkOverwrites(project);
|
||||
if (myAddedFiles.containsKey(project)) {
|
||||
processAddedFiles(project);
|
||||
@@ -772,7 +780,7 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
}
|
||||
}
|
||||
|
||||
private void runInBackground(final Project project, final String name, final Runnable runnable) {
|
||||
private static void runInBackground(final Project project, final String name, final Runnable runnable) {
|
||||
if (ApplicationManager.getApplication().isDispatchThread()) {
|
||||
ProgressManager.getInstance().runProcessWithProgressSynchronously(runnable, name, false, project);
|
||||
} else {
|
||||
@@ -780,7 +788,7 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
}
|
||||
}
|
||||
|
||||
private Runnable createAdditionRunnable(final Project project,
|
||||
private static Runnable createAdditionRunnable(final Project project,
|
||||
final SvnVcs vcs,
|
||||
final Map<VirtualFile, File> copyFromMap,
|
||||
final Collection<VirtualFile> filesToProcess,
|
||||
@@ -828,7 +836,7 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
};
|
||||
}
|
||||
|
||||
private Collection<VirtualFile> promptAboutAddition(SvnVcs vcs,
|
||||
private static Collection<VirtualFile> promptAboutAddition(SvnVcs vcs,
|
||||
List<VirtualFile> addedVFiles,
|
||||
VcsShowConfirmationOption.Value value,
|
||||
AbstractVcsHelper vcsHelper) {
|
||||
@@ -900,7 +908,7 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
filesToProcess.addAll(confirmed);
|
||||
}
|
||||
}
|
||||
if (filesToProcess != null && ! filesToProcess.isEmpty()) {
|
||||
if (!filesToProcess.isEmpty()) {
|
||||
runInBackground(project, "Deleting files from Subversion", createDeleteRunnable(project, vcs, filesToProcess, exceptions));
|
||||
}
|
||||
final List<FilePath> deletedFilesFiles = ObjectsConvertor.convert(deletedFiles, new Convertor<Pair<FilePath, WorkingCopyFormat>, FilePath>() {
|
||||
@@ -915,9 +923,7 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
myFilesToRefresh.add(parent.getVirtualFile());
|
||||
}
|
||||
}
|
||||
if (filesToProcess != null) {
|
||||
deletedFilesFiles.removeAll(filesToProcess);
|
||||
}
|
||||
deletedFilesFiles.removeAll(filesToProcess);
|
||||
for (FilePath file : deletedFilesFiles) {
|
||||
FileUtil.delete(file.getIOFile());
|
||||
}
|
||||
@@ -930,7 +936,7 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
}
|
||||
}
|
||||
|
||||
private Runnable createDeleteRunnable(final Project project,
|
||||
private static Runnable createDeleteRunnable(final Project project,
|
||||
final SvnVcs vcs,
|
||||
final Collection<FilePath> filesToProcess,
|
||||
final List<VcsException> exceptions) {
|
||||
@@ -957,7 +963,7 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
};
|
||||
}
|
||||
|
||||
private Collection<FilePath> promptAboutDeletion(List<Pair<FilePath, WorkingCopyFormat>> deletedFiles,
|
||||
private static Collection<FilePath> promptAboutDeletion(List<Pair<FilePath, WorkingCopyFormat>> deletedFiles,
|
||||
SvnVcs vcs,
|
||||
VcsShowConfirmationOption.Value value,
|
||||
AbstractVcsHelper vcsHelper) {
|
||||
@@ -1001,9 +1007,9 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
myT = vcs.getFactory(file).createStatusClient().doStatus(file, false);
|
||||
}
|
||||
}.compute();
|
||||
boolean isAdded = StatusType.STATUS_ADDED.equals(status.getNodeStatus());
|
||||
final FilePath filePath = VcsContextFactory.SERVICE.getInstance().createFilePathOn(file);
|
||||
if (isAdded) {
|
||||
|
||||
final FilePath filePath = VcsUtil.getFilePath(file);
|
||||
if (StatusType.STATUS_ADDED.equals(status.getNodeStatus())) {
|
||||
deleteAnyway.add(filePath);
|
||||
} else {
|
||||
deletedFiles.add(Pair.create(filePath, vcs.getWorkingCopyFormat(file)));
|
||||
@@ -1060,11 +1066,6 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isUndoOrRedo(@NotNull final Project project) {
|
||||
final UndoManager undoManager = UndoManager.getInstance(project);
|
||||
return undoManager.isUndoInProgress() || undoManager.isRedoInProgress();
|
||||
}
|
||||
|
||||
private static boolean isUndo(SvnVcs vcs) {
|
||||
if (vcs == null || vcs.getProject() == null) {
|
||||
return false;
|
||||
@@ -1073,6 +1074,20 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
return UndoManager.getInstance(p).isUndoInProgress();
|
||||
}
|
||||
|
||||
public void startOperation(@NotNull VirtualFile file) {
|
||||
if (!myIsInCommand) {
|
||||
// currently actions like "new project", "import project" (probably also others) are not performed under command
|
||||
myGuessedProject = ProjectLocator.getInstance().guessProjectForFile(file);
|
||||
if (myGuessedProject != null) {
|
||||
commandStarted(myGuessedProject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void afterDone(final ThrowableConsumer<LocalFileOperationsHandler, IOException> invoker) {
|
||||
if (!myIsInCommand && myGuessedProject != null) {
|
||||
commandFinished(myGuessedProject);
|
||||
myGuessedProject = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,187 +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 org.jetbrains.idea.svn;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.command.CommandEvent;
|
||||
import com.intellij.openapi.command.CommandListener;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectLocator;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.vfs.LocalFileOperationsHandler;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.ThrowableConsumer;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class SvnFileSystemListenerWrapper {
|
||||
private final LocalFileOperationsHandler myProxy;
|
||||
private final CommandListener myListener;
|
||||
|
||||
public SvnFileSystemListenerWrapper(final SvnFileSystemListener delegate) {
|
||||
final MyCommandListener listener = new MyCommandListener(delegate);
|
||||
myListener = listener;
|
||||
final MyStorage storage = new MyStorage(listener);
|
||||
myProxy = (LocalFileOperationsHandler) Proxy.newProxyInstance(LocalFileOperationsHandler.class.getClassLoader(),
|
||||
new Class<?>[]{LocalFileOperationsHandler.class}, new MyInvoker(storage, delegate));
|
||||
}
|
||||
|
||||
public void registerSelf() {
|
||||
LocalFileSystem.getInstance().registerAuxiliaryFileOperationsHandler(myProxy);
|
||||
CommandProcessor.getInstance().addCommandListener(myListener);
|
||||
}
|
||||
|
||||
public void unregisterSelf() {
|
||||
LocalFileSystem.getInstance().unregisterAuxiliaryFileOperationsHandler(myProxy);
|
||||
CommandProcessor.getInstance().removeCommandListener(myListener);
|
||||
}
|
||||
|
||||
private static class MyCommandListener implements CommandListener, MyMarker {
|
||||
private volatile boolean myInCommand;
|
||||
private final SvnFileSystemListener myDelegate;
|
||||
|
||||
public MyCommandListener(final SvnFileSystemListener delegate) {
|
||||
myDelegate = delegate;
|
||||
}
|
||||
|
||||
public void start(final Project project) {
|
||||
if (!myInCommand && project != null) {
|
||||
myDelegate.commandStarted(project);
|
||||
}
|
||||
}
|
||||
|
||||
public void finish(final Project project) {
|
||||
if (! myInCommand && project != null) {
|
||||
myDelegate.commandFinished(project);
|
||||
}
|
||||
}
|
||||
|
||||
public void commandStarted(CommandEvent event) {
|
||||
myInCommand = true;
|
||||
myDelegate.commandStarted(event);
|
||||
}
|
||||
|
||||
public void beforeCommandFinished(CommandEvent event) {
|
||||
myDelegate.beforeCommandFinished(event);
|
||||
}
|
||||
|
||||
public void commandFinished(CommandEvent event) {
|
||||
myInCommand = false;
|
||||
myDelegate.commandFinished(event);
|
||||
}
|
||||
|
||||
public void undoTransparentActionStarted() {
|
||||
myDelegate.undoTransparentActionStarted();
|
||||
}
|
||||
|
||||
public void undoTransparentActionFinished() {
|
||||
myDelegate.undoTransparentActionFinished();
|
||||
}
|
||||
}
|
||||
|
||||
private interface MyMarker {
|
||||
void start(final Project project);
|
||||
void finish(final Project project);
|
||||
}
|
||||
|
||||
private static class MyStorage implements InvocationHandler {
|
||||
private final MyMarker myMarker;
|
||||
private final Map<Project, Pair<String, Object[]>> myStarted;
|
||||
|
||||
private MyStorage(final MyMarker marker) {
|
||||
myMarker = marker;
|
||||
myStarted = new HashMap<Project, Pair<String, Object[]>>();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Project getProject(Object[] args) {
|
||||
for (Object arg : args) {
|
||||
if (arg instanceof VirtualFile) {
|
||||
return ProjectLocator.getInstance().guessProjectForFile((VirtualFile) arg);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
final Project project = getProject(args);
|
||||
if (project != null) {
|
||||
final Pair<String, Object[]> pair = myStarted.get(project);
|
||||
if (pair != null && method.getName().equals(pair.getFirst()) && Arrays.equals(args, pair.getSecond())) {
|
||||
myMarker.finish(project);
|
||||
}
|
||||
}
|
||||
//dont return null for auto unboxing to not face NPE
|
||||
return "boolean".equals(method.getReturnType().getName()) ? Boolean.TRUE : null;
|
||||
}
|
||||
|
||||
private void register(final Method method, final Object[] args) {
|
||||
final Object[] newArr = new Object[args.length];
|
||||
System.arraycopy(args, 0, newArr, 0, args.length);
|
||||
final Project project = getProject(args);
|
||||
if (project != null) {
|
||||
myMarker.start(project);
|
||||
myStarted.put(project, Pair.create(method.getName(), newArr));
|
||||
Disposer.register(project, new Disposable() {
|
||||
public void dispose() {
|
||||
myStarted.remove(project);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyInvoker implements InvocationHandler {
|
||||
private final Object myDelegate;
|
||||
private final MyStorage myParent;
|
||||
private final LocalFileOperationsHandler myParentProxy;
|
||||
|
||||
private MyInvoker(final MyStorage parent, Object delegate) {
|
||||
myParent = parent;
|
||||
myDelegate = delegate;
|
||||
myParentProxy = (LocalFileOperationsHandler) Proxy.newProxyInstance(LocalFileOperationsHandler.class.getClassLoader(),
|
||||
new Class<?>[]{LocalFileOperationsHandler.class}, myParent);
|
||||
}
|
||||
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
if ("afterDone".equals(method.getName()) && args.length == 1) {
|
||||
((ThrowableConsumer<LocalFileOperationsHandler, IOException>)args[0]).consume(myParentProxy);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (LocalFileOperationsHandler.class.equals(method.getDeclaringClass())) {
|
||||
myParent.register(method, args);
|
||||
}
|
||||
if ("equals".equals(method.getName())) {
|
||||
return args[0].equals(this);
|
||||
}
|
||||
else if ("hashCode".equals(method.getName())) {
|
||||
return 1;
|
||||
}
|
||||
return method.invoke(myDelegate, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -510,15 +510,6 @@ public class SvnUtil {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static VirtualFile correctRoot(final Project project, final VirtualFile file) {
|
||||
if (file.getPath().length() == 0) {
|
||||
// project root
|
||||
return project.getBaseDir();
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
public static boolean checkRepositoryVersion15(@NotNull SvnVcs vcs, @NotNull String url) {
|
||||
// Merge info tracking is supported in repositories since svn 1.5 (June 2008) - see http://subversion.apache.org/docs/release-notes/.
|
||||
// But still some users use 1.4 repositories and currently we need to know if repository supports merge info for some code flows.
|
||||
|
||||
+16
-32
@@ -24,6 +24,7 @@ import com.intellij.openapi.ui.MultiLineLabelUI;
|
||||
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.*;
|
||||
import com.intellij.ui.components.JBList;
|
||||
@@ -31,7 +32,10 @@ import com.intellij.util.ObjectUtils;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.svn.*;
|
||||
import org.jetbrains.idea.svn.RootUrlInfo;
|
||||
import org.jetbrains.idea.svn.SvnBundle;
|
||||
import org.jetbrains.idea.svn.SvnUtil;
|
||||
import org.jetbrains.idea.svn.SvnVcs;
|
||||
import org.jetbrains.idea.svn.commandLine.SvnBindException;
|
||||
import org.jetbrains.idea.svn.dialogs.SelectLocationDialog;
|
||||
import org.tmatesoft.svn.core.SVNURL;
|
||||
@@ -42,7 +46,6 @@ import javax.swing.event.DocumentEvent;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -78,9 +81,10 @@ public class BranchConfigurationDialog extends DialogWrapper {
|
||||
myTrunkLocationTextField.setText(configuration.getTrunkUrl());
|
||||
myTrunkLocationTextField.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(final ActionEvent e) {
|
||||
final String selectedUrl = SelectLocationDialog.selectLocation(project, myTrunkLocationTextField.getText());
|
||||
if (selectedUrl != null) {
|
||||
myTrunkLocationTextField.setText(selectedUrl);
|
||||
Pair<String, SVNURL> selectionData = SelectLocationDialog.selectLocation(project, rootUrl);
|
||||
|
||||
if (selectionData != null && selectionData.getFirst() != null) {
|
||||
myTrunkLocationTextField.setText(selectionData.getFirst());
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -154,7 +158,6 @@ public class BranchConfigurationDialog extends DialogWrapper {
|
||||
boolean isAncestor = SVNURLUtil.isAncestor(myRootUrl, url);
|
||||
boolean areNotSame = isAncestor && !url.equals(myRootUrl);
|
||||
|
||||
myTrunkLocationTextField.getButton().setEnabled(isAncestor);
|
||||
if (areNotSame) {
|
||||
myConfiguration.setTrunkUrl(url.toDecodedString());
|
||||
}
|
||||
@@ -188,34 +191,19 @@ public class BranchConfigurationDialog extends DialogWrapper {
|
||||
return "Subversion.BranchConfigurationDialog";
|
||||
}
|
||||
|
||||
public static void configureBranches(final Project project, final VirtualFile file) {
|
||||
configureBranches(project, file, false);
|
||||
}
|
||||
|
||||
public static void configureBranches(final Project project, final VirtualFile file, final boolean isRoot) {
|
||||
final VirtualFile vcsRoot = (isRoot) ? file : getRoot(project, file);
|
||||
if (vcsRoot == null) {
|
||||
public static void configureBranches(final Project project, @Nullable VirtualFile file) {
|
||||
if (file == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final VirtualFile directory = SvnUtil.correctRoot(project, file);
|
||||
if (directory == null) {
|
||||
return;
|
||||
}
|
||||
final RootUrlInfo wcRoot = SvnVcs.getInstance(project).getSvnFileUrlMapping().getWcRootForFilePath(new File(directory.getPath()));
|
||||
final RootUrlInfo wcRoot = SvnVcs.getInstance(project).getSvnFileUrlMapping().getWcRootForFilePath(VfsUtilCore.virtualToIoFile(file));
|
||||
if (wcRoot == null) {
|
||||
return;
|
||||
}
|
||||
final SVNURL rootUrl = wcRoot.getRepositoryUrlUrl();
|
||||
if (rootUrl == null) {
|
||||
Messages.showErrorDialog(project, SvnBundle.message("configure.branches.error.no.connection.title"),
|
||||
SvnBundle.message("configure.branches.title"));
|
||||
return;
|
||||
}
|
||||
|
||||
SvnBranchConfigurationNew configuration;
|
||||
try {
|
||||
configuration = SvnBranchConfigurationManager.getInstance(project).get(vcsRoot);
|
||||
configuration = SvnBranchConfigurationManager.getInstance(project).get(file);
|
||||
}
|
||||
catch (VcsException ex) {
|
||||
Messages.showErrorDialog(project, "Error loading branch configuration: " + ex.getMessage(),
|
||||
@@ -224,18 +212,14 @@ public class BranchConfigurationDialog extends DialogWrapper {
|
||||
}
|
||||
|
||||
final SvnBranchConfigurationNew clonedConfiguration = configuration.copy();
|
||||
BranchConfigurationDialog dlg = new BranchConfigurationDialog(project, clonedConfiguration, rootUrl, vcsRoot, wcRoot.getUrl());
|
||||
BranchConfigurationDialog dlg =
|
||||
new BranchConfigurationDialog(project, clonedConfiguration, wcRoot.getRepositoryUrlUrl(), file, wcRoot.getUrl());
|
||||
dlg.show();
|
||||
if (dlg.isOK()) {
|
||||
SvnBranchConfigurationManager.getInstance(project).setConfiguration(vcsRoot, clonedConfiguration);
|
||||
SvnBranchConfigurationManager.getInstance(project).setConfiguration(file, clonedConfiguration);
|
||||
}
|
||||
}
|
||||
|
||||
private static VirtualFile getRoot(Project project, VirtualFile file) {
|
||||
RootUrlInfo path = SvnVcs.getInstance(project).getSvnFileUrlMapping().getWcRootForFilePath(new File(file.getPath()));
|
||||
return path == null ? null : path.getVirtualFile();
|
||||
}
|
||||
|
||||
private static class MyListModel extends AbstractListModel {
|
||||
private final SvnBranchConfigurationNew myConfiguration;
|
||||
private List<String> myBranchUrls;
|
||||
|
||||
+1
-1
@@ -61,6 +61,6 @@ public class ConfigureBranchesAction extends AnAction implements DumbAware {
|
||||
return;
|
||||
}
|
||||
final SvnChangeList svnList = (SvnChangeList) cls[0];
|
||||
BranchConfigurationDialog.configureBranches(project, svnList.getRoot(), true);
|
||||
BranchConfigurationDialog.configureBranches(project, svnList.getRoot());
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -184,7 +184,7 @@ public class CreateBranchOrTagDialog extends DialogWrapper {
|
||||
});
|
||||
myBranchTagBaseComboBox.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
BranchConfigurationDialog.configureBranches(project, mySrcVirtualFile, true);
|
||||
BranchConfigurationDialog.configureBranches(project, mySrcVirtualFile);
|
||||
updateBranchTagBases();
|
||||
updateControls();
|
||||
}
|
||||
|
||||
@@ -173,7 +173,7 @@ public class SelectBranchPopup {
|
||||
if (CONFIGURE_MESSAGE.equals(selectedValue)) {
|
||||
return doFinalStep(new Runnable() {
|
||||
public void run() {
|
||||
BranchConfigurationDialog.configureBranches(myProject, myVcsRoot, true);
|
||||
BranchConfigurationDialog.configureBranches(myProject, myVcsRoot);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.jetbrains.idea.svn.commandLine.CommandExecutor;
|
||||
import org.jetbrains.idea.svn.commandLine.CommandUtil;
|
||||
import org.jetbrains.idea.svn.commandLine.SvnBindException;
|
||||
import org.jetbrains.idea.svn.commandLine.SvnCommandName;
|
||||
import org.jetbrains.idea.svn.info.Info;
|
||||
import org.jetbrains.idea.svn.lock.Lock;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.SVNURL;
|
||||
@@ -62,9 +63,10 @@ public class CmdBrowseClient extends BaseSvnClient implements BrowseClient {
|
||||
parameters.add("--xml");
|
||||
|
||||
CommandExecutor command = execute(myVcs, target, SvnCommandName.list, parameters, null);
|
||||
Info info = myFactory.createInfoClient().doInfo(target.getURL(), target.getPegRevision(), revision);
|
||||
|
||||
try {
|
||||
parseOutput(target.getURL(), command, handler);
|
||||
parseOutput(target.getURL(), command, handler, info != null ? info.getRepositoryRootURL() : null);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
throw new SvnBindException(e);
|
||||
@@ -89,15 +91,18 @@ public class CmdBrowseClient extends BaseSvnClient implements BrowseClient {
|
||||
return listener.getCommittedRevision();
|
||||
}
|
||||
|
||||
private static void parseOutput(@NotNull SVNURL url, @NotNull CommandExecutor command, @Nullable DirectoryEntryConsumer handler)
|
||||
throws VcsException, SVNException {
|
||||
private static void parseOutput(@NotNull SVNURL url,
|
||||
@NotNull CommandExecutor command,
|
||||
@Nullable DirectoryEntryConsumer handler,
|
||||
@Nullable SVNURL repositoryUrl)
|
||||
throws VcsException, SVNException {
|
||||
try {
|
||||
TargetLists lists = CommandUtil.parse(command.getOutput(), TargetLists.class);
|
||||
|
||||
if (handler != null && lists != null) {
|
||||
for (TargetList list : lists.lists) {
|
||||
for (Entry entry : list.entries) {
|
||||
handler.consume(entry.toDirectoryEntry(url));
|
||||
handler.consume(entry.toDirectoryEntry(url, repositoryUrl));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -140,9 +145,8 @@ public class CmdBrowseClient extends BaseSvnClient implements BrowseClient {
|
||||
public Lock.Builder lock;
|
||||
|
||||
@NotNull
|
||||
public DirectoryEntry toDirectoryEntry(@NotNull SVNURL url) throws SVNException {
|
||||
// TODO: repository is not used for now
|
||||
return new DirectoryEntry(url.appendPath(name, false), null, PathUtil.getFileName(name), kind,
|
||||
public DirectoryEntry toDirectoryEntry(@NotNull SVNURL url, @Nullable SVNURL repositoryUrl) throws SVNException {
|
||||
return new DirectoryEntry(url.appendPath(name, false), repositoryUrl, PathUtil.getFileName(name), kind,
|
||||
commit != null ? commit.build() : null, name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,7 +221,7 @@ public class CopiesPanel {
|
||||
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
|
||||
if (CONFIGURE_BRANCHES.equals(e.getDescription())) {
|
||||
if (! checkRoot(root, wcInfo.getPath(), " invoke Configure Branches")) return;
|
||||
BranchConfigurationDialog.configureBranches(myProject, root, true);
|
||||
BranchConfigurationDialog.configureBranches(myProject, root);
|
||||
} else if (FIX_DEPTH.equals(e.getDescription())) {
|
||||
final int result =
|
||||
Messages.showOkCancelDialog(myVcs.getProject(), "You are going to checkout into '" + wcInfo.getPath() + "' with 'infinity' depth.\n" +
|
||||
|
||||
+13
-2
@@ -18,13 +18,13 @@ package org.jetbrains.idea.svn.dialogs;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.actionSystem.DataProvider;
|
||||
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
|
||||
import com.intellij.openapi.fileTypes.FileTypeManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.vcs.vfs.VcsFileSystem;
|
||||
import com.intellij.openapi.vcs.vfs.VcsVirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.pom.NavigatableAdapter;
|
||||
import com.intellij.ui.ScrollPaneFactory;
|
||||
import com.intellij.ui.SpeedSearchComparator;
|
||||
import com.intellij.ui.TreeSpeedSearch;
|
||||
@@ -282,7 +282,18 @@ public class RepositoryBrowserComponent extends JPanel implements Disposable, Da
|
||||
return null;
|
||||
}
|
||||
final VirtualFile vcsFile = getSelectedVcsFile();
|
||||
return vcsFile != null ? new OpenFileDescriptor(project, vcsFile) : null;
|
||||
|
||||
// do not return OpenFileDescriptor instance here as in that case SelectInAction will be enabled and its invocation (using keyboard)
|
||||
// will raise error - see IDEA-104113 - because of the following operations inside SelectInAction.actionPerformed():
|
||||
// - at first VcsVirtualFile content will be loaded which for svn results in showing progress dialog
|
||||
// - then DataContext from SelectInAction will still be accessed which results in error as current event count has already changed
|
||||
// (because of progress dialog)
|
||||
return vcsFile != null ? new NavigatableAdapter() {
|
||||
@Override
|
||||
public void navigate(boolean requestFocus) {
|
||||
navigate(project, vcsFile, requestFocus);
|
||||
}
|
||||
} : null;
|
||||
} else if (CommonDataKeys.PROJECT.is(dataId)) {
|
||||
return myVCS.getProject();
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.fileChooser.FileChooser;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.ide.CopyPasteManager;
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
@@ -192,6 +191,7 @@ public class RepositoryBrowserDialog extends DialogWrapper {
|
||||
}
|
||||
|
||||
protected JPopupMenu createPopup(boolean toolWindow) {
|
||||
ActionManager actionManager = ActionManager.getInstance();
|
||||
DefaultActionGroup group = new DefaultActionGroup();
|
||||
DefaultActionGroup newGroup = new DefaultActionGroup("_New", true);
|
||||
final RepositoryBrowserComponent browser = getRepositoryBrowser();
|
||||
@@ -200,7 +200,7 @@ public class RepositoryBrowserDialog extends DialogWrapper {
|
||||
group.add(newGroup);
|
||||
group.addSeparator();
|
||||
if (toolWindow) {
|
||||
group.add(new OpenAction());
|
||||
group.add(actionManager.getAction(IdeActions.ACTION_EDIT_SOURCE));
|
||||
group.add(new HistoryAction());
|
||||
}
|
||||
group.add(new CheckoutAction());
|
||||
@@ -218,7 +218,7 @@ public class RepositoryBrowserDialog extends DialogWrapper {
|
||||
group.add(new RefreshAction(browser));
|
||||
group.add(new EditLocationAction(browser));
|
||||
group.add(new DiscardLocationAction(browser));
|
||||
ActionPopupMenu menu = ActionManager.getInstance().createActionPopupMenu(PLACE_MENU, group);
|
||||
ActionPopupMenu menu = actionManager.createActionPopupMenu(PLACE_MENU, group);
|
||||
return menu.getComponent();
|
||||
}
|
||||
|
||||
@@ -928,23 +928,6 @@ public class RepositoryBrowserDialog extends DialogWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
protected class OpenAction extends AnAction {
|
||||
public void update(AnActionEvent e) {
|
||||
e.getPresentation().setEnabled(false);
|
||||
if (myVCS == null) {
|
||||
return;
|
||||
}
|
||||
e.getPresentation().setText("_Open", true);
|
||||
e.getPresentation().setEnabled(getRepositoryBrowser().getSelectedVcsFile() != null);
|
||||
}
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
VirtualFile vcsVF = getRepositoryBrowser().getSelectedVcsFile();
|
||||
if (vcsVF != null) {
|
||||
FileEditorManager.getInstance(myVCS.getProject()).openFile(vcsVF, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected class DetailsAction extends ToggleAction {
|
||||
|
||||
private boolean myIsSelected;
|
||||
|
||||
@@ -387,7 +387,7 @@ class BaseInterpreterInterface:
|
||||
|
||||
def getArray(self, attr, roffset, coffset, rows, cols, format):
|
||||
xml = "<xml>"
|
||||
name = ".".join(attr.split("\t"))
|
||||
name = attr.split("\t")[-1]
|
||||
array = pydevd_vars.evalInContext(name, self.getNamespace(), self.getNamespace())
|
||||
|
||||
if rows == -1 and cols == -1:
|
||||
|
||||
@@ -974,15 +974,15 @@ class InternalGetArray(InternalThreadCommand):
|
||||
self.thread_id = thread_id
|
||||
self.frame_id = frame_id
|
||||
self.scope = scope
|
||||
self.name = ".".join(attrs.split("\t"))
|
||||
self.name = attrs.split("\t")[-1]
|
||||
self.attrs = attrs
|
||||
self.roffset = int(roffset)
|
||||
self.coffset = int(coffset)
|
||||
self.rows = int(rows)
|
||||
self.cols = int(cols)
|
||||
self.format = format
|
||||
if hasattr(self.format, 'decode'):
|
||||
self.format = self.format.decode('utf-8')
|
||||
if hasattr(self.format, 'encode'):
|
||||
self.format = self.format.encode('utf-8')
|
||||
|
||||
def doIt(self, dbg):
|
||||
try:
|
||||
|
||||
@@ -15,7 +15,7 @@ import javax.swing.*;
|
||||
// todo: null modifier for modify modules, class objects etc.
|
||||
public class PyDebugValue extends XNamedValue {
|
||||
private static final Logger LOG = Logger.getInstance("#com.jetbrains.python.pydev.PyDebugValue");
|
||||
public static final int MAX_VALUE = 512;
|
||||
public static final int MAX_VALUE = 256;
|
||||
|
||||
private String myTempName = null;
|
||||
private final String myType;
|
||||
@@ -134,12 +134,23 @@ public class PyDebugValue extends XNamedValue {
|
||||
return "__len__".equals(name);
|
||||
}
|
||||
|
||||
private String getFullName() {
|
||||
String result = myName;
|
||||
PyDebugValue parent = myParent;
|
||||
while (parent != null) {
|
||||
result = "." + result;
|
||||
result = parent.getName() + result;
|
||||
parent = parent.getParent();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void computePresentation(@NotNull XValueNode node, @NotNull XValuePlace place) {
|
||||
String value = PyTypeHandler.format(this);
|
||||
|
||||
if (value.length() >= MAX_VALUE) {
|
||||
node.setFullValueEvaluator(new PyFullValueEvaluator(myFrameAccessor, myName));
|
||||
node.setFullValueEvaluator(new PyFullValueEvaluator(myFrameAccessor, getFullName()));
|
||||
value = value.substring(0, MAX_VALUE);
|
||||
}
|
||||
|
||||
|
||||
+7
-3
@@ -19,6 +19,7 @@ import com.intellij.openapi.editor.CaretModel;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.psi.PsiComment;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiWhiteSpace;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.jetbrains.python.codeInsight.editorActions.smartEnter.SmartEnterUtil;
|
||||
|
||||
@@ -34,12 +35,15 @@ public class PyCommentBreakerEnterProcessor implements EnterProcessor {
|
||||
return false;
|
||||
}
|
||||
final CaretModel caretModel = editor.getCaretModel();
|
||||
final PsiElement atCaret = psiElement.getContainingFile().findElementAt(caretModel.getOffset());
|
||||
PsiElement atCaret = psiElement.getContainingFile().findElementAt(caretModel.getOffset());
|
||||
if (atCaret instanceof PsiWhiteSpace) {
|
||||
atCaret = atCaret.getPrevSibling();
|
||||
}
|
||||
final PsiElement comment = PsiTreeUtil.getParentOfType(atCaret, PsiComment.class, false);
|
||||
if (comment != null) {
|
||||
SmartEnterUtil.plainEnter(editor);
|
||||
editor.getDocument().insertString(caretModel.getOffset(), "#");
|
||||
caretModel.moveToOffset(caretModel.getOffset() + 1);
|
||||
editor.getDocument().insertString(caretModel.getOffset(), "# ");
|
||||
caretModel.moveToOffset(caretModel.getOffset() + 2);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -25,10 +25,14 @@ import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiFileSystemItem;
|
||||
import com.intellij.psi.util.QualifiedName;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* An immutable holder of information for one auto-import candidate.
|
||||
* <p/>
|
||||
@@ -131,15 +135,15 @@ class ImportCandidateHolder implements Comparable<ImportCandidateHolder> {
|
||||
sb.append(((PyFunction)myImportable).getParameterList().getPresentableText(false));
|
||||
}
|
||||
else if (myImportable instanceof PyClass) {
|
||||
final PyClass[] supers = ((PyClass)myImportable).getSuperClasses();
|
||||
if (supers.length > 0) {
|
||||
final List<String> supers = ContainerUtil.mapNotNull(((PyClass)myImportable).getSuperClasses(), new Function<PyClass, String>() {
|
||||
@Override
|
||||
public String fun(PyClass cls) {
|
||||
return PyUtil.isObjectClass(cls) ? null : cls.getName();
|
||||
}
|
||||
});
|
||||
if (!supers.isEmpty()) {
|
||||
sb.append("(");
|
||||
// ", ".join(x.getName() for x in getSuperClasses())
|
||||
final String[] superNames = new String[supers.length];
|
||||
for (int i = 0; i < supers.length; i += 1) {
|
||||
superNames[i] = supers[i].getName();
|
||||
}
|
||||
sb.append(StringUtil.join(superNames, ", "));
|
||||
StringUtil.join(supers, ", ", sb);
|
||||
sb.append(")");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -554,14 +554,7 @@ public class PydevConsoleCommunication extends AbstractConsoleCommunication impl
|
||||
throws PyDebuggerException {
|
||||
if (myClient != null) {
|
||||
try {
|
||||
String fullName = var.getName();
|
||||
PyDebugValue child = var;
|
||||
while (child.getParent() != null) {
|
||||
child = child.getParent();
|
||||
fullName = child.getName() + "\t" + fullName;
|
||||
}
|
||||
|
||||
Object ret = myClient.execute(GET_ARRAY, new Object[]{fullName, rowOffset, colOffset, rows, cols, format});
|
||||
Object ret = myClient.execute(GET_ARRAY, new Object[]{var.getName(), rowOffset, colOffset, rows, cols, format});
|
||||
if (ret instanceof String) {
|
||||
return ProtocolParser.parseArrayValues((String)ret, this);
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ public class AsyncArrayTableModel extends AbstractTableModel {
|
||||
final PyDebugValue value = myProvider.getDebugValue();
|
||||
final PyDebugValue slicedValue =
|
||||
new PyDebugValue(myProvider.getSliceText(), value.getType(), value.getValue(), value.isContainer(), value.isErrorOnEval(),
|
||||
value.getFrameAccessor());
|
||||
value.getParent(), value.getFrameAccessor());
|
||||
|
||||
ListenableFutureTask<ArrayChunk> task = ListenableFutureTask.create(new Callable<ArrayChunk>() {
|
||||
@Override
|
||||
|
||||
@@ -167,7 +167,7 @@ public class NumpyArrayTable {
|
||||
}
|
||||
|
||||
public void init() {
|
||||
init(myValue.getName(), false);
|
||||
init(getDebugValue().getEvaluationExpression(), false);
|
||||
}
|
||||
|
||||
public void init(final String slice, final boolean inPlace) {
|
||||
@@ -181,14 +181,8 @@ public class NumpyArrayTable {
|
||||
public void run() {
|
||||
final PyDebugValue value = getDebugValue();
|
||||
PyDebugValue parent = value.getParent();
|
||||
String sl = slice;
|
||||
|
||||
if (slice.contains(".")) {
|
||||
sl = slice.substring(slice.lastIndexOf(".") + 1);
|
||||
}
|
||||
|
||||
final PyDebugValue slicedValue =
|
||||
new PyDebugValue(sl, value.getType(), value.getValue(), value.isContainer(), value.isErrorOnEval(),
|
||||
new PyDebugValue(slice, value.getType(), value.getValue(), value.isContainer(), value.isErrorOnEval(),
|
||||
parent, value.getFrameAccessor());
|
||||
|
||||
final String format = getFormat().isEmpty() ? "%" : getFormat();
|
||||
@@ -433,14 +427,7 @@ public class NumpyArrayTable {
|
||||
}
|
||||
|
||||
public String getNodeFullName() {
|
||||
String fullName = getDebugValue().getName();
|
||||
PyDebugValue child = getDebugValue();
|
||||
while (child.getParent() != null) {
|
||||
child = child.getParent();
|
||||
fullName = child.getName() + "." + fullName;
|
||||
}
|
||||
|
||||
return fullName;
|
||||
return getDebugValue().getEvaluationExpression();
|
||||
}
|
||||
|
||||
public String getFormat() {
|
||||
|
||||
@@ -1 +1 @@
|
||||
#<caret>comment
|
||||
# <caret>comment
|
||||
@@ -1,2 +1,2 @@
|
||||
#comment
|
||||
#<caret>
|
||||
# comment
|
||||
# <caret>
|
||||
@@ -0,0 +1,2 @@
|
||||
# foo <caret>
|
||||
pass
|
||||
@@ -0,0 +1,3 @@
|
||||
# foo
|
||||
# <caret>
|
||||
pass
|
||||
@@ -0,0 +1 @@
|
||||
<error descr="Unresolved reference 'MyOldStyleClass'">MyOldStyleCl<caret>ass</error>
|
||||
@@ -0,0 +1,2 @@
|
||||
class MyOldStyleClass:
|
||||
pass
|
||||
@@ -50,6 +50,16 @@ public class PyQuickFixTest extends PyTestCase {
|
||||
PyUnresolvedReferencesInspection.class, "Import 'importFromModule.foo.baz'", true, true);
|
||||
}
|
||||
|
||||
// PY-14365
|
||||
public void testObjectBaseIsNotShownInAutoImportQuickfix() {
|
||||
myFixture.copyDirectoryToProject("objectBaseIsNotShownInAutoImportQuickfix", "");
|
||||
myFixture.configureByFile("main.py");
|
||||
myFixture.enableInspections(PyUnresolvedReferencesInspection.class);
|
||||
final IntentionAction intention = myFixture.findSingleIntention("Import");
|
||||
assertNotNull(intention);
|
||||
assertEquals("Import 'module.MyOldStyleClass'", intention.getText());
|
||||
}
|
||||
|
||||
public void testImportFromModuleStar() { // PY-6302
|
||||
myFixture.enableInspections(PyUnresolvedReferencesInspection.class);
|
||||
myFixture.copyDirectoryToProject("importFromModuleStar", "");
|
||||
|
||||
@@ -189,4 +189,9 @@ public class PySmartEnterTest extends PyTestCase {
|
||||
public void testWithOnlyColonMissing() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-9209
|
||||
public void testSpaceInsertedAfterHashSignInComment() {
|
||||
doTest();
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ public class RelaxedHtmlFromSchemaElementDescriptor extends XmlElementDescriptor
|
||||
}
|
||||
|
||||
public static XmlAttributeDescriptor[] getCommonAttributeDescriptors(XmlTag context) {
|
||||
final XmlNSDescriptor nsDescriptor = context != null ? context.getNSDescriptor("", false) : null;
|
||||
final XmlNSDescriptor nsDescriptor = context != null ? context.getNSDescriptor(context.getNamespace(), false) : null;
|
||||
if (nsDescriptor != null) {
|
||||
for (XmlElementDescriptor descriptor : nsDescriptor.getRootElementsDescriptors(null)) {
|
||||
final String name = descriptor.getName();
|
||||
|
||||
Reference in New Issue
Block a user