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:
Generated
+2
-2
@@ -1,11 +1,11 @@
|
||||
<component name="libraryTable">
|
||||
<library name="pty4j">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/lib/pty4j-0.4.17.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/pty4j-0.4.19.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$PROJECT_DIR$/lib/src/pty4j-0.4.17-src.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/src/pty4j-0.4.19-src.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
|
||||
+13
-6
@@ -16,9 +16,7 @@
|
||||
package com.intellij.packaging.impl.artifacts;
|
||||
|
||||
import com.intellij.compiler.server.BuildManager;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.Result;
|
||||
import com.intellij.openapi.application.WriteAction;
|
||||
import com.intellij.openapi.application.*;
|
||||
import com.intellij.openapi.components.*;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.ProjectLoadingErrorsNotifier;
|
||||
@@ -193,9 +191,18 @@ public class ArtifactManagerImpl extends ArtifactManager implements ProjectCompo
|
||||
|
||||
@Override
|
||||
public void loadState(ArtifactManagerState managerState) {
|
||||
final List<ArtifactImpl> artifacts = new ArrayList<ArtifactImpl>();
|
||||
for (ArtifactState state : managerState.getArtifacts()) {
|
||||
artifacts.add(loadArtifact(state));
|
||||
List<ArtifactState> artifactStates = managerState.getArtifacts();
|
||||
final List<ArtifactImpl> artifacts = new ArrayList<ArtifactImpl>(artifactStates.size());
|
||||
if (!artifactStates.isEmpty()) {
|
||||
AccessToken token = ReadAction.start();
|
||||
try {
|
||||
for (ArtifactState state : artifactStates) {
|
||||
artifacts.add(loadArtifact(state));
|
||||
}
|
||||
}
|
||||
finally {
|
||||
token.finish();
|
||||
}
|
||||
}
|
||||
|
||||
if (myLoaded) {
|
||||
|
||||
+1
-7
@@ -49,7 +49,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
private final DfaValueFactory myFactory;
|
||||
|
||||
private final List<EqClass> myEqClasses;
|
||||
// dfa value id -> indices in myEqClasses list of the classes which contain the id (or negated or wrapped)
|
||||
// dfa value id -> indices in myEqClasses list of the classes which contain the id (or wrapped)
|
||||
private final TIntObjectHashMap<int[]> myIdToEqClassesIndices;
|
||||
private final Stack<DfaValue> myStack;
|
||||
private final TLongHashSet myDistinctClasses;
|
||||
@@ -321,7 +321,6 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
}
|
||||
|
||||
private void removeFromMap(int id, int index) {
|
||||
if (id < 0) return;
|
||||
id = unwrap(myFactory.getValue(id)).getID();
|
||||
int[] classes = myIdToEqClassesIndices.get(id);
|
||||
if (classes != null) {
|
||||
@@ -487,11 +486,6 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
}
|
||||
|
||||
EqClass newClass = new EqClass(c1);
|
||||
for (int i = 0; i < newClass.size(); i++) {
|
||||
int c = newClass.get(i);
|
||||
removeFromMap(c, c1Index);
|
||||
addToMap(c, c1Index);
|
||||
}
|
||||
|
||||
myEqClasses.set(c1Index, newClass);
|
||||
for (int i = 0; i < c2.size(); i++) {
|
||||
|
||||
+7
-4
@@ -376,10 +376,13 @@ public class DuplicatesFinder {
|
||||
final PsiClass patternClass = RefactoringChangeUtil.getThisClass(pattern);
|
||||
final PsiClass candidateClass = RefactoringChangeUtil.getThisClass(candidate);
|
||||
if (resolveResult1 == resolveResult2 &&
|
||||
resolveResult1 instanceof PsiMember &&
|
||||
!InheritanceUtil.isInheritorOrSelf(candidateClass, patternClass, true) &&
|
||||
InheritanceUtil.isInheritorOrSelf(candidateClass, ((PsiMember)resolveResult1).getContainingClass(), true)) {
|
||||
return false;
|
||||
resolveResult1 instanceof PsiMember) {
|
||||
final PsiClass containingClass = ((PsiMember)resolveResult1).getContainingClass();
|
||||
if (!InheritanceUtil.isInheritorOrSelf(candidateClass, patternClass, true) &&
|
||||
InheritanceUtil.isInheritorOrSelf(candidateClass, containingClass, true) &&
|
||||
InheritanceUtil.isInheritorOrSelf(patternClass, containingClass, true)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+14
-1
@@ -42,12 +42,14 @@ import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.statistics.JavaStatisticsManager;
|
||||
import com.intellij.psi.statistics.StatisticsManager;
|
||||
import com.intellij.ui.popup.list.ListPopupImpl;
|
||||
import com.intellij.ui.popup.list.PopupListElementRenderer;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -161,7 +163,18 @@ public class AddImportAction implements QuestionAction {
|
||||
ListPopupImpl popup = new ListPopupImpl(step) {
|
||||
@Override
|
||||
protected ListCellRenderer getListElementRenderer() {
|
||||
return new DefaultPsiElementCellRenderer();
|
||||
final PopupListElementRenderer baseRenderer = (PopupListElementRenderer)super.getListElementRenderer();
|
||||
final DefaultPsiElementCellRenderer psiRenderer = new DefaultPsiElementCellRenderer();
|
||||
return new ListCellRenderer() {
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
baseRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
panel.add(baseRenderer.getNextStepLabel(), BorderLayout.EAST);
|
||||
panel.add(psiRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus));
|
||||
return panel;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
popup.showInBestPositionFor(myEditor);
|
||||
|
||||
+35
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,10 +17,12 @@ package com.intellij.codeInsight.daemon.impl.quickfix;
|
||||
|
||||
import com.intellij.codeInsight.intention.impl.ParameterClassMember;
|
||||
import com.intellij.ide.util.MemberChooser;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiParameter;
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -32,24 +34,42 @@ import java.util.List;
|
||||
*/
|
||||
public class DefineParamsDefaultValueAction extends DelegateWithDefaultParamValueIntentionAction {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getText() {
|
||||
return "Define params default value";
|
||||
public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) {
|
||||
if (!JavaLanguage.INSTANCE.equals(element.getLanguage())) {
|
||||
return false;
|
||||
}
|
||||
final PsiElement parent = PsiTreeUtil.getParentOfType(element, PsiMethod.class, PsiCodeBlock.class);
|
||||
if (!(parent instanceof PsiMethod)) {
|
||||
return false;
|
||||
}
|
||||
final PsiMethod method = (PsiMethod)parent;
|
||||
final PsiParameterList parameterList = method.getParameterList();
|
||||
if (parameterList.getParametersCount() == 0) {
|
||||
return false;
|
||||
}
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass == null || (containingClass.isInterface() && !PsiUtil.isLanguageLevel8OrHigher(method))) {
|
||||
return false;
|
||||
}
|
||||
setText("Generate overloaded " + (method.isConstructor() ? "constructor" : "method") + " with default parameter values");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected PsiParameter[] getParams(PsiElement element) {
|
||||
final PsiMethod method = PsiTreeUtil.getParentOfType(element, PsiMethod.class);
|
||||
assert method != null;
|
||||
final PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
final ParameterClassMember[] members = new ParameterClassMember[parameters.length];
|
||||
for (int i = 0; i < members.length; i++) {
|
||||
members[i] = new ParameterClassMember(parameters[i]);
|
||||
}
|
||||
final MemberChooser<ParameterClassMember> chooser = new MemberChooser<ParameterClassMember>(members, false, true, element.getProject());
|
||||
final MemberChooser<ParameterClassMember> chooser =
|
||||
new MemberChooser<ParameterClassMember>(members, false, true, element.getProject());
|
||||
chooser.selectElements(members);
|
||||
chooser.setTitle("Choose " + (method.isConstructor() ? "Constructor" : "Method") + " Parameters");
|
||||
chooser.setTitle("Choose Default Value Parameters");
|
||||
if (chooser.showAndGet()) {
|
||||
final List<ParameterClassMember> elements = chooser.getSelectedElements();
|
||||
if (elements != null) {
|
||||
@@ -67,4 +87,10 @@ public class DefineParamsDefaultValueAction extends DelegateWithDefaultParamValu
|
||||
public boolean startInWriteAction() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return "Generate overloaded method with default parameter values";
|
||||
}
|
||||
}
|
||||
|
||||
+16
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -33,6 +33,7 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.refactoring.util.RefactoringUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Function;
|
||||
@@ -57,8 +58,12 @@ public class DelegateWithDefaultParamValueIntentionAction extends PsiElementBase
|
||||
if (declarationScope instanceof PsiMethod) {
|
||||
final PsiMethod method = (PsiMethod)declarationScope;
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass != null && !containingClass.isInterface()) {
|
||||
return containingClass.findMethodBySignature(generateMethodPrototype(method, parameter), false) == null;
|
||||
if (containingClass != null && (!containingClass.isInterface() || PsiUtil.isLanguageLevel7OrHigher(method))) {
|
||||
if (containingClass.findMethodBySignature(generateMethodPrototype(method, parameter), false) != null) {
|
||||
return false;
|
||||
}
|
||||
setText("Generate overloaded " + (method.isConstructor() ? "constructor" : "method") + " with default parameter value");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -81,6 +86,11 @@ public class DelegateWithDefaultParamValueIntentionAction extends PsiElementBase
|
||||
prototype.getModifierList().setModifierProperty(PsiModifier.ABSTRACT, false);
|
||||
prototype.addBefore(emptyBody, null);
|
||||
}
|
||||
final PsiClass aClass = method.getContainingClass();
|
||||
if (aClass != null && aClass.isInterface()) {
|
||||
prototype.getModifierList().setModifierProperty(PsiModifier.DEFAULT, true);
|
||||
}
|
||||
|
||||
for (int i = params.length - 1; i >= 0; i--) {
|
||||
PsiParameter param = params[i];
|
||||
final int parameterIndex = method.getParameterList().getParameterIndex(param);
|
||||
@@ -98,7 +108,8 @@ public class DelegateWithDefaultParamValueIntentionAction extends PsiElementBase
|
||||
final PsiMethod existingMethod = method.getContainingClass().findMethodBySignature(methodPrototype, false);
|
||||
if (existingMethod != null) {
|
||||
editor.getCaretModel().moveToOffset(existingMethod.getTextOffset());
|
||||
HintManager.getInstance().showErrorHint(editor, "Method with the chosen signature already exist");
|
||||
HintManager.getInstance().showErrorHint(editor, (existingMethod.isConstructor() ? "Constructor" : "Method") +
|
||||
" with the chosen signature already exists");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -170,15 +181,9 @@ public class DelegateWithDefaultParamValueIntentionAction extends PsiElementBase
|
||||
return new PsiParameter[]{PsiTreeUtil.getParentOfType(element, PsiParameter.class)};
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getText() {
|
||||
return "Generate delegated method with default parameter value";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return getText();
|
||||
return "Generate overloaded method with default parameter value";
|
||||
}
|
||||
}
|
||||
|
||||
+1
-7
@@ -189,13 +189,7 @@ public class JavaSmartEnterProcessor extends SmartEnterProcessor {
|
||||
return;
|
||||
}
|
||||
PsiElement parent = atCaret.getParent();
|
||||
if (parent instanceof PsiCodeBlock) {
|
||||
final PsiCodeBlock block = (PsiCodeBlock) parent;
|
||||
if (block.getStatements().length > 0 && block.getStatements()[0] == atCaret) {
|
||||
atCaret = block;
|
||||
}
|
||||
}
|
||||
else if (parent instanceof PsiForStatement) {
|
||||
if (parent instanceof PsiForStatement) {
|
||||
atCaret = parent;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -28,8 +28,8 @@ import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplate
|
||||
import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.selectorTopmost;
|
||||
|
||||
public class ForeachPostfixTemplate extends StringBasedPostfixTemplate {
|
||||
public ForeachPostfixTemplate() {
|
||||
super("for", "for (T item : expr)", selectorTopmost(IS_ITERABLE_OR_ARRAY));
|
||||
public ForeachPostfixTemplate(String name) {
|
||||
super(name, "for (T item : expr)", selectorTopmost(IS_ITERABLE_OR_ARRAY));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+2
-1
@@ -42,7 +42,8 @@ public class JavaPostfixTemplateProvider implements PostfixTemplateProvider {
|
||||
new ElseStatementPostfixTemplate(),
|
||||
new ForAscendingPostfixTemplate(),
|
||||
new ForDescendingPostfixTemplate(),
|
||||
new ForeachPostfixTemplate(),
|
||||
new ForeachPostfixTemplate("iter"),
|
||||
new ForeachPostfixTemplate("for"),
|
||||
new FormatPostfixTemplate(),
|
||||
new IfStatementPostfixTemplate(),
|
||||
new InstanceofExpressionPostfixTemplate(),
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
|
||||
class Foo {
|
||||
abstract void a();
|
||||
|
||||
{
|
||||
a();<caret>
|
||||
a();
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -1,8 +1,7 @@
|
||||
|
||||
class Foo {
|
||||
abstract void a();
|
||||
|
||||
{
|
||||
a();<caret>
|
||||
a();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
class Foo {
|
||||
boolean a;
|
||||
|
||||
{
|
||||
if (a) {
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
public class Test {
|
||||
public void foo(int x) {
|
||||
int a = 2<caret>
|
||||
|
||||
System.out.println("");
|
||||
System.out.println("");
|
||||
System.out.println("");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
public class Test {
|
||||
public void foo(int x) {
|
||||
int a = 2;
|
||||
|
||||
System.out.println("");
|
||||
System.out.println("");
|
||||
System.out.println("");
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "Generate delegated method with default parameter value" "true"
|
||||
// "Generate overloaded method with default parameter value" "true"
|
||||
class Test {
|
||||
void foo() {
|
||||
foo(<caret>);
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "Generate delegated method with default parameter value" "true"
|
||||
// "Generate overloaded method with default parameter value" "true"
|
||||
abstract class Test {
|
||||
int foo(boolean... args) {
|
||||
return foo(<caret>, args);
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "Generate delegated method with default parameter value" "true"
|
||||
// "Generate overloaded method with default parameter value" "true"
|
||||
class Test {
|
||||
int foo() {
|
||||
return foo();
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "Generate delegated method with default parameter value" "true"
|
||||
// "Generate overloaded constructor with default parameter value" "true"
|
||||
class Test {
|
||||
Test() {
|
||||
this(<caret>);
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// "Generate overloaded method with default parameter value" "true"
|
||||
interface Test {
|
||||
default void foo() {
|
||||
foo();
|
||||
}
|
||||
|
||||
void foo(int ii);
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "Generate delegated method with default parameter value" "true"
|
||||
// "Generate overloaded method with default parameter value" "true"
|
||||
class Test {
|
||||
/**
|
||||
*/
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "Generate delegated method with default parameter value" "true"
|
||||
// "Generate overloaded method with default parameter value" "true"
|
||||
class Test {
|
||||
int foo() {
|
||||
return foo(<caret>);
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "Generate delegated method with default parameter value" "true"
|
||||
// "Generate overloaded method with default parameter value" "true"
|
||||
class Test {
|
||||
<T> int foo(boolean... args) {
|
||||
return foo(<caret>, args);
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "Generate delegated method with default parameter value" "true"
|
||||
// "Generate overloaded method with default parameter value" "true"
|
||||
class Test {
|
||||
int foo(boolean... args) {
|
||||
return foo(<caret>, args);
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "Generate delegated method with default parameter value" "true"
|
||||
// "Generate overloaded method with default parameter value" "true"
|
||||
class Test {
|
||||
void foo(int i<caret>i){
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "Generate delegated method with default parameter value" "true"
|
||||
// "Generate overloaded method with default parameter value" "true"
|
||||
abstract class Test {
|
||||
abstract int foo(int i<caret>i, boolean... args);
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "Generate delegated method with default parameter value" "true"
|
||||
// "Generate overloaded method with default parameter value" "true"
|
||||
class Test {
|
||||
int foo(int i<caret>i){
|
||||
//comment1
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "Generate delegated method with default parameter value" "true"
|
||||
// "Generate overloaded constructor with default parameter value" "true"
|
||||
class Test {
|
||||
Test(int i<caret>i){}
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "Generate delegated method with default parameter value" "false"
|
||||
// "Generate overloaded method with default parameter value" "false"
|
||||
class Test {
|
||||
void foo(){}
|
||||
void foo(int i<caret>i){
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "Generate delegated method with default parameter value" "false"
|
||||
// "Generate overloaded method with default parameter value" "true"
|
||||
interface Test {
|
||||
void foo(int i<caret>i);
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "Generate delegated method with default parameter value" "true"
|
||||
// "Generate overloaded method with default parameter value" "true"
|
||||
class Test {
|
||||
/**
|
||||
* @param i
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "Generate delegated method with default parameter value" "true"
|
||||
// "Generate overloaded method with default parameter value" "true"
|
||||
class Test {
|
||||
int foo(int i<caret>i){
|
||||
return 1;
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "Generate delegated method with default parameter value" "true"
|
||||
// "Generate overloaded method with default parameter value" "true"
|
||||
class Test {
|
||||
<T> int foo(T i<caret>i, boolean... args){
|
||||
return 1;
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "Generate delegated method with default parameter value" "true"
|
||||
// "Generate overloaded method with default parameter value" "true"
|
||||
class Test {
|
||||
int foo(int i<caret>i, boolean... args){
|
||||
return 1;
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
Cleaning output files:
|
||||
out/production/ChangeExtends/Super.class
|
||||
out/production/ChangeExtends/Super2.class
|
||||
End of files
|
||||
Compiling files:
|
||||
src/Super.java
|
||||
src/Super2.java
|
||||
End of files
|
||||
Cleaning output files:
|
||||
out/production/ChangeExtends/Client.class
|
||||
@@ -13,4 +15,4 @@ Compiling files:
|
||||
src/Client.java
|
||||
src/Client2.java
|
||||
src/Client3.java
|
||||
End of files
|
||||
End of files
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
class Super2 {
|
||||
char s = 's';
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
class Client4 extends Hyper<Client4>{
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
class Super2 extends Hyper<Integer> {
|
||||
char s = 's';
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import java.util.*;
|
||||
|
||||
class Main {
|
||||
|
||||
private final Map<Integer, Map<String, String>> myScheduledUpdates = null;
|
||||
|
||||
void foo() {
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
<selection>myScheduledUpdates.keySet().toArray(new Object[myScheduledUpdates.keySet().size()])</selection>;
|
||||
}
|
||||
};
|
||||
myScheduledUpdates.keySet().toArray(new Object[myScheduledUpdates.keySet().size()]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import java.util.*;
|
||||
|
||||
class Main {
|
||||
|
||||
private final Map<Integer, Map<String, String>> myScheduledUpdates = null;
|
||||
|
||||
void foo() {
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
newMethod();
|
||||
}
|
||||
};
|
||||
newMethod();
|
||||
}
|
||||
|
||||
private Object[] newMethod() {
|
||||
return myScheduledUpdates.keySet().toArray(new Object[myScheduledUpdates.keySet().size()]);
|
||||
}
|
||||
}
|
||||
@@ -67,6 +67,8 @@ public class CompleteStatementTest extends EditorActionTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testNoBlockReformat() { doTest(); }
|
||||
|
||||
public void testCompleteCatchWithExpression() throws Exception { doTest(); }
|
||||
|
||||
public void testCompleteCatchBody() throws Exception { doTest(); }
|
||||
|
||||
-31
@@ -28,8 +28,6 @@ import com.intellij.openapi.editor.event.DocumentEvent;
|
||||
import com.intellij.openapi.editor.event.DocumentListener;
|
||||
import com.intellij.openapi.editor.event.EditorEventMulticaster;
|
||||
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.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.util.Segment;
|
||||
@@ -672,35 +670,6 @@ public class SmartPsiElementPointersTest extends CodeInsightTestCase {
|
||||
assertNotNull(node);
|
||||
}
|
||||
|
||||
public void testSmartPointersForOpenFilesAreFastened() {
|
||||
PsiJavaFile file = (PsiJavaFile)myJavaFacade.findClass("AClass", GlobalSearchScope.allScope(getProject())).getContainingFile();
|
||||
|
||||
SmartPointerManagerImpl manager = (SmartPointerManagerImpl)SmartPointerManager.getInstance(myProject);
|
||||
VirtualFile virtualFile = file.getVirtualFile();
|
||||
|
||||
assertFalse(manager.areBeltsFastened(virtualFile));
|
||||
FileEditor[] editors = FileEditorManager.getInstance(myProject).openFile(virtualFile, true);
|
||||
assertTrue(editors.length != 0);
|
||||
|
||||
assertTrue(manager.areBeltsFastened(virtualFile));
|
||||
|
||||
FileEditorManager.getInstance(myProject).closeFile(virtualFile);
|
||||
assertFalse(manager.areBeltsFastened(virtualFile));
|
||||
|
||||
SmartPsiElementPointer<PsiClass> pointer = manager.createSmartPsiElementPointer(file.getClasses()[0]);
|
||||
|
||||
assertFalse(manager.areBeltsFastened(virtualFile));
|
||||
editors = FileEditorManager.getInstance(myProject).openFile(virtualFile, true);
|
||||
assertTrue(editors.length != 0);
|
||||
|
||||
assertTrue(manager.areBeltsFastened(virtualFile));
|
||||
|
||||
FileEditorManager.getInstance(myProject).closeFile(virtualFile);
|
||||
assertFalse(manager.areBeltsFastened(virtualFile));
|
||||
|
||||
assertEquals(file.getClasses()[0], pointer.getElement()); // retain pointer from gc
|
||||
}
|
||||
|
||||
public void testLargeFileWithManyChanges() {
|
||||
configureByText(PlainTextFileType.INSTANCE, StringUtil.repeat("foo foo \n", 50000));
|
||||
final TextRange range = TextRange.from(10, 10);
|
||||
|
||||
@@ -225,6 +225,10 @@ public class ExtractMethodTest extends LightCodeInsightTestCase {
|
||||
doDuplicatesTest();
|
||||
}
|
||||
|
||||
public void testDuplicatesFromAnonymous() throws Exception {
|
||||
doDuplicatesTest();
|
||||
}
|
||||
|
||||
public void testCodeDuplicatesWithContinueNoReturn() throws Exception {
|
||||
doDuplicatesTest();
|
||||
}
|
||||
|
||||
@@ -79,23 +79,23 @@ public class CompilerTestUtil {
|
||||
}
|
||||
|
||||
public static void enableExternalCompiler() {
|
||||
ApplicationManagerEx.getApplicationEx().doNotSave(false);
|
||||
final JavaAwareProjectJdkTableImpl table = JavaAwareProjectJdkTableImpl.getInstanceEx();
|
||||
new WriteAction() {
|
||||
@Override
|
||||
protected void run(@NotNull final Result result) {
|
||||
ApplicationManagerEx.getApplicationEx().doNotSave(false);
|
||||
JavaAwareProjectJdkTableImpl table = JavaAwareProjectJdkTableImpl.getInstanceEx();
|
||||
table.addJdk(table.getInternalJdk());
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
public static void disableExternalCompiler(final Project project) {
|
||||
ApplicationManagerEx.getApplicationEx().doNotSave(true);
|
||||
final JavaAwareProjectJdkTableImpl table = JavaAwareProjectJdkTableImpl.getInstanceEx();
|
||||
new WriteAction() {
|
||||
@Override
|
||||
protected void run(@NotNull final Result result) {
|
||||
ApplicationManagerEx.getApplicationEx().doNotSave(true);
|
||||
Module[] modules = ModuleManager.getInstance(project).getModules();
|
||||
JavaAwareProjectJdkTableImpl table = JavaAwareProjectJdkTableImpl.getInstanceEx();
|
||||
Sdk internalJdk = table.getInternalJdk();
|
||||
List<Module> modulesToRestore = new ArrayList<Module>();
|
||||
for (Module module : modules) {
|
||||
|
||||
@@ -69,12 +69,12 @@ public class CompilerTester {
|
||||
myMainOutput = new TempDirTestFixtureImpl();
|
||||
myMainOutput.setUp();
|
||||
|
||||
CompilerTestUtil.enableExternalCompiler();
|
||||
new WriteCommandAction(getProject()) {
|
||||
@Override
|
||||
protected void run(@NotNull Result result) throws Throwable {
|
||||
//noinspection ConstantConditions
|
||||
CompilerProjectExtension.getInstance(getProject()).setCompilerOutputUrl(myMainOutput.findOrCreateDir("out").getUrl());
|
||||
CompilerTestUtil.enableExternalCompiler();
|
||||
for (Module module : myModules) {
|
||||
ModuleRootModificationUtil.setModuleSdk(module, JavaAwareProjectJdkTableImpl.getInstanceEx().getInternalJdk());
|
||||
}
|
||||
|
||||
+72
-46
@@ -217,61 +217,21 @@ class ClassfileAnalyzer {
|
||||
}
|
||||
}
|
||||
|
||||
private final SignatureVisitor mySignatureCrawler = new SignatureVisitor(Opcodes.ASM5) {
|
||||
public void visitFormalTypeParameter(String name) {
|
||||
}
|
||||
|
||||
private final SignatureVisitor mySignatureCrawler = new BaseSignatureVisitor() {
|
||||
public SignatureVisitor visitClassBound() {
|
||||
return this;
|
||||
return mySignatureWithGenericBoundUsageCrawler;
|
||||
}
|
||||
|
||||
public SignatureVisitor visitInterfaceBound() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public SignatureVisitor visitSuperclass() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public SignatureVisitor visitInterface() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public SignatureVisitor visitParameterType() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public SignatureVisitor visitReturnType() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public SignatureVisitor visitExceptionType() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void visitBaseType(char descriptor) {
|
||||
}
|
||||
|
||||
public void visitTypeVariable(String name) {
|
||||
}
|
||||
|
||||
public SignatureVisitor visitArrayType() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void visitInnerClassType(String name) {
|
||||
}
|
||||
|
||||
public void visitTypeArgument() {
|
||||
return mySignatureWithGenericBoundUsageCrawler;
|
||||
}
|
||||
|
||||
public SignatureVisitor visitTypeArgument(char wildcard) {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void visitEnd() {
|
||||
return mySignatureWithGenericBoundUsageCrawler;
|
||||
}
|
||||
};
|
||||
|
||||
private final SignatureVisitor mySignatureWithGenericBoundUsageCrawler = new BaseSignatureVisitor() {
|
||||
public void visitClassType(String name) {
|
||||
final int className = myContext.get(name);
|
||||
myUsages.add(UsageRepr.createClassUsage(myContext, className));
|
||||
@@ -653,6 +613,72 @@ class ClassfileAnalyzer {
|
||||
myLocalClassFlag.set(true);
|
||||
}
|
||||
}
|
||||
|
||||
private class BaseSignatureVisitor extends SignatureVisitor {
|
||||
|
||||
public BaseSignatureVisitor() {
|
||||
super(Opcodes.ASM5);
|
||||
}
|
||||
|
||||
public void visitFormalTypeParameter(String name) {
|
||||
}
|
||||
|
||||
public SignatureVisitor visitClassBound() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public SignatureVisitor visitInterfaceBound() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public SignatureVisitor visitSuperclass() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public SignatureVisitor visitInterface() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public SignatureVisitor visitParameterType() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public SignatureVisitor visitReturnType() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public SignatureVisitor visitExceptionType() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void visitBaseType(char descriptor) {
|
||||
}
|
||||
|
||||
public void visitTypeVariable(String name) {
|
||||
}
|
||||
|
||||
public SignatureVisitor visitArrayType() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void visitInnerClassType(String name) {
|
||||
}
|
||||
|
||||
public void visitTypeArgument() {
|
||||
}
|
||||
|
||||
public SignatureVisitor visitTypeArgument(char wildcard) {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void visitEnd() {
|
||||
}
|
||||
|
||||
public void visitClassType(String name) {
|
||||
final int className = myContext.get(name);
|
||||
myUsages.add(UsageRepr.createClassUsage(myContext, className));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Pair<ClassRepr, Set<UsageRepr.Usage>> analyze(final int fileName, final ClassReader cr) {
|
||||
|
||||
@@ -716,6 +716,28 @@ public class Mappings {
|
||||
public abstract boolean checkResidence(final int residence);
|
||||
}
|
||||
|
||||
public class FileFilterConstraint extends UsageConstraint {
|
||||
@NotNull
|
||||
private final DependentFilesFilter myFilter;
|
||||
|
||||
public FileFilterConstraint(@NotNull DependentFilesFilter filter) {
|
||||
myFilter = filter;
|
||||
}
|
||||
|
||||
public boolean checkResidence(int residence) {
|
||||
final Collection<File> fNames = myClassToSourceFile.get(residence);
|
||||
if (fNames == null || fNames.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
for (File fName : fNames) {
|
||||
if (myFilter.accept(fName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public class PackageConstraint extends UsageConstraint {
|
||||
public final String packageName;
|
||||
|
||||
@@ -1132,6 +1154,11 @@ public class Mappings {
|
||||
debug("Class is annotation, skipping method analysis");
|
||||
return;
|
||||
}
|
||||
|
||||
assert myFuture != null;
|
||||
assert myPresent != null;
|
||||
assert myAffectedFiles != null;
|
||||
|
||||
Ref<ClassRepr> oldItRef = null;
|
||||
for (final MethodRepr m : added) {
|
||||
debug("Method: ", m.name);
|
||||
@@ -1256,6 +1283,10 @@ public class Mappings {
|
||||
if (removed.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
assert myFuture != null;
|
||||
assert myAffectedFiles != null;
|
||||
assert myCompiledFiles != null;
|
||||
|
||||
debug("Processing removed methods:");
|
||||
for (final MethodRepr m : removed) {
|
||||
debug("Method ", m.name);
|
||||
@@ -1362,6 +1393,10 @@ public class Mappings {
|
||||
return;
|
||||
}
|
||||
debug("Processing changed methods:");
|
||||
|
||||
assert myFuture != null;
|
||||
assert myAffectedFiles != null;
|
||||
|
||||
for (final Pair<MethodRepr, Difference> mr : changed) {
|
||||
final MethodRepr m = mr.first;
|
||||
final MethodRepr.Diff d = (MethodRepr.Diff)mr.second;
|
||||
@@ -1473,6 +1508,11 @@ public class Mappings {
|
||||
}
|
||||
debug("Processing added fields");
|
||||
|
||||
assert myFuture != null;
|
||||
assert myPresent != null;
|
||||
assert myCompiledFiles != null;
|
||||
assert myAffectedFiles != null;
|
||||
|
||||
for (final FieldRepr f : added) {
|
||||
debug("Field: ", f.name);
|
||||
|
||||
@@ -1535,23 +1575,23 @@ public class Mappings {
|
||||
// nothing
|
||||
}
|
||||
else {
|
||||
Util.UsageConstraint constaint;
|
||||
Util.UsageConstraint constraint;
|
||||
|
||||
if ((ff.isProtected() && f.isPublic()) || (f.isProtected() && ff.isPublic()) || (ff.isPackageLocal() && f.isProtected())) {
|
||||
constaint = myFuture.new NegationConstraint(myFuture.new InheritanceConstraint(cc.name));
|
||||
constraint = myFuture.new NegationConstraint(myFuture.new InheritanceConstraint(cc.name));
|
||||
}
|
||||
else if (ff.isPublic() && ff.isPackageLocal()) {
|
||||
constaint = myFuture.new NegationConstraint(myFuture.new PackageConstraint(cc.getPackageName()));
|
||||
constraint = myFuture.new NegationConstraint(myFuture.new PackageConstraint(cc.getPackageName()));
|
||||
}
|
||||
else {
|
||||
constaint =
|
||||
constraint =
|
||||
myFuture.new IntersectionConstraint(myFuture.new NegationConstraint(myFuture.new InheritanceConstraint(cc.name)),
|
||||
myFuture.new NegationConstraint(
|
||||
myFuture.new PackageConstraint(cc.getPackageName())));
|
||||
}
|
||||
|
||||
for (final UsageRepr.Usage usage : localUsages) {
|
||||
state.myUsageConstraints.put(usage, constaint);
|
||||
state.myUsageConstraints.put(usage, constraint);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1569,6 +1609,8 @@ public class Mappings {
|
||||
if (removed.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
assert myFuture != null;
|
||||
|
||||
debug("Processing removed fields:");
|
||||
|
||||
for (final FieldRepr f : removed) {
|
||||
@@ -1577,6 +1619,7 @@ public class Mappings {
|
||||
if (!f.isPrivate() && (f.access & DESPERATE_MASK) == DESPERATE_MASK && f.hasValue()) {
|
||||
debug("Field had value and was (non-private) final static => a switch to non-incremental mode requested");
|
||||
if (myConstantSearch != null) {
|
||||
assert myDelayedWorks != null;
|
||||
myDelayedWorks.addConstantWork(it.name, f, true, false);
|
||||
}
|
||||
else {
|
||||
@@ -1601,6 +1644,7 @@ public class Mappings {
|
||||
return true;
|
||||
}
|
||||
debug("Processing changed fields:");
|
||||
assert myFuture != null;
|
||||
|
||||
for (final Pair<FieldRepr, Difference> f : changed) {
|
||||
final Difference d = f.second;
|
||||
@@ -1619,6 +1663,7 @@ public class Mappings {
|
||||
if (harmful || valueChanged || becameLessAccessible) {
|
||||
debug("Inline field changed it's access or value => a switch to non-incremental mode requested");
|
||||
if (myConstantSearch != null) {
|
||||
assert myDelayedWorks != null;
|
||||
myDelayedWorks.addConstantWork(it.name, field, false, accessChanged);
|
||||
}
|
||||
else {
|
||||
@@ -1687,6 +1732,10 @@ public class Mappings {
|
||||
final Collection<Pair<ClassRepr, Difference>> changedClasses = state.myClassDiff.changed();
|
||||
if (!changedClasses.isEmpty()) {
|
||||
debug("Processing changed classes:");
|
||||
assert myFuture != null;
|
||||
assert myPresent != null;
|
||||
|
||||
final Util.FileFilterConstraint fileFilterConstraint = myFilter != null? myPresent.new FileFilterConstraint(myFilter) : null;
|
||||
|
||||
for (final Pair<ClassRepr, Difference> changed : changedClasses) {
|
||||
final ClassRepr changedClass = changed.first;
|
||||
@@ -1753,7 +1802,11 @@ public class Mappings {
|
||||
@Override
|
||||
public boolean execute(int className) {
|
||||
debug("Affecting usages in generic type parameter bounds of class: ", className);
|
||||
state.myAffectedUsages.add(UsageRepr.createClassAsGenericBoundUsage(myContext, className));
|
||||
final UsageRepr.Usage usage = UsageRepr.createClassAsGenericBoundUsage(myContext, className);
|
||||
state.myAffectedUsages.add(usage);
|
||||
if (fileFilterConstraint != null) {
|
||||
state.myUsageConstraints.put(usage, fileFilterConstraint);
|
||||
}
|
||||
|
||||
final TIntHashSet depClasses = myClassToClassDependency.get(className);
|
||||
if (depClasses != null) {
|
||||
@@ -1869,6 +1922,9 @@ public class Mappings {
|
||||
if (removed.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
assert myPresent != null;
|
||||
assert myDelta.myChangedFiles != null;
|
||||
|
||||
myDelta.myChangedFiles.add(fileName);
|
||||
|
||||
debug("Processing removed classes:");
|
||||
@@ -1896,6 +1952,9 @@ public class Mappings {
|
||||
|
||||
if (!myEasyMode && myFilter != null) {
|
||||
// checking if this newly added class duplicates already existing one
|
||||
assert myCompiledFiles != null;
|
||||
assert myAffectedFiles != null;
|
||||
|
||||
for (ClassRepr c : addedClasses) {
|
||||
if (!c.isLocal() && !c.isAnonymous() && isEmpty(c.getOuterClassName())) {
|
||||
final Set<File> candidates = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
|
||||
@@ -1976,6 +2035,8 @@ public class Mappings {
|
||||
}
|
||||
|
||||
private void affectCorrespondingSourceFiles(TIntHashSet toAffect) {
|
||||
assert myAffectedFiles != null;
|
||||
|
||||
toAffect.forEach(new TIntProcedure() {
|
||||
@Override
|
||||
public boolean execute(int depClass) {
|
||||
@@ -1995,6 +2056,8 @@ public class Mappings {
|
||||
|
||||
private void calculateAffectedFiles(final DiffState state) {
|
||||
debug("Checking dependent classes:");
|
||||
assert myAffectedFiles != null;
|
||||
assert myCompiledFiles != null;
|
||||
|
||||
state.myDependants.forEach(new TIntProcedure() {
|
||||
@Override
|
||||
@@ -2106,6 +2169,8 @@ public class Mappings {
|
||||
if (myEasyMode) {
|
||||
return false;
|
||||
}
|
||||
assert myAffectedFiles != null;
|
||||
assert myDelayedWorks != null;
|
||||
|
||||
final Collection<String> removed = myDelta.myRemovedFiles;
|
||||
if (removed != null) {
|
||||
@@ -2117,6 +2182,7 @@ public class Mappings {
|
||||
}
|
||||
finally {
|
||||
if (myFilesToCompile != null) {
|
||||
assert myDelta.myChangedFiles != null;
|
||||
// if some class is associated with several sources,
|
||||
// some of them may not have been compiled in this round, so such files should be considered unchanged
|
||||
myDelta.myChangedFiles.retainAll(myFilesToCompile);
|
||||
@@ -2463,7 +2529,9 @@ public class Mappings {
|
||||
}
|
||||
for (final String s : staticImports) {
|
||||
int i = s.length() - 1;
|
||||
for (; s.charAt(i) != '.'; i--) ;
|
||||
while (s.charAt(i) != '.') {
|
||||
i--;
|
||||
}
|
||||
final String anImport = s.substring(0, i);
|
||||
if (!anImport.endsWith("*")) {
|
||||
allImports.add(anImport); // filter out wildcard imports
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -55,7 +55,7 @@ oromatcher.jar
|
||||
picocontainer.jar
|
||||
protobuf-2.5.0.jar
|
||||
proxy-vole_20131209.jar
|
||||
pty4j-0.4.17.jar
|
||||
pty4j-0.4.19.jar
|
||||
purejavacomm.jar
|
||||
resolver.jar
|
||||
rhino-js-1_7R4.jar
|
||||
|
||||
Binary file not shown.
@@ -19,6 +19,7 @@ import com.intellij.openapi.components.PathMacroManager
|
||||
import com.intellij.openapi.components.PathMacroSubstitutor
|
||||
import com.intellij.openapi.components.impl.stores.StorageData
|
||||
import org.jdom.Element
|
||||
import org.jetbrains.annotations.NotNull
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
abstract class BaseFileConfigurableStoreImpl(protected val pathMacroManager: PathMacroManager) : ComponentStoreImpl() {
|
||||
@@ -39,7 +40,7 @@ open class ProjectStorageData : StorageData {
|
||||
|
||||
private var version = CURRENT_FORMAT_VERSION
|
||||
|
||||
constructor(rootElementName: String) : super(rootElementName) {
|
||||
constructor() : super() {
|
||||
}
|
||||
|
||||
protected constructor(storageData: ProjectStorageData) : super(storageData) {
|
||||
@@ -51,11 +52,8 @@ open class ProjectStorageData : StorageData {
|
||||
version = rootElement.getAttributeValue(VERSION_OPTION)?.toInt() ?: CURRENT_FORMAT_VERSION
|
||||
}
|
||||
|
||||
override fun save(newLiveStates: Map<String, Element>): Element {
|
||||
var root = super.save(newLiveStates)
|
||||
if (root == null) {
|
||||
root = Element(myRootElementName)
|
||||
}
|
||||
override fun save(newLiveStates: Map<String, Element>, rootElementName: String): Element {
|
||||
val root = super.save(newLiveStates, rootElementName) ?: Element(rootElementName)
|
||||
writeOptions(root)
|
||||
return root
|
||||
}
|
||||
|
||||
@@ -17,13 +17,15 @@ package com.intellij.configurationStore
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.components.*
|
||||
import com.intellij.openapi.components.impl.stores.FileBasedStorage
|
||||
import com.intellij.openapi.components.impl.stores.FileStorage
|
||||
import com.intellij.openapi.components.impl.stores.StateStorageManager
|
||||
import com.intellij.openapi.components.impl.stores.StorageData
|
||||
import com.intellij.openapi.components.impl.stores.StreamProvider
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.project.impl.ProjectImpl
|
||||
import com.intellij.openapi.util.Couple
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
import org.jdom.Element
|
||||
import java.io.File
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
@@ -38,6 +40,25 @@ class DefaultProjectStoreImpl(override val project: ProjectImpl, private val pat
|
||||
|
||||
private val storage by Delegates.lazy { DefaultProjectStorage(File(ApplicationManager.getApplication().stateStore.getStateStorageManager().expandMacros(FILE_SPEC)), FILE_SPEC, pathMacroManager) }
|
||||
|
||||
private class DefaultProjectStorage(file: File, fileSpec: String, pathMacroManager: PathMacroManager) : FileBasedStorage(file, fileSpec, "defaultProject", pathMacroManager.createTrackingSubstitutor(), RoamingType.DISABLED) {
|
||||
override public fun loadLocalData(): Element? {
|
||||
val element = super.loadLocalData() ?: return null
|
||||
try {
|
||||
return element.getChild("component").getChild("defaultProject")
|
||||
}
|
||||
catch (e: NullPointerException) {
|
||||
LOG.warn("Cannot read default project")
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
override fun createSaveSession(storageData: StorageData) = object : FileBasedStorage.FileSaveSession(storageData, this) {
|
||||
override fun saveLocally(element: Element?) {
|
||||
super.saveLocally(Element("application").addContent(Element("component").setAttribute("name", "ProjectManager").addContent(element)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val storageManager = object : StateStorageManager {
|
||||
override fun rename(path: String, newName: String) {
|
||||
}
|
||||
@@ -48,7 +69,7 @@ class DefaultProjectStoreImpl(override val project: ProjectImpl, private val pat
|
||||
|
||||
override fun getStateStorage(fileSpec: String, roamingType: RoamingType) = storage
|
||||
|
||||
override fun getCachedFileStateStorages(changed: Collection<String>, deleted: Collection<String>): Couple<Collection<FileBasedStorage>> = Couple(emptyList<FileBasedStorage>(), emptyList<FileBasedStorage>())
|
||||
override fun getCachedFileStateStorages(changed: Collection<String>, deleted: Collection<String>): Couple<Collection<FileStorage>> = Couple(emptyList<FileStorage>(), emptyList<FileStorage>())
|
||||
|
||||
override fun startExternalization(): StateStorageManager.ExternalizationSession? {
|
||||
val externalizationSession = storage.startExternalization()
|
||||
|
||||
@@ -29,7 +29,7 @@ class ModuleFileData : ProjectStorageData, OptionManager {
|
||||
|
||||
override fun isDirty() = dirty
|
||||
|
||||
public constructor(rootElementName: String) : super(rootElementName) {
|
||||
public constructor() : super() {
|
||||
options = TreeMap<String, String>()
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.intellij.openapi.components.StateStorage
|
||||
import com.intellij.openapi.components.StateStorageOperation
|
||||
import com.intellij.openapi.components.StoragePathMacros
|
||||
import com.intellij.openapi.components.TrackingPathMacroSubstitutor
|
||||
import com.intellij.openapi.components.impl.stores.StorageData
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.module.impl.ModuleEx
|
||||
import com.intellij.openapi.module.impl.ModuleManagerImpl
|
||||
@@ -29,14 +30,14 @@ import com.intellij.util.PathUtilRt
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
|
||||
class ModuleStateStorageManager(macroSubstitutor: TrackingPathMacroSubstitutor, module: Module) : StateStorageManagerImpl("module", macroSubstitutor, module) {
|
||||
override fun createStorageData(fileSpec: String) = ModuleFileData(rootTagName)
|
||||
override fun createStorageData(fileSpec: String) = ModuleFileData()
|
||||
|
||||
override fun startExternalization() = MyStateStorageManagerExternalizationSession(this)
|
||||
|
||||
private class MyStateStorageManagerExternalizationSession(storageManager: StateStorageManagerImpl) : StateStorageManagerImpl.StateStorageManagerExternalizationSession(storageManager) {
|
||||
override fun createSaveSessions(): List<StateStorage.SaveSession> {
|
||||
val storage = ContainerUtil.getFirstItem(storageManager.getCachedFileStorages(listOf(StoragePathMacros.MODULE_FILE)))
|
||||
if (storage != null && storage.getStorageData().isDirty()) {
|
||||
if (storage != null && (storage.getStorageData() as StorageData).isDirty()) {
|
||||
// force XmlElementStorageSaveSession creation
|
||||
getExternalizationSession(storage)
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import com.intellij.openapi.components.TrackingPathMacroSubstitutor
|
||||
import com.intellij.openapi.project.impl.ProjectImpl
|
||||
|
||||
class ProjectStateStorageManager(macroSubstitutor: TrackingPathMacroSubstitutor, private val project: ProjectImpl) : StateStorageManagerImpl("project", macroSubstitutor, project) {
|
||||
override fun createStorageData(fileSpec: String) = ProjectStorageData(rootTagName)
|
||||
override fun createStorageData(fileSpec: String) = ProjectStorageData()
|
||||
|
||||
override fun getOldStorageSpec(component: Any, componentName: String, operation: StateStorageOperation): String? {
|
||||
val workspace = project.isWorkspaceComponent(component.javaClass)
|
||||
|
||||
@@ -23,7 +23,6 @@ import com.intellij.openapi.application.ReadAction
|
||||
import com.intellij.openapi.application.invokeAndWaitIfNeed
|
||||
import com.intellij.openapi.components.*
|
||||
import com.intellij.openapi.components.StateStorage.SaveSession
|
||||
import com.intellij.openapi.components.impl.stores.FileBasedStorage
|
||||
import com.intellij.openapi.components.impl.stores.IComponentStore
|
||||
import com.intellij.openapi.components.impl.stores.IProjectStore
|
||||
import com.intellij.openapi.fileTypes.FileTypeManager
|
||||
@@ -148,7 +147,7 @@ open class ProjectStoreImpl(override val project: ProjectImpl, pathMacroManager:
|
||||
return baseDir.getName().replace(":", "")
|
||||
}
|
||||
else {
|
||||
var temp = PathUtilRt.getFileName(getProjectFileStorage().getFilePath())
|
||||
var temp = PathUtilRt.getFileName(getProjectFilePath())
|
||||
val fileType = FileTypeManager.getInstance().getFileTypeByFileName(temp)
|
||||
if (fileType is ProjectFileType) {
|
||||
temp = temp.substring(0, temp.length() - fileType.getDefaultExtension().length() - 1)
|
||||
@@ -175,16 +174,13 @@ open class ProjectStoreImpl(override val project: ProjectImpl, pathMacroManager:
|
||||
|
||||
override fun getProjectFile() = getProjectFileStorage().getVirtualFile()
|
||||
|
||||
override fun getProjectFilePath() = getProjectFileStorage().getFilePath()
|
||||
override fun getProjectFilePath() = storageManager.expandMacros(StoragePathMacros.PROJECT_FILE)
|
||||
|
||||
private fun getProjectFileStorage() = storageManager.getStateStorage(StoragePathMacros.PROJECT_FILE, RoamingType.PER_USER) as FileBasedStorage
|
||||
|
||||
override fun getWorkspaceFile() = workspaceStorage?.getVirtualFile()
|
||||
override fun getWorkspaceFile() = (storageManager.getStateStorage(StoragePathMacros.WORKSPACE_FILE, RoamingType.DISABLED) as FileBasedStorage?)?.getVirtualFile()
|
||||
|
||||
override fun getWorkspaceFilePath() = workspaceStorage?.getFilePath()
|
||||
|
||||
private val workspaceStorage: FileBasedStorage?
|
||||
get() = storageManager.getStateStorage(StoragePathMacros.WORKSPACE_FILE, RoamingType.DISABLED) as FileBasedStorage?
|
||||
override fun getWorkspaceFilePath() = storageManager.expandMacros(StoragePathMacros.WORKSPACE_FILE)
|
||||
|
||||
override fun loadProjectFromTemplate(defaultProject: Project) {
|
||||
defaultProject.save()
|
||||
|
||||
@@ -46,7 +46,7 @@ import kotlin.reflect.jvm.java
|
||||
/**
|
||||
* If componentManager not specified, storage will not add file tracker (see VirtualFileTracker)
|
||||
*/
|
||||
open class StateStorageManagerImpl(protected val rootTagName: String,
|
||||
open class StateStorageManagerImpl(private val rootTagName: String,
|
||||
private val pathMacroSubstitutor: TrackingPathMacroSubstitutor? = null,
|
||||
val componentManager: ComponentManager? = null,
|
||||
private val virtualFileTracker: StorageVirtualFileTracker? = StateStorageManagerImpl.createDefaultVirtualTracker(componentManager) ) : StateStorageManager {
|
||||
@@ -155,7 +155,7 @@ open class StateStorageManagerImpl(protected val rootTagName: String,
|
||||
|
||||
override final fun getCachedFileStateStorages(changed: MutableCollection<String>, deleted: MutableCollection<String>) = storageLock.withLock { Couple.of(getCachedFileStorages(changed), getCachedFileStorages(deleted)) }
|
||||
|
||||
fun getCachedFileStorages(fileSpecs: Collection<String>): Collection<FileBasedStorage> {
|
||||
fun getCachedFileStorages(fileSpecs: Collection<String>): Collection<FileStorage> {
|
||||
if (fileSpecs.isEmpty()) {
|
||||
return emptyList()
|
||||
}
|
||||
@@ -185,13 +185,7 @@ open class StateStorageManagerImpl(protected val rootTagName: String,
|
||||
val file = File(filePath)
|
||||
|
||||
if (isUseVfsListener == ThreeState.UNSURE) {
|
||||
if (streamProvider != null && streamProvider!!.enabled) {
|
||||
isUseVfsListener = ThreeState.NO
|
||||
}
|
||||
else {
|
||||
isUseVfsListener = ThreeState.YES
|
||||
// addVfsChangesListener(componentManager!!)
|
||||
}
|
||||
isUseVfsListener = ThreeState.fromBoolean(streamProvider == null || !streamProvider!!.enabled)
|
||||
}
|
||||
|
||||
//noinspection deprecation
|
||||
@@ -207,22 +201,25 @@ open class StateStorageManagerImpl(protected val rootTagName: String,
|
||||
|
||||
val effectiveRoamingType = if (roamingType == RoamingType.PER_USER && fileSpec == StoragePathMacros.WORKSPACE_FILE) RoamingType.DISABLED else roamingType
|
||||
val storage = MyFileStorage(this, file, fileSpec, rootTagName, effectiveRoamingType, getMacroSubstitutor(fileSpec), streamProvider)
|
||||
virtualFileTracker?.put(filePath.normalizePath(), storage)
|
||||
if (isUseVfsListener == ThreeState.YES) {
|
||||
virtualFileTracker?.put(filePath.normalizePath(), storage)
|
||||
}
|
||||
return storage
|
||||
}
|
||||
|
||||
private class MyDirectoryStorage(override val storageManager: StateStorageManagerImpl, file: File, splitter: StateSplitter) : DirectoryBasedStorage(storageManager.pathMacroSubstitutor, file, splitter), StorageVirtualFileTracker.TrackedStorage
|
||||
|
||||
private class MyFileStorage(override val storageManager: StateStorageManagerImpl,
|
||||
file: File,
|
||||
fileSpec: String,
|
||||
rootElementName: String,
|
||||
roamingType: RoamingType? = null,
|
||||
pathMacroManager: TrackingPathMacroSubstitutor? = null,
|
||||
streamProvider: StreamProvider? = null) : FileBasedStorage(file, fileSpec, roamingType, pathMacroManager, rootElementName, streamProvider), StorageVirtualFileTracker.TrackedStorage {
|
||||
override fun createStorageData() = storageManager.createStorageData(myFileSpec)
|
||||
file: File,
|
||||
fileSpec: String,
|
||||
rootElementName: String,
|
||||
roamingType: RoamingType,
|
||||
pathMacroManager: TrackingPathMacroSubstitutor? = null,
|
||||
provider: StreamProvider? = null) : FileBasedStorage(file, fileSpec, rootElementName, pathMacroManager, roamingType, provider), StorageVirtualFileTracker.TrackedStorage {
|
||||
override val isUseXmlProlog: Boolean
|
||||
get() = storageManager.isUseXmlProlog
|
||||
|
||||
override fun isUseXmlProlog() = storageManager.isUseXmlProlog
|
||||
override fun createStorageData() = storageManager.createStorageData(fileSpec)
|
||||
}
|
||||
|
||||
private fun String.normalizePath(): String {
|
||||
@@ -272,7 +269,7 @@ open class StateStorageManagerImpl(protected val rootTagName: String,
|
||||
|
||||
protected open fun getMacroSubstitutor(fileSpec: String): TrackingPathMacroSubstitutor? = pathMacroSubstitutor
|
||||
|
||||
protected open fun createStorageData(fileSpec: String): StorageData = StorageData(rootTagName)
|
||||
protected open fun createStorageData(fileSpec: String): StorageData = StorageData()
|
||||
|
||||
override final fun expandMacros(path: String): String {
|
||||
// replacement can contains $ (php tests), so, this check must be performed before expand
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.intellij.configurationStore
|
||||
|
||||
import com.intellij.openapi.components.StateStorage
|
||||
import com.intellij.openapi.components.impl.stores.DirectoryBasedStorage
|
||||
import com.intellij.openapi.components.impl.stores.FileBasedStorage
|
||||
import com.intellij.openapi.components.impl.stores.StateStorageManager
|
||||
import com.intellij.openapi.components.impl.stores.StorageUtil
|
||||
import com.intellij.openapi.util.text.StringUtilRt
|
||||
|
||||
-46
@@ -1,46 +0,0 @@
|
||||
package com.intellij.configurationStore;
|
||||
|
||||
import com.intellij.openapi.components.PathMacroManager;
|
||||
import com.intellij.openapi.components.RoamingType;
|
||||
import com.intellij.openapi.components.impl.stores.FileBasedStorage;
|
||||
import com.intellij.openapi.components.impl.stores.StorageData;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
public class DefaultProjectStorage extends FileBasedStorage {
|
||||
public DefaultProjectStorage(@NotNull File file, @NotNull String fileSpec, PathMacroManager pathMacroManager) {
|
||||
super(file, fileSpec, RoamingType.DISABLED, pathMacroManager.createTrackingSubstitutor(), "defaultProject", null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected Element loadLocalData() {
|
||||
Element element = super.loadLocalData();
|
||||
if (element == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return element.getChild("component").getChild("defaultProject");
|
||||
}
|
||||
catch (NullPointerException e) {
|
||||
LOG.warn("Cannot read default project");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected XmlElementStorageSaveSession createSaveSession(@NotNull StorageData storageData) {
|
||||
return new FileSaveSession(storageData) {
|
||||
@Override
|
||||
protected void doSave(@Nullable Element element) throws IOException {
|
||||
super.doSave(new Element("application").addContent(new Element("component").setAttribute("name", "ProjectManager").addContent(element)));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
-5
@@ -12,11 +12,6 @@ public final class DefaultStorageAnnotation implements Storage {
|
||||
return "___Default___";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDefault() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String file() {
|
||||
return StoragePathMacros.PROJECT_FILE;
|
||||
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.configurationStore
|
||||
|
||||
import com.intellij.notification.Notification
|
||||
import com.intellij.notification.NotificationType
|
||||
import com.intellij.notification.Notifications
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.components.RoamingType
|
||||
import com.intellij.openapi.components.StoragePathMacros
|
||||
import com.intellij.openapi.components.TrackingPathMacroSubstitutor
|
||||
import com.intellij.openapi.components.impl.stores.*
|
||||
import com.intellij.openapi.util.JDOMUtil
|
||||
import com.intellij.openapi.util.io.FileUtilRt
|
||||
import com.intellij.openapi.util.io.systemIndependentPath
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.openapi.vfs.CharsetToolkit
|
||||
import com.intellij.openapi.vfs.LocalFileSystem
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.util.LineSeparator
|
||||
import org.jdom.Element
|
||||
import org.jdom.JDOMException
|
||||
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.CharBuffer
|
||||
|
||||
open class FileBasedStorage(private volatile var file: File,
|
||||
fileSpec: String,
|
||||
rootElementName: String,
|
||||
pathMacroManager: TrackingPathMacroSubstitutor? = null,
|
||||
roamingType: RoamingType? = null,
|
||||
provider: StreamProvider? = null) : XmlElementStorage(fileSpec, rootElementName, pathMacroManager, roamingType, provider), FileStorage {
|
||||
private volatile var cachedVirtualFile: VirtualFile? = null
|
||||
private var lineSeparator: LineSeparator? = null
|
||||
private var blockSavingTheContent = false
|
||||
|
||||
init {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode() && file.getPath().startsWith('$')) {
|
||||
throw AssertionError("It seems like some macros were not expanded for path: $file")
|
||||
}
|
||||
}
|
||||
|
||||
protected open val isUseXmlProlog: Boolean = false
|
||||
|
||||
// we never set io file to null
|
||||
override fun setFile(virtualFile: VirtualFile?, ioFileIfChanged: File?) {
|
||||
cachedVirtualFile = virtualFile
|
||||
if (ioFileIfChanged != null) {
|
||||
file = ioFileIfChanged
|
||||
}
|
||||
}
|
||||
|
||||
override fun createSaveSession(storageData: StorageData) = FileSaveSession(storageData, this)
|
||||
|
||||
protected open class FileSaveSession(storageData: StorageData, storage: FileBasedStorage) : XmlElementStorage.XmlElementStorageSaveSession<FileBasedStorage>(storageData, storage) {
|
||||
override fun save() {
|
||||
if (!storage.blockSavingTheContent) {
|
||||
super.save()
|
||||
}
|
||||
}
|
||||
|
||||
override fun saveLocally(element: Element?) {
|
||||
if (storage.lineSeparator == null) {
|
||||
storage.lineSeparator = if (storage.isUseXmlProlog) LineSeparator.LF else LineSeparator.getSystemLineSeparator()
|
||||
}
|
||||
|
||||
val virtualFile = storage.getVirtualFile()
|
||||
if (element == null) {
|
||||
StorageUtil.deleteFile(storage.file, this, virtualFile)
|
||||
storage.cachedVirtualFile = null
|
||||
}
|
||||
else {
|
||||
storage.cachedVirtualFile = StorageUtil.writeFile(storage.file, this, virtualFile, element, if (storage.isUseXmlProlog) storage.lineSeparator!! else LineSeparator.LF, storage.isUseXmlProlog)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getVirtualFile(): VirtualFile? {
|
||||
var result = cachedVirtualFile
|
||||
if (result == null) {
|
||||
result = LocalFileSystem.getInstance().findFileByIoFile(file)
|
||||
cachedVirtualFile = result
|
||||
}
|
||||
return cachedVirtualFile
|
||||
}
|
||||
|
||||
override fun getFile() = file
|
||||
|
||||
override fun loadLocalData(): Element? {
|
||||
blockSavingTheContent = false
|
||||
try {
|
||||
val file = getVirtualFile()
|
||||
if (file == null || file.isDirectory() || !file.isValid()) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Document was not loaded for $fileSpec file is ${if (file == null) "null" else "directory"}")
|
||||
}
|
||||
}
|
||||
else if (file.getLength() == 0L) {
|
||||
processReadException(null)
|
||||
}
|
||||
else {
|
||||
val charBuffer = CharsetToolkit.UTF8_CHARSET.decode(ByteBuffer.wrap(file.contentsToByteArray()))
|
||||
lineSeparator = StorageUtil.detectLineSeparators(charBuffer, if (isUseXmlProlog) null else LineSeparator.LF)
|
||||
return JDOMUtil.loadDocument(charBuffer).detachRootElement()
|
||||
}
|
||||
}
|
||||
catch (e: JDOMException) {
|
||||
processReadException(e)
|
||||
}
|
||||
catch (e: IOException) {
|
||||
processReadException(e)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun processReadException(e: Exception?) {
|
||||
val contentTruncated = e == null
|
||||
blockSavingTheContent = !contentTruncated && (StorageUtil.isProjectOrModuleFile(fileSpec) || fileSpec == StoragePathMacros.WORKSPACE_FILE)
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode() && !ApplicationManager.getApplication().isHeadlessEnvironment()) {
|
||||
if (e != null) {
|
||||
LOG.info(e)
|
||||
}
|
||||
Notification(Notifications.SYSTEM_MESSAGES_GROUP_ID, "Load Settings", "Cannot load settings from file '$file': ${if (contentTruncated) "content truncated" else e!!.getMessage()}\n${if (blockSavingTheContent) "Please correct the file content" else "File content will be recreated"}", NotificationType.WARNING).notify(null)
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString() = file.systemIndependentPath
|
||||
}
|
||||
+202
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.configurationStore
|
||||
|
||||
import com.intellij.openapi.components.RoamingType
|
||||
import com.intellij.openapi.components.StateStorage
|
||||
import com.intellij.openapi.components.TrackingPathMacroSubstitutor
|
||||
import com.intellij.openapi.components.impl.stores.*
|
||||
import com.intellij.openapi.util.JDOMUtil
|
||||
import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream
|
||||
import com.intellij.util.LineSeparator
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
import gnu.trove.THashMap
|
||||
import org.jdom.Element
|
||||
import org.jdom.JDOMException
|
||||
|
||||
import java.io.IOException
|
||||
|
||||
abstract class XmlElementStorage protected constructor(protected val fileSpec: String,
|
||||
protected val rootElementName: String,
|
||||
protected val pathMacroSubstitutor: TrackingPathMacroSubstitutor?,
|
||||
roamingType: RoamingType?,
|
||||
provider: StreamProvider?) : StateStorageBase<StorageData>() {
|
||||
protected val roamingType: RoamingType = roamingType ?: RoamingType.PER_USER
|
||||
private val provider: StreamProvider? = if (provider == null || roamingType == RoamingType.DISABLED || !provider.isApplicable(fileSpec, this.roamingType)) null else provider
|
||||
|
||||
protected abstract fun loadLocalData(): Element?
|
||||
|
||||
override fun getStateAndArchive(storageData: StorageData, component: Any, componentName: String) = storageData.getStateAndArchive(componentName)
|
||||
|
||||
override fun loadData(): StorageData {
|
||||
val storageData = createStorageData()
|
||||
val element: Element?
|
||||
// we don't use local data if has stream provider
|
||||
if (provider != null && provider.enabled) {
|
||||
try {
|
||||
element = loadDataFromProvider()
|
||||
if (element != null) {
|
||||
storageData.loadState(element)
|
||||
}
|
||||
}
|
||||
catch (e: Exception) {
|
||||
LOG.error(e)
|
||||
element = null
|
||||
}
|
||||
}
|
||||
else {
|
||||
element = loadLocalData()
|
||||
}
|
||||
|
||||
if (element != null) {
|
||||
storageData.loadState(element)
|
||||
}
|
||||
return storageData
|
||||
}
|
||||
|
||||
throws(IOException::class, JDOMException::class)
|
||||
private fun loadDataFromProvider() = JDOMUtil.load(provider!!.loadContent(fileSpec, roamingType))
|
||||
|
||||
private fun StorageData.loadState(element: Element) {
|
||||
load(element, pathMacroSubstitutor, true)
|
||||
}
|
||||
|
||||
protected open fun createStorageData(): StorageData = StorageData()
|
||||
|
||||
fun setDefaultState(element: Element) {
|
||||
element.setName(rootElementName)
|
||||
val storageData = createStorageData()
|
||||
storageData.loadState(element)
|
||||
storageDataRef.set(storageData)
|
||||
}
|
||||
|
||||
override fun startExternalization() = if (checkIsSavingDisabled()) null else createSaveSession(getStorageData())
|
||||
|
||||
protected abstract fun createSaveSession(storageData: StorageData): StateStorage.ExternalizationSession
|
||||
|
||||
override fun analyzeExternalChangesAndUpdateIfNeed(componentNames: MutableSet<String>) {
|
||||
val oldData = storageDataRef.get()
|
||||
val newData = getStorageData(true)
|
||||
if (oldData == null) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("analyzeExternalChangesAndUpdateIfNeed: old data null, load new for ${toString()}")
|
||||
}
|
||||
componentNames.addAll(newData.getComponentNames())
|
||||
}
|
||||
else {
|
||||
val changedComponentNames = oldData.getChangedComponentNames(newData, pathMacroSubstitutor)
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("analyzeExternalChangesAndUpdateIfNeed: changedComponentNames $changedComponentNames for ${toString()}")
|
||||
}
|
||||
if (!ContainerUtil.isEmpty(changedComponentNames)) {
|
||||
componentNames.addAll(changedComponentNames)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setStorageData(oldStorageData: StorageData, newStorageData: StorageData?) {
|
||||
if (oldStorageData !== newStorageData && storageDataRef.getAndSet(newStorageData) !== oldStorageData) {
|
||||
LOG.warn("Old storage data is not equal to current, new storage data was set anyway")
|
||||
}
|
||||
}
|
||||
|
||||
abstract class XmlElementStorageSaveSession<T : XmlElementStorage>(private val originalStorageData: StorageData, protected val storage: T) : SaveSessionBase() {
|
||||
private var copiedStorageData: StorageData? = null
|
||||
|
||||
private val newLiveStates = THashMap<String, Element>()
|
||||
|
||||
override fun createSaveSession() = if (storage.checkIsSavingDisabled() || (copiedStorageData == null && !originalStorageData.isDirty())) null else this
|
||||
|
||||
override fun setSerializedState(component: Any, componentName: String, element: Element?) {
|
||||
if (copiedStorageData == null) {
|
||||
copiedStorageData = StorageData.setStateAndCloneIfNeed(componentName, element, originalStorageData, newLiveStates)
|
||||
}
|
||||
else {
|
||||
copiedStorageData!!.setState(componentName, element, newLiveStates)
|
||||
}
|
||||
}
|
||||
|
||||
override fun save() {
|
||||
var storageData = copiedStorageData
|
||||
if (storageData == null) {
|
||||
storageData = originalStorageData
|
||||
if (!storageData.isDirty()) {
|
||||
LOG.warn("Copied storage data must be not null because original storage data is not dirty")
|
||||
}
|
||||
}
|
||||
|
||||
var element = storageData.save(newLiveStates, storage.rootElementName)
|
||||
if (element == null || JDOMUtil.isEmpty(element)) {
|
||||
element = null
|
||||
}
|
||||
else if (storage.pathMacroSubstitutor != null) {
|
||||
try {
|
||||
storage.pathMacroSubstitutor.collapsePaths(element)
|
||||
}
|
||||
finally {
|
||||
storage.pathMacroSubstitutor.reset()
|
||||
}
|
||||
}
|
||||
|
||||
val provider = storage.provider
|
||||
if (provider != null && provider.enabled) {
|
||||
if (element == null) {
|
||||
provider.delete(storage.fileSpec, storage.roamingType)
|
||||
}
|
||||
else {
|
||||
// we should use standard line-separator (\n) - stream provider can share file content on any OS
|
||||
val content = StorageUtil.writeToBytes(element, "\n")
|
||||
provider.saveContent(storage.fileSpec, content.getInternalBuffer(), content.size(), storage.roamingType)
|
||||
}
|
||||
}
|
||||
else {
|
||||
saveLocally(element)
|
||||
}
|
||||
storage.setStorageData(originalStorageData, storageData)
|
||||
}
|
||||
|
||||
throws(IOException::class)
|
||||
protected abstract fun saveLocally(element: Element?)
|
||||
}
|
||||
|
||||
public fun updatedFromStreamProvider(changedComponentNames: MutableSet<String>, deleted: Boolean) {
|
||||
if (roamingType == RoamingType.DISABLED) {
|
||||
// storage roaming was changed to DISABLED, but settings repository has old state
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
val newElement = if (deleted) null else loadDataFromProvider()
|
||||
val storageData = storageDataRef.get()
|
||||
if (newElement == null) {
|
||||
// if data was loaded, mark as changed all loaded components
|
||||
if (storageData != null) {
|
||||
changedComponentNames.addAll(storageData.getComponentNames())
|
||||
setStorageData(storageData, null)
|
||||
}
|
||||
}
|
||||
else if (storageData != null) {
|
||||
val newStorageData = createStorageData()
|
||||
newStorageData.loadState(newElement)
|
||||
changedComponentNames.addAll(storageData.getChangedComponentNames(newStorageData, pathMacroSubstitutor))
|
||||
setStorageData(storageData, newStorageData)
|
||||
}
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
LOG.error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,8 +9,6 @@ import java.io.FileInputStream
|
||||
import java.io.InputStream
|
||||
|
||||
class MockStreamProvider(private val myBaseDir: File) : StreamProvider {
|
||||
override fun isApplicable(fileSpec: String, roamingType: RoamingType) = roamingType === RoamingType.PER_USER
|
||||
|
||||
override fun saveContent(fileSpec: String, content: ByteArray, size: Int, roamingType: RoamingType) {
|
||||
FileUtil.writeToFile(File(myBaseDir, fileSpec), content, 0, size)
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import com.intellij.openapi.application.invokeAndWaitIfNeed
|
||||
import com.intellij.openapi.application.runWriteAction
|
||||
import com.intellij.openapi.components.RoamingType
|
||||
import com.intellij.openapi.components.StoragePathMacros
|
||||
import com.intellij.openapi.components.impl.stores.FileBasedStorage
|
||||
import com.intellij.openapi.components.impl.stores.StoreUtil
|
||||
import com.intellij.openapi.components.stateStore
|
||||
import com.intellij.openapi.module.ModifiableModuleModel
|
||||
|
||||
+9
-18
@@ -13,15 +13,13 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.components.impl;
|
||||
package com.intellij.configurationStore;
|
||||
|
||||
import com.intellij.openapi.components.PersistentStateComponent;
|
||||
import com.intellij.openapi.components.State;
|
||||
import com.intellij.openapi.components.Storage;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ex.ProjectManagerEx;
|
||||
import com.intellij.openapi.util.JDOMBuilder;
|
||||
import com.intellij.openapi.util.JDOMUtil;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.testFramework.PlatformTestCase;
|
||||
|
||||
@@ -35,23 +33,16 @@ public abstract class ProjectStoreBaseTestCase extends PlatformTestCase {
|
||||
}
|
||||
|
||||
protected byte[] getIprFileContent() throws UnsupportedEncodingException {
|
||||
final String iprContent = JDOMUtil.writeDocument(
|
||||
JDOMBuilder.document(JDOMBuilder.tag("project",
|
||||
JDOMBuilder.attr("version", "4"),
|
||||
JDOMBuilder.tag("component", JDOMBuilder.attr("name", "TestIprComponent"),
|
||||
JDOMBuilder.tag("option", JDOMBuilder.attr("name", "VALUE"), JDOMBuilder.attr("value", "true")))
|
||||
)),
|
||||
"\n");
|
||||
return iprContent.getBytes(CharsetToolkit.UTF8);
|
||||
return ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
|
||||
"<project version=\"4\">" +
|
||||
" <component name=\"TestComponent\">" +
|
||||
" <option name=\"VALUE\" value=\"true\"/>" +
|
||||
" </component>" +
|
||||
"</project>").getBytes(CharsetToolkit.UTF8);
|
||||
}
|
||||
|
||||
@State(
|
||||
name = "TestIprComponent",
|
||||
storages = {
|
||||
@Storage(file = "$PROJECT_FILE$")
|
||||
}
|
||||
)
|
||||
public static class TestIprComponent implements PersistentStateComponent<DataBean> {
|
||||
@State(name = "TestComponent", storages = @Storage(file = "$PROJECT_FILE$"))
|
||||
public static class TestComponent implements PersistentStateComponent<DataBean> {
|
||||
ProjectStoreBaseTestCase.DataBean myState;
|
||||
|
||||
@Override
|
||||
+5
-5
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.components.impl;
|
||||
package com.intellij.configurationStore;
|
||||
|
||||
import com.intellij.openapi.components.ComponentsPackage;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -26,7 +26,7 @@ import java.io.IOException;
|
||||
public class ProjectStoreImplIdeaDirTest extends ProjectStoreBaseTestCase {
|
||||
@Override
|
||||
protected File getIprFile() throws IOException {
|
||||
final File projectDir = FileUtil.createTempDirectory(getTestName(true), "project");
|
||||
File projectDir = FileUtil.createTempDirectory(getTestName(true), "project");
|
||||
File ideaDir = new File(projectDir, Project.DIRECTORY_STORE_FOLDER);
|
||||
assertTrue(ideaDir.mkdir() || ideaDir.isDirectory());
|
||||
File iprFile = new File(ideaDir, "misc.xml");
|
||||
@@ -39,8 +39,8 @@ public class ProjectStoreImplIdeaDirTest extends ProjectStoreBaseTestCase {
|
||||
public void testLoadFromDirectoryStorage() throws Exception {
|
||||
((ProjectEx)myProject).setOptimiseTestLoadSpeed(false);
|
||||
|
||||
final TestIprComponent testIprComponent = new TestIprComponent();
|
||||
ComponentsPackage.getStateStore(myProject).initComponent(testIprComponent, false);
|
||||
assertNotNull(testIprComponent.myState);
|
||||
TestComponent testComponent = new TestComponent();
|
||||
ComponentsPackage.getStateStore(myProject).initComponent(testComponent, false);
|
||||
assertNotNull(testComponent.myState);
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.components.impl;
|
||||
package com.intellij.configurationStore;
|
||||
|
||||
import com.intellij.openapi.components.ComponentsPackage;
|
||||
import com.intellij.openapi.project.ex.ProjectEx;
|
||||
@@ -34,8 +34,8 @@ public class ProjectStoreImplIprFileTest extends ProjectStoreBaseTestCase {
|
||||
|
||||
((ProjectEx)myProject).setOptimiseTestLoadSpeed(false);
|
||||
|
||||
final TestIprComponent testIprComponent = new TestIprComponent();
|
||||
ComponentsPackage.getStateStore(myProject).initComponent(testIprComponent, false);
|
||||
assertNotNull(testIprComponent.myState);
|
||||
final TestComponent testComponent = new TestComponent();
|
||||
ComponentsPackage.getStateStore(myProject).initComponent(testComponent, false);
|
||||
assertNotNull(testComponent.myState);
|
||||
}
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.configurationStore
|
||||
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.components.impl.stores.StorageData
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.util.JDOMBuilder.attr
|
||||
import com.intellij.openapi.util.JDOMBuilder.tag
|
||||
import com.intellij.testFramework.LightPlatformTestCase
|
||||
import junit.framework.TestCase
|
||||
import org.jdom.Element
|
||||
|
||||
class XmlElementStorageTest : LightPlatformTestCase() {
|
||||
public fun testGetStateSucceeded() {
|
||||
val storage = MyXmlElementStorage(tag("root", tag("component", attr("name", "test"), tag("foo"))))
|
||||
val state = storage.getState(this, "test", javaClass<Element>(), null)
|
||||
TestCase.assertNotNull(state)
|
||||
TestCase.assertEquals("component", state.getName())
|
||||
TestCase.assertNotNull(state.getChild("foo"))
|
||||
}
|
||||
|
||||
public fun testGetStateNotSucceeded() {
|
||||
val storage = MyXmlElementStorage(tag("root"))
|
||||
val state = storage.getState(this, "test", javaClass<Element>(), null)
|
||||
TestCase.assertNull(state)
|
||||
}
|
||||
|
||||
public fun testSetStateOverridesOldState() {
|
||||
val storage = MyXmlElementStorage(tag("root", tag("component", attr("name", "test"), tag("foo"))))
|
||||
val newState = tag("component", attr("name", "test"), tag("bar"))
|
||||
val externalizationSession = storage.startExternalization()!!
|
||||
externalizationSession.setState(this, "test", newState, null)
|
||||
externalizationSession.createSaveSession()!!.save()
|
||||
TestCase.assertNotNull(storage.mySavedElement)
|
||||
TestCase.assertNotNull(storage.mySavedElement!!.getChild("component").getChild("bar"))
|
||||
TestCase.assertNull(storage.mySavedElement!!.getChild("component").getChild("foo"))
|
||||
}
|
||||
|
||||
|
||||
private class MyXmlElementStorage(private val myElement: Element) : XmlElementStorage("", "root", null, null, null) {
|
||||
var mySavedElement: Element? = null
|
||||
|
||||
override fun loadLocalData() = myElement
|
||||
|
||||
override fun createSaveSession(storageData: StorageData) = object : XmlElementStorage.XmlElementStorageSaveSession<MyXmlElementStorage>(storageData, this) {
|
||||
override fun saveLocally(element: Element?) {
|
||||
mySavedElement = element?.clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@ import java.util.LinkedList;
|
||||
/**
|
||||
* @author gregsh
|
||||
*/
|
||||
public class SyntaxTraverser<T> extends FilteredTraverserBase<T, SyntaxTraverser<T>> implements Iterable<T>, UserDataHolder {
|
||||
public class SyntaxTraverser<T> extends FilteredTraverserBase<T, SyntaxTraverser<T>> implements UserDataHolder {
|
||||
|
||||
@NotNull
|
||||
public static ApiEx<PsiElement> psiApi() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.core;
|
||||
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.impl.DocumentCommitProcessor;
|
||||
@@ -30,6 +31,9 @@ class MockDocumentCommitProcessor extends DocumentCommitProcessor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commitAsynchronously(@NotNull Project project, @NotNull Document document, @NonNls @NotNull Object reason) {
|
||||
public void commitAsynchronously(@NotNull Project project,
|
||||
@NotNull Document document,
|
||||
@NonNls @NotNull Object reason,
|
||||
@NotNull ModalityState currentModalityState) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1660,7 +1660,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
|
||||
|
||||
if (child instanceof StartMarker && ((StartMarker)child).myDoneMarker.myCollapse) {
|
||||
int lastIndex = ((StartMarker)child).myDoneMarker.myLexemeIndex;
|
||||
insertLeaf(child.getTokenType(), marker.myBuilder, child.myLexemeIndex, lastIndex);
|
||||
insertLeaf(child.getTokenType(), marker.myBuilder, child.myLexemeIndex, lastIndex, true);
|
||||
}
|
||||
else {
|
||||
ensureCapacity();
|
||||
@@ -1710,17 +1710,25 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
|
||||
private int insertLeaves(int curToken, int lastIdx, PsiBuilderImpl builder) {
|
||||
lastIdx = Math.min(lastIdx, builder.myLexemeCount);
|
||||
while (curToken < lastIdx) {
|
||||
insertLeaf(builder.myLexTypes[curToken], builder, curToken, curToken + 1);
|
||||
insertLeaf(builder.myLexTypes[curToken], builder, curToken, curToken + 1, false);
|
||||
|
||||
curToken++;
|
||||
}
|
||||
return curToken;
|
||||
}
|
||||
|
||||
private void insertLeaf(@NotNull IElementType type, @NotNull PsiBuilderImpl builder, int startLexemeIndex, int endLexemeIndex) {
|
||||
private void insertLeaf(@NotNull IElementType type,
|
||||
@NotNull PsiBuilderImpl builder,
|
||||
int startLexemeIndex,
|
||||
int endLexemeIndex,
|
||||
boolean forceInsertion) {
|
||||
final int start = builder.myLexStarts[startLexemeIndex];
|
||||
final int end = builder.myLexStarts[endLexemeIndex];
|
||||
if (start > end || start == end && !(type instanceof ILeafElementType)) return;
|
||||
/** Corresponding code for heavy tree is located in {@link com.intellij.lang.impl.PsiBuilderImpl#insertLeaves}
|
||||
* and is applied only to plain lexemes */
|
||||
if (start > end || !forceInsertion && start == end && !(type instanceof ILeafElementType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Token lexeme;
|
||||
if (type instanceof ILightLazyParseableElementType) {
|
||||
|
||||
@@ -804,6 +804,12 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
|
||||
return myText;
|
||||
}
|
||||
|
||||
// Breaks encapsulation, yet required for current zero-latency typing implementation.
|
||||
// TODO Should be removed when we implement typing without starting write actions.
|
||||
@NotNull
|
||||
public ImmutableText getImmutableText() {
|
||||
return myText;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDocumentListener(@NotNull DocumentListener listener) {
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.intellij.psi.impl;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.diagnostic.Attachment;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
@@ -51,28 +52,34 @@ public abstract class DocumentCommitProcessor {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.DocumentCommitThread");
|
||||
|
||||
public abstract void commitSynchronously(@NotNull Document document, @NotNull Project project);
|
||||
public abstract void commitAsynchronously(@NotNull final Project project, @NotNull final Document document, @NonNls @NotNull Object reason);
|
||||
public abstract void commitAsynchronously(@NotNull final Project project,
|
||||
@NotNull final Document document,
|
||||
@NonNls @NotNull Object reason,
|
||||
@NotNull ModalityState currentModalityState);
|
||||
|
||||
protected static class CommitTask {
|
||||
@NotNull public final Document document;
|
||||
@NotNull public final Project project;
|
||||
@NotNull final Document document;
|
||||
@NotNull final Project project;
|
||||
|
||||
// when queued it's not started
|
||||
// when dequeued it's started
|
||||
// when failed it's canceled
|
||||
@NotNull public final ProgressIndicator indicator; // progress to commit this doc under.
|
||||
@NotNull public final Object reason;
|
||||
@NotNull final ProgressIndicator indicator; // progress to commit this doc under.
|
||||
@NotNull final Object reason;
|
||||
@NotNull final ModalityState myCreationModalityState;
|
||||
private final CharSequence myLastCommittedText;
|
||||
public boolean removed; // task marked as removed, should be ignored.
|
||||
|
||||
public CommitTask(@NotNull Document document,
|
||||
@NotNull Project project,
|
||||
@NotNull ProgressIndicator indicator,
|
||||
@NotNull Object reason) {
|
||||
@NotNull Object reason,
|
||||
@NotNull ModalityState currentModalityState) {
|
||||
this.document = document;
|
||||
this.project = project;
|
||||
this.indicator = indicator;
|
||||
this.reason = reason;
|
||||
myCreationModalityState = currentModalityState;
|
||||
myLastCommittedText = PsiDocumentManager.getInstance(project).getLastCommittedText(document);
|
||||
}
|
||||
|
||||
|
||||
@@ -157,24 +157,30 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commitAsynchronously(@NotNull final Project project, @NotNull final Document document, @NonNls @NotNull Object reason) {
|
||||
queueCommit(project, document, reason);
|
||||
public void commitAsynchronously(@NotNull final Project project,
|
||||
@NotNull final Document document,
|
||||
@NonNls @NotNull Object reason,
|
||||
@NotNull ModalityState currentModalityState) {
|
||||
queueCommit(project, document, reason, currentModalityState);
|
||||
}
|
||||
|
||||
void queueCommit(@NotNull final Project project, @NotNull final Document document, @NonNls @NotNull Object reason) {
|
||||
void queueCommit(@NotNull final Project project,
|
||||
@NotNull final Document document,
|
||||
@NonNls @NotNull Object reason,
|
||||
@NotNull ModalityState currentModalityState) {
|
||||
assert !isDisposed : "already disposed";
|
||||
|
||||
if (!project.isInitialized()) return;
|
||||
PsiFile psiFile = PsiDocumentManager.getInstance(project).getCachedPsiFile(document);
|
||||
if (psiFile == null) return;
|
||||
|
||||
doQueue(project, document, reason);
|
||||
doQueue(project, document, reason, currentModalityState);
|
||||
}
|
||||
|
||||
private void doQueue(@NotNull Project project, @NotNull Document document, @NotNull Object reason) {
|
||||
private void doQueue(@NotNull Project project, @NotNull Document document, @NotNull Object reason, @NotNull ModalityState currentModalityState) {
|
||||
synchronized (documentsToCommit) {
|
||||
ProgressIndicator indicator = createProgressIndicator();
|
||||
CommitTask newTask = new CommitTask(document, project, indicator, reason);
|
||||
CommitTask newTask = new CommitTask(document, project, indicator, reason, currentModalityState);
|
||||
|
||||
markRemovedFromDocsToCommit(newTask);
|
||||
markRemovedCurrentTask(newTask);
|
||||
@@ -358,7 +364,7 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
|
||||
|
||||
if (success) {
|
||||
assert !myApplication.isDispatchThread();
|
||||
myApplication.invokeLater(finishRunnable, ModalityState.NON_MODAL);
|
||||
myApplication.invokeLater(finishRunnable, task.myCreationModalityState);
|
||||
log("Invoked later finishRunnable", task, false, finishRunnable, indicator);
|
||||
}
|
||||
}
|
||||
@@ -379,7 +385,7 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
|
||||
synchronized (documentsToCommit) {
|
||||
if (!success && !task.removed) { // sync commit has not intervened
|
||||
// reset status for queue back successfully
|
||||
doQueue(project, document, "re-added on failure");
|
||||
doQueue(project, document, "re-added on failure", task.myCreationModalityState);
|
||||
}
|
||||
currentTask = null; // do not cancel, it's being invokeLatered
|
||||
}
|
||||
@@ -402,7 +408,7 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
|
||||
}
|
||||
|
||||
ProgressIndicator indicator = createProgressIndicator();
|
||||
CommitTask task = new CommitTask(document, project, indicator, "Sync commit");
|
||||
CommitTask task = new CommitTask(document, project, indicator, "Sync commit", ModalityState.any());
|
||||
synchronized (documentsToCommit) {
|
||||
markRemovedFromDocsToCommit(task);
|
||||
markRemovedCurrentTask(task);
|
||||
@@ -529,7 +535,7 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
|
||||
}
|
||||
if (!success) {
|
||||
// add document back to the queue
|
||||
queueCommit(project, document, "Re-added back");
|
||||
queueCommit(project, document, "Re-added back", task.myCreationModalityState);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -42,7 +42,6 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.smartPointers.SmartPointerManagerImpl;
|
||||
import com.intellij.psi.impl.source.PsiFileImpl;
|
||||
import com.intellij.psi.impl.source.text.BlockSupportImpl;
|
||||
import com.intellij.psi.text.BlockSupport;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.util.*;
|
||||
@@ -716,7 +715,7 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
|
||||
commitDocument(document);
|
||||
}
|
||||
else if (!((DocumentEx)document).isInBulkUpdate() && myPerformBackgroundCommit) {
|
||||
myDocumentCommitProcessor.commitAsynchronously(myProject, document, event);
|
||||
myDocumentCommitProcessor.commitAsynchronously(myProject, document, event, ApplicationManager.getApplication().getCurrentModalityState());
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -374,6 +374,10 @@ public class PsiManagerImpl extends PsiManagerEx {
|
||||
myTreeChangePreprocessors.add(preprocessor);
|
||||
}
|
||||
|
||||
public void removeTreeChangePreprocessor(@NotNull PsiTreeChangePreprocessor preprocessor) {
|
||||
myTreeChangePreprocessors.remove(preprocessor);
|
||||
}
|
||||
|
||||
private void fireEvent(@NotNull PsiTreeChangeEventImpl event) {
|
||||
boolean isRealTreeChange = event.getCode() != PsiTreeChangeEventImpl.PsiEventType.PROPERTY_CHANGED
|
||||
&& event.getCode() != PsiTreeChangeEventImpl.PsiEventType.BEFORE_PROPERTY_CHANGE;
|
||||
|
||||
@@ -77,7 +77,8 @@ public class PsiModificationTrackerImpl implements PsiModificationTracker, PsiTr
|
||||
@Override
|
||||
public void treeChanged(@NotNull PsiTreeChangeEventImpl event) {
|
||||
myModificationCount.getAndIncrement();
|
||||
if (event.getParent() instanceof PsiDirectory) {
|
||||
if (event.getParent() instanceof PsiDirectory
|
||||
|| event.getOldParent() instanceof PsiDirectory /* move events */) {
|
||||
myOutOfCodeBlockModificationCount.getAndIncrement();
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ package com.intellij.psi.impl.smartPointers;
|
||||
import com.intellij.lang.LanguageUtil;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.psi.PsiAnchor;
|
||||
import com.intellij.psi.PsiElement;
|
||||
@@ -110,11 +109,11 @@ class AnchorElementInfo extends SelfElementInfo {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fastenBelt(int offset, RangeMarker[] cachedRangeMarker) {
|
||||
public void fastenBelt() {
|
||||
if (getStubId() != -1) {
|
||||
switchToTree();
|
||||
}
|
||||
super.fastenBelt(offset, cachedRangeMarker);
|
||||
super.fastenBelt();
|
||||
}
|
||||
|
||||
private void switchToTree() {
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package com.intellij.psi.impl.smartPointers;
|
||||
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Segment;
|
||||
@@ -29,28 +27,13 @@ import org.jetbrains.annotations.NotNull;
|
||||
/**
|
||||
* User: cdr
|
||||
*/
|
||||
public class ClsElementInfo implements SmartPointerElementInfo {
|
||||
public class ClsElementInfo extends SmartPointerElementInfo {
|
||||
private final PsiAnchor.StubIndexReference myStubIndexReference;
|
||||
|
||||
public ClsElementInfo(@NotNull PsiAnchor.StubIndexReference stubReference) {
|
||||
myStubIndexReference = stubReference;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Document getDocumentToSynchronize() {
|
||||
return null;
|
||||
}
|
||||
|
||||
// before change
|
||||
@Override
|
||||
public void fastenBelt(int offset, RangeMarker[] cachedRangeMarker) {
|
||||
}
|
||||
|
||||
// after change
|
||||
@Override
|
||||
public void unfastenBelt(int offset) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement restoreElement() {
|
||||
return myStubIndexReference.retrieve();
|
||||
@@ -85,11 +68,6 @@ public class ClsElementInfo implements SmartPointerElementInfo {
|
||||
return myStubIndexReference.getProject();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiFile restoreFile() {
|
||||
return myStubIndexReference.getFile();
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
package com.intellij.psi.impl.smartPointers;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Segment;
|
||||
@@ -30,7 +28,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
/**
|
||||
* User: cdr
|
||||
*/
|
||||
class FileElementInfo implements SmartPointerElementInfo {
|
||||
class FileElementInfo extends SmartPointerElementInfo {
|
||||
protected final VirtualFile myVirtualFile;
|
||||
protected final Project myProject;
|
||||
protected final Language myLanguage;
|
||||
@@ -48,19 +46,6 @@ class FileElementInfo implements SmartPointerElementInfo {
|
||||
myLanguage = lang;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Document getDocumentToSynchronize() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fastenBelt(int offset, RangeMarker[] cachedRangeMarker) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unfastenBelt(int offset) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement restoreElement() {
|
||||
return SelfElementInfo.restoreFileFromVirtual(myVirtualFile, myProject, myLanguage);
|
||||
@@ -105,8 +90,4 @@ class FileElementInfo implements SmartPointerElementInfo {
|
||||
return myProject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package com.intellij.psi.impl.smartPointers;
|
||||
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Segment;
|
||||
@@ -29,7 +27,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
/**
|
||||
* User: cdr
|
||||
*/
|
||||
class HardElementInfo implements SmartPointerElementInfo {
|
||||
class HardElementInfo extends SmartPointerElementInfo {
|
||||
@NotNull
|
||||
private final PsiElement myElement;
|
||||
@NotNull
|
||||
@@ -40,19 +38,6 @@ class HardElementInfo implements SmartPointerElementInfo {
|
||||
myProject = project;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Document getDocumentToSynchronize() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fastenBelt(int offset, RangeMarker[] cachedRangeMarker) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unfastenBelt(int offset) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement restoreElement() {
|
||||
return myElement;
|
||||
@@ -89,8 +74,4 @@ class HardElementInfo implements SmartPointerElementInfo {
|
||||
return myProject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+1
-12
@@ -20,7 +20,6 @@ import com.intellij.injected.editor.VirtualFileWindow;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.lang.injection.InjectedLanguageManager;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.ProperTextRange;
|
||||
@@ -39,7 +38,7 @@ import java.util.List;
|
||||
/**
|
||||
* User: cdr
|
||||
*/
|
||||
class InjectedSelfElementInfo implements SmartPointerElementInfo {
|
||||
class InjectedSelfElementInfo extends SmartPointerElementInfo {
|
||||
private final SmartPsiFileRange myInjectedFileRangeInHostFile;
|
||||
private final Class<? extends PsiElement> anchorClass;
|
||||
private final Language anchorLanguage;
|
||||
@@ -193,16 +192,6 @@ class InjectedSelfElementInfo implements SmartPointerElementInfo {
|
||||
return ((SmartPsiElementPointerImpl)myHostContext).getElementInfo().getDocumentToSynchronize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fastenBelt(int offset, RangeMarker[] cachedRangeMarkers) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unfastenBelt(int offset) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int elementHashCode() {
|
||||
return ((SmartPsiElementPointerImpl)myHostContext).getElementInfo().elementHashCode();
|
||||
|
||||
@@ -18,7 +18,6 @@ package com.intellij.psi.impl.smartPointers;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.editor.event.DocumentEvent;
|
||||
import com.intellij.openapi.editor.impl.FrozenDocument;
|
||||
import com.intellij.openapi.editor.impl.ManualRangeMarker;
|
||||
@@ -38,7 +37,7 @@ import java.util.Set;
|
||||
/**
|
||||
* User: cdr
|
||||
*/
|
||||
public class SelfElementInfo implements SmartPointerElementInfo {
|
||||
public class SelfElementInfo extends SmartPointerElementInfo {
|
||||
private final VirtualFile myVirtualFile;
|
||||
private final Class myType;
|
||||
private final Project myProject;
|
||||
@@ -81,7 +80,7 @@ public class SelfElementInfo implements SmartPointerElementInfo {
|
||||
|
||||
// before change
|
||||
@Override
|
||||
public void fastenBelt(int offset, @Nullable RangeMarker[] cachedRangeMarkers) {
|
||||
public void fastenBelt() {
|
||||
if (myRangeMarker != null) return; // already tracks changes
|
||||
if (myPsiRange == null) return; // invalid
|
||||
|
||||
@@ -96,11 +95,6 @@ public class SelfElementInfo implements SmartPointerElementInfo {
|
||||
setRange(myPsiRange, document);
|
||||
}
|
||||
|
||||
// after change
|
||||
@Override
|
||||
public void unfastenBelt(int offset) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement restoreElement() {
|
||||
Segment segment = getPsiRange();
|
||||
|
||||
+16
-14
@@ -17,7 +17,6 @@
|
||||
package com.intellij.psi.impl.smartPointers;
|
||||
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Segment;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
@@ -26,27 +25,30 @@ import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
interface SmartPointerElementInfo {
|
||||
abstract class SmartPointerElementInfo {
|
||||
@Nullable
|
||||
Document getDocumentToSynchronize();
|
||||
public Document getDocumentToSynchronize() {
|
||||
return null;
|
||||
}
|
||||
|
||||
void fastenBelt(int offset, @Nullable RangeMarker[] cachedRangeMarkers);
|
||||
|
||||
void unfastenBelt(int offset);
|
||||
public void fastenBelt() {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
PsiElement restoreElement();
|
||||
public abstract PsiElement restoreElement();
|
||||
|
||||
PsiFile restoreFile();
|
||||
public abstract PsiFile restoreFile();
|
||||
|
||||
int elementHashCode(); // must be immutable
|
||||
boolean pointsToTheSameElementAs(@NotNull SmartPointerElementInfo other);
|
||||
public abstract int elementHashCode(); // must be immutable
|
||||
public abstract boolean pointsToTheSameElementAs(@NotNull SmartPointerElementInfo other);
|
||||
|
||||
VirtualFile getVirtualFile();
|
||||
public abstract VirtualFile getVirtualFile();
|
||||
|
||||
@Nullable
|
||||
Segment getRange();
|
||||
@NotNull Project getProject();
|
||||
public abstract Segment getRange();
|
||||
@NotNull
|
||||
public abstract Project getProject();
|
||||
|
||||
void cleanup();
|
||||
public void cleanup() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,15 +15,13 @@
|
||||
*/
|
||||
package com.intellij.psi.impl.smartPointers;
|
||||
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.SmartPsiElementPointer;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
interface SmartPointerEx<E extends PsiElement> extends SmartPsiElementPointer<E> {
|
||||
void fastenBelt(int offset, @Nullable RangeMarker[] cachedRangeMarkers);
|
||||
|
||||
void unfastenBelt(int offset);
|
||||
void fastenBelt();
|
||||
|
||||
@Nullable
|
||||
PsiElement getCachedElement();
|
||||
}
|
||||
|
||||
+2
-54
@@ -16,12 +16,9 @@
|
||||
|
||||
package com.intellij.psi.impl.smartPointers;
|
||||
|
||||
import com.intellij.injected.editor.DocumentWindow;
|
||||
import com.intellij.lang.injection.InjectedLanguageManager;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.editor.event.DocumentEvent;
|
||||
import com.intellij.openapi.editor.impl.FrozenDocument;
|
||||
import com.intellij.openapi.editor.impl.ManualRangeMarker;
|
||||
@@ -34,7 +31,6 @@ import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiDocumentManagerBase;
|
||||
import com.intellij.psi.impl.PsiManagerEx;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.reference.SoftReference;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
@@ -65,12 +61,10 @@ public class SmartPointerManagerImpl extends SmartPointerManager {
|
||||
|
||||
private final Project myProject;
|
||||
private final Key<FilePointersList> POINTERS_KEY;
|
||||
private final Key<Boolean> POINTERS_ARE_FASTENED_KEY;
|
||||
|
||||
public SmartPointerManagerImpl(Project project) {
|
||||
myProject = project;
|
||||
POINTERS_KEY = Key.create("SMART_POINTERS for "+project);
|
||||
POINTERS_ARE_FASTENED_KEY = Key.create("SMART_POINTERS_ARE_FASTENED for "+project);
|
||||
}
|
||||
|
||||
private static void processQueue() {
|
||||
@@ -89,50 +83,22 @@ public class SmartPointerManagerImpl extends SmartPointerManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void fastenBelts(@NotNull VirtualFile file, int offset, @Nullable RangeMarker[] cachedRangeMarkers) {
|
||||
public void fastenBelts(@NotNull VirtualFile file) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
processQueue();
|
||||
synchronized (lock) {
|
||||
if (getAndFasten(file)) return;
|
||||
FilePointersList pointers = getPointers(file);
|
||||
if (pointers != null && !pointers.isEmpty()) {
|
||||
for (PointerReference ref : pointers.references) {
|
||||
SmartPointerEx pointer = SoftReference.dereference(ref);
|
||||
if (pointer != null) {
|
||||
pointer.fastenBelt(offset, cachedRangeMarkers);
|
||||
pointer.fastenBelt();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void unfastenBelts(@NotNull VirtualFile file, int offset) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
processQueue();
|
||||
synchronized (lock) {
|
||||
if (!getAndUnfasten(file)) return;
|
||||
FilePointersList pointers = getPointers(file);
|
||||
if (pointers != null && !pointers.isEmpty()) {
|
||||
for (PointerReference ref : pointers.references) {
|
||||
SmartPointerEx pointer = SoftReference.dereference(ref);
|
||||
if (pointer != null) {
|
||||
pointer.unfastenBelt(offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PsiFile psiFile = ((PsiManagerEx)PsiManager.getInstance(myProject)).getFileManager().getCachedPsiFile(file);
|
||||
if (psiFile != null) {
|
||||
PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(myProject);
|
||||
for (DocumentWindow injectedDoc : InjectedLanguageManager.getInstance(myProject).getCachedInjectedDocuments(psiFile)) {
|
||||
PsiFile injectedFile = psiDocumentManager.getPsiFile(injectedDoc);
|
||||
if (injectedFile == null) continue;
|
||||
unfastenBelts(injectedFile.getViewProvider().getVirtualFile(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final Key<Reference<SmartPointerEx>> CACHED_SMART_POINTER_KEY = Key.create("CACHED_SMART_POINTER_KEY");
|
||||
@Override
|
||||
@NotNull
|
||||
@@ -158,11 +124,7 @@ public class SmartPointerManagerImpl extends SmartPointerManager {
|
||||
element.putUserData(CACHED_SMART_POINTER_KEY, new SoftReference<SmartPointerEx>(pointer));
|
||||
}
|
||||
else {
|
||||
containingFile = containingFile == null ? element.getContainingFile() : containingFile;
|
||||
synchronized (lock) {
|
||||
if (containingFile != null && areBeltsFastened(containingFile.getViewProvider().getVirtualFile())) {
|
||||
pointer.fastenBelt(0, null);
|
||||
}
|
||||
if (pointer instanceof SmartPsiElementPointerImpl) {
|
||||
((SmartPsiElementPointerImpl)pointer).incrementAndGetReferenceCount(1);
|
||||
}
|
||||
@@ -273,20 +235,6 @@ public class SmartPointerManagerImpl extends SmartPointerManager {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean getAndFasten(@NotNull VirtualFile file) {
|
||||
boolean fastened = areBeltsFastened(file);
|
||||
file.putUserData(POINTERS_ARE_FASTENED_KEY, Boolean.TRUE);
|
||||
return fastened;
|
||||
}
|
||||
private boolean getAndUnfasten(@NotNull VirtualFile file) {
|
||||
boolean fastened = areBeltsFastened(file);
|
||||
file.putUserData(POINTERS_ARE_FASTENED_KEY, null);
|
||||
return fastened;
|
||||
}
|
||||
boolean areBeltsFastened(@NotNull VirtualFile file) {
|
||||
return file.getUserData(POINTERS_ARE_FASTENED_KEY) == Boolean.TRUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean pointToTheSameElement(@NotNull SmartPsiElementPointer pointer1, @NotNull SmartPsiElementPointer pointer2) {
|
||||
return SmartPsiElementPointerImpl.pointsToTheSameElementAs(pointer1, pointer2);
|
||||
|
||||
+2
-8
@@ -20,7 +20,6 @@ import com.intellij.lang.LanguageUtil;
|
||||
import com.intellij.lang.injection.InjectedLanguageManager;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
@@ -178,13 +177,8 @@ class SmartPsiElementPointerImpl<E extends PsiElement> implements SmartPointerEx
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unfastenBelt(int offset) {
|
||||
myElementInfo.unfastenBelt(offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fastenBelt(int offset, @Nullable RangeMarker[] cachedRangeMarkers) {
|
||||
myElementInfo.fastenBelt(offset, cachedRangeMarkers);
|
||||
public void fastenBelt() {
|
||||
myElementInfo.fastenBelt();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -56,7 +56,7 @@ public class DuplicatesIndex extends FileBasedIndexExtension<Integer, TIntArrayL
|
||||
private static boolean ourEnabledOldProfiles = false;
|
||||
|
||||
@NonNls public static final ID<Integer, TIntArrayList> NAME = ID.create("DuplicatesIndex");
|
||||
private static final int myBaseVersion = 20;
|
||||
private static final int myBaseVersion = 21;
|
||||
|
||||
private final FileBasedIndex.InputFilter myInputFilter = new FileBasedIndex.InputFilter() {
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.ide.ui;
|
||||
|
||||
/**
|
||||
* @author Sergey.Malenkov
|
||||
*/
|
||||
public enum ColorBlindness {
|
||||
/**
|
||||
* Lacking the long-wavelength sensitive retinal cones,
|
||||
* those with this condition are unable to distinguish
|
||||
* between colors in the green–yellow–red section of the spectrum.
|
||||
* Protanopes are more likely to confuse
|
||||
* <ul>
|
||||
* <li>black with many shades of red;</li>
|
||||
* <li>dark brown with dark green, dark orange and dark red;</li>
|
||||
* <li>some blues with some reds, purples and dark pinks;</li>
|
||||
* <li>mid-greens with some oranges.</li>
|
||||
* </ul>
|
||||
*/
|
||||
protanopia,
|
||||
/**
|
||||
* Lacking the medium-wavelength sensitive retinal cones,
|
||||
* those with this condition are unable to distinguish
|
||||
* between colors in the green–yellow–red section of the spectrum.
|
||||
* Deuteranopes are more likely to confuse
|
||||
* <ul>
|
||||
* <li>mid-reds with mid-greens;</li>
|
||||
* <li>blue-greens with grey and mid-pinks;</li>
|
||||
* <li>bright greens with yellows;</li>
|
||||
* <li>pale pinks with light grey;</li>
|
||||
* <li>mid-reds with mid-brown</li>
|
||||
* <li>light blues with lilac.</li>
|
||||
* </ul>
|
||||
*/
|
||||
deuteranopia,
|
||||
/**
|
||||
* Lacking the short-wavelength sensitive retinal cones,
|
||||
* those affected see short-wavelength colors (blue, indigo and a spectral violet)
|
||||
* greenish and drastically dimmed, some of these colors even as black.
|
||||
* Tritanopes are more likely to confuse
|
||||
* <ul>
|
||||
* <li>light blues with greys;</li>
|
||||
* <li>dark purples with black;</li>
|
||||
* <li>mid-greens with blues;</li>
|
||||
* <li>oranges with reds.</li>
|
||||
* </ul>
|
||||
*/
|
||||
tritanopia,
|
||||
/**
|
||||
* Total color blindness is defined as the inability to see color.
|
||||
*/
|
||||
achromatopsia
|
||||
}
|
||||
@@ -101,6 +101,7 @@ public class UISettings extends SimpleModificationTracker implements PersistentS
|
||||
public boolean ANTIALIASING_IN_EDITOR = true;
|
||||
public boolean ANTIALIASING_IN_IDE = ANTIALIASING_IN_EDITOR;
|
||||
public LCDRenderingScope LCD_RENDERING_SCOPE = UIUtil.isRetina() ? LCDRenderingScope.OFF : LCDRenderingScope.IDE;
|
||||
public ColorBlindness COLOR_BLINDNESS;
|
||||
public boolean USE_LCD_RENDERING_IN_EDITOR = true;
|
||||
public boolean MOVE_MOUSE_ON_DEFAULT_BUTTON = false;
|
||||
public boolean ENABLE_ALPHA_MODE = false;
|
||||
|
||||
+36
-2
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
package com.intellij.openapi.editor.colors.impl;
|
||||
|
||||
import com.intellij.ide.ui.ColorBlindness;
|
||||
import com.intellij.ide.ui.UISettings;
|
||||
import com.intellij.openapi.editor.HighlighterColors;
|
||||
import com.intellij.openapi.editor.colors.*;
|
||||
@@ -70,6 +71,10 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme {
|
||||
|
||||
// version influences XML format and triggers migration
|
||||
private int myVersion = CURR_VERSION;
|
||||
/**
|
||||
* The version from the original file.
|
||||
*/
|
||||
private int myOriginalVersion = CURR_VERSION;
|
||||
|
||||
protected Map<ColorKey, Color> myColorsMap = ContainerUtilRt.newHashMap();
|
||||
protected Map<TextAttributesKey, TextAttributes> myAttributesMap = ContainerUtilRt.newHashMap();
|
||||
@@ -267,8 +272,9 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme {
|
||||
}
|
||||
|
||||
public void readExternal(Element parentNode) {
|
||||
String blindness = Registry.stringValue("color.blindness"); // TODO: get blindness
|
||||
myValueReader.setAttribute(blindness);
|
||||
UISettings settings = UISettings.getInstance();
|
||||
ColorBlindness blindness = settings == null ? null : settings.COLOR_BLINDNESS;
|
||||
myValueReader.setAttribute(blindness == null ? null : blindness.name());
|
||||
if (SCHEME_ELEMENT.equals(parentNode.getName())) {
|
||||
readScheme(parentNode);
|
||||
}
|
||||
@@ -294,6 +300,7 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme {
|
||||
}
|
||||
|
||||
myVersion = readVersion;
|
||||
myOriginalVersion = readVersion;
|
||||
String isDefaultScheme = node.getAttributeValue(DEFAULT_SCHEME_ATTR);
|
||||
boolean isDefault = isDefaultScheme != null && Boolean.parseBoolean(isDefaultScheme);
|
||||
if (!isDefault) {
|
||||
@@ -357,6 +364,33 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The method is called for the scheme when it is fully loaded including additional text attributes from providers.
|
||||
*/
|
||||
public void upgradeSchemeFromPreviousVersion() {
|
||||
setUndefinedAttributesAsInheritedForVersion142();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Defines empty attributes with fallback (inheritance) enabled for all the attributes explicitly defined in the parent scheme since
|
||||
* previously undefined attributes were treated as inherited, not taken from the parent scheme.
|
||||
*/
|
||||
private void setUndefinedAttributesAsInheritedForVersion142() {
|
||||
if (myOriginalVersion >= 142 || myParentScheme == null) return;
|
||||
if (myParentScheme instanceof AbstractColorsScheme) {
|
||||
for (TextAttributesKey key : ((AbstractColorsScheme)myParentScheme).myAttributesMap.keySet()) {
|
||||
TextAttributes parentAttributes = ((AbstractColorsScheme)myParentScheme).getDirectlyDefinedAttributes(key);
|
||||
if (key.getFallbackAttributeKey() != null &&
|
||||
parentAttributes != null &&
|
||||
!parentAttributes.isFallbackEnabled() &&
|
||||
!myAttributesMap.containsKey(key)) {
|
||||
myAttributesMap.put(key, new TextAttributes());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@SuppressWarnings("unused")
|
||||
public static final Map<String, Color> DEFAULT_ERROR_STRIPE_COLOR = new THashMap<String, Color>();
|
||||
|
||||
+40
@@ -28,6 +28,7 @@ import com.intellij.openapi.editor.ex.PrioritizedDocumentListener;
|
||||
import com.intellij.openapi.editor.highlighter.EditorHighlighter;
|
||||
import com.intellij.openapi.editor.highlighter.HighlighterClient;
|
||||
import com.intellij.openapi.editor.highlighter.HighlighterIterator;
|
||||
import com.intellij.openapi.editor.impl.DocumentImpl;
|
||||
import com.intellij.openapi.editor.impl.EditorDocumentPriorities;
|
||||
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.fileTypes.PlainSyntaxHighlighter;
|
||||
@@ -37,6 +38,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.text.ImmutableText;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -351,6 +353,44 @@ public class LexerEditorHighlighter implements EditorHighlighter, PrioritizedDoc
|
||||
return attrs;
|
||||
}
|
||||
|
||||
// Called to determine visual attributes of inserted character prior to starting a write action.
|
||||
// TODO Should be removed when we implement typing without starting write actions.
|
||||
public TextAttributes getAttributes(DocumentImpl document, int offset, char c) {
|
||||
final int segmentIndex;
|
||||
try {
|
||||
segmentIndex = mySegments.findSegmentIndex(offset) - 2;
|
||||
}
|
||||
catch (IndexOutOfBoundsException ex) {
|
||||
throw new IndexOutOfBoundsException(ex.getMessage() + " Lexer: " + myLexer);
|
||||
}
|
||||
int startIndex = Math.max(0, segmentIndex);
|
||||
|
||||
int data;
|
||||
do {
|
||||
data = mySegments.getSegmentData(startIndex);
|
||||
if (isInitialState(data)|| startIndex == 0) break;
|
||||
startIndex--;
|
||||
}
|
||||
while (true);
|
||||
|
||||
int startOffset = mySegments.getSegmentStart(startIndex);
|
||||
|
||||
ImmutableText newText = document.getImmutableText().insert(offset, Character.toString(c));
|
||||
|
||||
myLexer.start(newText, startOffset, newText.length(), myInitialState);
|
||||
|
||||
IElementType tokenType = null;
|
||||
while (myLexer.getTokenType() != null) {
|
||||
if (myLexer.getTokenEnd() >= offset + 1) {
|
||||
tokenType = myLexer.getTokenType();
|
||||
break;
|
||||
}
|
||||
myLexer.advance();
|
||||
}
|
||||
|
||||
return getAttributes(tokenType);
|
||||
}
|
||||
|
||||
protected TextAttributes convertAttributes(@NotNull TextAttributesKey[] keys) {
|
||||
TextAttributes attrs = myScheme.getAttributes(HighlighterColors.TEXT);
|
||||
for (TextAttributesKey key : keys) {
|
||||
|
||||
@@ -25,7 +25,7 @@ import javax.swing.*;
|
||||
|
||||
/**
|
||||
* Describes a specific way of executing any possible run configuration. The three default executors provided by the IntelliJ Platform
|
||||
* by default are Run, Debug and (in IntelliJ IDEA Ultimate and certain platform-based IDEs) Run with Coverage. Each executor gets its
|
||||
* by default are Run, Debug and Run with Coverage. Each executor gets its
|
||||
* own toolbar button, which starts the selected run configuration using this executor, and its own context menu item for starting
|
||||
* a configuration using this executor.
|
||||
*
|
||||
|
||||
+1
-4
@@ -17,20 +17,16 @@ package com.intellij.psi.codeStyle;
|
||||
|
||||
import com.intellij.application.options.IndentOptionsEditor;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@@ -189,6 +185,7 @@ public abstract class LanguageCodeStyleSettingsProvider {
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public static DisplayPriority getDisplayPriority(Language language) {
|
||||
LanguageCodeStyleSettingsProvider langProvider = forLanguage(language);
|
||||
if (langProvider == null) return DisplayPriority.LANGUAGE_SETTINGS;
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/testSources" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" />
|
||||
</content>
|
||||
<orderEntry type="module" module-name="boot" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user