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
+1
@@ -64,6 +64,7 @@
|
||||
<module fileurl="file://$PROJECT_DIR$/java/debugger/openapi/debugger-openapi.iml" filepath="$PROJECT_DIR$/java/debugger/openapi/debugger-openapi.iml" group="java" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/devkit/devkit.iml" filepath="$PROJECT_DIR$/plugins/devkit/devkit.iml" group="plugins" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/devkit/jps-plugin/devkit-jps-plugin.iml" filepath="$PROJECT_DIR$/plugins/devkit/jps-plugin/devkit-jps-plugin.iml" group="plugins" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/devkit/devkit-tests.iml" filepath="$PROJECT_DIR$/plugins/devkit/devkit-tests.iml" group="community/plugins" />
|
||||
<module fileurl="file://$PROJECT_DIR$/platform/diff-api/diff-api.iml" filepath="$PROJECT_DIR$/platform/diff-api/diff-api.iml" group="platform" />
|
||||
<module fileurl="file://$PROJECT_DIR$/platform/diff-impl/diff-impl.iml" filepath="$PROJECT_DIR$/platform/diff-impl/diff-impl.iml" group="platform" />
|
||||
<module fileurl="file://$PROJECT_DIR$/platform/diff-impl/diff-tests.iml" filepath="$PROJECT_DIR$/platform/diff-impl/diff-tests.iml" group="platform" />
|
||||
|
||||
@@ -90,15 +90,18 @@ public abstract class BaseCompilerTestCase extends ModuleTestCase {
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
for (Artifact artifact : getArtifactManager().getArtifacts()) {
|
||||
final String outputPath = artifact.getOutputPath();
|
||||
if (!StringUtil.isEmpty(outputPath)) {
|
||||
FileUtil.delete(new File(FileUtil.toSystemDependentName(outputPath)));
|
||||
try {
|
||||
for (Artifact artifact : getArtifactManager().getArtifacts()) {
|
||||
final String outputPath = artifact.getOutputPath();
|
||||
if (!StringUtil.isEmpty(outputPath)) {
|
||||
FileUtil.delete(new File(FileUtil.toSystemDependentName(outputPath)));
|
||||
}
|
||||
}
|
||||
CompilerTestUtil.disableExternalCompiler(getProject());
|
||||
}
|
||||
finally {
|
||||
super.tearDown();
|
||||
}
|
||||
CompilerTestUtil.disableExternalCompiler(getProject());
|
||||
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
protected ArtifactManager getArtifactManager() {
|
||||
|
||||
@@ -0,0 +1,252 @@
|
||||
/*
|
||||
* 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.debugger.actions;
|
||||
|
||||
import com.intellij.debugger.DebuggerBundle;
|
||||
import com.intellij.debugger.engine.DebugProcessImpl;
|
||||
import com.intellij.debugger.engine.JavaStackFrame;
|
||||
import com.intellij.debugger.engine.JavaValue;
|
||||
import com.intellij.debugger.engine.evaluation.EvaluateException;
|
||||
import com.intellij.debugger.engine.events.DebuggerCommandImpl;
|
||||
import com.intellij.debugger.engine.events.DebuggerContextCommandImpl;
|
||||
import com.intellij.debugger.impl.DebuggerContextImpl;
|
||||
import com.intellij.debugger.jdi.StackFrameProxyImpl;
|
||||
import com.intellij.debugger.jdi.ThreadReferenceProxyImpl;
|
||||
import com.intellij.idea.ActionsBundle;
|
||||
import com.intellij.openapi.actionSystem.ActionPlaces;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.xdebugger.XDebuggerBundle;
|
||||
import com.intellij.xdebugger.XExpression;
|
||||
import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
|
||||
import com.intellij.xdebugger.evaluation.XDebuggerEvaluator;
|
||||
import com.intellij.xdebugger.frame.XValue;
|
||||
import com.intellij.xdebugger.impl.breakpoints.XExpressionImpl;
|
||||
import com.intellij.xdebugger.impl.ui.XDebuggerExpressionEditor;
|
||||
import com.sun.jdi.Method;
|
||||
import com.sun.jdi.Value;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class ForceEarlyReturnAction extends DebuggerAction {
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
final Project project = e.getProject();
|
||||
final JavaStackFrame stackFrame = PopFrameAction.getStackFrame(e);
|
||||
if (stackFrame == null || project == null) {
|
||||
return;
|
||||
}
|
||||
final DebuggerContextImpl debuggerContext = DebuggerAction.getDebuggerContext(e.getDataContext());
|
||||
final DebugProcessImpl debugProcess = debuggerContext.getDebugProcess();
|
||||
if (debugProcess == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final StackFrameProxyImpl proxy = stackFrame.getStackFrameProxy();
|
||||
final ThreadReferenceProxyImpl thread = proxy.threadProxy();
|
||||
|
||||
debugProcess.getManagerThread().schedule(new DebuggerContextCommandImpl(debuggerContext, thread) {
|
||||
@Override
|
||||
public void threadAction() {
|
||||
Method method;
|
||||
try {
|
||||
method = proxy.location().method();
|
||||
}
|
||||
catch (EvaluateException e) {
|
||||
showError(project, DebuggerBundle.message("error.early.return", e.getLocalizedMessage()));
|
||||
return;
|
||||
}
|
||||
|
||||
if ("void".equals(method.returnTypeName())) {
|
||||
forceEarlyReturnWithFinally(thread.getVirtualMachine().mirrorOfVoid(), stackFrame, debugProcess, null);
|
||||
}
|
||||
else {
|
||||
//noinspection SSBasedInspection
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
new ReturnExpressionDialog(project, debugProcess.getXdebugProcess().getEditorsProvider(), debugProcess, stackFrame).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void forceEarlyReturnWithFinally(final Value value,
|
||||
final JavaStackFrame frame,
|
||||
final DebugProcessImpl debugProcess,
|
||||
@Nullable final DialogWrapper dialog) {
|
||||
//noinspection SSBasedInspection
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (PopFrameAction.evaluateFinallyBlocks(debugProcess.getProject(),
|
||||
UIUtil.removeMnemonic(ActionsBundle.actionText("Debugger.ForceEarlyReturn")),
|
||||
frame,
|
||||
new XDebuggerEvaluator.XEvaluationCallback() {
|
||||
@Override
|
||||
public void evaluated(@NotNull XValue result) {
|
||||
forceEarlyReturn(value, frame.getDescriptor().getFrameProxy().threadProxy(), debugProcess, dialog);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void errorOccurred(@NotNull String errorMessage) {
|
||||
showError(debugProcess.getProject(),
|
||||
DebuggerBundle.message("error.executing.finally", errorMessage));
|
||||
}
|
||||
})) {
|
||||
return;
|
||||
}
|
||||
forceEarlyReturn(value, frame.getDescriptor().getFrameProxy().threadProxy(), debugProcess, dialog);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void forceEarlyReturn(final Value value,
|
||||
final ThreadReferenceProxyImpl thread,
|
||||
final DebugProcessImpl debugProcess,
|
||||
@Nullable final DialogWrapper dialog) {
|
||||
debugProcess.getManagerThread().schedule(new DebuggerCommandImpl() {
|
||||
@Override
|
||||
protected void action() throws Exception {
|
||||
try {
|
||||
thread.forceEarlyReturn(value);
|
||||
}
|
||||
catch (Exception e) {
|
||||
showError(debugProcess.getProject(), DebuggerBundle.message("error.early.return", e.getLocalizedMessage()));
|
||||
return;
|
||||
}
|
||||
//noinspection SSBasedInspection
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (dialog != null) {
|
||||
dialog.close(DialogWrapper.OK_EXIT_CODE);
|
||||
}
|
||||
debugProcess.getSession().stepInto(true, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void evaluateAndReturn(final Project project,
|
||||
final JavaStackFrame stackFrame,
|
||||
final DebugProcessImpl debugProcess,
|
||||
XExpression expression,
|
||||
final DialogWrapper dialog) {
|
||||
XDebuggerEvaluator evaluator = stackFrame.getEvaluator();
|
||||
if (evaluator != null) {
|
||||
evaluator.evaluate(expression,
|
||||
new XDebuggerEvaluator.XEvaluationCallback() {
|
||||
@Override
|
||||
public void evaluated(@NotNull XValue result) {
|
||||
if (result instanceof JavaValue) {
|
||||
forceEarlyReturnWithFinally(((JavaValue)result).getDescriptor().getValue(),
|
||||
stackFrame,
|
||||
debugProcess,
|
||||
dialog);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void errorOccurred(@NotNull final String errorMessage) {
|
||||
showError(project, DebuggerBundle.message("error.unable.to.evaluate.expression") + ": " + errorMessage);
|
||||
}
|
||||
}, stackFrame.getSourcePosition());
|
||||
}
|
||||
else {
|
||||
showError(project, XDebuggerBundle.message("xdebugger.evaluate.stack.frame.has.not.evaluator"));
|
||||
}
|
||||
}
|
||||
|
||||
private static void showError(final Project project, final String message) {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Messages.showMessageDialog(project,
|
||||
message,
|
||||
UIUtil.removeMnemonic(ActionsBundle.actionText("Debugger.ForceEarlyReturn")),
|
||||
Messages.getErrorIcon());
|
||||
}
|
||||
}, ModalityState.any());
|
||||
}
|
||||
|
||||
public void update(@NotNull AnActionEvent e) {
|
||||
boolean enable = false;
|
||||
|
||||
JavaStackFrame stackFrame = PopFrameAction.getStackFrame(e);
|
||||
if (stackFrame != null && stackFrame.getDescriptor().getUiIndex() == 0) {
|
||||
enable = stackFrame.getStackFrameProxy().getVirtualMachine().canForceEarlyReturn();
|
||||
}
|
||||
|
||||
if (ActionPlaces.isMainMenuOrActionSearch(e.getPlace()) || ActionPlaces.DEBUGGER_TOOLBAR.equals(e.getPlace())) {
|
||||
e.getPresentation().setEnabled(enable);
|
||||
}
|
||||
else {
|
||||
e.getPresentation().setVisible(enable);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ReturnExpressionDialog extends DialogWrapper {
|
||||
private final Project myProject;
|
||||
private final XDebuggerEditorsProvider myEditorsProvider;
|
||||
private final DebugProcessImpl myProcess;
|
||||
private final JavaStackFrame myFrame;
|
||||
private final XDebuggerExpressionEditor myEditor;
|
||||
|
||||
public ReturnExpressionDialog(@NotNull Project project,
|
||||
XDebuggerEditorsProvider provider,
|
||||
DebugProcessImpl process,
|
||||
JavaStackFrame frame) {
|
||||
super(project);
|
||||
myProject = project;
|
||||
myEditorsProvider = provider;
|
||||
myProcess = process;
|
||||
myFrame = frame;
|
||||
myEditor = new XDebuggerExpressionEditor(myProject, myEditorsProvider, "forceReturnValue", myFrame.getSourcePosition(),
|
||||
XExpressionImpl.EMPTY_EXPRESSION, false);
|
||||
|
||||
setTitle("Return Value");
|
||||
init();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected JComponent createCenterPanel() {
|
||||
return myEditor.getComponent();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JComponent getPreferredFocusedComponent() {
|
||||
return myEditor.getPreferredFocusedComponent();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doOKAction() {
|
||||
evaluateAndReturn(myProject, myFrame, myProcess, myEditor.getExpression(), this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -70,7 +70,7 @@ public class PopFrameAction extends DebuggerAction {
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
final Project project = e.getData(CommonDataKeys.PROJECT);
|
||||
final JavaStackFrame stackFrame = getStackFrame(e);
|
||||
if(stackFrame == null) {
|
||||
if (stackFrame == null || stackFrame.getStackFrameProxy().isBottom()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
@@ -81,76 +81,29 @@ public class PopFrameAction extends DebuggerAction {
|
||||
}
|
||||
|
||||
debugProcess.getSession().setSteppingThrough(stackFrame.getStackFrameProxy().threadProxy());
|
||||
if (!DebuggerSettings.EVALUATE_FINALLY_NEVER.equals(DebuggerSettings.getInstance().EVALUATE_FINALLY_ON_POP_FRAME)) {
|
||||
List<PsiStatement> statements = getFinallyStatements(debuggerContext.getSourcePosition());
|
||||
if (!statements.isEmpty()) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (PsiStatement statement : statements) {
|
||||
sb.append("\n").append(statement.getText());
|
||||
}
|
||||
if (DebuggerSettings.EVALUATE_FINALLY_ALWAYS.equals(DebuggerSettings.getInstance().EVALUATE_FINALLY_ON_POP_FRAME)) {
|
||||
evaluateAndPop(project, stackFrame, debuggerContext, debugProcess, sb);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
int res = MessageDialogBuilder
|
||||
.yesNoCancel(UIUtil.removeMnemonic(ActionsBundle.actionText(DebuggerActions.POP_FRAME)),
|
||||
DebuggerBundle.message("warning.finally.block.detected") + sb)
|
||||
.project(project)
|
||||
.icon(Messages.getWarningIcon())
|
||||
.yesText(DebuggerBundle.message("button.execute.finally"))
|
||||
.noText(DebuggerBundle.message("button.drop.anyway"))
|
||||
.cancelText(CommonBundle.message("button.cancel"))
|
||||
.doNotAsk(
|
||||
new DialogWrapper.DoNotAskOption() {
|
||||
@Override
|
||||
public boolean isToBeShown() {
|
||||
return !DebuggerSettings.EVALUATE_FINALLY_ALWAYS.equals(DebuggerSettings.getInstance().EVALUATE_FINALLY_ON_POP_FRAME) &&
|
||||
!DebuggerSettings.EVALUATE_FINALLY_NEVER.equals(DebuggerSettings.getInstance().EVALUATE_FINALLY_ON_POP_FRAME);
|
||||
}
|
||||
if (evaluateFinallyBlocks(project,
|
||||
UIUtil.removeMnemonic(ActionsBundle.actionText(DebuggerActions.POP_FRAME)),
|
||||
stackFrame,
|
||||
new XDebuggerEvaluator.XEvaluationCallback() {
|
||||
@Override
|
||||
public void evaluated(@NotNull XValue result) {
|
||||
popFrame(debugProcess, debuggerContext, stackFrame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setToBeShown(boolean value, int exitCode) {
|
||||
if (!value) {
|
||||
DebuggerSettings.getInstance().EVALUATE_FINALLY_ON_POP_FRAME =
|
||||
exitCode == Messages.YES ? DebuggerSettings.EVALUATE_FINALLY_ALWAYS : DebuggerSettings.EVALUATE_FINALLY_NEVER;
|
||||
}
|
||||
else {
|
||||
DebuggerSettings.getInstance().EVALUATE_FINALLY_ON_POP_FRAME = DebuggerSettings.EVALUATE_FINALLY_ASK;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeHidden() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldSaveOptionsOnCancel() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDoNotShowMessage() {
|
||||
return CommonBundle.message("dialog.options.do.not.show");
|
||||
}
|
||||
})
|
||||
.show();
|
||||
|
||||
switch (res) {
|
||||
case Messages.CANCEL:
|
||||
return;
|
||||
case Messages.NO:
|
||||
break;
|
||||
case Messages.YES: // evaluate finally
|
||||
evaluateAndPop(project, stackFrame, debuggerContext, debugProcess, sb);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
debugProcess.getManagerThread().schedule(debugProcess.createPopFrameCommand(debuggerContext, stackFrame.getStackFrameProxy()));
|
||||
@Override
|
||||
public void errorOccurred(@NotNull final String errorMessage) {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Messages
|
||||
.showMessageDialog(project, DebuggerBundle.message("error.executing.finally", errorMessage),
|
||||
UIUtil.removeMnemonic(ActionsBundle.actionText(DebuggerActions.POP_FRAME)),
|
||||
Messages.getErrorIcon());
|
||||
}
|
||||
});
|
||||
}
|
||||
})) return;
|
||||
popFrame(debugProcess, debuggerContext, stackFrame);
|
||||
}
|
||||
catch (NativeMethodException e2){
|
||||
Messages.showMessageDialog(project, DebuggerBundle.message("error.native.method.exception"),
|
||||
@@ -162,33 +115,96 @@ public class PopFrameAction extends DebuggerAction {
|
||||
}
|
||||
}
|
||||
|
||||
private static void evaluateAndPop(final Project project,
|
||||
final JavaStackFrame stackFrame,
|
||||
final DebuggerContextImpl debuggerContext,
|
||||
final DebugProcessImpl debugProcess, StringBuilder sb) {
|
||||
static boolean evaluateFinallyBlocks(Project project,
|
||||
String title,
|
||||
JavaStackFrame stackFrame,
|
||||
XDebuggerEvaluator.XEvaluationCallback callback) {
|
||||
if (!DebuggerSettings.EVALUATE_FINALLY_NEVER.equals(DebuggerSettings.getInstance().EVALUATE_FINALLY_ON_POP_FRAME)) {
|
||||
List<PsiStatement> statements = getFinallyStatements(stackFrame.getDescriptor().getSourcePosition());
|
||||
if (!statements.isEmpty()) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (PsiStatement statement : statements) {
|
||||
sb.append("\n").append(statement.getText());
|
||||
}
|
||||
if (DebuggerSettings.EVALUATE_FINALLY_ALWAYS.equals(DebuggerSettings.getInstance().EVALUATE_FINALLY_ON_POP_FRAME)) {
|
||||
evaluateAndAct(project, stackFrame, sb, callback);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
int res = MessageDialogBuilder
|
||||
.yesNoCancel(title,
|
||||
DebuggerBundle.message("warning.finally.block.detected") + sb)
|
||||
.project(project)
|
||||
.icon(Messages.getWarningIcon())
|
||||
.yesText(DebuggerBundle.message("button.execute.finally"))
|
||||
.noText(DebuggerBundle.message("button.drop.anyway"))
|
||||
.cancelText(CommonBundle.message("button.cancel"))
|
||||
.doNotAsk(
|
||||
new DialogWrapper.DoNotAskOption() {
|
||||
@Override
|
||||
public boolean isToBeShown() {
|
||||
return !DebuggerSettings.EVALUATE_FINALLY_ALWAYS.equals(DebuggerSettings.getInstance().EVALUATE_FINALLY_ON_POP_FRAME) &&
|
||||
!DebuggerSettings.EVALUATE_FINALLY_NEVER.equals(DebuggerSettings.getInstance().EVALUATE_FINALLY_ON_POP_FRAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setToBeShown(boolean value, int exitCode) {
|
||||
if (!value) {
|
||||
DebuggerSettings.getInstance().EVALUATE_FINALLY_ON_POP_FRAME =
|
||||
exitCode == Messages.YES ? DebuggerSettings.EVALUATE_FINALLY_ALWAYS : DebuggerSettings.EVALUATE_FINALLY_NEVER;
|
||||
}
|
||||
else {
|
||||
DebuggerSettings.getInstance().EVALUATE_FINALLY_ON_POP_FRAME = DebuggerSettings.EVALUATE_FINALLY_ASK;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeHidden() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldSaveOptionsOnCancel() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDoNotShowMessage() {
|
||||
return CommonBundle.message("dialog.options.do.not.show");
|
||||
}
|
||||
})
|
||||
.show();
|
||||
|
||||
switch (res) {
|
||||
case Messages.CANCEL:
|
||||
return true;
|
||||
case Messages.NO:
|
||||
break;
|
||||
case Messages.YES: // evaluate finally
|
||||
evaluateAndAct(project, stackFrame, sb, callback);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void popFrame(DebugProcessImpl debugProcess, DebuggerContextImpl debuggerContext, JavaStackFrame stackFrame) {
|
||||
debugProcess.getManagerThread()
|
||||
.schedule(debugProcess.createPopFrameCommand(debuggerContext, stackFrame.getStackFrameProxy()));
|
||||
}
|
||||
|
||||
private static void evaluateAndAct(Project project,
|
||||
JavaStackFrame stackFrame,
|
||||
StringBuilder sb,
|
||||
XDebuggerEvaluator.XEvaluationCallback callback) {
|
||||
XDebuggerEvaluator evaluator = stackFrame.getEvaluator();
|
||||
if (evaluator != null) {
|
||||
evaluator.evaluate(XExpressionImpl.fromText(sb.toString(), EvaluationMode.CODE_FRAGMENT),
|
||||
new XDebuggerEvaluator.XEvaluationCallback() {
|
||||
@Override
|
||||
public void evaluated(@NotNull XValue result) {
|
||||
debugProcess.getManagerThread()
|
||||
.schedule(debugProcess.createPopFrameCommand(debuggerContext, stackFrame.getStackFrameProxy()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void errorOccurred(@NotNull final String errorMessage) {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Messages
|
||||
.showMessageDialog(project, DebuggerBundle.message("error.executing.finally", errorMessage),
|
||||
UIUtil.removeMnemonic(ActionsBundle.actionText(DebuggerActions.POP_FRAME)),
|
||||
Messages.getErrorIcon());
|
||||
}
|
||||
});
|
||||
}
|
||||
}, stackFrame.getSourcePosition());
|
||||
callback,
|
||||
stackFrame.getSourcePosition());
|
||||
}
|
||||
else {
|
||||
Messages.showMessageDialog(project, XDebuggerBundle.message("xdebugger.evaluate.stack.frame.has.not.evaluator"),
|
||||
@@ -214,21 +230,12 @@ public class PopFrameAction extends DebuggerAction {
|
||||
return res;
|
||||
}
|
||||
|
||||
private static JavaStackFrame getStackFrame(AnActionEvent e) {
|
||||
static JavaStackFrame getStackFrame(AnActionEvent e) {
|
||||
StackFrameDescriptorImpl descriptor = getSelectedStackFrameDescriptor(e);
|
||||
if (descriptor != null) {
|
||||
if (descriptor.getFrameProxy().isBottom()) {
|
||||
return null;
|
||||
}
|
||||
return new JavaStackFrame(descriptor, false);
|
||||
}
|
||||
JavaStackFrame frame = getSelectedStackFrame(e);
|
||||
if (frame != null) {
|
||||
StackFrameProxyImpl proxy = frame.getStackFrameProxy();
|
||||
if (proxy == null || proxy.isBottom()) return null;
|
||||
return frame;
|
||||
}
|
||||
return null;
|
||||
return getSelectedStackFrame(e);
|
||||
}
|
||||
|
||||
static StackFrameProxyImpl getStackFrameProxy(AnActionEvent e) {
|
||||
|
||||
@@ -397,6 +397,7 @@ public class JavaStackFrame extends XStackFrame {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public StackFrameProxyImpl getStackFrameProxy() {
|
||||
return myDescriptor.getFrameProxy();
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -30,7 +30,7 @@ public class BlockStatementEvaluator implements Evaluator {
|
||||
|
||||
@Override
|
||||
public Object evaluate(EvaluationContextImpl context) throws EvaluateException {
|
||||
Object result = context.getSuspendContext().getDebugProcess().getVirtualMachineProxy().mirrorOf();
|
||||
Object result = context.getSuspendContext().getDebugProcess().getVirtualMachineProxy().mirrorOfVoid();
|
||||
for (Evaluator statement : myStatements) {
|
||||
result = statement.evaluate(context);
|
||||
}
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ public class DoWhileStatementEvaluator extends LoopEvaluator {
|
||||
}
|
||||
|
||||
public Object evaluate(EvaluationContextImpl context) throws EvaluateException {
|
||||
Object value = context.getDebugProcess().getVirtualMachineProxy().mirrorOf();
|
||||
Object value = context.getDebugProcess().getVirtualMachineProxy().mirrorOfVoid();
|
||||
while (true) {
|
||||
if (body(context)) break;
|
||||
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ public abstract class ForStatementEvaluatorBase extends LoopEvaluator {
|
||||
}
|
||||
|
||||
public Object evaluate(EvaluationContextImpl context) throws EvaluateException {
|
||||
Object value = context.getDebugProcess().getVirtualMachineProxy().mirrorOf();
|
||||
Object value = context.getDebugProcess().getVirtualMachineProxy().mirrorOfVoid();
|
||||
value = evaluateInitialization(context, value);
|
||||
|
||||
while (true) {
|
||||
|
||||
+1
-1
@@ -54,7 +54,7 @@ public class IfStatementEvaluator implements Evaluator {
|
||||
value = myElseEvaluator.evaluate(context);
|
||||
myModifier = myElseEvaluator.getModifier();
|
||||
} else {
|
||||
value = context.getDebugProcess().getVirtualMachineProxy().mirrorOf();
|
||||
value = context.getDebugProcess().getVirtualMachineProxy().mirrorOfVoid();
|
||||
myModifier = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package com.intellij.debugger.jdi;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: lex
|
||||
@@ -23,10 +25,10 @@ package com.intellij.debugger.jdi;
|
||||
* To change this template use Options | File Templates.
|
||||
*/
|
||||
public abstract class JdiProxy {
|
||||
protected JdiTimer myTimer;
|
||||
@NotNull protected JdiTimer myTimer;
|
||||
private int myTimeStamp = 0;
|
||||
|
||||
public JdiProxy(JdiTimer timer) {
|
||||
public JdiProxy(@NotNull JdiTimer timer) {
|
||||
myTimer = timer;
|
||||
myTimeStamp = myTimer.getCurrentTime();
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.intellij.debugger.engine.evaluation.EvaluateException;
|
||||
import com.intellij.debugger.engine.evaluation.EvaluateExceptionUtil;
|
||||
import com.intellij.debugger.engine.jdi.StackFrameProxy;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.util.ThreeState;
|
||||
import com.sun.jdi.*;
|
||||
import gnu.trove.THashMap;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -46,10 +47,10 @@ public class StackFrameProxyImpl extends JdiProxy implements StackFrameProxy {
|
||||
private StackFrame myStackFrame;
|
||||
private ObjectReference myThisReference;
|
||||
private ClassLoaderReference myClassLoader;
|
||||
private Boolean myIsObsolete = null;
|
||||
private ThreeState myIsObsolete = ThreeState.UNSURE;
|
||||
private Map<LocalVariable, Value> myAllValues;
|
||||
|
||||
public StackFrameProxyImpl(ThreadReferenceProxyImpl threadProxy, @NotNull StackFrame frame, int fromBottomIndex /* 1-based */) {
|
||||
public StackFrameProxyImpl(@NotNull ThreadReferenceProxyImpl threadProxy, @NotNull StackFrame frame, int fromBottomIndex /* 1-based */) {
|
||||
super(threadProxy.getVirtualMachine());
|
||||
myThreadProxy = threadProxy;
|
||||
myFrameFromBottomIndex = fromBottomIndex;
|
||||
@@ -59,14 +60,14 @@ public class StackFrameProxyImpl extends JdiProxy implements StackFrameProxy {
|
||||
public boolean isObsolete() throws EvaluateException {
|
||||
DebuggerManagerThreadImpl.assertIsManagerThread();
|
||||
checkValid();
|
||||
if (myIsObsolete != null) {
|
||||
return myIsObsolete.booleanValue();
|
||||
if (myIsObsolete != ThreeState.UNSURE) {
|
||||
return myIsObsolete.toBoolean();
|
||||
}
|
||||
InvalidStackFrameException error = null;
|
||||
for (int attempt = 0; attempt < 2; attempt++) {
|
||||
try {
|
||||
boolean isObsolete = (getVirtualMachine().canRedefineClasses() && location().method().isObsolete());
|
||||
myIsObsolete = isObsolete? Boolean.TRUE : Boolean.FALSE;
|
||||
myIsObsolete = ThreeState.fromBoolean(isObsolete);
|
||||
return isObsolete;
|
||||
}
|
||||
catch (InvalidStackFrameException e) {
|
||||
@@ -75,7 +76,7 @@ public class StackFrameProxyImpl extends JdiProxy implements StackFrameProxy {
|
||||
}
|
||||
catch (InternalException e) {
|
||||
if (e.errorCode() == 23 /*INVALID_METHODID according to JDI sources*/) {
|
||||
myIsObsolete = Boolean.TRUE;
|
||||
myIsObsolete = ThreeState.YES;
|
||||
return true;
|
||||
}
|
||||
throw e;
|
||||
@@ -108,7 +109,7 @@ public class StackFrameProxyImpl extends JdiProxy implements StackFrameProxy {
|
||||
}
|
||||
myFrameIndex = -1;
|
||||
myStackFrame = null;
|
||||
myIsObsolete = null;
|
||||
myIsObsolete = ThreeState.UNSURE;
|
||||
myThisReference = null;
|
||||
myClassLoader = null;
|
||||
myAllValues = null;
|
||||
@@ -171,6 +172,7 @@ public class StackFrameProxyImpl extends JdiProxy implements StackFrameProxy {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public VirtualMachineProxyImpl getVirtualMachine() {
|
||||
return (VirtualMachineProxyImpl) myTimer;
|
||||
|
||||
@@ -65,6 +65,7 @@ public final class ThreadReferenceProxyImpl extends ObjectReferenceProxyImpl imp
|
||||
return (ThreadReference)getObjectReference();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public VirtualMachineProxyImpl getVirtualMachine() {
|
||||
DebuggerManagerThreadImpl.assertIsManagerThread();
|
||||
@@ -309,6 +310,17 @@ public final class ThreadReferenceProxyImpl extends ObjectReferenceProxyImpl imp
|
||||
}
|
||||
}
|
||||
|
||||
public void forceEarlyReturn(Value value) throws ClassNotLoadedException, IncompatibleThreadStateException, InvalidTypeException {
|
||||
DebuggerManagerThreadImpl.assertIsManagerThread();
|
||||
try {
|
||||
getThreadReference().forceEarlyReturn(value);
|
||||
}
|
||||
finally {
|
||||
clearCaches();
|
||||
getVirtualMachineProxy().clearCaches();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSuspended() throws ObjectCollectedException {
|
||||
try {
|
||||
DebuggerManagerThreadImpl.assertIsManagerThread();
|
||||
|
||||
@@ -88,6 +88,7 @@ public class VirtualMachineProxyImpl implements JdiTimer, VirtualMachineProxy {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public VirtualMachine getVirtualMachine() {
|
||||
return myVirtualMachine;
|
||||
}
|
||||
@@ -278,7 +279,15 @@ public class VirtualMachineProxyImpl implements JdiTimer, VirtualMachineProxy {
|
||||
return myVirtualMachine.eventRequestManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #mirrorOfVoid()} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public VoidValue mirrorOf() throws EvaluateException {
|
||||
return mirrorOfVoid();
|
||||
}
|
||||
|
||||
public VoidValue mirrorOfVoid() {
|
||||
return myVirtualMachine.mirrorOfVoid();
|
||||
}
|
||||
|
||||
@@ -461,6 +470,15 @@ public class VirtualMachineProxyImpl implements JdiTimer, VirtualMachineProxy {
|
||||
return myPopFrames.isAvailable();
|
||||
}
|
||||
|
||||
private final Capability myForceEarlyReturn = new Capability() {
|
||||
protected boolean calcValue() {
|
||||
return myVirtualMachine.canForceEarlyReturn();
|
||||
}
|
||||
};
|
||||
public boolean canForceEarlyReturn() {
|
||||
return myForceEarlyReturn.isAvailable();
|
||||
}
|
||||
|
||||
private final Capability myCanGetInstanceInfo = new Capability() {
|
||||
protected boolean calcValue() {
|
||||
if (!myVersionHigher_15) {
|
||||
|
||||
-7
@@ -43,13 +43,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
|
||||
/*
|
||||
execution-impl -> lang-impl(scratches are here)
|
||||
compiler-impl -> lang-impl
|
||||
|
||||
java-impl ->execution-impl, compiler-impl
|
||||
*/
|
||||
public class JavaScratchRunConfigurationExtension extends RunConfigurationExtension{
|
||||
|
||||
private static final Key<Integer> SCRATCH_FILE_ID = Key.create("_scratch_file_id_");
|
||||
|
||||
@@ -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.
|
||||
@@ -23,14 +23,13 @@ import com.intellij.openapi.util.MultiValuesMap;
|
||||
import com.intellij.openapi.util.SimpleModificationTracker;
|
||||
import com.intellij.openapi.vfs.*;
|
||||
import com.intellij.util.EventDispatcher;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.descriptors.*;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
@@ -77,11 +76,7 @@ public class ConfigFileContainerImpl extends SimpleModificationTracker implement
|
||||
@Override
|
||||
@Nullable
|
||||
public ConfigFile getConfigFile(ConfigFileMetaData metaData) {
|
||||
final Collection<ConfigFile> descriptors = myConfigFiles.get(metaData);
|
||||
if (descriptors == null || descriptors.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return descriptors.iterator().next();
|
||||
return ContainerUtil.getFirstItem(myConfigFiles.get(metaData));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -132,9 +127,9 @@ public class ConfigFileContainerImpl extends SimpleModificationTracker implement
|
||||
return myMetaDataProvider;
|
||||
}
|
||||
|
||||
public void updateDescriptors(final MultiValuesMap<ConfigFileMetaData, ConfigFileInfo> descriptorsMap) {
|
||||
Set<ConfigFile> toDelete = new HashSet<ConfigFile>(myConfigFiles.values());
|
||||
Set<ConfigFile> added = new HashSet<ConfigFile>();
|
||||
public void updateDescriptors(@NotNull MultiValuesMap<ConfigFileMetaData, ConfigFileInfo> descriptorsMap) {
|
||||
Set<ConfigFile> toDelete = myConfigFiles.isEmpty() ? Collections.<ConfigFile>emptySet() : new HashSet<ConfigFile>(myConfigFiles.values());
|
||||
Set<ConfigFile> added = null;
|
||||
|
||||
for (Map.Entry<ConfigFileMetaData, Collection<ConfigFileInfo>> entry : descriptorsMap.entrySet()) {
|
||||
ConfigFileMetaData metaData = entry.getKey();
|
||||
@@ -142,8 +137,7 @@ public class ConfigFileContainerImpl extends SimpleModificationTracker implement
|
||||
final Collection<ConfigFile> oldDescriptors = myConfigFiles.get(metaData);
|
||||
if (oldDescriptors != null) {
|
||||
for (ConfigFile descriptor : oldDescriptors) {
|
||||
if (newDescriptors.contains(descriptor.getInfo())) {
|
||||
newDescriptors.remove(descriptor.getInfo());
|
||||
if (newDescriptors.remove(descriptor.getInfo())) {
|
||||
toDelete.remove(descriptor);
|
||||
}
|
||||
}
|
||||
@@ -152,6 +146,9 @@ public class ConfigFileContainerImpl extends SimpleModificationTracker implement
|
||||
final ConfigFileImpl configFile = new ConfigFileImpl(this, configuration);
|
||||
Disposer.register(this, configFile);
|
||||
myConfigFiles.put(metaData, configFile);
|
||||
if (added == null) {
|
||||
added = new THashSet<ConfigFile>();
|
||||
}
|
||||
added.add(configFile);
|
||||
}
|
||||
}
|
||||
@@ -162,9 +159,11 @@ public class ConfigFileContainerImpl extends SimpleModificationTracker implement
|
||||
}
|
||||
|
||||
myCachedConfigFiles = null;
|
||||
for (ConfigFile configFile : added) {
|
||||
incModificationCount();
|
||||
myDispatcher.getMulticaster().configFileAdded(configFile);
|
||||
if (added != null) {
|
||||
for (ConfigFile configFile : added) {
|
||||
incModificationCount();
|
||||
myDispatcher.getMulticaster().configFileAdded(configFile);
|
||||
}
|
||||
}
|
||||
for (ConfigFile configFile : toDelete) {
|
||||
incModificationCount();
|
||||
|
||||
+39
-42
@@ -19,11 +19,11 @@ import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.codeInspection.dataFlow.instructions.*;
|
||||
import com.intellij.codeInspection.dataFlow.value.*;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.templateLanguages.OuterLanguageElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
@@ -42,18 +42,20 @@ import static com.intellij.psi.CommonClassNames.*;
|
||||
public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.dataFlow.ControlFlowAnalyzer");
|
||||
public static final String ORG_JETBRAINS_ANNOTATIONS_CONTRACT = Contract.class.getName();
|
||||
private final PsiElement myCodeFragment;
|
||||
private boolean myIgnoreAssertions;
|
||||
private final Project myProject;
|
||||
|
||||
private static class CannotAnalyzeException extends RuntimeException { }
|
||||
|
||||
private final DfaValueFactory myFactory;
|
||||
private ControlFlow myCurrentFlow;
|
||||
private Stack<CatchDescriptor> myCatchStack;
|
||||
private DfaValue myRuntimeException;
|
||||
private DfaValue myError;
|
||||
private DfaValue myString;
|
||||
private PsiType myNpe;
|
||||
private PsiType myAssertionError;
|
||||
private final DfaValue myRuntimeException;
|
||||
private final DfaValue myError;
|
||||
private final DfaValue myString;
|
||||
private final PsiType myNpe;
|
||||
private final PsiType myAssertionError;
|
||||
private final Stack<PsiElement> myElementStack = new Stack<PsiElement>();
|
||||
|
||||
/**
|
||||
@@ -61,50 +63,45 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
*/
|
||||
private FactoryMap<PsiTryStatement, DfaVariableValue> myExceptionHolders;
|
||||
|
||||
ControlFlowAnalyzer(final DfaValueFactory valueFactory) {
|
||||
ControlFlowAnalyzer(final DfaValueFactory valueFactory, @NotNull PsiElement codeFragment, boolean ignoreAssertions) {
|
||||
myFactory = valueFactory;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ControlFlow buildControlFlow(@NotNull PsiElement codeFragment, boolean ignoreAssertions) {
|
||||
if (PsiTreeUtil.findChildOfType(codeFragment, OuterLanguageElement.class) != null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
myCodeFragment = codeFragment;
|
||||
myProject = codeFragment.getProject();
|
||||
myIgnoreAssertions = ignoreAssertions;
|
||||
final PsiManager manager = codeFragment.getManager();
|
||||
GlobalSearchScope scope = codeFragment.getResolveScope();
|
||||
myRuntimeException = myFactory.createTypeValue(createClassType(manager, scope, JAVA_LANG_RUNTIME_EXCEPTION), Nullness.NOT_NULL);
|
||||
myError = myFactory.createTypeValue(createClassType(manager, scope, JAVA_LANG_ERROR), Nullness.NOT_NULL);
|
||||
myNpe = createClassType(manager, scope, JAVA_LANG_NULL_POINTER_EXCEPTION);
|
||||
myAssertionError = createClassType(manager, scope, JAVA_LANG_ASSERTION_ERROR);
|
||||
myString = myFactory.createTypeValue(createClassType(manager, scope, JAVA_LANG_STRING), Nullness.NOT_NULL);
|
||||
myRuntimeException = myFactory.createTypeValue(createClassType(scope, JAVA_LANG_RUNTIME_EXCEPTION), Nullness.NOT_NULL);
|
||||
myError = myFactory.createTypeValue(createClassType(scope, JAVA_LANG_ERROR), Nullness.NOT_NULL);
|
||||
myNpe = createClassType(scope, JAVA_LANG_NULL_POINTER_EXCEPTION);
|
||||
myAssertionError = createClassType(scope, JAVA_LANG_ASSERTION_ERROR);
|
||||
myString = myFactory.createTypeValue(createClassType(scope, JAVA_LANG_STRING), Nullness.NOT_NULL);
|
||||
|
||||
myExceptionHolders = new FactoryMap<PsiTryStatement, DfaVariableValue>() {
|
||||
@Nullable
|
||||
@Override
|
||||
protected DfaVariableValue create(PsiTryStatement key) {
|
||||
String text = "java.lang.Object $exception" + myExceptionHolders.size() + "$";
|
||||
PsiParameter mockVar = JavaPsiFacade.getElementFactory(manager.getProject()).createParameterFromText(text, null);
|
||||
PsiParameter mockVar = JavaPsiFacade.getElementFactory(myProject).createParameterFromText(text, null);
|
||||
return myFactory.getVarFactory().createVariableValue(mockVar, false);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ControlFlow buildControlFlow() {
|
||||
myCatchStack = new Stack<CatchDescriptor>();
|
||||
myCurrentFlow = new ControlFlow(myFactory);
|
||||
|
||||
try {
|
||||
codeFragment.accept(this);
|
||||
myCodeFragment.accept(this);
|
||||
}
|
||||
catch (CannotAnalyzeException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PsiElement parent = codeFragment.getParent();
|
||||
if (parent instanceof PsiLambdaExpression && codeFragment instanceof PsiExpression) {
|
||||
generateBoxingUnboxingInstructionFor((PsiExpression)codeFragment,
|
||||
PsiElement parent = myCodeFragment.getParent();
|
||||
if (parent instanceof PsiLambdaExpression && myCodeFragment instanceof PsiExpression) {
|
||||
generateBoxingUnboxingInstructionFor((PsiExpression)myCodeFragment,
|
||||
LambdaUtil.getFunctionalInterfaceReturnType((PsiLambdaExpression)parent));
|
||||
addInstruction(new CheckReturnValueInstruction(codeFragment));
|
||||
addInstruction(new CheckReturnValueInstruction(myCodeFragment));
|
||||
}
|
||||
|
||||
addInstruction(new ReturnInstruction(false, null));
|
||||
@@ -117,10 +114,10 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
}
|
||||
|
||||
|
||||
private static PsiClassType createClassType(PsiManager manager, GlobalSearchScope scope, String fqn) {
|
||||
PsiClass aClass = JavaPsiFacade.getInstance(manager.getProject()).findClass(fqn, scope);
|
||||
if (aClass != null) return JavaPsiFacade.getElementFactory(manager.getProject()).createType(aClass);
|
||||
return JavaPsiFacade.getElementFactory(manager.getProject()).createTypeByFQClassName(fqn, scope);
|
||||
private PsiClassType createClassType(GlobalSearchScope scope, String fqn) {
|
||||
PsiClass aClass = JavaPsiFacade.getInstance(myProject).findClass(fqn, scope);
|
||||
if (aClass != null) return JavaPsiFacade.getElementFactory(myProject).createType(aClass);
|
||||
return JavaPsiFacade.getElementFactory(myProject).createTypeByFQClassName(fqn, scope);
|
||||
}
|
||||
|
||||
private <T extends Instruction> T addInstruction(T i) {
|
||||
@@ -204,7 +201,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
lExpr.accept(this);
|
||||
addInstruction(new DupInstruction());
|
||||
rExpr.accept(this);
|
||||
addInstruction(new BinopInstruction(JavaTokenType.PLUS, null, lExpr.getProject()));
|
||||
addInstruction(new BinopInstruction(JavaTokenType.PLUS, null, myProject));
|
||||
}
|
||||
else {
|
||||
generateDefaultAssignmentBinOp(lExpr, rExpr, type);
|
||||
@@ -234,7 +231,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
generateBoxingUnboxingInstructionFor(lExpr,exprType);
|
||||
rExpr.accept(this);
|
||||
generateBoxingUnboxingInstructionFor(rExpr, exprType);
|
||||
addInstruction(new BinopInstruction(null, null, lExpr.getProject()));
|
||||
addInstruction(new BinopInstruction(null, null, myProject));
|
||||
}
|
||||
|
||||
@Override public void visitAssertStatement(PsiAssertStatement statement) {
|
||||
@@ -672,7 +669,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
|
||||
addInstruction(new PushInstruction(myFactory.createValue(caseExpression), caseExpression));
|
||||
caseValue.accept(this);
|
||||
addInstruction(new BinopInstruction(JavaTokenType.EQEQ, null, caseExpression.getProject()));
|
||||
addInstruction(new BinopInstruction(JavaTokenType.EQEQ, null, myProject));
|
||||
}
|
||||
else {
|
||||
pushUnknown();
|
||||
@@ -750,7 +747,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
addConditionalRuntimeThrow();
|
||||
addInstruction(new DupInstruction());
|
||||
addInstruction(new PushInstruction(myFactory.getConstFactory().getNull(), null));
|
||||
addInstruction(new BinopInstruction(JavaTokenType.EQEQ, null, statement.getProject()));
|
||||
addInstruction(new BinopInstruction(JavaTokenType.EQEQ, null, myProject));
|
||||
ConditionalGotoInstruction gotoInstruction = new ConditionalGotoInstruction(null, true, null);
|
||||
addInstruction(gotoInstruction);
|
||||
|
||||
@@ -972,7 +969,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
//if $exception$==null => continue normal execution
|
||||
addInstruction(new PushInstruction(getExceptionHolder(finallyDescriptor), null));
|
||||
addInstruction(new PushInstruction(myFactory.getConstFactory().getNull(), null));
|
||||
addInstruction(new BinopInstruction(JavaTokenType.EQEQ, null, statement.getProject()));
|
||||
addInstruction(new BinopInstruction(JavaTokenType.EQEQ, null, myProject));
|
||||
addInstruction(new ConditionalGotoInstruction(getEndOffset(statement), false, null));
|
||||
|
||||
// else throw $exception$
|
||||
@@ -999,7 +996,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
for (PsiType catchType : flattened) {
|
||||
addInstruction(new PushInstruction(exceptionHolder, null));
|
||||
addInstruction(new PushInstruction(myFactory.createTypeValue(catchType, Nullness.UNKNOWN), null));
|
||||
addInstruction(new BinopInstruction(JavaTokenType.INSTANCEOF_KEYWORD, null, section.getProject()));
|
||||
addInstruction(new BinopInstruction(JavaTokenType.INSTANCEOF_KEYWORD, null, myProject));
|
||||
addInstruction(new ConditionalGotoInstruction(ControlFlow.deltaOffset(getStartOffset(catchBlock), -5), false, null));
|
||||
}
|
||||
|
||||
@@ -1179,7 +1176,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
PsiType rType = rExpr.getType();
|
||||
|
||||
acceptBinaryRightOperand(op, type, lExpr, lType, rExpr, rType);
|
||||
addInstruction(new BinopInstruction(op, expression.isPhysical() ? expression : null, expression.getProject()));
|
||||
addInstruction(new BinopInstruction(op, expression.isPhysical() ? expression : null, myProject));
|
||||
|
||||
lExpr = rExpr;
|
||||
lType = rType;
|
||||
@@ -1256,7 +1253,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
operand.accept(this);
|
||||
generateBoxingUnboxingInstructionFor(operand, exprType);
|
||||
PsiElement psiAnchor = i == operands.length - 1 && expression.isPhysical() ? expression : null;
|
||||
addInstruction(new BinopInstruction(JavaTokenType.NE, psiAnchor, expression.getProject()));
|
||||
addInstruction(new BinopInstruction(JavaTokenType.NE, psiAnchor, myProject));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1399,7 +1396,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
type = ((PsiClassType)type).rawType();
|
||||
}
|
||||
addInstruction(new PushInstruction(myFactory.createTypeValue(type, Nullness.UNKNOWN), null));
|
||||
addInstruction(new InstanceofInstruction(expression, expression.getProject(), operand, type));
|
||||
addInstruction(new InstanceofInstruction(expression, myProject, operand, type));
|
||||
}
|
||||
else {
|
||||
pushUnknown();
|
||||
@@ -1481,7 +1478,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
// if a contract resulted in 'fail', handle it
|
||||
addInstruction(new DupInstruction());
|
||||
addInstruction(new PushInstruction(myFactory.getConstFactory().getContractFail(), null));
|
||||
addInstruction(new BinopInstruction(JavaTokenType.EQEQ, null, expression.getProject()));
|
||||
addInstruction(new BinopInstruction(JavaTokenType.EQEQ, null, myProject));
|
||||
ConditionalGotoInstruction ifNotFail = new ConditionalGotoInstruction(null, true, null);
|
||||
addInstruction(ifNotFail);
|
||||
returnCheckingFinally(true, expression);
|
||||
|
||||
+7
-8
@@ -34,6 +34,7 @@ import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.templateLanguages.OuterLanguageElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.Processor;
|
||||
@@ -87,21 +88,23 @@ public class DataFlowRunner {
|
||||
}
|
||||
}
|
||||
|
||||
return Arrays.asList(createMemoryState());
|
||||
return Collections.singletonList(createMemoryState());
|
||||
}
|
||||
|
||||
public final RunnerResult analyzeMethod(@NotNull PsiElement psiBlock, InstructionVisitor visitor) {
|
||||
Collection<DfaMemoryState> initialStates = createInitialStates(psiBlock, visitor);
|
||||
return initialStates == null ? RunnerResult.NOT_APPLICABLE : analyzeMethod(psiBlock, visitor, false, initialStates);
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
public final RunnerResult analyzeMethod(@NotNull PsiElement psiBlock,
|
||||
InstructionVisitor visitor,
|
||||
boolean ignoreAssertions,
|
||||
@NotNull Collection<DfaMemoryState> initialStates) {
|
||||
if (PsiTreeUtil.findChildOfType(psiBlock, OuterLanguageElement.class) != null) return RunnerResult.NOT_APPLICABLE;
|
||||
|
||||
try {
|
||||
ControlFlowAnalyzer analyzer = createControlFlowAnalyzer();
|
||||
final ControlFlow flow = analyzer.buildControlFlow(psiBlock, ignoreAssertions);
|
||||
final ControlFlow flow = new ControlFlowAnalyzer(myValueFactory, psiBlock, ignoreAssertions).buildControlFlow();
|
||||
if (flow == null) return RunnerResult.NOT_APPLICABLE;
|
||||
int[] loopNumber = LoopAnalyzer.calcInLoop(flow);
|
||||
|
||||
@@ -309,10 +312,6 @@ public class DataFlowRunner {
|
||||
}
|
||||
}
|
||||
|
||||
protected ControlFlowAnalyzer createControlFlowAnalyzer() {
|
||||
return new ControlFlowAnalyzer(myValueFactory);
|
||||
}
|
||||
|
||||
protected DfaMemoryState createMemoryState() {
|
||||
return new DfaMemoryStateImpl(myValueFactory);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.psi.impl;
|
||||
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.*;
|
||||
@@ -84,11 +85,14 @@ public class FindSuperElementsHelper {
|
||||
ClassInheritorsSearch.search(containingClass, containingClass.getUseScope(), true, true, false).forEach(new Processor<PsiClass>() {
|
||||
@Override
|
||||
public boolean process(PsiClass inheritor) {
|
||||
ProgressManager.checkCanceled();
|
||||
for (PsiClassType interfaceType : inheritor.getImplementsListTypes()) {
|
||||
ProgressManager.checkCanceled();
|
||||
PsiClassType.ClassResolveResult resolved = interfaceType.resolveGenerics();
|
||||
PsiClass anInterface = resolved.getElement();
|
||||
if (anInterface == null || !checkedInterfaces.add(PsiAnchor.create(anInterface))) continue;
|
||||
for (PsiMethod superMethod : anInterface.findMethodsByName(method.getName(), true)) {
|
||||
ProgressManager.checkCanceled();
|
||||
PsiClass superInterface = superMethod.getContainingClass();
|
||||
if (superInterface == null) {
|
||||
continue;
|
||||
|
||||
+5
-4
@@ -19,16 +19,17 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Segment;
|
||||
import com.intellij.psi.ImplicitVariable;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiIdentifier;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class ImplicitVariableElementInfoFactory implements SmartPointerElementInfoFactory {
|
||||
public class ImplicitVariableElementInfoFactory extends SmartPointerElementInfoFactory {
|
||||
@Override
|
||||
@Nullable
|
||||
public SmartPointerElementInfo createElementInfo(@NotNull final PsiElement element) {
|
||||
if (element instanceof ImplicitVariable && element.isValid()) {
|
||||
return new ImplicitVariableInfo((ImplicitVariable) element, element.getProject());
|
||||
public SmartPointerElementInfo createElementInfo(@NotNull final PsiElement element, @NotNull PsiFile containingFile) {
|
||||
if (element instanceof ImplicitVariable) {
|
||||
return new ImplicitVariableInfo((ImplicitVariable) element, containingFile.getProject());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
+4
-3
@@ -16,17 +16,18 @@
|
||||
package com.intellij.psi.impl.smartPointers;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiImportList;
|
||||
import com.intellij.psi.PsiJavaFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class ImportListElementInfoFactory implements SmartPointerElementInfoFactory {
|
||||
public class ImportListElementInfoFactory extends SmartPointerElementInfoFactory {
|
||||
@Override
|
||||
@Nullable
|
||||
public SmartPointerElementInfo createElementInfo(@NotNull final PsiElement element) {
|
||||
public SmartPointerElementInfo createElementInfo(@NotNull final PsiElement element, @NotNull PsiFile containingFile) {
|
||||
if (element instanceof PsiImportList) {
|
||||
return new ImportListInfo((PsiJavaFile)element.getContainingFile());
|
||||
return new ImportListInfo((PsiJavaFile)containingFile);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.psi.impl.file.impl;
|
||||
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.LanguageFileType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.ResolveScopeProvider;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Limited resolve scope for all java files in module content, but not under source roots.
|
||||
* For example, java files from test data.
|
||||
* There is still a possibility to modify this scope choice with the ResolveScopeEnlarger.
|
||||
*/
|
||||
public class JavaOutOfSourcesResolveScopeProvider extends ResolveScopeProvider {
|
||||
@Nullable
|
||||
@Override
|
||||
public GlobalSearchScope getResolveScope(@NotNull VirtualFile file, Project project) {
|
||||
// For java only! For other languages resolve may be implemented with different rules, requiring larger scope.
|
||||
final FileType type = file.getFileType();
|
||||
if (type instanceof LanguageFileType && ((LanguageFileType)type).getLanguage() == JavaLanguage.INSTANCE) {
|
||||
ProjectFileIndex index = ProjectRootManager.getInstance(project).getFileIndex();
|
||||
if (index.isInContent(file) && !index.isInSource(file)) {
|
||||
return GlobalSearchScope.fileScope(project, file);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+4
-3
@@ -21,6 +21,7 @@ import com.intellij.openapi.application.ReadActionProcessor;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressIndicatorProvider;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
@@ -81,7 +82,7 @@ public class JavaClassInheritorsSearcher extends QueryExecutorBase<PsiClass, Cla
|
||||
AllClassesSearch.search(searchScope, project, parameters.getNameCondition()).forEach(new Processor<PsiClass>() {
|
||||
@Override
|
||||
public boolean process(final PsiClass aClass) {
|
||||
ProgressIndicatorProvider.checkCanceled();
|
||||
ProgressManager.checkCanceled();
|
||||
return isJavaLangObject(aClass) || consumer.process(aClass);
|
||||
}
|
||||
});
|
||||
@@ -95,7 +96,7 @@ public class JavaClassInheritorsSearcher extends QueryExecutorBase<PsiClass, Cla
|
||||
final Processor<PsiClass> processor = new ReadActionProcessor<PsiClass>() {
|
||||
@Override
|
||||
public boolean processInReadAction(PsiClass candidate) {
|
||||
ProgressIndicatorProvider.checkCanceled();
|
||||
ProgressManager.checkCanceled();
|
||||
|
||||
if (parameters.isCheckInheritance() || parameters.isCheckDeep() && !(candidate instanceof PsiAnonymousClass)) {
|
||||
if (!candidate.isInheritor(currentBase.get(), false)) {
|
||||
@@ -130,7 +131,7 @@ public class JavaClassInheritorsSearcher extends QueryExecutorBase<PsiClass, Cla
|
||||
final GlobalSearchScope projectScope = GlobalSearchScope.allScope(project);
|
||||
|
||||
while (!stack.isEmpty()) {
|
||||
ProgressIndicatorProvider.checkCanceled();
|
||||
ProgressManager.checkCanceled();
|
||||
|
||||
final PsiAnchor anchor = stack.pop();
|
||||
if (!processed.add(anchor)) continue;
|
||||
|
||||
+8
-4
@@ -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.
|
||||
@@ -16,7 +16,7 @@
|
||||
package com.intellij.psi.impl.search;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.progress.ProgressIndicatorProvider;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
@@ -74,6 +74,7 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
|
||||
return AllClassesSearch.search(useScope, project).forEach(new Processor<PsiClass>() {
|
||||
@Override
|
||||
public boolean process(final PsiClass psiClass) {
|
||||
ProgressManager.checkCanceled();
|
||||
if (psiClass.isInterface()) {
|
||||
return consumer.process(psiClass);
|
||||
}
|
||||
@@ -113,7 +114,7 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
|
||||
Map<String, List<PsiClass>> classes = new HashMap<String, List<PsiClass>>();
|
||||
|
||||
for (final PsiReferenceList referenceList : candidates) {
|
||||
ProgressIndicatorProvider.checkCanceled();
|
||||
ProgressManager.checkCanceled();
|
||||
final PsiClass candidate = (PsiClass)ApplicationManager.getApplication().runReadAction(new Computable<PsiElement>() {
|
||||
@Override
|
||||
public PsiElement compute() {
|
||||
@@ -139,6 +140,7 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
|
||||
if (!classes.isEmpty()) {
|
||||
final VirtualFile jarFile = getJarFile(aClass);
|
||||
for (List<PsiClass> sameNamedClasses : classes.values()) {
|
||||
ProgressManager.checkCanceled();
|
||||
if (!processSameNamedClasses(consumer, sameNamedClasses, jarFile)) return false;
|
||||
}
|
||||
}
|
||||
@@ -155,7 +157,7 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
|
||||
});
|
||||
|
||||
for (PsiAnonymousClass candidate : anonymousCandidates) {
|
||||
ProgressIndicatorProvider.checkCanceled();
|
||||
ProgressManager.checkCanceled();
|
||||
if (!checkInheritance(p, aClass, candidate, project)) continue;
|
||||
|
||||
if (!consumer.process(candidate)) return false;
|
||||
@@ -176,6 +178,7 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
|
||||
}
|
||||
});
|
||||
for (final PsiField field : fields) {
|
||||
ProgressManager.checkCanceled();
|
||||
if (field instanceof PsiEnumConstant) {
|
||||
PsiEnumConstantInitializer initializingClass =
|
||||
ApplicationManager.getApplication().runReadAction(new Computable<PsiEnumConstantInitializer>() {
|
||||
@@ -210,6 +213,7 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
|
||||
|
||||
if (jarFile != null && sameNamedClasses.size() > 1) {
|
||||
for (PsiClass sameNamedClass : sameNamedClasses) {
|
||||
ProgressManager.checkCanceled();
|
||||
boolean fromSameJar = Comparing.equal(getJarFile(sameNamedClass), jarFile);
|
||||
if (fromSameJar) {
|
||||
sameJarClassFound = true;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -119,7 +119,7 @@ public class MethodUsagesSearcher extends QueryExecutorBase<PsiReference, Method
|
||||
});
|
||||
}
|
||||
|
||||
static <T> T resolveInReadAction(@NotNull Project p, Computable<T> computable) {
|
||||
static <T> T resolveInReadAction(@NotNull Project p, @NotNull Computable<T> computable) {
|
||||
return ApplicationManager.getApplication().isReadAccessAllowed() ? computable.compute() : DumbService.getInstance(p).runReadActionInSmartMode(computable);
|
||||
}
|
||||
|
||||
|
||||
@@ -151,7 +151,7 @@ public class PsiPrimitiveType extends PsiType.Stub {
|
||||
//[ven]previous call returns null for NULL, VOID
|
||||
if (boxedQName == null) return null;
|
||||
JavaPsiFacade facade = JavaPsiFacade.getInstance(file.getProject());
|
||||
PsiClass aClass = facade.findClass(boxedQName, context.getResolveScope());
|
||||
PsiClass aClass = facade.findClass(boxedQName, file.getResolveScope());
|
||||
if (aClass == null) return null;
|
||||
|
||||
PsiElementFactory factory = facade.getElementFactory();
|
||||
|
||||
@@ -117,6 +117,10 @@ public class JavaConstantExpressionEvaluator extends JavaRecursiveElementWalking
|
||||
final PsiConstantEvaluationHelper.AuxEvaluator auxEvaluator) {
|
||||
if (expression == null) return null;
|
||||
|
||||
if (expression instanceof PsiLiteralExpression) {
|
||||
return ((PsiLiteralExpression)expression).getValue(); // don't bother with caching etc
|
||||
}
|
||||
|
||||
JavaConstantExpressionEvaluator evaluator = new JavaConstantExpressionEvaluator(visitedVars, throwExceptionOnOverflow, expression.getProject(), auxEvaluator);
|
||||
|
||||
if (expression instanceof PsiCompiledElement) {
|
||||
|
||||
@@ -16,14 +16,9 @@
|
||||
package com.intellij.psi.impl.source;
|
||||
|
||||
import com.intellij.ide.highlighter.JavaFileType;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.roots.FileIndexFacade;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.FileViewProvider;
|
||||
import com.intellij.psi.impl.java.stubs.JavaStubElementTypes;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.testFramework.LightVirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class PsiJavaFileImpl extends PsiJavaFileBaseImpl {
|
||||
@@ -31,19 +26,6 @@ public class PsiJavaFileImpl extends PsiJavaFileBaseImpl {
|
||||
super(JavaStubElementTypes.JAVA_FILE, JavaStubElementTypes.JAVA_FILE, file);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public GlobalSearchScope getResolveScope() {
|
||||
final VirtualFile file = getVirtualFile();
|
||||
if (file != null && !(file instanceof LightVirtualFile)) {
|
||||
final FileIndexFacade index = ServiceManager.getService(getProject(), FileIndexFacade.class);
|
||||
if (!index.isInSource(file) && !index.isInLibraryClasses(file)) {
|
||||
return GlobalSearchScope.fileScope(this);
|
||||
}
|
||||
}
|
||||
return super.getResolveScope();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public FileType getFileType() {
|
||||
|
||||
+10
-3
@@ -26,6 +26,7 @@ import com.intellij.psi.scope.JavaScopeProcessorEvent;
|
||||
import com.intellij.psi.scope.PsiScopeProcessor;
|
||||
import com.intellij.util.containers.MostlySingularMultiMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
@@ -33,6 +34,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
public class SymbolCollectingProcessor extends BaseScopeProcessor implements ElementClassHint {
|
||||
private final MostlySingularMultiMap<String, ResultWithContext> myResult = new MostlySingularMultiMap<String, ResultWithContext>();
|
||||
private PsiElement myCurrentFileContext = null;
|
||||
private PsiAnchor myCurrentContextAnchor = null;
|
||||
|
||||
@Override
|
||||
public <T> T getHint(@NotNull Key<T> hintKey) {
|
||||
@@ -47,6 +49,7 @@ public class SymbolCollectingProcessor extends BaseScopeProcessor implements Ele
|
||||
public void handleEvent(@NotNull PsiScopeProcessor.Event event, Object associated) {
|
||||
if (event == JavaScopeProcessorEvent.SET_CURRENT_FILE_CONTEXT) {
|
||||
myCurrentFileContext = (PsiElement)associated;
|
||||
myCurrentContextAnchor = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +59,11 @@ public class SymbolCollectingProcessor extends BaseScopeProcessor implements Ele
|
||||
PsiNamedElement named = (PsiNamedElement)element;
|
||||
String name = named.getName();
|
||||
if (name != null) {
|
||||
myResult.add(name, new ResultWithContext(named, myCurrentFileContext));
|
||||
PsiAnchor context = myCurrentContextAnchor;
|
||||
if (context == null && myCurrentFileContext != null) {
|
||||
myCurrentContextAnchor = context = PsiAnchor.create(myCurrentFileContext);
|
||||
}
|
||||
myResult.add(name, new ResultWithContext(named, context));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -75,9 +82,9 @@ public class SymbolCollectingProcessor extends BaseScopeProcessor implements Ele
|
||||
private final PsiAnchor myElement;
|
||||
private final PsiAnchor myFileContext;
|
||||
|
||||
public ResultWithContext(@NotNull PsiNamedElement element, PsiElement fileContext) {
|
||||
public ResultWithContext(@NotNull PsiNamedElement element, @Nullable PsiAnchor fileContext) {
|
||||
myElement = PsiAnchor.create(element);
|
||||
myFileContext = fileContext == null ? null : PsiAnchor.create(fileContext);
|
||||
myFileContext = fileContext;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+2
-5
@@ -42,12 +42,8 @@ public class VariableResolverProcessor extends ConflictFilterProcessor implement
|
||||
private PsiElement myCurrentFileContext = null;
|
||||
|
||||
public VariableResolverProcessor(@NotNull PsiJavaCodeReferenceElement place, @NotNull PsiFile placeFile) {
|
||||
super(place.getText(), ourFilter, new PsiConflictResolver[]{new JavaVariableConflictResolver()}, new SmartList<CandidateInfo>(), place, placeFile);
|
||||
super(place.getReferenceName(), ourFilter, new PsiConflictResolver[]{new JavaVariableConflictResolver()}, new SmartList<CandidateInfo>(), place, placeFile);
|
||||
|
||||
PsiElement referenceName = place.getReferenceNameElement();
|
||||
if (referenceName instanceof PsiIdentifier){
|
||||
setName(referenceName.getText());
|
||||
}
|
||||
PsiClass access = null;
|
||||
PsiElement qualifier = place.getQualifier();
|
||||
if (qualifier instanceof PsiExpression) {
|
||||
@@ -108,6 +104,7 @@ public class VariableResolverProcessor extends ConflictFilterProcessor implement
|
||||
@Override
|
||||
public <T> T getHint(@NotNull Key<T> hintKey) {
|
||||
if (hintKey == ElementClassHint.KEY) {
|
||||
//noinspection unchecked
|
||||
return (T)this;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems>
|
||||
<problem>
|
||||
<file>testSimple_0.iml</file>
|
||||
<file>testSimple.iml</file>
|
||||
<problem_class>Unused library</problem_class>
|
||||
<description>Unused library 'JUnit'</description>
|
||||
</problem>
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.execution;
|
||||
|
||||
import com.intellij.execution.application.ApplicationConfigurable;
|
||||
@@ -135,7 +150,7 @@ public class ConfigurationsTest extends BaseConfigurationTestCase {
|
||||
PsiClass testA = findTestA(getModule1());
|
||||
JUnitConfiguration configuration = createConfiguration(testA);
|
||||
JavaParameters parameters = checkCanRun(configuration);
|
||||
CHECK.empty(parameters.getVMParametersList().getList());
|
||||
assertEmpty(parameters.getVMParametersList().getList());
|
||||
final SegmentedOutputStream notifications = new SegmentedOutputStream(System.out);
|
||||
assertTrue(JUnitStarter.checkVersion(parameters.getProgramParametersList().getArray(),
|
||||
new PrintStream(notifications)));
|
||||
|
||||
+26
-1
@@ -29,7 +29,7 @@ public class JavaFormatterMultilineMethodCallParamsTest extends AbstractJavaForm
|
||||
);
|
||||
}
|
||||
|
||||
public void IGNORED_testChainedMethodInsideCall_WithRParenOnNewLine() {
|
||||
public void testChainedMethodInsideCall_WithRParenOnNewLine() {
|
||||
doMethodTest(
|
||||
"call(new StringBuilder()\n" +
|
||||
".append(\"aaa\")\n" +
|
||||
@@ -41,6 +41,31 @@ public class JavaFormatterMultilineMethodCallParamsTest extends AbstractJavaForm
|
||||
");"
|
||||
);
|
||||
}
|
||||
|
||||
public void testLambdas() {
|
||||
doTextTest(
|
||||
"public class Main {\n" +
|
||||
" public static void main(String... args) throws Exception {\n" +
|
||||
" RatpackServer.start(server -> server\n" +
|
||||
" .handlers(chain -> chain\n" +
|
||||
" .get(ctx -> ctx.render(\"Hello World!\"))\n" +
|
||||
" .get(\":name\", ctx -> ctx.render(\"Hello \" + ctx.getPathTokens().get(\"name\") + \"!\"))\n" +
|
||||
" )\n" +
|
||||
" );\n" +
|
||||
" }\n" +
|
||||
"}",
|
||||
"public class Main {\n" +
|
||||
" public static void main(String... args) throws Exception {\n" +
|
||||
" RatpackServer.start(server -> server\n" +
|
||||
" .handlers(chain -> chain\n" +
|
||||
" .get(ctx -> ctx.render(\"Hello World!\"))\n" +
|
||||
" .get(\":name\", ctx -> ctx.render(\"Hello \" + ctx.getPathTokens().get(\"name\") + \"!\"))\n" +
|
||||
" )\n" +
|
||||
" );\n" +
|
||||
" }\n" +
|
||||
"}"
|
||||
);
|
||||
}
|
||||
|
||||
public void testChainedMethodInsideCall_Shifted() {
|
||||
doMethodTest(
|
||||
|
||||
@@ -16,36 +16,23 @@
|
||||
|
||||
package com.intellij.refactoring;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.openapi.application.ex.PathManagerEx;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleUtil;
|
||||
import com.intellij.openapi.roots.ModifiableRootModel;
|
||||
import com.intellij.openapi.roots.ModuleRootModificationUtil;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.refactoring.move.moveClassesOrPackages.MoveClassesOrPackagesProcessor;
|
||||
import com.intellij.refactoring.move.moveClassesOrPackages.SingleSourceRootMoveDestination;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.refactoring.util.RefactoringConflictsUtil;
|
||||
import com.intellij.testFramework.*;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
import com.intellij.testFramework.UsefulTestCase;
|
||||
import com.intellij.testFramework.builders.JavaModuleFixtureBuilder;
|
||||
import com.intellij.testFramework.fixtures.*;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
|
||||
public class MultipleJdksMoveClassTest extends RefactoringTestCase {
|
||||
|
||||
public class MultipleJdksMoveClassTest extends UsefulTestCase {
|
||||
private CodeInsightTestFixture myFixture;
|
||||
private Module myJava7Module;
|
||||
private Module myJava8Module;
|
||||
|
||||
@@ -127,9 +127,7 @@ public class RootsChangedTest extends ModuleTestCase {
|
||||
public void testEditLibraryForModuleLoadFromXml() throws IOException {
|
||||
final File tempDirectory = createTempDirectory();
|
||||
ApplicationManager.getApplication().runWriteAction(() -> {
|
||||
File moduleFile =
|
||||
PathManagerEx.findFileUnderProjectHome("java/java-tests/testData/moduleRootManager/rootsChanged/emptyModule/a.iml", RootsChangedTest.this.getClass());
|
||||
Module a = loadModule(moduleFile, true);
|
||||
Module a = loadModule(PathManagerEx.getHomePath(getClass()) + "/java/java-tests/testData/moduleRootManager/rootsChanged/emptyModule/a.iml");
|
||||
assertEventsCount(1);
|
||||
|
||||
final Sdk jdk = IdeaTestUtil.getMockJdk17();
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
package com.intellij.compiler;
|
||||
|
||||
import com.intellij.compiler.server.BuildManager;
|
||||
import com.intellij.openapi.application.AccessToken;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.application.Result;
|
||||
import com.intellij.openapi.application.WriteAction;
|
||||
import com.intellij.openapi.application.ex.ApplicationManagerEx;
|
||||
@@ -31,9 +31,11 @@ import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.roots.ModuleRootModificationUtil;
|
||||
import com.intellij.testFramework.EdtTestUtil;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.ThrowableRunnable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -55,22 +57,22 @@ public class CompilerTestUtil {
|
||||
}
|
||||
|
||||
public static void saveApplicationSettings() {
|
||||
ApplicationManager.getApplication().invokeAndWait(new Runnable() {
|
||||
EdtTestUtil.runInEdtAndWait(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
doSaveComponent(ProjectJdkTable.getInstance());
|
||||
doSaveComponent(FileTypeManager.getInstance());
|
||||
}
|
||||
}, ModalityState.any());
|
||||
});
|
||||
}
|
||||
|
||||
public static void saveApplicationComponent(final Object appComponent) {
|
||||
ApplicationManager.getApplication().invokeAndWait(new Runnable() {
|
||||
EdtTestUtil.runInEdtAndWait(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
doSaveComponent(appComponent);
|
||||
}
|
||||
}, ModalityState.any());
|
||||
});
|
||||
}
|
||||
|
||||
private static void doSaveComponent(Object appComponent) {
|
||||
@@ -89,27 +91,36 @@ public class CompilerTestUtil {
|
||||
}.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) {
|
||||
Module[] modules = ModuleManager.getInstance(project).getModules();
|
||||
Sdk internalJdk = table.getInternalJdk();
|
||||
List<Module> modulesToRestore = new ArrayList<Module>();
|
||||
for (Module module : modules) {
|
||||
Sdk sdk = ModuleRootManager.getInstance(module).getSdk();
|
||||
if (sdk != null && sdk.equals(internalJdk)) {
|
||||
modulesToRestore.add(module);
|
||||
public static void disableExternalCompiler(@NotNull final Project project) {
|
||||
try {
|
||||
EdtTestUtil.runInEdtAndWait(new ThrowableRunnable<Throwable>() {
|
||||
@Override
|
||||
public void run() throws Throwable {
|
||||
JavaAwareProjectJdkTableImpl table = JavaAwareProjectJdkTableImpl.getInstanceEx();
|
||||
AccessToken token = WriteAction.start();
|
||||
try {
|
||||
Sdk internalJdk = table.getInternalJdk();
|
||||
List<Module> modulesToRestore = new SmartList<Module>();
|
||||
for (Module module : ModuleManager.getInstance(project).getModules()) {
|
||||
Sdk sdk = ModuleRootManager.getInstance(module).getSdk();
|
||||
if (sdk != null && sdk.equals(internalJdk)) {
|
||||
modulesToRestore.add(module);
|
||||
}
|
||||
}
|
||||
table.removeJdk(internalJdk);
|
||||
for (Module module : modulesToRestore) {
|
||||
ModuleRootModificationUtil.setModuleSdk(module, internalJdk);
|
||||
}
|
||||
BuildManager.getInstance().clearState(project);
|
||||
}
|
||||
finally {
|
||||
token.finish();
|
||||
}
|
||||
}
|
||||
table.removeJdk(internalJdk);
|
||||
for (Module module : modulesToRestore) {
|
||||
ModuleRootModificationUtil.setModuleSdk(module, internalJdk);
|
||||
}
|
||||
BuildManager.getInstance().clearState(project);
|
||||
}
|
||||
}.execute();
|
||||
});
|
||||
}
|
||||
finally {
|
||||
ApplicationManagerEx.getApplicationEx().doNotSave(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+11
-6
@@ -39,10 +39,11 @@ import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.testFramework.CompositeException;
|
||||
import com.intellij.ui.classFilter.ClassFilter;
|
||||
import com.intellij.util.IJSwingUtilities;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.TimeoutUtil;
|
||||
import com.intellij.util.lang.CompoundRuntimeException;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.sun.jdi.Method;
|
||||
import com.sun.jdi.ThreadReference;
|
||||
@@ -58,7 +59,7 @@ public abstract class ExecutionWithDebuggerToolsTestCase extends ExecutionTestCa
|
||||
private final SynchronizationBasedSemaphore myScriptRunnablesSema = new SynchronizationBasedSemaphore();
|
||||
protected static final int RATHER_LATER_INVOKES_N = 10;
|
||||
public DebugProcessImpl myDebugProcess = null;
|
||||
private final CompositeException myException = new CompositeException();
|
||||
private final List<Throwable> myException = new SmartList<Throwable>();
|
||||
|
||||
private static class InvokeRatherLaterRequest {
|
||||
private final DebuggerCommandImpl myDebuggerCommand;
|
||||
@@ -112,13 +113,17 @@ public abstract class ExecutionWithDebuggerToolsTestCase extends ExecutionTestCa
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
throwExceptionsIfAny();
|
||||
try {
|
||||
super.tearDown();
|
||||
}
|
||||
finally {
|
||||
throwExceptionsIfAny();
|
||||
}
|
||||
}
|
||||
|
||||
protected void throwExceptionsIfAny() throws CompositeException {
|
||||
protected void throwExceptionsIfAny() {
|
||||
synchronized (myException) {
|
||||
myException.throwIfNotEmpty();
|
||||
CompoundRuntimeException.throwIfNotEmpty(myException);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -31,13 +31,10 @@ import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.testFramework.CompilerTester;
|
||||
import com.intellij.testFramework.IdeaTestCase;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
import com.intellij.testFramework.PsiTestUtil;
|
||||
import com.intellij.testFramework.*;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.PathUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.util.ThrowableRunnable;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import java.io.File;
|
||||
@@ -70,16 +67,10 @@ public abstract class ExecutionTestCase extends IdeaTestCase {
|
||||
}
|
||||
myModuleOutputDir = new File(ourOutputRoot, PathUtil.getFileName(getTestAppPath()));
|
||||
myChecker = initOutputChecker();
|
||||
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
|
||||
EdtTestUtil.runInEdtAndWait(new ThrowableRunnable<Throwable>() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
ExecutionTestCase.super.setUp();
|
||||
}
|
||||
catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
assertTrue(false);
|
||||
}
|
||||
public void run() throws Throwable {
|
||||
ExecutionTestCase.super.setUp();
|
||||
}
|
||||
});
|
||||
if (!myModuleOutputDir.exists()) {
|
||||
@@ -129,7 +120,7 @@ public abstract class ExecutionTestCase extends IdeaTestCase {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void runBareRunnable(Runnable runnable) throws Throwable {
|
||||
protected void runBareRunnable(ThrowableRunnable<Throwable> runnable) throws Throwable {
|
||||
runnable.run();
|
||||
}
|
||||
|
||||
@@ -144,15 +135,10 @@ public abstract class ExecutionTestCase extends IdeaTestCase {
|
||||
if (myCompilerTester != null) {
|
||||
myCompilerTester.tearDown();
|
||||
}
|
||||
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
|
||||
EdtTestUtil.runInEdtAndWait(new ThrowableRunnable<Throwable>() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
ExecutionTestCase.super.tearDown();
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
public void run() throws Throwable {
|
||||
ExecutionTestCase.super.tearDown();
|
||||
}
|
||||
});
|
||||
//myChecker.checkValid(getTestProjectJdk());
|
||||
|
||||
@@ -16,17 +16,15 @@
|
||||
package com.intellij.testFramework;
|
||||
|
||||
import com.intellij.ide.highlighter.ModuleFileType;
|
||||
import com.intellij.openapi.application.AccessToken;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.WriteAction;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.components.ComponentsPackage;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.module.ModuleType;
|
||||
import com.intellij.openapi.module.StdModuleTypes;
|
||||
import com.intellij.openapi.module.impl.ModuleImpl;
|
||||
import com.intellij.openapi.project.ex.ProjectEx;
|
||||
import com.intellij.openapi.project.impl.ProjectImpl;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
@@ -34,6 +32,9 @@ import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileVisitor;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.lang.CompoundRuntimeException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -41,7 +42,7 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class ModuleTestCase extends IdeaTestCase {
|
||||
protected final Collection<Module> myModulesToDispose = new ArrayList<Module>();
|
||||
@@ -55,18 +56,30 @@ public abstract class ModuleTestCase extends IdeaTestCase {
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
try {
|
||||
final ModuleManager moduleManager = ModuleManager.getInstance(myProject);
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (Module module : myModulesToDispose) {
|
||||
ModuleManager moduleManager = ModuleManager.getInstance(myProject);
|
||||
List<Throwable> errors = null;
|
||||
AccessToken token = WriteAction.start();
|
||||
try {
|
||||
for (Module module : myModulesToDispose) {
|
||||
try {
|
||||
String moduleName = module.getName();
|
||||
if (moduleManager.findModuleByName(moduleName) != null) {
|
||||
moduleManager.disposeModule(module);
|
||||
}
|
||||
}
|
||||
catch (Throwable e) {
|
||||
if (errors == null) {
|
||||
errors = new SmartList<Throwable>();
|
||||
}
|
||||
errors.add(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
finally {
|
||||
token.finish();
|
||||
}
|
||||
|
||||
CompoundRuntimeException.throwIfNotEmpty(errors);
|
||||
}
|
||||
finally {
|
||||
myModulesToDispose.clear();
|
||||
@@ -97,53 +110,45 @@ public abstract class ModuleTestCase extends IdeaTestCase {
|
||||
return module;
|
||||
}
|
||||
|
||||
protected Module loadModule(final File moduleFile) {
|
||||
return loadModule(moduleFile, false);
|
||||
}
|
||||
protected Module loadModule(@NotNull String modulePath) {
|
||||
String normalizedPath = FileUtil.toSystemIndependentName(modulePath);
|
||||
LocalFileSystem.getInstance().refreshAndFindFileByPath(normalizedPath);
|
||||
|
||||
protected Module loadModule(final File moduleFile, final boolean loadComponentStates) {
|
||||
Module module = ApplicationManager.getApplication().runWriteAction(
|
||||
new Computable<Module>() {
|
||||
@Override
|
||||
public Module compute() {
|
||||
ProjectImpl project = (ProjectImpl)myProject;
|
||||
boolean oldOptimiseTestLoadSpeed = project.isOptimiseTestLoadSpeed();
|
||||
if (loadComponentStates) {
|
||||
project.setOptimiseTestLoadSpeed(false);
|
||||
}
|
||||
try {
|
||||
LocalFileSystem.getInstance().refreshIoFiles(Collections.singletonList(moduleFile));
|
||||
return ModuleManager.getInstance(myProject).loadModule(moduleFile.getAbsolutePath());
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error(e);
|
||||
return null;
|
||||
}
|
||||
finally {
|
||||
project.setOptimiseTestLoadSpeed(oldOptimiseTestLoadSpeed);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
ModuleManager moduleManager = ModuleManager.getInstance(myProject);
|
||||
Module module;
|
||||
AccessToken token = WriteAction.start();
|
||||
try {
|
||||
module = moduleManager.loadModule(normalizedPath);
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error(e);
|
||||
return null;
|
||||
}
|
||||
finally {
|
||||
token.finish();
|
||||
}
|
||||
|
||||
myModulesToDispose.add(module);
|
||||
return module;
|
||||
}
|
||||
|
||||
protected Module loadModule(final String modulePath) {
|
||||
return loadModule(new File(modulePath));
|
||||
@Nullable
|
||||
protected Module loadAllModulesUnder(@NotNull VirtualFile rootDir) {
|
||||
return loadAllModulesUnder(rootDir, null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected Module loadAllModulesUnder(@NotNull VirtualFile rootDir) throws Exception {
|
||||
protected Module loadAllModulesUnder(@NotNull VirtualFile rootDir, @Nullable final Consumer<Module> moduleConsumer) {
|
||||
final Ref<Module> result = Ref.create();
|
||||
|
||||
VfsUtilCore.visitChildrenRecursively(rootDir, new VirtualFileVisitor() {
|
||||
@Override
|
||||
public boolean visitFile(@NotNull VirtualFile file) {
|
||||
if (!file.isDirectory() && file.getName().endsWith(ModuleFileType.DOT_DEFAULT_EXTENSION)) {
|
||||
ModuleImpl module = (ModuleImpl)loadModule(new File(file.getPath()));
|
||||
readJdomExternalizables(module);
|
||||
ModuleImpl module = (ModuleImpl)loadModule(file.getPath());
|
||||
if (moduleConsumer != null) {
|
||||
moduleConsumer.consume(module);
|
||||
}
|
||||
result.setIfNull(module);
|
||||
}
|
||||
return true;
|
||||
@@ -153,21 +158,6 @@ public abstract class ModuleTestCase extends IdeaTestCase {
|
||||
return result.get();
|
||||
}
|
||||
|
||||
protected void readJdomExternalizables(@NotNull Module module) {
|
||||
loadModuleComponentState(module, ModuleRootManager.getInstance(module));
|
||||
}
|
||||
|
||||
protected final void loadModuleComponentState(@NotNull Module module, @NotNull Object component) {
|
||||
ProjectEx project = (ProjectEx)myProject;
|
||||
project.setOptimiseTestLoadSpeed(false);
|
||||
try {
|
||||
ComponentsPackage.getStateStore(module).initComponent(component, false);
|
||||
}
|
||||
finally {
|
||||
project.setOptimiseTestLoadSpeed(true);
|
||||
}
|
||||
}
|
||||
|
||||
protected Module createModuleFromTestData(final String dirInTestData, final String newModuleFileName, final ModuleType moduleType,
|
||||
final boolean addSourceRoot)
|
||||
throws IOException {
|
||||
|
||||
@@ -62,11 +62,15 @@ public abstract class PsiTestCase extends ModuleTestCase {
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
myPsiManager = null;
|
||||
myFile = null;
|
||||
myTestDataBefore = null;
|
||||
myTestDataAfter = null;
|
||||
super.tearDown();
|
||||
try {
|
||||
myPsiManager = null;
|
||||
myFile = null;
|
||||
myTestDataBefore = null;
|
||||
myTestDataAfter = null;
|
||||
}
|
||||
finally {
|
||||
super.tearDown();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+51
-41
@@ -27,6 +27,7 @@ import com.intellij.openapi.projectRoots.impl.ProjectJdkImpl;
|
||||
import com.intellij.openapi.roots.*;
|
||||
import com.intellij.openapi.roots.libraries.Library;
|
||||
import com.intellij.openapi.roots.libraries.LibraryTable;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.JarFileSystem;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
@@ -39,6 +40,7 @@ import com.intellij.testFramework.fixtures.IdeaProjectTestFixture;
|
||||
import com.intellij.testFramework.fixtures.ModuleFixture;
|
||||
import com.intellij.testFramework.fixtures.TestFixtureBuilder;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import java.io.File;
|
||||
@@ -116,51 +118,59 @@ abstract class JavaModuleFixtureBuilderImpl<T extends ModuleFixture> extends Mod
|
||||
protected void initModule(final Module module) {
|
||||
super.initModule(module);
|
||||
|
||||
final ModifiableRootModel model = ModuleRootManager.getInstance(module).getModifiableModel();
|
||||
final LibraryTable libraryTable = model.getModuleLibraryTable();
|
||||
|
||||
for (Lib lib : myLibraries) {
|
||||
String libraryName = lib.getName();
|
||||
|
||||
final Library library = libraryTable.createLibrary(libraryName);
|
||||
|
||||
final Library.ModifiableModel libraryModel = library.getModifiableModel();
|
||||
|
||||
for (OrderRootType rootType : OrderRootType.getAllTypes()) {
|
||||
final String[] roots = lib.getRoots(rootType);
|
||||
for (String root : roots) {
|
||||
VirtualFile vRoot = LocalFileSystem.getInstance().refreshAndFindFileByPath(root);
|
||||
if (vRoot != null && OrderRootType.CLASSES.equals(rootType) && !vRoot.isDirectory()) {
|
||||
final VirtualFile jar = JarFileSystem.getInstance().refreshAndFindFileByPath(root + "!/");
|
||||
if (jar != null) vRoot = jar;
|
||||
ModuleRootModificationUtil.updateModel(module, new Consumer<ModifiableRootModel>() {
|
||||
@Override
|
||||
public void consume(ModifiableRootModel model) {
|
||||
LibraryTable libraryTable = model.getModuleLibraryTable();
|
||||
for (Lib lib : myLibraries) {
|
||||
Library library = libraryTable.createLibrary(lib.getName());
|
||||
Library.ModifiableModel libraryModel = library.getModifiableModel();
|
||||
boolean success = false;
|
||||
try {
|
||||
for (OrderRootType rootType : OrderRootType.getAllTypes()) {
|
||||
for (String root : lib.getRoots(rootType)) {
|
||||
VirtualFile vRoot = LocalFileSystem.getInstance().refreshAndFindFileByPath(root);
|
||||
if (vRoot != null && OrderRootType.CLASSES.equals(rootType) && !vRoot.isDirectory()) {
|
||||
VirtualFile jar = JarFileSystem.getInstance().refreshAndFindFileByPath(root + "!/");
|
||||
if (jar != null) {
|
||||
vRoot = jar;
|
||||
}
|
||||
}
|
||||
if (vRoot != null) {
|
||||
libraryModel.addRoot(vRoot, rootType);
|
||||
}
|
||||
}
|
||||
}
|
||||
success = true;
|
||||
}
|
||||
if (vRoot != null) {
|
||||
libraryModel.addRoot(vRoot, rootType);
|
||||
finally {
|
||||
if (!success) {
|
||||
Disposer.dispose(libraryModel);
|
||||
}
|
||||
}
|
||||
|
||||
libraryModel.commit();
|
||||
}
|
||||
|
||||
final Sdk jdk;
|
||||
if (myJdk != null) {
|
||||
VfsRootAccess.allowRootAccessTemporarily(module, myJdk);
|
||||
jdk = JavaSdk.getInstance().createJdk(module.getName() + "_jdk", myJdk, false);
|
||||
((ProjectJdkImpl)jdk).setVersionString(StringUtil.notNullize(IdeaTestUtil.getMockJdkVersion(myJdk), "java 1.5"));
|
||||
}
|
||||
else {
|
||||
jdk = IdeaTestUtil.getMockJdk17();
|
||||
}
|
||||
model.setSdk(new MockJdkWrapper(CompilerConfigurationImpl.getTestsExternalCompilerHome(), jdk));
|
||||
|
||||
if (myLanguageLevel != null) {
|
||||
model.getModuleExtension(LanguageLevelModuleExtension.class).setLanguageLevel(myLanguageLevel);
|
||||
}
|
||||
else if (myMockJdkLevel == MockJdkLevel.jdk15) {
|
||||
model.getModuleExtension(LanguageLevelModuleExtension.class).setLanguageLevel(LanguageLevel.JDK_1_5);
|
||||
}
|
||||
}
|
||||
libraryModel.commit();
|
||||
}
|
||||
|
||||
final Sdk jdk;
|
||||
if (myJdk != null) {
|
||||
VfsRootAccess.allowRootAccessTemporarily(module, myJdk);
|
||||
jdk = JavaSdk.getInstance().createJdk(module.getName() + "_jdk", myJdk, false);
|
||||
((ProjectJdkImpl)jdk).setVersionString(StringUtil.notNullize(IdeaTestUtil.getMockJdkVersion(myJdk), "java 1.5"));
|
||||
}
|
||||
else {
|
||||
jdk = IdeaTestUtil.getMockJdk17();
|
||||
}
|
||||
model.setSdk(new MockJdkWrapper(CompilerConfigurationImpl.getTestsExternalCompilerHome(), jdk));
|
||||
|
||||
if (myLanguageLevel != null) {
|
||||
model.getModuleExtension(LanguageLevelModuleExtension.class).setLanguageLevel(myLanguageLevel);
|
||||
}
|
||||
else if (myMockJdkLevel == MockJdkLevel.jdk15) {
|
||||
model.getModuleExtension(LanguageLevelModuleExtension.class).setLanguageLevel(LanguageLevel.JDK_1_5);
|
||||
}
|
||||
|
||||
model.commit();
|
||||
});
|
||||
|
||||
for (OrderEntry entry : ModuleRootManager.getInstance(module).getOrderEntries()) {
|
||||
if (entry instanceof LibraryOrderEntry) {
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<orderEntry type="library" name="JDOM" level="project" />
|
||||
<orderEntry type="library" name="Log4J" level="project" />
|
||||
<orderEntry type="module" module-name="lang-api" exported="" />
|
||||
<orderEntry type="module" module-name="lang-impl" exported="" />
|
||||
<orderEntry type="module" module-name="lang-impl" />
|
||||
<orderEntry type="module" module-name="compiler-impl" />
|
||||
<orderEntry type="module" module-name="java-impl" exported="" />
|
||||
<orderEntry type="module" module-name="execution-impl" exported="" scope="RUNTIME" />
|
||||
|
||||
@@ -59,7 +59,7 @@ public abstract class DefaultProjectProfileManager extends ProjectProfileManager
|
||||
protected final Project myProject;
|
||||
|
||||
private String myProjectProfile;
|
||||
/** This field is used for serialization. Do not rename it or make access weaker */
|
||||
|
||||
@OptionTag("USE_PROJECT_PROFILE")
|
||||
private boolean useProjectProfile = true;
|
||||
|
||||
|
||||
+1
-4
@@ -21,7 +21,6 @@ import com.intellij.lang.annotation.HighlightSeverity;
|
||||
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.JDOMExternalizable;
|
||||
import com.intellij.openapi.util.JDOMExternalizableStringList;
|
||||
import com.intellij.profile.codeInspection.InspectionProfileManager;
|
||||
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
|
||||
@@ -47,7 +46,7 @@ import java.util.List;
|
||||
* User: anna
|
||||
* Date: 24-Feb-2006
|
||||
*/
|
||||
public class SeverityRegistrar implements JDOMExternalizable, Comparator<HighlightSeverity> {
|
||||
public class SeverityRegistrar implements Comparator<HighlightSeverity> {
|
||||
@NonNls private static final String INFO_TAG = "info";
|
||||
@NonNls private static final String COLOR_ATTRIBUTE = "color";
|
||||
private final Map<String, SeverityBasedTextAttributes> myMap = ContainerUtil.newConcurrentMap();
|
||||
@@ -132,7 +131,6 @@ public class SeverityRegistrar implements JDOMExternalizable, Comparator<Highlig
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void readExternal(Element element) {
|
||||
myMap.clear();
|
||||
myRendererColors.clear();
|
||||
@@ -178,7 +176,6 @@ public class SeverityRegistrar implements JDOMExternalizable, Comparator<Highlig
|
||||
severitiesChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeExternal(Element element) {
|
||||
List<HighlightSeverity> list = getOrderAsList(getOrderMap());
|
||||
for (HighlightSeverity severity : list) {
|
||||
|
||||
+37
-31
@@ -124,6 +124,15 @@ public class FileReferenceSet {
|
||||
return "/";
|
||||
}
|
||||
|
||||
protected int findSeparatorLength(@NotNull CharSequence sequence, int atOffset) {
|
||||
return StringUtil.startsWith(sequence, atOffset, getSeparatorString()) ?
|
||||
getSeparatorString().length() : 0;
|
||||
}
|
||||
|
||||
protected int findSeparatorOffset(@NotNull CharSequence sequence, int startingFrom) {
|
||||
return StringUtil.indexOf(sequence, getSeparatorString(), startingFrom);
|
||||
}
|
||||
|
||||
/**
|
||||
* This should be removed. Please use {@link FileReference#getContexts()} instead.
|
||||
*/
|
||||
@@ -216,17 +225,12 @@ public class FileReferenceSet {
|
||||
}
|
||||
|
||||
protected void reparse() {
|
||||
String str = myPathStringNonTrimmed;
|
||||
|
||||
final List<FileReference> referencesList = reparse(str, myStartInElement);
|
||||
|
||||
List<FileReference> referencesList = reparse(myPathStringNonTrimmed, myStartInElement);
|
||||
myReferences = referencesList.toArray(new FileReference[referencesList.size()]);
|
||||
}
|
||||
|
||||
protected List<FileReference> reparse(String str, int startInElement) {
|
||||
String separatorString = getSeparatorString(); // separator's length can be more then 1 char
|
||||
int sepLen = separatorString.length();
|
||||
int currentSlash = -sepLen;
|
||||
int wsHead = 0;
|
||||
int wsTail = 0;
|
||||
|
||||
LiteralTextEscaper<? extends PsiLanguageInjectionHost> escaper;
|
||||
@@ -239,7 +243,7 @@ public class FileReferenceSet {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
escaper.decode(valueRange, sb);
|
||||
decoded = sb;
|
||||
currentSlash += startInElement - valueRange.getStartOffset();
|
||||
wsHead += Math.max(0, startInElement - valueRange.getStartOffset());
|
||||
}
|
||||
else {
|
||||
escaper = null;
|
||||
@@ -248,36 +252,38 @@ public class FileReferenceSet {
|
||||
}
|
||||
List<FileReference> referencesList = ContainerUtil.newArrayList();
|
||||
|
||||
// skip head white spaces
|
||||
for (int i = currentSlash + sepLen; i < decoded.length() && Character.isWhitespace(decoded.charAt(i)); i++) {
|
||||
currentSlash++;
|
||||
for (int i = wsHead; i < decoded.length() && Character.isWhitespace(decoded.charAt(i)); i++) {
|
||||
wsHead++; // skip head white spaces
|
||||
}
|
||||
// skip tail white spaces
|
||||
for (int i = decoded.length() - 1; i >= 0 && Character.isWhitespace(decoded.charAt(i)); i--) {
|
||||
wsTail++;
|
||||
wsTail++; // skip tail white spaces
|
||||
}
|
||||
|
||||
if (currentSlash + 2 * sepLen < decoded.length() &&
|
||||
StringUtil.equals(decoded.subSequence(currentSlash + sepLen, currentSlash + 2 * sepLen), separatorString)) {
|
||||
currentSlash += sepLen;
|
||||
}
|
||||
int index = 0;
|
||||
int curSep = findSeparatorOffset(decoded, wsHead);
|
||||
int sepLen = curSep >= wsHead ? findSeparatorLength(decoded, curSep) : 0;
|
||||
|
||||
if (decoded.equals(separatorString)) {
|
||||
TextRange r = new TextRange(startInElement, offset(sepLen, escaper, valueRange) + 1);
|
||||
referencesList.add(createFileReference(r, index++, separatorString));
|
||||
if (curSep >= 0 && decoded.length() == wsHead + sepLen + wsTail) {
|
||||
// add extra reference for the only & leading "/"
|
||||
TextRange r = TextRange.create(startInElement, offset(curSep + Math.max(0, sepLen - 1), escaper, valueRange) + 1);
|
||||
referencesList.add(createFileReference(r, 0, decoded.subSequence(curSep, curSep + sepLen).toString()));
|
||||
}
|
||||
|
||||
while (true) {
|
||||
int nextSlash = StringUtil.indexOf(decoded, separatorString, currentSlash + sepLen);
|
||||
String subReferenceText = decoded.subSequence(currentSlash + sepLen, nextSlash > 0 ? nextSlash : decoded.length()).toString();
|
||||
int end = nextSlash > 0 ? nextSlash : Math.max(currentSlash + sepLen, decoded.length() - 1 - wsTail);
|
||||
TextRange r = new TextRange(offset(currentSlash + sepLen, escaper, valueRange),
|
||||
offset(end, escaper, valueRange) + (nextSlash > 0 ? 0 : 1));
|
||||
referencesList.add(createFileReference(r, index++, subReferenceText));
|
||||
if ((currentSlash = nextSlash) < 0) {
|
||||
break;
|
||||
}
|
||||
curSep = curSep == wsHead ? curSep + sepLen : wsHead; // reset offsets & start again for simplicity
|
||||
sepLen = 0;
|
||||
while (curSep >= 0) {
|
||||
int nextSep = findSeparatorOffset(decoded, curSep + sepLen);
|
||||
int start = curSep + sepLen;
|
||||
int endTrimmed = nextSep > 0 ? nextSep : Math.max(start, decoded.length() - wsTail);
|
||||
int endInclusive = nextSep > 0 ? nextSep : Math.max(start, decoded.length() - 1 - wsTail);
|
||||
// todo move ${placeholder} support (the str usage below) to a reference implementation
|
||||
// todo reference-set should be bound to exact range & text in a file, consider: ${slash}path${slash}file&.txt
|
||||
String refText = index == 0 && nextSep < 0 && !StringUtil.contains(decoded, str) ? str :
|
||||
decoded.subSequence(start, endTrimmed).toString();
|
||||
TextRange r = new TextRange(offset(start, escaper, valueRange),
|
||||
offset(endInclusive, escaper, valueRange) + (nextSep < 0 && refText.length() > 0 ? 1 : 0));
|
||||
referencesList.add(createFileReference(r, index++, refText));
|
||||
curSep = nextSep;
|
||||
sepLen = curSep > 0 ? findSeparatorLength(decoded, curSep) : 0;
|
||||
}
|
||||
|
||||
return referencesList;
|
||||
|
||||
@@ -44,9 +44,9 @@ import java.io.File
|
||||
import java.net.InetAddress
|
||||
import java.net.UnknownHostException
|
||||
|
||||
public class BuiltInWebServer : HttpRequestHandler() {
|
||||
class BuiltInWebServer : HttpRequestHandler() {
|
||||
companion object {
|
||||
val LOG = Logger.getInstance(javaClass<BuiltInWebServer>())
|
||||
val LOG = Logger.getInstance(BuiltInWebServer::class.java)
|
||||
|
||||
private fun doProcess(request: FullHttpRequest, context: ChannelHandlerContext, projectNameAsHost: String?): Boolean {
|
||||
val decodedPath = URLUtil.unescapePercentSequences(UriUtil.trimParameters(request.uri()))
|
||||
@@ -67,15 +67,15 @@ public class BuiltInWebServer : HttpRequestHandler() {
|
||||
}
|
||||
|
||||
var candidateByDirectoryName: Project? = null
|
||||
val project = ProjectManager.getInstance().getOpenProjects().firstOrNull(fun(project: Project): Boolean {
|
||||
if (project.isDisposed()) {
|
||||
val project = ProjectManager.getInstance().openProjects.firstOrNull(fun(project: Project): Boolean {
|
||||
if (project.isDisposed) {
|
||||
return false
|
||||
}
|
||||
|
||||
val name = project.getName()
|
||||
val name = project.name
|
||||
if (isCustomHost) {
|
||||
// domain name is case-insensitive
|
||||
if (projectName.equals(project.getName(), ignoreCase = true)) {
|
||||
if (projectName.equals(project.name, ignoreCase = true)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -101,7 +101,7 @@ public class BuiltInWebServer : HttpRequestHandler() {
|
||||
if (emptyPath) {
|
||||
if (!SystemInfoRt.isFileSystemCaseSensitive) {
|
||||
// may be passed path is not correct
|
||||
projectName = project.getName()
|
||||
projectName = project.name
|
||||
}
|
||||
|
||||
// we must redirect "jsdebug" to "jsdebug/" as nginx does, otherwise browser will treat it as file instead of directory, so, relative path will not work
|
||||
@@ -110,7 +110,7 @@ public class BuiltInWebServer : HttpRequestHandler() {
|
||||
}
|
||||
|
||||
val path = FileUtil.toCanonicalPath(decodedPath.substring(offset + 1), '/')
|
||||
for (pathHandler in WebServerPathHandler.EP_NAME.getExtensions()) {
|
||||
for (pathHandler in WebServerPathHandler.EP_NAME.extensions) {
|
||||
try {
|
||||
if (pathHandler.process(path, project, request, context, projectName, decodedPath, isCustomHost)) {
|
||||
return true
|
||||
@@ -157,12 +157,12 @@ public class BuiltInWebServer : HttpRequestHandler() {
|
||||
}
|
||||
|
||||
public fun compareNameAndProjectBasePath(projectName: String, project: Project): Boolean {
|
||||
val basePath = project.getBasePath()
|
||||
val basePath = project.basePath
|
||||
return basePath != null && basePath.length() > projectName.length() && basePath.endsWith(projectName) && basePath.charAt(basePath.length() - projectName.length() - 1) == '/'
|
||||
}
|
||||
|
||||
public fun findIndexFile(basedir: VirtualFile): VirtualFile? {
|
||||
val children = basedir.getChildren()
|
||||
val children = basedir.children
|
||||
if (children == null || children.isEmpty()) {
|
||||
return null
|
||||
}
|
||||
@@ -171,8 +171,8 @@ public fun findIndexFile(basedir: VirtualFile): VirtualFile? {
|
||||
var index: VirtualFile? = null
|
||||
val preferredName = indexNamePrefix + "html"
|
||||
for (child in children) {
|
||||
if (!child.isDirectory()) {
|
||||
val name = child.getName()
|
||||
if (!child.isDirectory) {
|
||||
val name = child.name
|
||||
//noinspection IfStatementWithIdenticalBranches
|
||||
if (name == preferredName) {
|
||||
return child
|
||||
@@ -196,11 +196,11 @@ public fun isOwnHostName(host: String): Boolean {
|
||||
|
||||
try {
|
||||
val address = InetAddress.getByName(host)
|
||||
if (host == address.getHostAddress() || host.equals(address.getCanonicalHostName(), ignoreCase = true)) {
|
||||
if (host == address.hostAddress || host.equals(address.canonicalHostName, ignoreCase = true)) {
|
||||
return true
|
||||
}
|
||||
|
||||
val localHostName = InetAddress.getLocalHost().getHostName()
|
||||
val localHostName = InetAddress.getLocalHost().hostName
|
||||
// WEB-8889
|
||||
// develar.local is own host name: develar. equals to "develar.labs.intellij.net" (canonical host name)
|
||||
return localHostName.equals(host, ignoreCase = true) || (host.endsWith(".local") && localHostName.regionMatches(0, host, 0, host.length() - ".local".length(), true))
|
||||
@@ -214,8 +214,8 @@ private class StaticFileHandler : WebServerFileHandler() {
|
||||
private var ssiProcessor: SsiProcessor? = null
|
||||
|
||||
override fun process(file: VirtualFile, canonicalRequestPath: CharSequence, project: Project, request: FullHttpRequest, channel: Channel, isCustomHost: Boolean): Boolean {
|
||||
if (file.isInLocalFileSystem()) {
|
||||
val nameSequence = file.getNameSequence()
|
||||
if (file.isInLocalFileSystem) {
|
||||
val nameSequence = file.nameSequence
|
||||
//noinspection SpellCheckingInspection
|
||||
if (StringUtilRt.endsWithIgnoreCase(nameSequence, ".shtml") || StringUtilRt.endsWithIgnoreCase(nameSequence, ".stm") || StringUtilRt.endsWithIgnoreCase(nameSequence, ".shtm")) {
|
||||
processSsi(file, canonicalRequestPath, project, request, channel, isCustomHost)
|
||||
@@ -231,17 +231,17 @@ private class StaticFileHandler : WebServerFileHandler() {
|
||||
}
|
||||
}
|
||||
else {
|
||||
val response = FileResponses.prepareSend(request, channel, file.getTimeStamp(), file.getPath()) ?: return true
|
||||
val response = FileResponses.prepareSend(request, channel, file.timeStamp, file.path) ?: return true
|
||||
|
||||
val keepAlive = addKeepAliveIfNeed(response, request)
|
||||
if (request.method() !== HttpMethod.HEAD) {
|
||||
HttpUtil.setContentLength(response, file.getLength())
|
||||
HttpUtil.setContentLength(response, file.length)
|
||||
}
|
||||
|
||||
channel.write(response)
|
||||
|
||||
if (request.method() != HttpMethod.HEAD) {
|
||||
channel.write(ChunkedStream(file.getInputStream()))
|
||||
channel.write(ChunkedStream(file.inputStream))
|
||||
}
|
||||
|
||||
val future = channel.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT)
|
||||
@@ -267,9 +267,9 @@ private class StaticFileHandler : WebServerFileHandler() {
|
||||
val keepAlive: Boolean
|
||||
var releaseBuffer = true
|
||||
try {
|
||||
val lastModified = ssiProcessor!!.process(SsiExternalResolver(project, request, path, file.getParent()), VfsUtilCore.loadText(file), file.getTimeStamp(), ByteBufUtf8Writer(buffer))
|
||||
val lastModified = ssiProcessor!!.process(SsiExternalResolver(project, request, path, file.parent), VfsUtilCore.loadText(file), file.timeStamp, ByteBufUtf8Writer(buffer))
|
||||
|
||||
val response = FileResponses.prepareSend(request, channel, lastModified, file.getPath()) ?: return
|
||||
val response = FileResponses.prepareSend(request, channel, lastModified, file.path) ?: return
|
||||
|
||||
keepAlive = addKeepAliveIfNeed(response, request)
|
||||
if (request.method() !== HttpMethod.HEAD) {
|
||||
@@ -296,5 +296,5 @@ private class StaticFileHandler : WebServerFileHandler() {
|
||||
}
|
||||
|
||||
// deny access to .htaccess files
|
||||
private fun hasAccess(result: File) = !result.isDirectory() && result.canRead() && !(result.isHidden() || result.getName().startsWith(".ht"))
|
||||
private fun hasAccess(result: File) = !result.isDirectory && result.canRead() && !(result.isHidden || result.name.startsWith(".ht"))
|
||||
}
|
||||
@@ -22,7 +22,7 @@ import org.jetbrains.util.concurrency
|
||||
import org.jetbrains.util.concurrency.toPromise
|
||||
import javax.swing.Icon
|
||||
|
||||
val LOG: Logger = Logger.getInstance(javaClass<NetService>())
|
||||
val LOG: Logger = Logger.getInstance(NetService::class.java)
|
||||
|
||||
public abstract class NetService @jvmOverloads protected constructor(protected val project: Project, private val consoleManager: ConsoleManager = ConsoleManager()) : Disposable {
|
||||
protected val processHandler: AsyncValueLoader<OSProcessHandler> = object : AsyncValueLoader<OSProcessHandler>() {
|
||||
|
||||
@@ -76,7 +76,7 @@ class FastCgiDecoder(private val errorOutputConsumer: Consumer<String>, private
|
||||
|
||||
override fun channelInactive(context: ChannelHandlerContext) {
|
||||
try {
|
||||
if (!dataBuffers.isEmpty()) {
|
||||
if (!dataBuffers.isEmpty) {
|
||||
dataBuffers.forEachEntry(object : TIntObjectProcedure<ByteBuf> {
|
||||
override fun execute(a: Int, buffer: ByteBuf): Boolean {
|
||||
try {
|
||||
@@ -92,7 +92,7 @@ class FastCgiDecoder(private val errorOutputConsumer: Consumer<String>, private
|
||||
}
|
||||
}
|
||||
finally {
|
||||
super<Decoder>.channelInactive(context)
|
||||
super.channelInactive(context)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,8 +136,10 @@ class FastCgiDecoder(private val errorOutputConsumer: Consumer<String>, private
|
||||
data.writerIndex(data.writerIndex() + data.readableBytes())
|
||||
}
|
||||
else {
|
||||
// must be computed here before we set data to new composite buffer
|
||||
val newLength = data.readableBytes() + sliced.readableBytes()
|
||||
data = context.alloc().compositeBuffer(Decoder.DEFAULT_MAX_COMPOSITE_BUFFER_COMPONENTS).addComponents(data, sliced)
|
||||
data.writerIndex(data.writerIndex() + data.readableBytes() + sliced.readableBytes())
|
||||
data.writerIndex(data.writerIndex() + newLength)
|
||||
}
|
||||
dataBuffers.put(id, data)
|
||||
}
|
||||
@@ -153,7 +155,7 @@ class FastCgiDecoder(private val errorOutputConsumer: Consumer<String>, private
|
||||
}
|
||||
}
|
||||
|
||||
else -> LOG.error("Unknown type " + type)
|
||||
else -> LOG.error("Unknown type $type")
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import io.netty.handler.codec.http.HttpHeaderNames
|
||||
import org.jetbrains.builtInWebServer.WebServerPathToFileManager
|
||||
import org.jetbrains.io.Responses
|
||||
import java.net.InetSocketAddress
|
||||
import java.util.Locale
|
||||
import java.util.*
|
||||
|
||||
class FastCgiRequest(val requestId: Int, allocator: ByteBufAllocator) {
|
||||
companion object {
|
||||
@@ -37,8 +37,8 @@ class FastCgiRequest(val requestId: Int, allocator: ByteBufAllocator) {
|
||||
public fun writeFileHeaders(file: VirtualFile, project: Project, canonicalRequestPath: CharSequence) {
|
||||
val root = WebServerPathToFileManager.getInstance(project).getRoot(file)
|
||||
LOG.assertTrue(root != null)
|
||||
addHeader("DOCUMENT_ROOT", root!!.getRoot().getPath())
|
||||
addHeader("SCRIPT_FILENAME", file.getPath())
|
||||
addHeader("DOCUMENT_ROOT", root!!.root.path)
|
||||
addHeader("SCRIPT_FILENAME", file.path)
|
||||
addHeader("SCRIPT_NAME", canonicalRequestPath)
|
||||
}
|
||||
|
||||
@@ -80,19 +80,19 @@ class FastCgiRequest(val requestId: Int, allocator: ByteBufAllocator) {
|
||||
addHeader("REQUEST_METHOD", request.method().name())
|
||||
|
||||
val remote = clientChannel.remoteAddress() as InetSocketAddress
|
||||
addHeader("REMOTE_ADDR", remote.getAddress().getHostAddress())
|
||||
addHeader("REMOTE_PORT", Integer.toString(remote.getPort()))
|
||||
addHeader("REMOTE_ADDR", remote.address.hostAddress)
|
||||
addHeader("REMOTE_PORT", Integer.toString(remote.port))
|
||||
|
||||
val local = clientChannel.localAddress() as InetSocketAddress
|
||||
addHeader("SERVER_SOFTWARE", Responses.getServerHeaderValue())
|
||||
addHeader("SERVER_NAME", Responses.getServerHeaderValue())
|
||||
|
||||
addHeader("SERVER_ADDR", local.getAddress().getHostAddress())
|
||||
addHeader("SERVER_PORT", Integer.toString(local.getPort()))
|
||||
addHeader("SERVER_ADDR", local.address.hostAddress)
|
||||
addHeader("SERVER_PORT", Integer.toString(local.port))
|
||||
|
||||
addHeader("GATEWAY_INTERFACE", "CGI/1.1")
|
||||
addHeader("SERVER_PROTOCOL", request.protocolVersion().text())
|
||||
addHeader("CONTENT_TYPE", request.headers().get(HttpHeaderNames.CONTENT_TYPE))
|
||||
addHeader("CONTENT_TYPE", request.headers().getAsString(HttpHeaderNames.CONTENT_TYPE))
|
||||
|
||||
// PHP only, required if PHP was built with --enable-force-cgi-redirect
|
||||
addHeader("REDIRECT_STATUS", "200")
|
||||
@@ -106,8 +106,8 @@ class FastCgiRequest(val requestId: Int, allocator: ByteBufAllocator) {
|
||||
|
||||
addHeader("CONTENT_LENGTH", request.content().readableBytes().toString())
|
||||
|
||||
for (entry in request.headers()) {
|
||||
addHeader("HTTP_${entry.getKey().replace('-', '_').toUpperCase(Locale.ENGLISH)}", entry.getValue())
|
||||
for ((key, value) in request.headers().iteratorAsString()) {
|
||||
addHeader("HTTP_${key.replace('-', '_').toUpperCase(Locale.ENGLISH)}", value)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ import org.jetbrains.concurrency.Promise
|
||||
import org.jetbrains.io.*
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
val LOG: Logger = Logger.getInstance(javaClass<FastCgiService>())
|
||||
val LOG: Logger = Logger.getInstance(FastCgiService::class.java)
|
||||
|
||||
// todo send FCGI_ABORT_REQUEST if client channel disconnected
|
||||
public abstract class FastCgiService(project: Project) : SingleConnectionNetService(project) {
|
||||
@@ -51,7 +51,7 @@ public abstract class FastCgiService(project: Project) : SingleConnectionNetServ
|
||||
|
||||
private fun parseHeaders(response: HttpResponse, buffer: ByteBuf) {
|
||||
val builder = StringBuilder()
|
||||
while (buffer.isReadable()) {
|
||||
while (buffer.isReadable) {
|
||||
builder.setLength(0)
|
||||
|
||||
var key: String? = null
|
||||
@@ -149,10 +149,10 @@ public abstract class FastCgiService(project: Project) : SingleConnectionNetServ
|
||||
fastCgiRequest.writeToServerChannel(notEmptyContent, processChannel!!)
|
||||
}
|
||||
})
|
||||
.rejected(Consumer {
|
||||
.rejected {
|
||||
Promise.logError(LOG, it)
|
||||
handleError(fastCgiRequest, notEmptyContent)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
@@ -187,7 +187,7 @@ public abstract class FastCgiService(project: Project) : SingleConnectionNetServ
|
||||
|
||||
fun responseReceived(id: Int, buffer: ByteBuf?) {
|
||||
val channel = requests.remove(id)
|
||||
if (channel == null || !channel.isActive()) {
|
||||
if (channel == null || !channel.isActive) {
|
||||
buffer?.release()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ class TestManager(val projectRule: ProjectRule, private val tempDirManager: Temp
|
||||
public val status: Int = 200)
|
||||
|
||||
override fun starting(description: Description) {
|
||||
annotation = description.getAnnotation(javaClass<TestDescriptor>())
|
||||
annotation = description.getAnnotation(TestDescriptor::class.java)
|
||||
if (annotation == null) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -37,6 +37,10 @@ class ApplicationPathMacroManager : BasePathMacroManager(null)
|
||||
class ApplicationStoreImpl(private val application: Application, pathMacroManager: PathMacroManager) : ComponentStoreImpl() {
|
||||
override val storageManager = ApplicationStorageManager(application, pathMacroManager)
|
||||
|
||||
// number of app components require some state, so, we load default state in test mode
|
||||
override val loadPolicy: StateLoadPolicy
|
||||
get() = if (application.isUnitTestMode()) StateLoadPolicy.LOAD_ONLY_DEFAULT else StateLoadPolicy.LOAD
|
||||
|
||||
override fun setPath(path: String) {
|
||||
storageManager.addMacro(ROOT_CONFIG, path)
|
||||
storageManager.addMacro(StoragePathMacros.APP_CONFIG, "$path/${ApplicationStorageManager.FILE_STORAGE_DIR}")
|
||||
|
||||
@@ -31,7 +31,10 @@ import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.progress.ProcessCanceledException
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util
|
||||
import com.intellij.openapi.util.*
|
||||
import com.intellij.openapi.util.InvalidDataException
|
||||
import com.intellij.openapi.util.JDOMExternalizable
|
||||
import com.intellij.openapi.util.JDOMUtil
|
||||
import com.intellij.openapi.util.NamedJDOMExternalizable
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess
|
||||
@@ -49,7 +52,7 @@ import java.io.IOException
|
||||
import java.util.*
|
||||
import java.util.concurrent.CopyOnWriteArrayList
|
||||
|
||||
private val LOG = Logger.getInstance(javaClass<ComponentStoreImpl>())
|
||||
private val LOG = Logger.getInstance(ComponentStoreImpl::class.java)
|
||||
|
||||
/**
|
||||
* <b>Note:</b> this class is used in upsource, please notify upsource team in case you change its API.
|
||||
@@ -61,6 +64,9 @@ abstract class ComponentStoreImpl : IComponentStore {
|
||||
protected open val project: Project?
|
||||
get() = null
|
||||
|
||||
open val loadPolicy: StateLoadPolicy
|
||||
get() = StateLoadPolicy.LOAD
|
||||
|
||||
abstract val storageManager: StateStorageManager
|
||||
|
||||
override final fun getStateStorageManager() = storageManager
|
||||
@@ -82,6 +88,7 @@ abstract class ComponentStoreImpl : IComponentStore {
|
||||
componentNameIfStateExists = if (component is PersistentStateComponent<*>) {
|
||||
val stateSpec = StoreUtil.getStateSpec(component)
|
||||
doAddComponent(stateSpec.name, component)
|
||||
@suppress("UNCHECKED_CAST")
|
||||
initPersistentComponent(stateSpec, component as PersistentStateComponent<Any>, null, false)
|
||||
}
|
||||
else {
|
||||
@@ -129,8 +136,10 @@ abstract class ComponentStoreImpl : IComponentStore {
|
||||
}
|
||||
}
|
||||
|
||||
errors = doSave(externalizationSession!!.createSaveSessions(), readonlyFiles, errors)
|
||||
CompoundRuntimeException.doThrow(errors)
|
||||
if (externalizationSession != null) {
|
||||
errors = doSave(externalizationSession.createSaveSessions(), readonlyFiles, errors)
|
||||
}
|
||||
CompoundRuntimeException.throwIfNotEmpty(errors)
|
||||
}
|
||||
|
||||
override TestOnly fun saveApplicationComponent(component: Any) {
|
||||
@@ -157,7 +166,7 @@ abstract class ComponentStoreImpl : IComponentStore {
|
||||
val token = WriteAction.start()
|
||||
try {
|
||||
VfsRootAccess.allowRootAccess(file.getAbsolutePath())
|
||||
CompoundRuntimeException.doThrow(doSave(sessions))
|
||||
CompoundRuntimeException.throwIfNotEmpty(doSave(sessions))
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
@@ -194,18 +203,18 @@ abstract class ComponentStoreImpl : IComponentStore {
|
||||
val componentName = ComponentManagerImpl.getComponentName(component)
|
||||
doAddComponent(componentName, component)
|
||||
|
||||
if (optimizeTestLoading()) {
|
||||
if (loadPolicy != StateLoadPolicy.LOAD) {
|
||||
return null
|
||||
}
|
||||
|
||||
try {
|
||||
getDefaultState(component, componentName, javaClass<Element>())?.let { component.readExternal(it) }
|
||||
getDefaultState(component, componentName, Element::class.java)?.let { component.readExternal(it) }
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
LOG.error(e)
|
||||
}
|
||||
|
||||
val element = storageManager.getOldStorage(component, componentName, StateStorageOperation.READ)?.getState(component, componentName, javaClass<Element>(), null, false) ?: return null
|
||||
val element = storageManager.getOldStorage(component, componentName, StateStorageOperation.READ)?.getState(component, componentName, Element::class.java, null, false) ?: return null
|
||||
try {
|
||||
component.readExternal(element)
|
||||
}
|
||||
@@ -224,8 +233,8 @@ abstract class ComponentStoreImpl : IComponentStore {
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T : Any> initPersistentComponent(stateSpec: State, component: PersistentStateComponent<T>, changedStorages: Set<StateStorage>?, reloadData: Boolean): String? {
|
||||
if (optimizeTestLoading()) {
|
||||
private fun <T: Any> initPersistentComponent(stateSpec: State, component: PersistentStateComponent<T>, changedStorages: Set<StateStorage>?, reloadData: Boolean): String? {
|
||||
if (loadPolicy == StateLoadPolicy.NOT_LOAD) {
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -236,41 +245,44 @@ abstract class ComponentStoreImpl : IComponentStore {
|
||||
}
|
||||
|
||||
val defaultState = if (stateSpec.defaultStateAsResource) getDefaultState(component, name, stateClass) else null
|
||||
val storageSpecs = getStorageSpecs(component, stateSpec, StateStorageOperation.READ)
|
||||
val storageChooser = component as? StateStorageChooserEx
|
||||
for (storageSpec in storageSpecs) {
|
||||
if (storageChooser?.getResolution(storageSpec, StateStorageOperation.READ) == Resolution.SKIP) {
|
||||
continue
|
||||
}
|
||||
|
||||
val storage = storageManager.getStateStorage(storageSpec)
|
||||
var stateGetter = if (isUseLoadedStateAsExisting(storage) && (ApplicationManager.getApplication().isUnitTestMode() || Registry.`is`("use.loaded.state.as.existing", false))) {
|
||||
(storage as? StorageBaseEx<*>)?.createGetSession(component, name, stateClass)
|
||||
}
|
||||
else {
|
||||
null
|
||||
}
|
||||
var state = if (stateGetter == null) storage.getState(component, name, stateClass, defaultState, reloadData) else stateGetter.getState(defaultState)
|
||||
if (state == null) {
|
||||
if (changedStorages != null && changedStorages.contains(storage)) {
|
||||
// state will be null if file deleted
|
||||
// we must create empty (initial) state to reinit component
|
||||
state = DefaultStateSerializer.deserializeState(Element("state"), stateClass, null)!!
|
||||
}
|
||||
else {
|
||||
if (loadPolicy == StateLoadPolicy.LOAD) {
|
||||
val storageSpecs = getStorageSpecs(component, stateSpec, StateStorageOperation.READ)
|
||||
val storageChooser = component as? StateStorageChooserEx
|
||||
for (storageSpec in storageSpecs) {
|
||||
if (storageChooser?.getResolution(storageSpec, StateStorageOperation.READ) == Resolution.SKIP) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
component.loadState(state)
|
||||
val storage = storageManager.getStateStorage(storageSpec)
|
||||
var stateGetter = if (isUseLoadedStateAsExisting(storage) && (ApplicationManager.getApplication().isUnitTestMode() || Registry.`is`("use.loaded.state.as.existing", false))) {
|
||||
(storage as? StorageBaseEx<*>)?.createGetSession(component, name, stateClass)
|
||||
}
|
||||
else {
|
||||
null
|
||||
}
|
||||
var state = if (stateGetter == null) storage.getState(component, name, stateClass, defaultState, reloadData) else stateGetter.getState(defaultState)
|
||||
if (state == null) {
|
||||
if (changedStorages != null && changedStorages.contains(storage)) {
|
||||
// state will be null if file deleted
|
||||
// we must create empty (initial) state to reinit component
|
||||
state = DefaultStateSerializer.deserializeState(Element("state"), stateClass, null)!!
|
||||
}
|
||||
else {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
component.loadState(state)
|
||||
}
|
||||
finally {
|
||||
stateGetter?.close()
|
||||
}
|
||||
return name
|
||||
}
|
||||
finally {
|
||||
stateGetter?.close()
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
// we load default state even if isLoadComponentState false - required for app components (for example, at least one color scheme must exists)
|
||||
if (defaultState != null) {
|
||||
component.loadState(defaultState)
|
||||
}
|
||||
@@ -298,7 +310,14 @@ abstract class ComponentStoreImpl : IComponentStore {
|
||||
if (storages.size() == 1 || component is StateStorageChooserEx) {
|
||||
return storages
|
||||
}
|
||||
assert(!storages.isEmpty())
|
||||
|
||||
if (storages.isEmpty()) {
|
||||
if (stateSpec.defaultStateAsResource) {
|
||||
return storages
|
||||
}
|
||||
|
||||
throw AssertionError("No storage specified")
|
||||
}
|
||||
|
||||
val defaultStorages = selectDefaultStorages(storages, operation)
|
||||
if (defaultStorages != null) {
|
||||
@@ -330,8 +349,6 @@ abstract class ComponentStoreImpl : IComponentStore {
|
||||
return sorted
|
||||
}
|
||||
|
||||
protected open fun optimizeTestLoading(): Boolean = false
|
||||
|
||||
override final fun isReloadPossible(componentNames: MutableSet<String>) = !componentNames.any { isNotReloadable(it) }
|
||||
|
||||
private fun isNotReloadable(component: Any?) = component != null && (component !is PersistentStateComponent<*> || !StoreUtil.getStateSpec(component).reloadable)
|
||||
@@ -357,6 +374,7 @@ abstract class ComponentStoreImpl : IComponentStore {
|
||||
|
||||
override final fun reloadState(componentClass: Class<out PersistentStateComponent<*>>) {
|
||||
val stateSpec = StoreUtil.getStateSpecOrError(componentClass)
|
||||
@suppress("UNCHECKED_CAST")
|
||||
val component = components.get(stateSpec.name) as PersistentStateComponent<Any>?
|
||||
if (component != null) {
|
||||
initPersistentComponent(stateSpec, component, emptySet(), true)
|
||||
@@ -364,6 +382,7 @@ abstract class ComponentStoreImpl : IComponentStore {
|
||||
}
|
||||
|
||||
private fun reloadState(componentName: String, changedStorages: Set<StateStorage>): Boolean {
|
||||
@suppress("UNCHECKED_CAST")
|
||||
val component = components.get(componentName) as PersistentStateComponent<Any>?
|
||||
if (component == null) {
|
||||
return false
|
||||
@@ -447,4 +466,8 @@ abstract class ComponentStoreImpl : IComponentStore {
|
||||
return errors
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class StateLoadPolicy {
|
||||
LOAD, LOAD_ONLY_DEFAULT, NOT_LOAD
|
||||
}
|
||||
@@ -30,6 +30,10 @@ class DefaultProjectStoreImpl(override val project: ProjectImpl, private val pat
|
||||
val FILE_SPEC = "${StoragePathMacros.APP_CONFIG}/project.default.xml"
|
||||
}
|
||||
|
||||
// see note about default state in project store
|
||||
override val loadPolicy: StateLoadPolicy
|
||||
get() = if (ApplicationManager.getApplication().isUnitTestMode()) StateLoadPolicy.NOT_LOAD else StateLoadPolicy.LOAD
|
||||
|
||||
init {
|
||||
service<DefaultProjectExportableAndSaveTrigger>().project = project
|
||||
}
|
||||
|
||||
@@ -17,11 +17,11 @@ package com.intellij.configurationStore
|
||||
|
||||
import com.intellij.openapi.components.PathMacroManager
|
||||
import com.intellij.openapi.components.StoragePathMacros
|
||||
import com.intellij.openapi.components.stateStore
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.project.ex.ProjectEx
|
||||
import java.io.File
|
||||
|
||||
class ModuleStoreImpl(module: Module, private val pathMacroManager: PathMacroManager) : ComponentStoreImpl() {
|
||||
open private class ModuleStoreImpl(module: Module, private val pathMacroManager: PathMacroManager) : ComponentStoreImpl() {
|
||||
override val project = module.getProject()
|
||||
|
||||
override val storageManager = ModuleStateStorageManager(pathMacroManager.createTrackingSubstitutor(), module)
|
||||
@@ -32,7 +32,20 @@ class ModuleStoreImpl(module: Module, private val pathMacroManager: PathMacroMan
|
||||
}
|
||||
}
|
||||
|
||||
override fun optimizeTestLoading() = (project as ProjectEx).isOptimiseTestLoadSpeed()
|
||||
|
||||
override final fun getPathMacroManagerForDefaults() = pathMacroManager
|
||||
}
|
||||
|
||||
private class TestModuleStore(module: Module, pathMacroManager: PathMacroManager) : ModuleStoreImpl(module, pathMacroManager) {
|
||||
private var moduleComponentLoadPolicy: StateLoadPolicy? = null
|
||||
|
||||
override fun setPath(path: String) {
|
||||
super.setPath(path)
|
||||
|
||||
if (File(path).exists()) {
|
||||
moduleComponentLoadPolicy = StateLoadPolicy.LOAD
|
||||
}
|
||||
}
|
||||
|
||||
override val loadPolicy: StateLoadPolicy
|
||||
get() = moduleComponentLoadPolicy ?: (project.stateStore as ProjectStoreImpl).loadPolicy
|
||||
}
|
||||
@@ -20,6 +20,6 @@ import com.intellij.openapi.project.impl.ProjectStoreClassProvider
|
||||
|
||||
class PlatformProjectStoreClassProvider : ProjectStoreClassProvider {
|
||||
override fun getProjectStoreClass(isDefaultProject: Boolean): Class<out IComponentStore> {
|
||||
return if (isDefaultProject) javaClass<DefaultProjectStoreImpl>() else javaClass<ProjectStoreImpl>()
|
||||
return if (isDefaultProject) DefaultProjectStoreImpl::class.java else ProjectStoreImpl::class.java
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ import com.intellij.ide.highlighter.ProjectFileType
|
||||
import com.intellij.ide.highlighter.WorkspaceFileType
|
||||
import com.intellij.notification.Notifications
|
||||
import com.intellij.notification.NotificationsManager
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.ReadAction
|
||||
import com.intellij.openapi.application.invokeAndWaitIfNeed
|
||||
import com.intellij.openapi.components.*
|
||||
@@ -41,7 +42,7 @@ import java.io.BufferedReader
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.io.InputStreamReader
|
||||
import java.util.ArrayList
|
||||
import java.util.*
|
||||
|
||||
open class ProjectStoreImpl(override val project: ProjectImpl, private val pathMacroManager: PathMacroManager) : ComponentStoreImpl(), IProjectStore {
|
||||
// protected setter used in upsource
|
||||
@@ -50,11 +51,20 @@ open class ProjectStoreImpl(override val project: ProjectImpl, private val pathM
|
||||
|
||||
private var presentableUrl: String? = null
|
||||
|
||||
override var loadPolicy = StateLoadPolicy.LOAD
|
||||
|
||||
init {
|
||||
assert(!project.isDefault())
|
||||
}
|
||||
|
||||
override fun optimizeTestLoading() = project.isOptimiseTestLoadSpeed()
|
||||
override final fun isOptimiseTestLoadSpeed() = loadPolicy != StateLoadPolicy.LOAD
|
||||
|
||||
override final fun setOptimiseTestLoadSpeed(value: Boolean) {
|
||||
// we don't load default state in tests as app store does because
|
||||
// 1) we should not do it
|
||||
// 2) it was so before, so, we preserve old behavior (otherwise RunManager will load template run configurations)
|
||||
loadPolicy = if (value) StateLoadPolicy.NOT_LOAD else StateLoadPolicy.LOAD
|
||||
}
|
||||
|
||||
override final fun getPathMacroManagerForDefaults() = pathMacroManager
|
||||
|
||||
@@ -74,6 +84,11 @@ open class ProjectStoreImpl(override val project: ProjectImpl, private val pathM
|
||||
invokeAndWaitIfNeed {
|
||||
VfsUtil.markDirtyAndRefresh(false, true, false, fs.refreshAndFindFileByPath(filePath), fs.refreshAndFindFileByPath(workspacePath))
|
||||
}
|
||||
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
// load state only if there are existing files
|
||||
setOptimiseTestLoadSpeed(!File(filePath).exists())
|
||||
}
|
||||
}
|
||||
else {
|
||||
scheme = StorageScheme.DIRECTORY_BASED
|
||||
@@ -91,6 +106,11 @@ open class ProjectStoreImpl(override val project: ProjectImpl, private val pathM
|
||||
}
|
||||
|
||||
invokeAndWaitIfNeed { VfsUtil.markDirtyAndRefresh(false, true, true, fs.refreshAndFindFileByPath(projectConfigDir)) }
|
||||
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
// load state only if there are existing files
|
||||
setOptimiseTestLoadSpeed(!dirStore.exists())
|
||||
}
|
||||
}
|
||||
|
||||
presentableUrl = null
|
||||
@@ -130,7 +150,6 @@ open class ProjectStoreImpl(override val project: ProjectImpl, private val pathM
|
||||
}
|
||||
catch (ignored: IOException) {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,7 +203,7 @@ open class ProjectStoreImpl(override val project: ProjectImpl, private val pathM
|
||||
|
||||
super<ComponentStoreImpl>.doSave(saveSessions, readonlyFiles, errors)
|
||||
|
||||
val notifications = NotificationsManager.getNotificationsManager().getNotificationsOfType(javaClass<UnableToSaveProjectNotification>(), project)
|
||||
val notifications = NotificationsManager.getNotificationsManager().getNotificationsOfType(UnableToSaveProjectNotification::class.java, project)
|
||||
if (readonlyFiles.isEmpty()) {
|
||||
for (notification in notifications) {
|
||||
notification.expire()
|
||||
@@ -216,7 +235,7 @@ open class ProjectStoreImpl(override val project: ProjectImpl, private val pathM
|
||||
}
|
||||
|
||||
if (errors != null) {
|
||||
CompoundRuntimeException.doThrow(errors)
|
||||
CompoundRuntimeException.throwIfNotEmpty(errors)
|
||||
}
|
||||
|
||||
if (!readonlyFiles.isEmpty()) {
|
||||
@@ -267,7 +286,7 @@ open class ProjectStoreImpl(override val project: ProjectImpl, private val pathM
|
||||
}
|
||||
|
||||
private fun dropUnableToSaveProjectNotification(project: Project, readOnlyFiles: Array<VirtualFile>) {
|
||||
val notifications = NotificationsManager.getNotificationsManager().getNotificationsOfType(javaClass<UnableToSaveProjectNotification>(), project)
|
||||
val notifications = NotificationsManager.getNotificationsManager().getNotificationsOfType(UnableToSaveProjectNotification::class.java, project)
|
||||
if (notifications.isEmpty()) {
|
||||
Notifications.Bus.notify(UnableToSaveProjectNotification(project, readOnlyFiles), project)
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ import com.intellij.openapi.vfs.VirtualFile
|
||||
|
||||
class PlatformLangProjectStoreClassProvider : ProjectStoreClassProvider {
|
||||
override fun getProjectStoreClass(isDefaultProject: Boolean): Class<out IComponentStore> {
|
||||
return if (isDefaultProject) javaClass<DefaultProjectStoreImpl>() else javaClass<ProjectWithModulesStoreImpl>()
|
||||
return if (isDefaultProject) DefaultProjectStoreImpl::class.java else ProjectWithModulesStoreImpl::class.java
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ public abstract class SchemeManagerFactoryBase : SchemesManagerFactory(), Settin
|
||||
}
|
||||
}
|
||||
|
||||
CompoundRuntimeException.doThrow(errors)
|
||||
CompoundRuntimeException.throwIfNotEmpty(errors)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -349,7 +349,7 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
val fileNameWithoutExtension = fileName.subSequence(0, fileName.length() - extension.length()).toString()
|
||||
if (duringLoad) {
|
||||
if (filesToDelete.isNotEmpty() && filesToDelete.contains(fileName.toString())) {
|
||||
LOG.warn("Scheme file $fileName is not loaded because marked to delete")
|
||||
LOG.warn("Scheme file \"$fileName\" is not loaded because marked to delete")
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -367,7 +367,7 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
else {
|
||||
// We don't load scheme with duplicated name - if we generate unique name for it, it will be saved then with new name.
|
||||
// It is not what all can expect. Such situation in most cases indicates error on previous level, so, we just warn about it.
|
||||
LOG.warn("Scheme file $fileName is not loaded because defines duplicated name ${scheme.getName()}")
|
||||
LOG.warn("Scheme file \"$fileName\" is not loaded because defines duplicated name \"${scheme.getName()}\"")
|
||||
}
|
||||
return null
|
||||
}
|
||||
@@ -428,13 +428,13 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
@suppress("UNCHECKED_CAST")
|
||||
if (scheme is ExternalizableScheme) {
|
||||
val state = getState(scheme as E)
|
||||
if (state === BaseSchemeProcessor.State.NON_PERSISTENT) {
|
||||
if (state == BaseSchemeProcessor.State.NON_PERSISTENT) {
|
||||
continue
|
||||
}
|
||||
|
||||
hasSchemes = true
|
||||
|
||||
if (state !== BaseSchemeProcessor.State.UNCHANGED) {
|
||||
if (state != BaseSchemeProcessor.State.UNCHANGED) {
|
||||
schemesToSave.add(scheme)
|
||||
}
|
||||
|
||||
|
||||
@@ -36,11 +36,10 @@ import org.jdom.Element
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.util.LinkedHashMap
|
||||
import java.util.*
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
import java.util.regex.Pattern
|
||||
import kotlin.concurrent.withLock
|
||||
import kotlin.reflect.jvm.java
|
||||
|
||||
/**
|
||||
* If componentManager not specified, storage will not add file tracker (see VirtualFileTracker)
|
||||
@@ -147,9 +146,9 @@ open class StateStorageManagerImpl(private val rootTagName: String,
|
||||
*/
|
||||
open fun expandNormalizedPath(path: String): String = expandMacros(path)
|
||||
|
||||
fun getOrCreateStorage(fileSpec: String, roamingType: RoamingType = RoamingType.DEFAULT, storageClass: Class<out StateStorage> = javaClass<StateStorage>(), @SuppressWarnings("deprecation") stateSplitter: Class<out StateSplitter> = javaClass<StateSplitterEx>()): StateStorage {
|
||||
fun getOrCreateStorage(fileSpec: String, roamingType: RoamingType = RoamingType.DEFAULT, storageClass: Class<out StateStorage> = StateStorage::class.java, @SuppressWarnings("deprecation") stateSplitter: Class<out StateSplitter> = StateSplitterEx::class.java): StateStorage {
|
||||
val collapsedPath = normalizeFileSpec(fileSpec)
|
||||
val key = if (storageClass == javaClass<StateStorage>()) collapsedPath else storageClass.getName()
|
||||
val key = if (storageClass == StateStorage::class.java) collapsedPath else storageClass.getName()
|
||||
storageLock.withLock {
|
||||
var storage = storages.get(key)
|
||||
if (storage == null) {
|
||||
@@ -184,7 +183,7 @@ open class StateStorageManagerImpl(private val rootTagName: String,
|
||||
|
||||
// overridden in upsource
|
||||
protected open fun createStateStorage(storageClass: Class<out StateStorage>, collapsedPath: String, roamingType: RoamingType, @SuppressWarnings("deprecation") stateSplitter: Class<out StateSplitter>): StateStorage {
|
||||
if (storageClass != javaClass<StateStorage>()) {
|
||||
if (storageClass != StateStorage::class.java) {
|
||||
val constructor = storageClass.getConstructors()[0]!!
|
||||
constructor.setAccessible(true)
|
||||
return constructor.newInstance(componentManager!!, this) as StateStorage
|
||||
@@ -195,7 +194,7 @@ open class StateStorageManagerImpl(private val rootTagName: String,
|
||||
}
|
||||
|
||||
val filePath = expandNormalizedPath(collapsedPath)
|
||||
if (stateSplitter != javaClass<StateSplitter>() && stateSplitter != javaClass<StateSplitterEx>()) {
|
||||
if (stateSplitter != StateSplitter::class.java && stateSplitter != StateSplitterEx::class.java) {
|
||||
val storage = MyDirectoryStorage(this, File(filePath), ReflectionUtil.newInstance(stateSplitter))
|
||||
virtualFileTracker?.put(filePath, storage)
|
||||
return storage
|
||||
|
||||
@@ -67,7 +67,7 @@ class ApplicationStoreTest {
|
||||
component.foo = "newValue"
|
||||
componentStore.save(SmartList())
|
||||
|
||||
assertThat(streamProvider.data.get(RoamingType.DEFAULT)!!.get("proxy.xml")).isEqualTo("<application>\n" + " <component name=\"HttpConfigurable\">\n" + " <option name=\"foo\" value=\"newValue\" />\n" + " </component>\n" + "</application>")
|
||||
assertThat(streamProvider.data.get(RoamingType.DEFAULT)!!.get("new.xml")).isEqualTo("<application>\n" + " <component name=\"A\" foo=\"newValue\" />\n" + "</application>")
|
||||
}
|
||||
|
||||
@Test fun `load from stream provider`() {
|
||||
@@ -75,8 +75,8 @@ class ApplicationStoreTest {
|
||||
|
||||
val streamProvider = MyStreamProvider()
|
||||
val map = THashMap<String, String>()
|
||||
val fileSpec = "proxy.xml"
|
||||
map.put(fileSpec, "<application>\n <component name=\"HttpConfigurable\">\n <option name=\"foo\" value=\"newValue\" />\n </component>\n</application>")
|
||||
val fileSpec = "new.xml"
|
||||
map.put(fileSpec, "<application>\n <component name=\"A\" foo=\"newValue\" />\n</application>")
|
||||
streamProvider.data.put(RoamingType.DEFAULT, map)
|
||||
|
||||
componentStore.storageManager.streamProvider = streamProvider
|
||||
@@ -95,8 +95,8 @@ class ApplicationStoreTest {
|
||||
}
|
||||
|
||||
private fun doRemoveDeprecatedStorageOnWrite(component: Foo) {
|
||||
val oldFile = writeConfig("other.xml", "<application><component name=\"HttpConfigurable\"><option name=\"foo\" value=\"old\" /></component></application>")
|
||||
writeConfig("proxy.xml", "<application><component name=\"HttpConfigurable\"><option name=\"foo\" value=\"new\" /></component></application>")
|
||||
val oldFile = writeConfig("old.xml", "<application>${createComponentData("old")}</application>")
|
||||
writeConfig("new.xml", "<application>${createComponentData("new")}</application>")
|
||||
|
||||
testAppConfig.refreshVfs()
|
||||
|
||||
@@ -109,6 +109,29 @@ class ApplicationStoreTest {
|
||||
assertThat(oldFile).doesNotExist()
|
||||
}
|
||||
|
||||
private fun createComponentData(foo: String) = """<component name="A" foo="$foo" />"""
|
||||
|
||||
@Test fun `remove data from deprecated storage if another component data exists`() {
|
||||
val data = createComponentData("new")
|
||||
val oldFile = writeConfig("old.xml", """<application>
|
||||
<component name="OtherComponent" foo="old" />
|
||||
${createComponentData("old")}
|
||||
</application>""")
|
||||
writeConfig("new.xml", "<application>$data</application>")
|
||||
|
||||
testAppConfig.refreshVfs()
|
||||
|
||||
val component = SeveralStoragesConfigured()
|
||||
componentStore.initComponent(component, false)
|
||||
assertThat(component.foo).isEqualTo("new")
|
||||
|
||||
saveStore()
|
||||
|
||||
assertThat(oldFile).hasContent("""<application>
|
||||
<component name="OtherComponent" foo="old" />
|
||||
</application>""")
|
||||
}
|
||||
|
||||
@State(name = "A", storages = arrayOf(Storage(file = "a.xml")))
|
||||
private open class A : PersistentStateComponent<Element> {
|
||||
data class State(@Attribute var foo: String = "", @Attribute var bar: String = "")
|
||||
@@ -118,7 +141,7 @@ class ApplicationStoreTest {
|
||||
override fun getState() = state.serialize()
|
||||
|
||||
override fun loadState(state: Element) {
|
||||
this.state = XmlSerializer.deserialize(state, javaClass<State>())!!
|
||||
this.state = XmlSerializer.deserialize(state, State::class.java)!!
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,10 +232,11 @@ class ApplicationStoreTest {
|
||||
}
|
||||
|
||||
abstract class Foo {
|
||||
public var foo: String = "defaultValue"
|
||||
@Attribute
|
||||
var foo = "defaultValue"
|
||||
}
|
||||
|
||||
@State(name = "HttpConfigurable", storages = arrayOf(Storage(file = "proxy.xml"), Storage(file = StoragePathMacros.APP_CONFIG + "/other.xml", deprecated = true)))
|
||||
@State(name = "A", storages = arrayOf(Storage(file = "new.xml"), Storage(file = StoragePathMacros.APP_CONFIG + "/old.xml", deprecated = true)))
|
||||
class SeveralStoragesConfigured : Foo(), PersistentStateComponent<SeveralStoragesConfigured> {
|
||||
override fun getState(): SeveralStoragesConfigured? {
|
||||
return this
|
||||
@@ -223,7 +247,7 @@ class ApplicationStoreTest {
|
||||
}
|
||||
}
|
||||
|
||||
@State(name = "HttpConfigurable", storages = arrayOf(Storage(file = "other.xml", deprecated = true), Storage(file = "${StoragePathMacros.APP_CONFIG}/proxy.xml")))
|
||||
@State(name = "A", storages = arrayOf(Storage(file = "old.xml", deprecated = true), Storage(file = "${StoragePathMacros.APP_CONFIG}/new.xml")))
|
||||
class ActualStorageLast : Foo(), PersistentStateComponent<ActualStorageLast> {
|
||||
override fun getState() = this
|
||||
|
||||
|
||||
@@ -5,28 +5,30 @@ import com.intellij.externalDependencies.ExternalDependenciesManager
|
||||
import com.intellij.externalDependencies.ProjectExternalDependency
|
||||
import com.intellij.openapi.application.ex.ApplicationManagerEx
|
||||
import com.intellij.openapi.components.StoragePathMacros
|
||||
import com.intellij.openapi.components.impl.stores.IComponentStore
|
||||
import com.intellij.openapi.components.impl.stores.StateStorageManager
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.components.stateStore
|
||||
import com.intellij.openapi.project.ProjectManager
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.testFramework.ProjectRule
|
||||
import com.intellij.testFramework.RuleChain
|
||||
import com.intellij.testFramework.TemporaryDirectory
|
||||
import com.intellij.testFramework.deleteRecursively
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.ClassRule
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.ExternalResource
|
||||
import java.io.File
|
||||
import java.nio.file.Paths
|
||||
|
||||
class DefaultProjectStoreTest {
|
||||
companion object {
|
||||
ClassRule val projectRule = ProjectRule()
|
||||
@ClassRule val projectRule = ProjectRule()
|
||||
}
|
||||
|
||||
private val tempDirManager = TemporaryDirectory()
|
||||
|
||||
private val requiredPlugins: List<ProjectExternalDependency> = listOf(DependencyOnPlugin("fake", "0", "1"))
|
||||
private val requiredPlugins = listOf<ProjectExternalDependency>(DependencyOnPlugin("fake", "0", "1"))
|
||||
|
||||
private val ruleChain = RuleChain(
|
||||
tempDirManager,
|
||||
@@ -45,7 +47,7 @@ class DefaultProjectStoreTest {
|
||||
app.doNotSave(isDoNotSave)
|
||||
}
|
||||
finally {
|
||||
FileUtil.delete(File(app.stateStore.getStateStorageManager().expandMacros(StoragePathMacros.APP_CONFIG)))
|
||||
Paths.get(app.stateStore.storageManager.expandMacros(StoragePathMacros.APP_CONFIG)).deleteRecursively()
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -63,11 +65,14 @@ class DefaultProjectStoreTest {
|
||||
}
|
||||
)
|
||||
|
||||
public Rule fun getChain(): RuleChain = ruleChain
|
||||
@Rule fun getChain() = ruleChain
|
||||
|
||||
public Test fun `new project from default`() {
|
||||
createProject(tempDirManager) {
|
||||
@Test fun `new project from default`() {
|
||||
createProjectAndUseInLoadComponentStateMode(tempDirManager) {
|
||||
assertThat(it.service<ExternalDependenciesManager>().getAllDependencies()).isEqualTo(requiredPlugins)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val IComponentStore.storageManager: StateStorageManager
|
||||
get() = getStateStorageManager()
|
||||
@@ -47,7 +47,7 @@ class ModuleStoreTest {
|
||||
private val tempDirManager = TemporaryDirectory()
|
||||
|
||||
private val ruleChain = RuleChain(tempDirManager, EdtRule(), ActiveStoreRule(projectRule), DisposeModulesRule(projectRule))
|
||||
public Rule fun getChain(): RuleChain = ruleChain
|
||||
@Rule fun getChain() = ruleChain
|
||||
|
||||
@Test fun `set option`() {
|
||||
val moduleFile = runWriteAction {
|
||||
|
||||
@@ -32,11 +32,11 @@ import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import java.io.File
|
||||
|
||||
fun createProject(tempDirManager: TemporaryDirectory, task: (Project) -> Unit) {
|
||||
fun createProjectAndUseInLoadComponentStateMode(tempDirManager: TemporaryDirectory, task: (Project) -> Unit) {
|
||||
createOrLoadProject(tempDirManager, task)
|
||||
}
|
||||
|
||||
fun loadProject(tempDirManager: TemporaryDirectory, projectCreator: ((VirtualFile) -> String)? = null, task: (Project) -> Unit) {
|
||||
fun loadAndUseProject(tempDirManager: TemporaryDirectory, projectCreator: ((VirtualFile) -> String)? = null, task: (Project) -> Unit) {
|
||||
createOrLoadProject(tempDirManager, task, projectCreator)
|
||||
}
|
||||
|
||||
@@ -51,20 +51,22 @@ private fun createOrLoadProject(tempDirManager: TemporaryDirectory, task: (Proje
|
||||
}
|
||||
|
||||
val projectManager = ProjectManagerEx.getInstanceEx() as ProjectManagerImpl
|
||||
var project = if (projectCreator == null) projectManager.newProject(null, filePath, true, false, false)!! else projectManager.loadProject(filePath)!!
|
||||
try {
|
||||
projectManager.openTestProject(project)
|
||||
task(project)
|
||||
}
|
||||
finally {
|
||||
projectManager.closeProject(project, false, true, false)
|
||||
var project = if (projectCreator == null) projectManager.newProject(null, filePath, true, false)!! else projectManager.loadProject(filePath)!!
|
||||
project.runInLoadComponentStateMode {
|
||||
try {
|
||||
projectManager.openTestProject(project)
|
||||
task(project)
|
||||
}
|
||||
finally {
|
||||
projectManager.closeProject(project, false, true, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ProjectStoreTest {
|
||||
companion object {
|
||||
ClassRule val projectRule = ProjectRule()
|
||||
@ClassRule val projectRule = ProjectRule()
|
||||
}
|
||||
|
||||
val tempDirManager = TemporaryDirectory()
|
||||
@@ -72,7 +74,7 @@ class ProjectStoreTest {
|
||||
private val ruleChain = RuleChain(tempDirManager)
|
||||
@Rule fun getChain() = ruleChain
|
||||
|
||||
Language("XML")
|
||||
@Language("XML")
|
||||
private val iprFileContent =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
|
||||
"<project version=\"4\">\n" +
|
||||
@@ -81,7 +83,7 @@ class ProjectStoreTest {
|
||||
" </component>\n" +
|
||||
"</project>"
|
||||
|
||||
State(name = "AATestComponent", storages = arrayOf(Storage(file = StoragePathMacros.PROJECT_FILE)))
|
||||
@State(name = "AATestComponent", storages = arrayOf(Storage(file = StoragePathMacros.PROJECT_FILE)))
|
||||
private class TestComponent : PersistentStateComponent<TestState> {
|
||||
private var state: TestState? = null
|
||||
|
||||
@@ -94,8 +96,8 @@ class ProjectStoreTest {
|
||||
|
||||
data class TestState(var value: String = "default")
|
||||
|
||||
public Test fun directoryBasedStorage() {
|
||||
loadProject(tempDirManager, {
|
||||
@Test fun directoryBasedStorage() {
|
||||
loadAndUseProject(tempDirManager, {
|
||||
it.writeChild("${Project.DIRECTORY_STORE_FOLDER}/misc.xml", iprFileContent)
|
||||
it.path
|
||||
}) { project ->
|
||||
@@ -112,8 +114,8 @@ class ProjectStoreTest {
|
||||
}
|
||||
}
|
||||
|
||||
public Test fun fileBasedStorage() {
|
||||
loadProject(tempDirManager, { it.writeChild("test${ProjectFileType.DOT_DEFAULT_EXTENSION}", iprFileContent).path }) { project ->
|
||||
@Test fun fileBasedStorage() {
|
||||
loadAndUseProject(tempDirManager, { it.writeChild("test${ProjectFileType.DOT_DEFAULT_EXTENSION}", iprFileContent).path }) { project ->
|
||||
test(project)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,26 +49,26 @@ val FILE_SPEC = "REMOTE"
|
||||
*/
|
||||
class SchemeManagerTest {
|
||||
companion object {
|
||||
ClassRule val projectRule = ProjectRule()
|
||||
@ClassRule val projectRule = ProjectRule()
|
||||
}
|
||||
|
||||
private val tempDirManager = TemporaryDirectory()
|
||||
public Rule fun getTemporaryFolder(): TemporaryDirectory = tempDirManager
|
||||
@Rule fun getTemporaryFolder() = tempDirManager
|
||||
|
||||
private var localBaseDir: File? = null
|
||||
private var remoteBaseDir: File? = null
|
||||
|
||||
private fun getTestDataPath() = PlatformTestUtil.getCommunityPath().replace(File.separatorChar, '/') + "/platform/platform-tests/testData/options"
|
||||
|
||||
public Test fun testLoadSchemes() {
|
||||
@Test fun testLoadSchemes() {
|
||||
doLoadSaveTest("options1", "1->first;2->second")
|
||||
}
|
||||
|
||||
public Test fun testLoadSimpleSchemes() {
|
||||
@Test fun testLoadSimpleSchemes() {
|
||||
doLoadSaveTest("options", "1->1")
|
||||
}
|
||||
|
||||
public Test fun testDeleteScheme() {
|
||||
@Test fun testDeleteScheme() {
|
||||
val manager = createAndLoad("options1")
|
||||
manager.removeScheme(TestScheme("first"))
|
||||
manager.save()
|
||||
@@ -76,7 +76,7 @@ class SchemeManagerTest {
|
||||
checkSchemes("2->second")
|
||||
}
|
||||
|
||||
public Test fun testRenameScheme() {
|
||||
@Test fun testRenameScheme() {
|
||||
val manager = createAndLoad("options1")
|
||||
|
||||
val scheme = manager.findSchemeByName("first")
|
||||
@@ -87,7 +87,7 @@ class SchemeManagerTest {
|
||||
checkSchemes("2->second;renamed->renamed")
|
||||
}
|
||||
|
||||
public Test fun testRenameScheme2() {
|
||||
@Test fun testRenameScheme2() {
|
||||
val manager = createAndLoad("options1")
|
||||
|
||||
val first = manager.findSchemeByName("first")
|
||||
@@ -103,7 +103,7 @@ class SchemeManagerTest {
|
||||
checkSchemes("1->1;2->2")
|
||||
}
|
||||
|
||||
public Test fun testDeleteRenamedScheme() {
|
||||
@Test fun testDeleteRenamedScheme() {
|
||||
val manager = createAndLoad("options1")
|
||||
|
||||
val firstScheme = manager.findSchemeByName("first")
|
||||
@@ -123,7 +123,7 @@ class SchemeManagerTest {
|
||||
checkSchemes(localBaseDir!!, "", false)
|
||||
}
|
||||
|
||||
public Test fun testDeleteAndCreateSchemeWithTheSameName() {
|
||||
@Test fun testDeleteAndCreateSchemeWithTheSameName() {
|
||||
val manager = createAndLoad("options1")
|
||||
val firstScheme = manager.findSchemeByName("first")
|
||||
assertThat(firstScheme).isNotNull()
|
||||
@@ -134,7 +134,7 @@ class SchemeManagerTest {
|
||||
checkSchemes("2->second;first->first")
|
||||
}
|
||||
|
||||
public Test fun testGenerateUniqueSchemeName() {
|
||||
@Test fun testGenerateUniqueSchemeName() {
|
||||
val manager = createAndLoad("options1")
|
||||
val scheme = TestScheme("first")
|
||||
manager.addNewScheme(scheme, false)
|
||||
@@ -146,7 +146,7 @@ class SchemeManagerTest {
|
||||
FileUtil.writeToFile(file, _serialize().toByteArray())
|
||||
}
|
||||
|
||||
public Test fun `different extensions`() {
|
||||
@Test fun `different extensions`() {
|
||||
val dir = tempDirManager.newDirectory()
|
||||
|
||||
val scheme = TestScheme("local", "true")
|
||||
@@ -159,7 +159,7 @@ class SchemeManagerTest {
|
||||
override fun getSchemeExtension() = ".icls"
|
||||
}, null, dir)
|
||||
schemesManager.loadSchemes()
|
||||
assertThat(schemesManager.getAllSchemes()).containsOnly(scheme)
|
||||
assertThat(schemesManager.allSchemes).containsOnly(scheme)
|
||||
|
||||
assertThat(File(dir, "1.icls")).isFile()
|
||||
assertThat(File(dir, "1.xml")).isFile()
|
||||
@@ -171,16 +171,16 @@ class SchemeManagerTest {
|
||||
assertThat(File(dir, "1.xml")).doesNotExist()
|
||||
}
|
||||
|
||||
public Test fun setSchemes() {
|
||||
@Test fun setSchemes() {
|
||||
val dir = tempDirManager.newDirectory()
|
||||
val schemeManager = createSchemeManager(dir)
|
||||
schemeManager.loadSchemes()
|
||||
assertThat(schemeManager.getAllSchemes()).isEmpty()
|
||||
assertThat(schemeManager.allSchemes).isEmpty()
|
||||
|
||||
val scheme = TestScheme("s1")
|
||||
schemeManager.setSchemes(listOf(scheme))
|
||||
|
||||
val schemes = schemeManager.getAllSchemes()
|
||||
val schemes = schemeManager.allSchemes
|
||||
assertThat(schemes).containsOnly(scheme)
|
||||
|
||||
assertThat(File(dir, "s1.xml")).doesNotExist()
|
||||
@@ -197,13 +197,13 @@ class SchemeManagerTest {
|
||||
assertThat(dir).doesNotExist()
|
||||
}
|
||||
|
||||
public Test fun `save only if scheme differs from bundled`() {
|
||||
@Test fun `save only if scheme differs from bundled`() {
|
||||
val dir = tempDirManager.newDirectory()
|
||||
var schemeManager = createSchemeManager(dir)
|
||||
val converter: (Element) -> TestScheme = { XmlSerializer.deserialize(it, javaClass<TestScheme>())!! }
|
||||
val converter: (Element) -> TestScheme = { XmlSerializer.deserialize(it, TestScheme::class.java)!! }
|
||||
val bundledPath = "/bundledSchemes/default"
|
||||
schemeManager.loadBundledScheme(bundledPath, this, converter)
|
||||
var schemes = schemeManager.getAllSchemes()
|
||||
var schemes = schemeManager.allSchemes
|
||||
val customScheme = TestScheme("default")
|
||||
assertThat(schemes).containsOnly(customScheme)
|
||||
|
||||
@@ -214,7 +214,7 @@ class SchemeManagerTest {
|
||||
schemeManager.setSchemes(listOf(customScheme))
|
||||
assertThat(dir).doesNotExist()
|
||||
|
||||
schemes = schemeManager.getAllSchemes()
|
||||
schemes = schemeManager.allSchemes
|
||||
assertThat(schemes).containsOnly(customScheme)
|
||||
|
||||
customScheme.data = "foo"
|
||||
@@ -225,11 +225,11 @@ class SchemeManagerTest {
|
||||
schemeManager.loadBundledScheme(bundledPath, this, converter)
|
||||
schemeManager.loadSchemes()
|
||||
|
||||
schemes = schemeManager.getAllSchemes()
|
||||
schemes = schemeManager.allSchemes
|
||||
assertThat(schemes).containsOnly(customScheme)
|
||||
}
|
||||
|
||||
public Test fun `don't remove dir if no schemes but at least one non-hidden file exists`() {
|
||||
@Test fun `don't remove dir if no schemes but at least one non-hidden file exists`() {
|
||||
val dir = tempDirManager.newDirectory()
|
||||
val schemeManager = createSchemeManager(dir)
|
||||
|
||||
@@ -251,7 +251,7 @@ class SchemeManagerTest {
|
||||
assertThat(dir).isDirectory()
|
||||
}
|
||||
|
||||
public Test fun `remove empty directory only if some file was deleted`() {
|
||||
@Test fun `remove empty directory only if some file was deleted`() {
|
||||
val dir = tempDirManager.newDirectory()
|
||||
val schemeManager = createSchemeManager(dir)
|
||||
schemeManager.loadSchemes()
|
||||
@@ -269,16 +269,16 @@ class SchemeManagerTest {
|
||||
assertThat(dir).doesNotExist()
|
||||
}
|
||||
|
||||
public Test fun rename() {
|
||||
@Test fun rename() {
|
||||
val dir = tempDirManager.newDirectory()
|
||||
val schemeManager = createSchemeManager(dir)
|
||||
schemeManager.loadSchemes()
|
||||
assertThat(schemeManager.getAllSchemes()).isEmpty()
|
||||
assertThat(schemeManager.allSchemes).isEmpty()
|
||||
|
||||
val scheme = TestScheme("s1")
|
||||
schemeManager.setSchemes(listOf(scheme))
|
||||
|
||||
val schemes = schemeManager.getAllSchemes()
|
||||
val schemes = schemeManager.allSchemes
|
||||
assertThat(schemes).containsOnly(scheme)
|
||||
|
||||
assertThat(File(dir, "s1.xml")).doesNotExist()
|
||||
@@ -296,11 +296,11 @@ class SchemeManagerTest {
|
||||
assertThat(File(dir, "s2.xml")).isFile()
|
||||
}
|
||||
|
||||
public Test fun `path must not contains ROOT_CONFIG macro`() {
|
||||
@Test fun `path must not contains ROOT_CONFIG macro`() {
|
||||
assertThatThrownBy({ SchemesManagerFactory.getInstance().create<TestScheme, TestScheme>("\$ROOT_CONFIG$/foo", TestSchemesProcessor()) }).hasMessage("Path must not contains ROOT_CONFIG macro, corrected: foo")
|
||||
}
|
||||
|
||||
public Test fun `path must be system-independent`() {
|
||||
@Test fun `path must be system-independent`() {
|
||||
assertThatThrownBy({SchemesManagerFactory.getInstance().create<TestScheme, TestScheme>("foo\\bar", TestSchemesProcessor())}).hasMessage("Path must be system-independent, use forward slash instead of backslash")
|
||||
}
|
||||
|
||||
@@ -369,20 +369,20 @@ private fun checkSchemes(baseDir: File, expected: String, ignoreDeleted: Boolean
|
||||
}
|
||||
}
|
||||
|
||||
Tag("scheme")
|
||||
public data class TestScheme(@Attribute private var name: String = "", @Attribute public var data: String? = null) : ExternalizableScheme {
|
||||
@Tag("scheme")
|
||||
data class TestScheme(@field:Attribute private var name: String = "", @field:Attribute var data: String? = null) : ExternalizableScheme {
|
||||
override fun getName() = name
|
||||
|
||||
override Transient fun setName(newName: String) {
|
||||
override @Transient fun setName(newName: String) {
|
||||
name = newName
|
||||
}
|
||||
|
||||
@suppress("DEPRECATED_SYMBOL_WITH_MESSAGE")
|
||||
@Suppress("DEPRECATED_SYMBOL_WITH_MESSAGE")
|
||||
override fun getExternalInfo() = null
|
||||
}
|
||||
|
||||
public open class TestSchemesProcessor : BaseSchemeProcessor<TestScheme>() {
|
||||
override fun readScheme(element: Element) = XmlSerializer.deserialize(element, javaClass<TestScheme>())
|
||||
override fun readScheme(element: Element) = XmlSerializer.deserialize(element, TestScheme::class.java)
|
||||
|
||||
override fun writeScheme(scheme: TestScheme) = scheme._serialize()
|
||||
}
|
||||
@@ -390,7 +390,7 @@ public open class TestSchemesProcessor : BaseSchemeProcessor<TestScheme>() {
|
||||
fun SchemeManagerImpl<*, *>.save() {
|
||||
val errors = SmartList<Throwable>()
|
||||
save(errors)
|
||||
CompoundRuntimeException.doThrow(errors)
|
||||
CompoundRuntimeException.throwIfNotEmpty(errors)
|
||||
}
|
||||
|
||||
public fun <T : Any> T._serialize(filter: SerializationFilter? = SkipDefaultValuesSerializationFilters()): Element = XmlSerializer.serialize(this, filter)
|
||||
@@ -19,8 +19,8 @@ import org.junit.runner.RunWith
|
||||
import org.junit.runners.Suite
|
||||
|
||||
// All in package is very slow, so, we have to use Suite to speedup
|
||||
RunWith(Suite::class)
|
||||
Suite.SuiteClasses(
|
||||
@RunWith(Suite::class)
|
||||
@Suite.SuiteClasses(
|
||||
ApplicationStoreTest::class,
|
||||
ProjectStoreTest::class, DefaultProjectStoreTest::class,
|
||||
ModuleStoreTest::class, ModuleStoreRenameTest::class,
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.junit.Test
|
||||
class XmlElementStorageTest {
|
||||
@Test fun testGetStateSucceeded() {
|
||||
val storage = MyXmlElementStorage(tag("root", tag("component", attr("name", "test"), tag("foo"))))
|
||||
val state = storage.getState(this, "test", javaClass<Element>())
|
||||
val state = storage.getState(this, "test", Element::class.java)
|
||||
assertThat(state).isNotNull()
|
||||
assertThat(state!!.getName()).isEqualTo("component")
|
||||
assertThat(state.getChild("foo")).isNotNull()
|
||||
@@ -32,7 +32,7 @@ class XmlElementStorageTest {
|
||||
|
||||
@Test fun `get state not succeeded`() {
|
||||
val storage = MyXmlElementStorage(tag("root"))
|
||||
val state = storage.getState(this, "test", javaClass<Element>())
|
||||
val state = storage.getState(this, "test", Element::class.java)
|
||||
assertThat(state).isNull()
|
||||
}
|
||||
|
||||
|
||||
@@ -125,6 +125,17 @@ public abstract class PsiDocumentManager {
|
||||
*/
|
||||
public abstract long getLastCommittedStamp(@NotNull Document document);
|
||||
|
||||
/**
|
||||
* Returns the document for specified PsiFile intended to be used when working with committed PSI, e.g. outside dispatch thread.
|
||||
* @param file the file for which the document is requested.
|
||||
* @return an immutable document corresponding to the current PSI state. For committed documents, the contents and timestamp are equal to
|
||||
* the ones of {@link #getDocument(PsiFile)}. For uncommitted documents, the text is {@link #getLastCommittedText(Document)} and
|
||||
* the modification stamp is {@link #getLastCommittedStamp(Document)}.
|
||||
* @since 143.* builds
|
||||
*/
|
||||
@Nullable
|
||||
public abstract Document getLastCommittedDocument(@NotNull PsiFile file);
|
||||
|
||||
/**
|
||||
* Returns the list of documents which have been modified but not committed.
|
||||
*
|
||||
|
||||
@@ -47,6 +47,23 @@ public class ILazyParseableElementType extends IElementType {
|
||||
super(debugName, language, register);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the contents of the specified chameleon node and returns PsiBuilder.
|
||||
* In future this method should deprecate all other parsing methods: parseContents(), doParseContents(), etc.
|
||||
* It provides more flexible and CPU/memory efficient access to parser algorithms for all needs:
|
||||
* editing, indexing and analysis.
|
||||
* <p/>
|
||||
*
|
||||
* The parseContent() implementation in terms of parseLight() is just the following:
|
||||
* {@code}parseLight().getTreeBuilt().getFirstChildNode(){@code}
|
||||
*
|
||||
* @param chameleon the node to parse.
|
||||
* @return the parsed contents of the node in the form PsiBuilder.
|
||||
*/
|
||||
public PsiBuilder parseLight(ASTNode chameleon) {
|
||||
throw new UnsupportedOperationException(String.valueOf(chameleon));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the contents of the specified chameleon node and returns the AST tree
|
||||
* representing the parsed contents.
|
||||
@@ -54,13 +71,13 @@ public class ILazyParseableElementType extends IElementType {
|
||||
* @param chameleon the node to parse.
|
||||
* @return the parsed contents of the node.
|
||||
*/
|
||||
public ASTNode parseContents(final ASTNode chameleon) {
|
||||
final PsiElement parentElement = chameleon.getTreeParent().getPsi();
|
||||
assert parentElement != null : "Bad chameleon: " + chameleon;
|
||||
public ASTNode parseContents(ASTNode chameleon) {
|
||||
PsiElement parentElement = chameleon.getTreeParent().getPsi();
|
||||
assert parentElement != null : "parent psi is null: " + chameleon;
|
||||
return doParseContents(chameleon, parentElement);
|
||||
}
|
||||
|
||||
protected ASTNode doParseContents(@NotNull final ASTNode chameleon, @NotNull final PsiElement psi) {
|
||||
protected ASTNode doParseContents(@NotNull ASTNode chameleon, @NotNull PsiElement psi) {
|
||||
Project project = psi.getProject();
|
||||
Language languageForParser = getLanguageForParser(psi);
|
||||
PsiBuilder builder = PsiBuilderFactory.getInstance().createBuilder(project, chameleon, null, languageForParser, chameleon.getChars());
|
||||
|
||||
@@ -123,8 +123,13 @@ public abstract class CachedValuesManager {
|
||||
* @return The cached value
|
||||
*/
|
||||
public static <T> T getCachedValue(@NotNull final PsiElement psi, @NotNull final CachedValueProvider<T> provider) {
|
||||
CachedValuesManager manager = getManager(psi.getProject());
|
||||
return manager.getCachedValue(psi, manager.<T>getKeyForClass(provider.getClass()), new CachedValueProvider<T>() {
|
||||
Key<CachedValue<T>> key = getKeyForClass(provider.getClass(), globalKeyForProvider);
|
||||
CachedValue<T> value = psi.getUserData(key);
|
||||
if (value != null) {
|
||||
return value.getValue();
|
||||
}
|
||||
|
||||
return getManager(psi.getProject()).getCachedValue(psi, key, new CachedValueProvider<T>() {
|
||||
@Nullable
|
||||
@Override
|
||||
public Result<T> compute() {
|
||||
@@ -138,8 +143,15 @@ public abstract class CachedValuesManager {
|
||||
}
|
||||
|
||||
private final ConcurrentMap<String, Key<CachedValue>> keyForProvider = ContainerUtil.newConcurrentMap();
|
||||
private static final ConcurrentMap<String, Key<CachedValue>> globalKeyForProvider = ContainerUtil.newConcurrentMap();
|
||||
|
||||
@NotNull
|
||||
public <T> Key<CachedValue<T>> getKeyForClass(@NotNull Class<?> providerClass) {
|
||||
return getKeyForClass(providerClass, keyForProvider);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static <T> Key<CachedValue<T>> getKeyForClass(@NotNull Class<?> providerClass, ConcurrentMap<String, Key<CachedValue>> keyForProvider) {
|
||||
String name = providerClass.getName();
|
||||
assert name != null : providerClass + " doesn't have a name; can't be used for cache value provider";
|
||||
Key<CachedValue> key = keyForProvider.get(name);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,6 +17,7 @@ package com.intellij.util;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.IndexNotReadyException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -40,6 +41,7 @@ public final class ExecutorsQuery<Result, Parameter> extends AbstractQuery<Resul
|
||||
protected boolean processResults(@NotNull final Processor<Result> consumer) {
|
||||
for (QueryExecutor<Result, Parameter> executor : myExecutors) {
|
||||
try {
|
||||
ProgressManager.checkCanceled();
|
||||
if (!executor.execute(myParameters, consumer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
+17
-26
@@ -19,9 +19,9 @@ import com.intellij.ide.plugins.PluginManagerCore;
|
||||
import com.intellij.openapi.application.ApplicationNamesInfo;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.application.ex.ApplicationInfoEx;
|
||||
import com.intellij.openapi.components.NamedComponent;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.util.BuildNumber;
|
||||
import com.intellij.openapi.util.JDOMUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
@@ -45,7 +45,7 @@ import java.util.List;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
public class ApplicationInfoImpl extends ApplicationInfoEx implements JDOMExternalizable, NamedComponent {
|
||||
public class ApplicationInfoImpl extends ApplicationInfoEx {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.application.impl.ApplicationInfoImpl");
|
||||
|
||||
private String myCodeName = null;
|
||||
@@ -187,6 +187,19 @@ public class ApplicationInfoImpl extends ApplicationInfoEx implements JDOMExtern
|
||||
|
||||
private static final String DEFAULT_PLUGINS_HOST = "http://plugins.jetbrains.com";
|
||||
|
||||
ApplicationInfoImpl() {
|
||||
try {
|
||||
Document doc = JDOMUtil.loadDocument(ApplicationInfoImpl.class, IDEA_PATH + ApplicationNamesInfo.getComponentName() + XML_EXTENSION);
|
||||
loadState(doc.getRootElement());
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
LOG.error("Resource is not in classpath or wrong platform prefix: " + System.getProperty(PlatformUtils.PLATFORM_PREFIX_KEY), e);
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Calendar getBuildDate() {
|
||||
return myBuildDate;
|
||||
@@ -536,22 +549,11 @@ public class ApplicationInfoImpl extends ApplicationInfoEx implements JDOMExtern
|
||||
public static ApplicationInfoEx getShadowInstance() {
|
||||
if (ourShadowInstance == null) {
|
||||
ourShadowInstance = new ApplicationInfoImpl();
|
||||
try {
|
||||
Document doc = JDOMUtil.loadDocument(ApplicationInfoImpl.class, IDEA_PATH + ApplicationNamesInfo.getComponentName() + XML_EXTENSION);
|
||||
ourShadowInstance.readExternal(doc.getRootElement());
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
LOG.error("Resource is not in classpath or wrong platform prefix: " + System.getProperty(PlatformUtils.PLATFORM_PREFIX_KEY), e);
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
return ourShadowInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readExternal(Element parentNode) throws InvalidDataException {
|
||||
private void loadState(Element parentNode) {
|
||||
Element versionElement = parentNode.getChild(ELEMENT_VERSION);
|
||||
if (versionElement != null) {
|
||||
myMajorVersion = versionElement.getAttributeValue(ATTRIBUTE_MAJOR);
|
||||
@@ -845,11 +847,6 @@ public class ApplicationInfoImpl extends ApplicationInfoEx implements JDOMExtern
|
||||
return new Color((int)rgb, rgb > 0xffffff);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeExternal(Element element) throws WriteExternalException {
|
||||
throw new WriteExternalException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PluginChooserPage> getPluginChooserPages() {
|
||||
return myPluginChooserPages;
|
||||
@@ -860,12 +857,6 @@ public class ApplicationInfoImpl extends ApplicationInfoEx implements JDOMExtern
|
||||
return PluginManagerCore.CORE_PLUGIN_ID.equals(pluginId) || ArrayUtil.contains(pluginId, myEssentialPluginsIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getComponentName() {
|
||||
return ApplicationNamesInfo.getComponentName();
|
||||
}
|
||||
|
||||
private static class UpdateUrlsImpl implements UpdateUrls {
|
||||
private String myCheckingUrl;
|
||||
private String myPatchesUrl;
|
||||
|
||||
@@ -210,7 +210,7 @@ public class PomModelImpl extends UserDataHolderBase implements PomModel {
|
||||
finally {
|
||||
DebugUtil.finishPsiModification();
|
||||
}
|
||||
if (!throwables.isEmpty()) CompoundRuntimeException.doThrow(throwables);
|
||||
if (!throwables.isEmpty()) CompoundRuntimeException.throwIfNotEmpty(throwables);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,6 @@ import com.intellij.psi.stubs.StubElement;
|
||||
import com.intellij.psi.stubs.StubTree;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.IStubFileElementType;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -456,8 +455,6 @@ public abstract class PsiAnchor {
|
||||
private final int myIndex;
|
||||
private final Language myLanguage;
|
||||
private final IStubElementType myElementType;
|
||||
private final short myCreationModCount;
|
||||
private final short myCreationStamp;
|
||||
|
||||
private StubIndexReference(@NotNull final PsiFile file, final int index, @NotNull Language language, IStubElementType elementType) {
|
||||
myLanguage = language;
|
||||
@@ -465,16 +462,6 @@ public abstract class PsiAnchor {
|
||||
myVirtualFile = file.getVirtualFile();
|
||||
myProject = file.getProject();
|
||||
myIndex = index;
|
||||
myCreationModCount = getModCount();
|
||||
myCreationStamp = (short)file.getModificationStamp();
|
||||
}
|
||||
|
||||
private short getModCount() {
|
||||
final PsiModificationTracker tracker = PsiManager.getInstance(getProject()).getModificationTracker();
|
||||
if (myVirtualFile.getName().endsWith(".java")) {
|
||||
return (short)tracker.getJavaStructureModificationCount();
|
||||
}
|
||||
return (short)tracker.getModificationCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -521,11 +508,10 @@ public abstract class PsiAnchor {
|
||||
}
|
||||
catch (AssertionError e) {
|
||||
String msg = e.getMessage();
|
||||
msg += "\n current (java)modCount=" + getModCount() + "; creation (java)modCount=" + myCreationModCount;
|
||||
if (file == null) {
|
||||
msg += "\n no PSI file";
|
||||
} else {
|
||||
msg += "\n current file stamp=" + (short)file.getModificationStamp() + "; creation file stamp=" + myCreationStamp;
|
||||
msg += "\n current file stamp=" + (short)file.getModificationStamp();
|
||||
}
|
||||
final Document document = FileDocumentManager.getInstance().getCachedDocument(myVirtualFile);
|
||||
if (document != null) {
|
||||
|
||||
@@ -17,12 +17,15 @@
|
||||
package com.intellij.psi.impl;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectRootModificationTracker;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.util.CachedValueBase;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -38,8 +41,23 @@ public abstract class PsiCachedValue<T> extends CachedValueBase<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void valueUpdated() {
|
||||
myLastPsiTimeStamp = myManager.getModificationTracker().getModificationCount();
|
||||
protected void valueUpdated(@Nullable Object[] dependencies) {
|
||||
myLastPsiTimeStamp = hasOnlyPhysicalPsiDependencies(dependencies) ? myManager.getModificationTracker().getModificationCount() : -1;
|
||||
}
|
||||
|
||||
private static boolean hasOnlyPhysicalPsiDependencies(@Nullable Object[] dependencies) {
|
||||
return dependencies != null && dependencies.length > 0 && ContainerUtil.and(dependencies, new Condition<Object>() {
|
||||
@Override
|
||||
public boolean value(Object o) {
|
||||
return o instanceof PsiElement && ((PsiElement)o).isValid() && ((PsiElement)o).isPhysical() ||
|
||||
o instanceof ProjectRootModificationTracker ||
|
||||
o instanceof PsiModificationTracker ||
|
||||
o == PsiModificationTracker.MODIFICATION_COUNT ||
|
||||
o == PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT ||
|
||||
o == PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT ||
|
||||
o == PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -55,10 +73,7 @@ public abstract class PsiCachedValue<T> extends CachedValueBase<T> {
|
||||
|
||||
@Override
|
||||
protected boolean isDependencyOutOfDate(Object dependency, long oldTimeStamp) {
|
||||
if (dependency instanceof PsiElement &&
|
||||
myLastPsiTimeStamp == myManager.getModificationTracker().getModificationCount() &&
|
||||
((PsiElement)dependency).isValid() &&
|
||||
((PsiElement)dependency).isPhysical()) {
|
||||
if (myLastPsiTimeStamp != -1 && myLastPsiTimeStamp == myManager.getModificationTracker().getModificationCount()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -578,6 +578,13 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
|
||||
return getLastCommittedDocument(document).getModificationStamp();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Document getLastCommittedDocument(@NotNull PsiFile file) {
|
||||
Document document = getDocument(file);
|
||||
return document == null ? null : getLastCommittedDocument(document);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public DocumentEx getLastCommittedDocument(@NotNull Document document) {
|
||||
if (document instanceof FrozenDocument) return (DocumentEx)document;
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -45,6 +46,10 @@ public abstract class ResolveScopeManager {
|
||||
|
||||
@NotNull
|
||||
public static GlobalSearchScope getElementResolveScope(@NotNull PsiElement element) {
|
||||
PsiFile file = element.getContainingFile();
|
||||
if (file != null) {
|
||||
return getInstance(file.getProject()).getResolveScope(file);
|
||||
}
|
||||
return getInstance(element.getProject()).getResolveScope(element);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -29,11 +29,10 @@ import com.intellij.psi.util.PsiUtilCore;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class AnchorElementInfoFactory implements SmartPointerElementInfoFactory {
|
||||
public class AnchorElementInfoFactory extends SmartPointerElementInfoFactory {
|
||||
@Override
|
||||
@Nullable
|
||||
public SmartPointerElementInfo createElementInfo(@NotNull PsiElement element) {
|
||||
PsiFile containingFile = element.getContainingFile();
|
||||
public SmartPointerElementInfo createElementInfo(@NotNull PsiElement element, @NotNull PsiFile containingFile) {
|
||||
if (element instanceof StubBasedPsiElement && containingFile instanceof PsiFileWithStubSupport) {
|
||||
PsiFileWithStubSupport stubFile = (PsiFileWithStubSupport)containingFile;
|
||||
StubTree stubTree = stubFile.getStubTree();
|
||||
|
||||
+4
-3
@@ -18,15 +18,16 @@ package com.intellij.psi.impl.smartPointers;
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public interface SmartPointerElementInfoFactory {
|
||||
ExtensionPointName<SmartPointerElementInfoFactory> EP_NAME = ExtensionPointName.create("com.intellij.smartPointerElementInfoFactory");
|
||||
public abstract class SmartPointerElementInfoFactory {
|
||||
public static final ExtensionPointName<SmartPointerElementInfoFactory> EP_NAME = ExtensionPointName.create("com.intellij.smartPointerElementInfoFactory");
|
||||
|
||||
@Nullable
|
||||
SmartPointerElementInfo createElementInfo(@NotNull PsiElement element);
|
||||
public abstract SmartPointerElementInfo createElementInfo(@NotNull PsiElement element, @NotNull PsiFile containingFile);
|
||||
}
|
||||
|
||||
+1
-1
@@ -183,7 +183,7 @@ class SmartPsiElementPointerImpl<E extends PsiElement> implements SmartPointerEx
|
||||
}
|
||||
|
||||
for(SmartPointerElementInfoFactory factory: Extensions.getExtensions(SmartPointerElementInfoFactory.EP_NAME)) {
|
||||
final SmartPointerElementInfo result = factory.createElementInfo(element);
|
||||
final SmartPointerElementInfo result = factory.createElementInfo(element, containingFile);
|
||||
if (result != null) return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -182,11 +182,11 @@ public abstract class CachedValueBase<T> {
|
||||
public T setValue(final CachedValueProvider.Result<T> result) {
|
||||
Data<T> data = computeData(result);
|
||||
setData(data);
|
||||
valueUpdated();
|
||||
valueUpdated(result.getDependencyItems());
|
||||
return data.myValue;
|
||||
}
|
||||
|
||||
protected void valueUpdated() {}
|
||||
protected void valueUpdated(@Nullable Object[] dependencies) {}
|
||||
|
||||
public abstract boolean isFromMyProject(Project project);
|
||||
|
||||
@@ -227,7 +227,7 @@ public abstract class CachedValueBase<T> {
|
||||
boolean reuse = alreadyComputed != null && isUpToDate(alreadyComputed);
|
||||
Data<T> toReturn = cacheOrGetData(alreadyComputed, reuse ? null : data);
|
||||
if (toReturn != null) {
|
||||
valueUpdated();
|
||||
valueUpdated(toReturn.myDependencies);
|
||||
return toReturn.myValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,12 +16,16 @@
|
||||
package com.intellij.diff.merge;
|
||||
|
||||
import com.intellij.diff.DiffContext;
|
||||
import com.intellij.diff.util.DiffUserDataKeysEx;
|
||||
import com.intellij.diff.util.DiffUtil;
|
||||
import com.intellij.diff.util.ThreeSide;
|
||||
import com.intellij.openapi.diff.DiffBundle;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.Couple;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -32,6 +36,10 @@ import java.util.List;
|
||||
public class MergeUtil {
|
||||
@NotNull
|
||||
public static String getResolveActionTitle(@NotNull MergeResult result, @NotNull MergeRequest request, @NotNull MergeContext context) {
|
||||
Function<MergeResult, String> getter = DiffUtil.getUserData(request, context, DiffUserDataKeysEx.MERGE_ACTION_CAPTIONS);
|
||||
String message = getter != null ? getter.fun(result) : null;
|
||||
if (message != null) return message;
|
||||
|
||||
switch (result) {
|
||||
case CANCEL:
|
||||
return "Abort";
|
||||
@@ -95,9 +103,15 @@ public class MergeUtil {
|
||||
}
|
||||
|
||||
public static boolean showExitWithoutApplyingChangesDialog(@NotNull JComponent component, @NotNull MergeRequest request, @NotNull MergeContext context) {
|
||||
return Messages.showYesNoDialog(component.getRootPane(),
|
||||
DiffBundle.message("merge.dialog.exit.without.applying.changes.confirmation.message"),
|
||||
DiffBundle.message("cancel.visual.merge.dialog.title"), Messages.getQuestionIcon()) ==
|
||||
Messages.YES;
|
||||
String message = DiffBundle.message("merge.dialog.exit.without.applying.changes.confirmation.message");
|
||||
String title = DiffBundle.message("cancel.visual.merge.dialog.title");
|
||||
|
||||
Couple<String> customMessage = DiffUtil.getUserData(request, context, DiffUserDataKeysEx.MERGE_CANCEL_MESSAGE);
|
||||
if (customMessage != null) {
|
||||
title = customMessage.first;
|
||||
message = customMessage.second;
|
||||
}
|
||||
|
||||
return Messages.showYesNoDialog(component.getRootPane(), message, title, Messages.getQuestionIcon()) == Messages.YES;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,7 +299,7 @@ public class TextMergeChange extends ThreesideDiffChangeBase {
|
||||
@Nullable
|
||||
private GutterIconRenderer createApplyRenderer(@NotNull final Side side, final boolean modifier) {
|
||||
if (isResolved(side)) return null;
|
||||
Icon icon = isOnesideAppliedConflict() ? AllIcons.Diff.ArrowLeftDown : AllIcons.Diff.Arrow;
|
||||
Icon icon = isOnesideAppliedConflict() ? DiffUtil.getArrowDownIcon(side) : DiffUtil.getArrowIcon(side);
|
||||
return createIconRenderer(DiffBundle.message("merge.dialog.apply.change.action.name"), icon, isConflict(), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
@@ -417,7 +417,7 @@ public class TextMergeTool implements MergeTool {
|
||||
return apply(mergeFragments, outputModificationStamp);
|
||||
}
|
||||
catch (DiffTooBigException e) {
|
||||
return applyNotification(DiffNotifications.DIFF_TOO_BIG);
|
||||
return applyNotification(DiffNotifications.createDiffTooBig());
|
||||
}
|
||||
catch (ProcessCanceledException e) {
|
||||
throw e;
|
||||
|
||||
@@ -43,7 +43,7 @@ public class OnesideBinaryDiffViewer extends OnesideDiffViewer<BinaryEditorHolde
|
||||
@Override
|
||||
@NotNull
|
||||
protected Runnable performRediff(@NotNull final ProgressIndicator indicator) {
|
||||
JComponent notification = getSide().select(DiffNotifications.REMOVED_CONTENT, DiffNotifications.INSERTED_CONTENT);
|
||||
JComponent notification = getSide().select(DiffNotifications.createRemovedContent(), DiffNotifications.createInsertedContent());
|
||||
return applyNotification(notification);
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ public class TwosideBinaryDiffViewer extends TwosideDiffViewer<BinaryEditorHolde
|
||||
final VirtualFile file1 = ((FileContent)contents.get(0)).getFile();
|
||||
final VirtualFile file2 = ((FileContent)contents.get(1)).getFile();
|
||||
if (!file1.isValid() || !file2.isValid()) {
|
||||
return applyNotification(DiffNotifications.ERROR);
|
||||
return applyNotification(DiffNotifications.createError());
|
||||
}
|
||||
|
||||
final boolean equal = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
@@ -98,14 +98,14 @@ public class TwosideBinaryDiffViewer extends TwosideDiffViewer<BinaryEditorHolde
|
||||
}
|
||||
});
|
||||
|
||||
return applyNotification(equal ? DiffNotifications.EQUAL_CONTENTS : null);
|
||||
return applyNotification(equal ? DiffNotifications.createEqualContents(): null);
|
||||
}
|
||||
catch (ProcessCanceledException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Throwable e) {
|
||||
LOG.error(e);
|
||||
return applyNotification(DiffNotifications.ERROR);
|
||||
return applyNotification(DiffNotifications.createError());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@ import com.intellij.diff.tools.util.base.*;
|
||||
import com.intellij.diff.tools.util.side.TwosideTextDiffViewer;
|
||||
import com.intellij.diff.util.*;
|
||||
import com.intellij.diff.util.DiffUserDataKeysEx.ScrollToPolicy;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
@@ -220,11 +219,9 @@ public class UnifiedDiffViewer extends ListenerDiffViewerBase {
|
||||
List<AnAction> group = new ArrayList<AnAction>();
|
||||
|
||||
group.add(new ReplaceSelectedChangesAction(Side.LEFT, false));
|
||||
group.add(new AppendSelectedChangesAction(Side.LEFT, false));
|
||||
group.add(new ReplaceSelectedChangesAction(Side.RIGHT, false));
|
||||
group.add(new AppendSelectedChangesAction(Side.LEFT, false));
|
||||
group.add(new AppendSelectedChangesAction(Side.RIGHT, false));
|
||||
group.add(new RevertSelectedChangesAction(Side.LEFT));
|
||||
group.add(new RevertSelectedChangesAction(Side.RIGHT));
|
||||
|
||||
group.add(Separator.getInstance());
|
||||
group.addAll(TextDiffViewerUtil.createEditorPopupActions());
|
||||
@@ -383,7 +380,7 @@ public class UnifiedDiffViewer extends ListenerDiffViewerBase {
|
||||
myFoldingModel.updateContext(myRequest, getFoldingModelSettings());
|
||||
|
||||
clearDiffPresentation();
|
||||
if (isEqual) myPanel.addNotification(DiffNotifications.EQUAL_CONTENTS);
|
||||
if (isEqual) myPanel.addNotification(DiffNotifications.createEqualContents());
|
||||
|
||||
TIntFunction separatorLines = myFoldingModel.getLineNumberConvertor();
|
||||
myEditor.getGutterComponentEx().setLineNumberConvertor(mergeConverters(data.getLineConvertor1(), separatorLines),
|
||||
@@ -648,7 +645,7 @@ public class UnifiedDiffViewer extends ListenerDiffViewerBase {
|
||||
|
||||
private abstract class ApplySelectedChangesActionBase extends AnAction implements DumbAware {
|
||||
@NotNull protected final Side myModifiedSide;
|
||||
private final boolean myShortcut;
|
||||
protected final boolean myShortcut;
|
||||
|
||||
public ApplySelectedChangesActionBase(@NotNull Side modifiedSide, boolean shortcut) {
|
||||
myModifiedSide = modifiedSide;
|
||||
@@ -674,6 +671,7 @@ public class UnifiedDiffViewer extends ListenerDiffViewerBase {
|
||||
return;
|
||||
}
|
||||
|
||||
e.getPresentation().setText(getText());
|
||||
e.getPresentation().setVisible(true);
|
||||
e.getPresentation().setEnabled(isSomeChangeSelected());
|
||||
}
|
||||
@@ -714,6 +712,9 @@ public class UnifiedDiffViewer extends ListenerDiffViewerBase {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public abstract String getText();
|
||||
|
||||
@CalledWithWriteLock
|
||||
protected abstract void apply(@NotNull List<UnifiedDiffChange> changes);
|
||||
}
|
||||
@@ -723,8 +724,19 @@ public class UnifiedDiffViewer extends ListenerDiffViewerBase {
|
||||
super(focusedSide.other(), shortcut);
|
||||
|
||||
setShortcutSet(ActionManager.getInstance().getAction(focusedSide.select("Diff.ApplyLeftSide", "Diff.ApplyRightSide")).getShortcutSet());
|
||||
getTemplatePresentation().setText("Replace");
|
||||
getTemplatePresentation().setIcon(focusedSide.select(AllIcons.Diff.ArrowRight, AllIcons.Diff.Arrow));
|
||||
getTemplatePresentation().setIcon(DiffUtil.getArrowIcon(focusedSide));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getText() {
|
||||
boolean bothEditable = isEditable(Side.LEFT, true) && isEditable(Side.RIGHT, true);
|
||||
if (bothEditable) {
|
||||
return myModifiedSide.select("Apply After", "Apply Before");
|
||||
}
|
||||
else {
|
||||
return "Apply";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -740,8 +752,19 @@ public class UnifiedDiffViewer extends ListenerDiffViewerBase {
|
||||
super(focusedSide.other(), shortcut);
|
||||
|
||||
setShortcutSet(ActionManager.getInstance().getAction(focusedSide.select("Diff.AppendLeftSide", "Diff.AppendRightSide")).getShortcutSet());
|
||||
getTemplatePresentation().setText("Insert");
|
||||
getTemplatePresentation().setIcon(focusedSide.select(AllIcons.Diff.ArrowRightDown, AllIcons.Diff.ArrowLeftDown));
|
||||
getTemplatePresentation().setIcon(DiffUtil.getArrowDownIcon(focusedSide));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getText() {
|
||||
boolean bothEditable = isEditable(Side.LEFT, true) && isEditable(Side.RIGHT, true);
|
||||
if (bothEditable) {
|
||||
return myModifiedSide.select("Append Right Side", "Append Left Side");
|
||||
}
|
||||
else {
|
||||
return "Append";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -752,21 +775,6 @@ public class UnifiedDiffViewer extends ListenerDiffViewerBase {
|
||||
}
|
||||
}
|
||||
|
||||
private class RevertSelectedChangesAction extends ApplySelectedChangesActionBase {
|
||||
public RevertSelectedChangesAction(@NotNull Side focusedSide) {
|
||||
super(focusedSide, false);
|
||||
getTemplatePresentation().setText("Revert");
|
||||
getTemplatePresentation().setIcon(AllIcons.Diff.Remove);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void apply(@NotNull List<UnifiedDiffChange> changes) {
|
||||
for (UnifiedDiffChange change : changes) {
|
||||
replaceChange(change, myModifiedSide.other());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@CalledWithWriteLock
|
||||
public void replaceChange(@NotNull UnifiedDiffChange change, @NotNull Side sourceSide) {
|
||||
Side outputSide = sourceSide.other();
|
||||
|
||||
@@ -267,7 +267,7 @@ public class SimpleDiffChange {
|
||||
|
||||
@Nullable
|
||||
private GutterIconRenderer createApplyRenderer(@NotNull final Side side) {
|
||||
return createIconRenderer(side, "Replace", AllIcons.Diff.Arrow, new Runnable() {
|
||||
return createIconRenderer(side, "Replace", DiffUtil.getArrowIcon(side), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myViewer.replaceChange(SimpleDiffChange.this, side);
|
||||
@@ -277,7 +277,7 @@ public class SimpleDiffChange {
|
||||
|
||||
@Nullable
|
||||
private GutterIconRenderer createAppendRenderer(@NotNull final Side side) {
|
||||
return createIconRenderer(side, "Insert", AllIcons.Diff.ArrowLeftDown, new Runnable() {
|
||||
return createIconRenderer(side, "Insert", DiffUtil.getArrowDownIcon(side), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myViewer.appendChange(SimpleDiffChange.this, side);
|
||||
|
||||
@@ -216,14 +216,14 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer {
|
||||
return apply(new CompareData(lineFragments, isEqualContents));
|
||||
}
|
||||
catch (DiffTooBigException e) {
|
||||
return applyNotification(DiffNotifications.DIFF_TOO_BIG);
|
||||
return applyNotification(DiffNotifications.createDiffTooBig());
|
||||
}
|
||||
catch (ProcessCanceledException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Throwable e) {
|
||||
LOG.error(e);
|
||||
return applyNotification(DiffNotifications.ERROR);
|
||||
return applyNotification(DiffNotifications.createError());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,7 +235,7 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer {
|
||||
myFoldingModel.updateContext(myRequest, getFoldingModelSettings());
|
||||
clearDiffPresentation();
|
||||
|
||||
if (data.isEqualContent()) myPanel.addNotification(DiffNotifications.EQUAL_CONTENTS);
|
||||
if (data.isEqualContent()) myPanel.addNotification(DiffNotifications.createEqualContents());
|
||||
|
||||
if (data.getFragments() != null) {
|
||||
for (LineFragment fragment : data.getFragments()) {
|
||||
@@ -589,7 +589,7 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer {
|
||||
|
||||
setShortcutSet(ActionManager.getInstance().getAction(focusedSide.select("Diff.ApplyLeftSide", "Diff.ApplyRightSide")).getShortcutSet());
|
||||
getTemplatePresentation().setText("Replace");
|
||||
getTemplatePresentation().setIcon(focusedSide.select(AllIcons.Diff.ArrowRight, AllIcons.Diff.Arrow));
|
||||
getTemplatePresentation().setIcon(DiffUtil.getArrowIcon(focusedSide));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -611,7 +611,7 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer {
|
||||
|
||||
setShortcutSet(ActionManager.getInstance().getAction(focusedSide.select("Diff.AppendLeftSide", "Diff.AppendRightSide")).getShortcutSet());
|
||||
getTemplatePresentation().setText("Insert");
|
||||
getTemplatePresentation().setIcon(focusedSide.select(AllIcons.Diff.ArrowRightDown, AllIcons.Diff.ArrowLeftDown));
|
||||
getTemplatePresentation().setIcon(DiffUtil.getArrowDownIcon(focusedSide));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+2
-2
@@ -145,14 +145,14 @@ public class SimpleThreesideDiffViewer extends ThreesideTextDiffViewerEx {
|
||||
return apply(mergeFragments, comparisonPolicy);
|
||||
}
|
||||
catch (DiffTooBigException e) {
|
||||
return applyNotification(DiffNotifications.DIFF_TOO_BIG);
|
||||
return applyNotification(DiffNotifications.createDiffTooBig());
|
||||
}
|
||||
catch (ProcessCanceledException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Throwable e) {
|
||||
LOG.error(e);
|
||||
return applyNotification(DiffNotifications.ERROR);
|
||||
return applyNotification(DiffNotifications.createError());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,19 +25,46 @@ import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class DiffNotifications {
|
||||
@NotNull public static final JPanel INSERTED_CONTENT =
|
||||
createNotification("Content added", TextDiffType.INSERTED.getColor(null));
|
||||
@NotNull public static final JPanel REMOVED_CONTENT =
|
||||
createNotification("Content removed", TextDiffType.DELETED.getColor(null));
|
||||
@Deprecated @NotNull public static final JPanel INSERTED_CONTENT = createInsertedContent();
|
||||
@Deprecated @NotNull public static final JPanel REMOVED_CONTENT = createRemovedContent();
|
||||
@Deprecated @NotNull public static final JPanel EQUAL_CONTENTS = createEqualContents();
|
||||
@Deprecated @NotNull public static final JPanel ERROR = createError();
|
||||
@Deprecated @NotNull public static final JPanel OPERATION_CANCELED = createOperationCanceled();
|
||||
@Deprecated @NotNull public static final JPanel DIFF_TOO_BIG = createDiffTooBig();
|
||||
|
||||
@NotNull public static final JPanel EQUAL_CONTENTS =
|
||||
createNotification(DiffBundle.message("diff.contents.are.identical.message.text"));
|
||||
@NotNull public static final JPanel ERROR =
|
||||
createNotification("Can not calculate diff");
|
||||
@NotNull public static final JPanel OPERATION_CANCELED =
|
||||
createNotification("Can not calculate diff. Operation canceled.");
|
||||
@NotNull public static final JPanel DIFF_TOO_BIG =
|
||||
createNotification("Can not calculate diff. " + DiffTooBigException.MESSAGE);
|
||||
@NotNull
|
||||
public static JPanel createInsertedContent() {
|
||||
return createNotification("Content added", TextDiffType.INSERTED.getColor(null));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JPanel createRemovedContent() {
|
||||
return createNotification("Content removed", TextDiffType.DELETED.getColor(null));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JPanel createEqualContents() {
|
||||
return createNotification(DiffBundle.message("diff.contents.are.identical.message.text"));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JPanel createError() {
|
||||
return createNotification("Can not calculate diff");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JPanel createOperationCanceled() {
|
||||
return createNotification("Can not calculate diff. Operation canceled.");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JPanel createDiffTooBig() {
|
||||
return createNotification("Can not calculate diff. " + DiffTooBigException.MESSAGE);
|
||||
}
|
||||
|
||||
//
|
||||
// Impl
|
||||
//
|
||||
|
||||
@NotNull
|
||||
public static JPanel createNotification(@NotNull String text) {
|
||||
|
||||
@@ -15,9 +15,12 @@
|
||||
*/
|
||||
package com.intellij.diff.util;
|
||||
|
||||
import com.intellij.diff.merge.MergeResult;
|
||||
import com.intellij.openapi.diff.DiffNavigationContext;
|
||||
import com.intellij.openapi.editor.LogicalPosition;
|
||||
import com.intellij.openapi.util.Couple;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -53,4 +56,13 @@ public interface DiffUserDataKeysEx extends DiffUserDataKeys {
|
||||
Key<JComponent> BOTTOM_PANEL = Key.create("Diff.BottomPanel"); // Could implement Disposable
|
||||
|
||||
Key<Boolean> SHOW_READ_ONLY_LOCK = Key.create("Diff.ShowReadOnlyLock");
|
||||
|
||||
//
|
||||
// MergeContext / MergeRequest
|
||||
//
|
||||
|
||||
// (title, message)
|
||||
Key<Couple<String>> MERGE_CANCEL_MESSAGE = Key.create("Diff.MergeCancelMessage");
|
||||
// null -> default
|
||||
Key<Function<MergeResult, String>> MERGE_ACTION_CAPTIONS = Key.create("Diff.MergeActionCaptions");
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import com.intellij.diff.requests.ContentDiffRequest;
|
||||
import com.intellij.diff.requests.DiffRequest;
|
||||
import com.intellij.diff.tools.util.base.HighlightPolicy;
|
||||
import com.intellij.diff.tools.util.base.IgnorePolicy;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.DataProvider;
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup;
|
||||
@@ -241,6 +242,20 @@ public class DiffUtil {
|
||||
return editor != null ? editor.getCaretModel().getLogicalPosition() : new LogicalPosition(0, 0);
|
||||
}
|
||||
|
||||
//
|
||||
// Icons
|
||||
//
|
||||
|
||||
@NotNull
|
||||
public static Icon getArrowIcon(@NotNull Side sourceSide) {
|
||||
return sourceSide.select(AllIcons.Diff.ArrowRight, AllIcons.Diff.Arrow);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Icon getArrowDownIcon(@NotNull Side sourceSide) {
|
||||
return sourceSide.select(AllIcons.Diff.ArrowRightDown, AllIcons.Diff.ArrowLeftDown);
|
||||
}
|
||||
|
||||
//
|
||||
// UI
|
||||
//
|
||||
@@ -916,25 +931,13 @@ public class DiffUtil {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static <T> T getUserData(@Nullable DiffRequest request, @Nullable DiffContext context, @NotNull Key<T> key) {
|
||||
if (request != null) {
|
||||
T data = request.getUserData(key);
|
||||
public static <T> T getUserData(@Nullable UserDataHolder first, @Nullable UserDataHolder second, @NotNull Key<T> key) {
|
||||
if (first != null) {
|
||||
T data = first.getUserData(key);
|
||||
if (data != null) return data;
|
||||
}
|
||||
if (context != null) {
|
||||
T data = context.getUserData(key);
|
||||
if (data != null) return data;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T> T getUserData(@Nullable DiffContext context, @Nullable DiffRequest request, @NotNull Key<T> key) {
|
||||
if (context != null) {
|
||||
T data = context.getUserData(key);
|
||||
if (data != null) return data;
|
||||
}
|
||||
if (request != null) {
|
||||
T data = request.getUserData(key);
|
||||
if (second != null) {
|
||||
T data = second.getUserData(key);
|
||||
if (data != null) return data;
|
||||
}
|
||||
return null;
|
||||
|
||||
+6
-13
@@ -44,13 +44,11 @@ import com.intellij.openapi.vfs.*;
|
||||
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess;
|
||||
import com.intellij.packaging.artifacts.Artifact;
|
||||
import com.intellij.packaging.impl.compiler.ArtifactCompileScope;
|
||||
import com.intellij.testFramework.CompilerTester;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
import com.intellij.testFramework.PsiTestUtil;
|
||||
import com.intellij.testFramework.UsefulTestCase;
|
||||
import com.intellij.testFramework.*;
|
||||
import com.intellij.testFramework.fixtures.IdeaProjectTestFixture;
|
||||
import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.ThrowableRunnable;
|
||||
import com.intellij.util.io.TestFileSystemItem;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -176,16 +174,11 @@ public abstract class ExternalSystemTestCase extends UsefulTestCase {
|
||||
@Override
|
||||
public void tearDown() throws Exception {
|
||||
try {
|
||||
edt(new Runnable() {
|
||||
EdtTestUtil.runInEdtAndWait(new ThrowableRunnable<Throwable>() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
CompilerTestUtil.disableExternalCompiler(myProject);
|
||||
tearDownFixtures();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
public void run() throws Throwable {
|
||||
CompilerTestUtil.disableExternalCompiler(myProject);
|
||||
tearDownFixtures();
|
||||
}
|
||||
});
|
||||
myProject = null;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.psi.search.searches;
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiReference;
|
||||
@@ -31,13 +32,13 @@ public class ReferenceDescriptor {
|
||||
public ReferenceDescriptor fun(PsiReference psiReference) {
|
||||
final PsiElement element = psiReference.getElement();
|
||||
final PsiFile file = element.getContainingFile();
|
||||
return new ReferenceDescriptor(file, element.getTextRange().getStartOffset() + psiReference.getRangeInElement().getStartOffset());
|
||||
return new ReferenceDescriptor(file.getViewProvider().getVirtualFile(), element.getTextRange().getStartOffset() + psiReference.getRangeInElement().getStartOffset());
|
||||
}
|
||||
};
|
||||
private final PsiFile file;
|
||||
private final VirtualFile file;
|
||||
private final int offset;
|
||||
|
||||
private ReferenceDescriptor(@NotNull PsiFile file, int offset) {
|
||||
private ReferenceDescriptor(@NotNull VirtualFile file, int offset) {
|
||||
this.file = file;
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,18 +15,18 @@
|
||||
*/
|
||||
package com.intellij.usageView;
|
||||
|
||||
import com.intellij.openapi.components.NamedComponent;
|
||||
import com.intellij.openapi.components.PersistentStateComponent;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.components.State;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsManager;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsUtil;
|
||||
import com.intellij.openapi.util.JDOMExternalizable;
|
||||
import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class UsageTreeColorsScheme implements NamedComponent, JDOMExternalizable {
|
||||
@State(name = "FindViewColorsScheme", defaultStateAsResource = true, storages = {})
|
||||
public class UsageTreeColorsScheme implements PersistentStateComponent<Element> {
|
||||
private EditorColorsScheme myColorsScheme;
|
||||
|
||||
/**
|
||||
@@ -39,26 +39,21 @@ public class UsageTreeColorsScheme implements NamedComponent, JDOMExternalizable
|
||||
return ServiceManager.getService(UsageTreeColorsScheme.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getComponentName() {
|
||||
return "FindViewColorsScheme";
|
||||
}
|
||||
|
||||
public EditorColorsScheme getScheme() {
|
||||
return myColorsScheme;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public void readExternal(Element element) {
|
||||
if (myColorsScheme == null) {
|
||||
myColorsScheme = (EditorColorsScheme)EditorColorsUtil.getColorSchemeForBackground(UIUtil.getTreeTextBackground()).clone();
|
||||
}
|
||||
myColorsScheme.readExternal(element);
|
||||
public Element getState() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeExternal(Element element) throws WriteExternalException {
|
||||
throw new WriteExternalException();
|
||||
public void loadState(Element state) {
|
||||
if (myColorsScheme == null) {
|
||||
myColorsScheme = (EditorColorsScheme)EditorColorsUtil.getColorSchemeForBackground(UIUtil.getTreeTextBackground()).clone();
|
||||
}
|
||||
myColorsScheme.readExternal(state);
|
||||
}
|
||||
}
|
||||
|
||||
+27
-9
@@ -23,14 +23,12 @@ import com.intellij.openapi.options.colors.AttributesDescriptor;
|
||||
import com.intellij.openapi.options.colors.ColorSettingsPage;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.ui.CollectionComboBoxModel;
|
||||
import com.intellij.ui.ColorPanel;
|
||||
import com.intellij.ui.HyperlinkAdapter;
|
||||
import com.intellij.ui.ListCellRendererWrapper;
|
||||
import com.intellij.ui.*;
|
||||
import com.intellij.ui.components.JBCheckBox;
|
||||
import com.intellij.util.FontUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -38,8 +36,8 @@ import javax.swing.event.HyperlinkEvent;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author cdr
|
||||
@@ -70,6 +68,7 @@ public class ColorAndFontDescriptionPanel extends JPanel {
|
||||
myEffectsMap = Collections.unmodifiableMap(map);
|
||||
}
|
||||
private JComboBox myEffectsCombo;
|
||||
private final EffectsComboModel myEffectsModel;
|
||||
|
||||
private JBCheckBox myCbBold;
|
||||
private JBCheckBox myCbItalic;
|
||||
@@ -83,7 +82,10 @@ public class ColorAndFontDescriptionPanel extends JPanel {
|
||||
add(myPanel, BorderLayout.CENTER);
|
||||
|
||||
setBorder(BorderFactory.createEmptyBorder(4, 0, 4, 4));
|
||||
myEffectsCombo.setModel(new CollectionComboBoxModel(ContainerUtil.newArrayList(myEffectsMap.keySet())));
|
||||
myEffectsModel = new EffectsComboModel(ContainerUtil.newArrayList(myEffectsMap.keySet()));
|
||||
//noinspection unchecked
|
||||
myEffectsCombo.setModel(myEffectsModel);
|
||||
//noinspection unchecked
|
||||
myEffectsCombo.setRenderer(new ListCellRendererWrapper<String>() {
|
||||
@Override
|
||||
public void customize(JList list, String value, int index, boolean selected, boolean hasFocus) {
|
||||
@@ -152,7 +154,7 @@ public class ColorAndFontDescriptionPanel extends JPanel {
|
||||
colorPanel.setSelectedColor(color);
|
||||
}
|
||||
else {
|
||||
colorPanel.setSelectedColor(Color.white);
|
||||
colorPanel.setSelectedColor(JBColor.WHITE);
|
||||
}
|
||||
colorPanel.setEnabled(isChecked);
|
||||
}
|
||||
@@ -189,7 +191,7 @@ public class ColorAndFontDescriptionPanel extends JPanel {
|
||||
|
||||
if (description.isEffectsColorEnabled() && description.isEffectsColorChecked()) {
|
||||
myEffectsCombo.setEnabled(true);
|
||||
myEffectsCombo.getModel().setSelectedItem(ContainerUtil.reverseMap(myEffectsMap).get(effectType));
|
||||
myEffectsModel.setEffectName(ContainerUtil.reverseMap(myEffectsMap).get(effectType));
|
||||
}
|
||||
else {
|
||||
myEffectsCombo.setEnabled(false);
|
||||
@@ -293,4 +295,20 @@ public class ColorAndFontDescriptionPanel extends JPanel {
|
||||
description.apply(scheme);
|
||||
}
|
||||
}
|
||||
|
||||
private static class EffectsComboModel extends CollectionComboBoxModel<String> {
|
||||
public EffectsComboModel(List<String> names) {
|
||||
super(names);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current effect name when a text attribute selection changes without notifying the listeners since otherwise it will
|
||||
* be considered as an actual change and lead to unnecessary evens including 'read-only scheme' check.
|
||||
*
|
||||
* @param effectName
|
||||
*/
|
||||
public void setEffectName(@NotNull String effectName) {
|
||||
mySelection = effectName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
@@ -73,6 +73,10 @@ public class LegacyCompletionContributor extends CompletionContributor {
|
||||
completionData.completeReference(reference, lookupSet, parameters.getPosition(), parameters.getOriginalFile());
|
||||
for (final LookupElement item : lookupSet) {
|
||||
if (resultSet.getPrefixMatcher().prefixMatches(item)) {
|
||||
if (!item.isValid()) {
|
||||
LOG.error(completionData + " has returned an invalid lookup element " + item + " of " + item.getClass() +
|
||||
" in " + parameters.getOriginalFile() + " of " + parameters.getOriginalFile().getClass());
|
||||
}
|
||||
hasVariants.set(true);
|
||||
resultSet.addElement(item);
|
||||
}
|
||||
|
||||
+2
-1
@@ -125,7 +125,8 @@ public class CompletionServiceImpl extends CompletionService{
|
||||
@Override
|
||||
public void addElement(@NotNull final LookupElement element) {
|
||||
if (!element.isValid()) {
|
||||
LOG.error("Invalid lookup element: " + element);
|
||||
LOG.error("Invalid lookup element: " + element + " of " + element.getClass() +
|
||||
" in " + myParameters.getOriginalFile() + " of " + myParameters.getOriginalFile().getClass());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.actionSystem.DataProvider;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.ide.CopyPasteManager;
|
||||
import com.intellij.openapi.util.InvalidDataException;
|
||||
import com.intellij.openapi.util.JDOMUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.ui.CheckboxTree;
|
||||
@@ -144,15 +143,13 @@ class LiveTemplateTree extends CheckboxTree implements DataProvider, CopyProvide
|
||||
assert buffer != null;
|
||||
|
||||
try {
|
||||
for (Element templateElement : JDOMUtil.load(new StringReader("<root>" + buffer + "</root>")).getChildren()) {
|
||||
try {
|
||||
TemplateImpl template = TemplateSettings.readTemplateFromElement(group.getName(), templateElement, getClass().getClassLoader());
|
||||
myConfigurable.addTemplate(template);
|
||||
}
|
||||
catch (InvalidDataException ignore) { }
|
||||
for (Element templateElement : JDOMUtil.load(new StringReader("<root>" + buffer + "</root>")).getChildren(TemplateSettings.TEMPLATE)) {
|
||||
myConfigurable.addTemplate(TemplateSettings.readTemplateFromElement(group.getName(), templateElement, getClass().getClassLoader()));
|
||||
}
|
||||
}
|
||||
catch (JDOMException ignore) { }
|
||||
catch (IOException ignore) { }
|
||||
catch (JDOMException ignore) {
|
||||
}
|
||||
catch (IOException ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user