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:
@@ -26,6 +26,7 @@ import com.intellij.psi.impl.source.PsiFileImpl;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.IFileElementType;
|
||||
import com.intellij.psi.tree.ILightStubFileElementType;
|
||||
import com.intellij.reference.SoftReference;
|
||||
import com.intellij.util.CharTable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -50,7 +51,7 @@ public class FileElement extends LazyParseableElement implements FileASTNode, Ge
|
||||
return myCharTable;
|
||||
}
|
||||
|
||||
private static final Key<LighterAST> ourTreeKey = Key.create("lighter.key");
|
||||
private static final Key<SoftReference<LighterAST>> ourTreeKey = Key.create("lighter.key");
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
@@ -60,11 +61,11 @@ public class FileElement extends LazyParseableElement implements FileASTNode, Ge
|
||||
|
||||
LighterAST tree;
|
||||
if (!isParsed()) {
|
||||
tree = getUserData(ourTreeKey);
|
||||
tree = SoftReference.dereference(getUserData(ourTreeKey));
|
||||
if (tree == null) {
|
||||
final ILightStubFileElementType<?> type = (ILightStubFileElementType)contentType;
|
||||
tree = new FCTSBackedLighterAST(getCharTable(), type.parseContentsLight(this));
|
||||
putUserData(ourTreeKey, tree);
|
||||
putUserData(ourTreeKey, new SoftReference<LighterAST>(tree));
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -22,9 +22,11 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.wm.ToolWindow;
|
||||
import com.intellij.ui.content.Content;
|
||||
import com.intellij.ui.content.ContentManager;
|
||||
import com.intellij.ui.content.ContentManagerAdapter;
|
||||
import com.intellij.ui.content.ContentManagerEvent;
|
||||
import com.intellij.ui.switcher.QuickActionProvider;
|
||||
import com.intellij.ui.tabs.JBTabs;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.ui.AwtVisitor;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
@@ -189,7 +191,21 @@ public class SimpleToolWindowPanel extends JPanel implements QuickActionProvider
|
||||
myToolWindow.getContentManager().addContentManagerListener(new ContentManagerAdapter() {
|
||||
@Override
|
||||
public void contentAdded(ContentManagerEvent event) {
|
||||
setContentToolbarVisible(event.getContent(), getVisibilityValue());
|
||||
JComponent component = event.getContent().getComponent();
|
||||
setContentToolbarVisible(component, getVisibilityValue());
|
||||
|
||||
// support nested content managers, e.g. RunnerLayoutUi as content component
|
||||
ContentManager contentManager =
|
||||
component instanceof DataProvider ? PlatformDataKeys.CONTENT_MANAGER.getData((DataProvider)component) : null;
|
||||
if (contentManager != null) contentManager.addContentManagerListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectionChanged(ContentManagerEvent event) {
|
||||
Content content = event.getContent();
|
||||
if (content != null) {
|
||||
setContentToolbarVisible(content.getComponent(), getVisibilityValue());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -203,7 +219,7 @@ public class SimpleToolWindowPanel extends JPanel implements QuickActionProvider
|
||||
public void setSelected(AnActionEvent e, boolean state) {
|
||||
myPropertiesComponent.setValue(getProperty(), String.valueOf(state), String.valueOf(true));
|
||||
for (Content content : myToolWindow.getContentManager().getContents()) {
|
||||
setContentToolbarVisible(content, state);
|
||||
setContentToolbarVisible(content.getComponent(), state);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,19 +232,17 @@ public class SimpleToolWindowPanel extends JPanel implements QuickActionProvider
|
||||
return myPropertiesComponent.getBoolean(getProperty(), true);
|
||||
}
|
||||
|
||||
private static void setContentToolbarVisible(Content content, boolean state) {
|
||||
LinkedList<JComponent> deque = ContainerUtil.newLinkedList(content.getComponent());
|
||||
private static void setContentToolbarVisible(@NotNull JComponent root, boolean state) {
|
||||
LinkedList<JComponent> deque = ContainerUtil.newLinkedList(root);
|
||||
while(!deque.isEmpty()) {
|
||||
JComponent component = deque.pollFirst();
|
||||
if (!(component instanceof JPanel)) continue;
|
||||
|
||||
for (int i = 0, count = component.getComponentCount(); i < count; i++) {
|
||||
Component c = component.getComponent(i);
|
||||
if (c instanceof ActionToolbar) {
|
||||
c.setVisible(state);
|
||||
}
|
||||
else if (c instanceof JPanel) {
|
||||
deque.addLast((JPanel)c);
|
||||
else if (c instanceof JPanel || c instanceof JLayeredPane || c instanceof JBTabs) {
|
||||
deque.addLast((JComponent)c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
package com.jetbrains.python.edu;
|
||||
|
||||
import com.intellij.openapi.actionSystem.ActionManager;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.KeyboardShortcut;
|
||||
import com.intellij.openapi.fileEditor.impl.EditorEmptyTextPainter;
|
||||
import com.intellij.openapi.fileEditor.impl.EditorsSplitters;
|
||||
import com.intellij.openapi.keymap.KeymapUtil;
|
||||
import com.intellij.openapi.util.Couple;
|
||||
import com.intellij.ui.Gray;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.util.PairFunction;
|
||||
import com.intellij.util.ui.GraphicsUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.jetbrains.python.edu.actions.*;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
@@ -27,12 +33,18 @@ public class StudyInstructionPainter extends EditorEmptyTextPainter {
|
||||
UIUtil.TextPainter painter = new UIUtil.TextPainter().withLineSpacing(1.5f);
|
||||
|
||||
painter.appendLine("PyCharm Educational Edition").underlined(new JBColor(Gray._150, Gray._180));
|
||||
painter.appendLine("Navigate to the next task window with Ctrl + Enter").smaller().withBullet();
|
||||
painter.appendLine("Navigate between task windows with Ctrl + Shift + < and Ctrl + Shift + >").smaller().withBullet();
|
||||
painter.appendLine("Navigate between tasks with Ctrl + < and Ctrl + >").smaller().withBullet();
|
||||
painter.appendLine("Reset current task file with Ctrl + Shift + X").smaller().withBullet();
|
||||
painter.appendLine("Check task with Alt + Ctrl + Enter").smaller().withBullet();
|
||||
painter.appendLine("Get hint for the task window using Ctrl + 7").smaller().withBullet();
|
||||
addAction(painter, "Navigate to the next task window", StudyNextWindowAction.ACTION_ID, StudyNextWindowAction.SHORTCUT2, true);
|
||||
String shortcut1 = getShortcutText(StudyPrevWindowAction.ACTION_ID, StudyPrevWindowAction.SHORTCUT, false, false);
|
||||
String shortcut2 = getShortcutText(StudyNextWindowAction.ACTION_ID, StudyNextWindowAction.SHORTCUT, false, false);
|
||||
String text = "Navigate between task windows with " + shortcut1 +
|
||||
" and " + shortcut2;
|
||||
painter.appendLine(text).smaller().withBullet();
|
||||
shortcut1 = getShortcutText(StudyPreviousStudyTaskAction.ACTION_ID, StudyPreviousStudyTaskAction.SHORTCUT, false, false);
|
||||
shortcut2 = getShortcutText(StudyNextStudyTaskAction.ACTION_ID, StudyNextStudyTaskAction.SHORTCUT, false, false);
|
||||
painter.appendLine("Navigate between tasks with " + shortcut1 + " and " + shortcut2).smaller().withBullet();
|
||||
addAction(painter, "Reset current task file", StudyRefreshTaskFileAction.ACTION_ID, StudyRefreshTaskFileAction.SHORTCUT, false);
|
||||
addAction(painter, "Check task", StudyCheckAction.ACTION_ID, StudyCheckAction.SHORTCUT, false);
|
||||
addAction(painter, "Get hint for the task window", StudyShowHintAction.ACTION_ID, StudyShowHintAction.SHORTCUT, false);
|
||||
painter.appendLine("To see your progress open the 'Course Description' panel").smaller().withBullet();
|
||||
painter.draw(g, new PairFunction<Integer, Integer, Couple<Integer>>() {
|
||||
@Override
|
||||
@@ -42,4 +54,25 @@ public class StudyInstructionPainter extends EditorEmptyTextPainter {
|
||||
}
|
||||
});
|
||||
}
|
||||
private static void addAction(UIUtil.TextPainter painter, String text, String actionId, String defaultShortcutString, boolean useDefault) {
|
||||
String shortcut = getShortcutText(actionId, defaultShortcutString, useDefault, true);
|
||||
String actionText = text + " with " + shortcut;
|
||||
painter.appendLine(actionText).smaller().withBullet();
|
||||
}
|
||||
|
||||
private static String getShortcutText(String actionId, String defaultShortcutString, boolean useDefault, boolean wrapTag) {
|
||||
AnAction action = ActionManager.getInstance().getAction(actionId);
|
||||
String shortcut = "";
|
||||
if (!useDefault) {
|
||||
shortcut = KeymapUtil.getFirstKeyboardShortcutText(action);
|
||||
}
|
||||
if (shortcut.isEmpty() && defaultShortcutString != null) {
|
||||
KeyboardShortcut keyboardShortcut = new KeyboardShortcut(KeyStroke.getKeyStroke(defaultShortcutString), null);
|
||||
shortcut = KeymapUtil.getShortcutText(keyboardShortcut);
|
||||
}
|
||||
if (!wrapTag) {
|
||||
return shortcut;
|
||||
}
|
||||
return "<shortcut>" + shortcut + "</shortcut>";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,6 +235,10 @@ public class StudyTaskManager implements ProjectComponent, PersistentStateCompon
|
||||
|
||||
private static void addShortcut(@NotNull final String shortcutString, @NotNull final String actionIdString) {
|
||||
Keymap keymap = KeymapManager.getInstance().getActiveKeymap();
|
||||
Shortcut[] shortcuts = keymap.getShortcuts(actionIdString);
|
||||
if (shortcuts.length > 0) {
|
||||
return;
|
||||
}
|
||||
Shortcut studyActionShortcut = new KeyboardShortcut(KeyStroke.getKeyStroke(shortcutString), null);
|
||||
String[] actionsIds = keymap.getActionIds(studyActionShortcut);
|
||||
for (String actionId : actionsIds) {
|
||||
|
||||
@@ -4,6 +4,8 @@ import com.intellij.codeHighlighting.BackgroundEditorHighlighter;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.structureView.StructureViewBuilder;
|
||||
import com.intellij.openapi.actionSystem.ActionManager;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.KeyboardShortcut;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
@@ -16,6 +18,7 @@ import com.intellij.openapi.fileEditor.*;
|
||||
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
|
||||
import com.intellij.openapi.fileEditor.impl.text.PsiAwareTextEditorImpl;
|
||||
import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider;
|
||||
import com.intellij.openapi.keymap.KeymapUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Key;
|
||||
@@ -48,8 +51,9 @@ import java.awt.*;
|
||||
import java.awt.datatransfer.StringSelection;
|
||||
import java.awt.event.*;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Implementation of StudyEditor which has panel with special buttons and task text
|
||||
@@ -79,7 +83,14 @@ public class StudyEditor implements TextEditor {
|
||||
return myTaskFile;
|
||||
}
|
||||
|
||||
private static JButton addButton(@NotNull final JComponent parentComponent, String toolTipText, Icon icon) {
|
||||
private static JButton addButton(@NotNull final JComponent parentComponent, String actionID, Icon icon,
|
||||
@Nullable String defaultShortcutString) {
|
||||
AnAction action = ActionManager.getInstance().getAction(actionID);
|
||||
String toolTipText = KeymapUtil.createTooltipText(action.getTemplatePresentation().getText(), action);
|
||||
if (!toolTipText.contains("(") && defaultShortcutString != null) {
|
||||
KeyboardShortcut shortcut = new KeyboardShortcut(KeyStroke.getKeyStroke(defaultShortcutString), null);
|
||||
toolTipText += " (" + KeymapUtil.getShortcutText(shortcut) + ")";
|
||||
}
|
||||
JButton newButton = new JButton();
|
||||
newButton.setToolTipText(toolTipText);
|
||||
newButton.setIcon(icon);
|
||||
@@ -192,13 +203,13 @@ public class StudyEditor implements TextEditor {
|
||||
}
|
||||
|
||||
private void initializeButtons(@NotNull final JPanel taskActionsPanel, @NotNull final TaskFile taskFile) {
|
||||
myCheckButton = addButton(taskActionsPanel, "Check Task (Ctrl + Alt + Enter)", StudyIcons.Resolve);
|
||||
myPrevTaskButton = addButton(taskActionsPanel, "Previous Task (Ctrl + <)", StudyIcons.Prev);
|
||||
myNextTaskButton = addButton(taskActionsPanel, "Next Task (Ctrl + >)", AllIcons.Actions.Forward);
|
||||
myRefreshButton = addButton(taskActionsPanel, "Reset Task File (Ctrl + Shift + X)", AllIcons.Actions.Refresh);
|
||||
JButton myShowHintButton = addButton(taskActionsPanel, "Show Hint for Task Window (Ctrl + 7)", StudyIcons.ShowHint);
|
||||
myCheckButton = addButton(taskActionsPanel, StudyCheckAction.ACTION_ID, StudyIcons.Resolve, StudyCheckAction.SHORTCUT);
|
||||
myPrevTaskButton = addButton(taskActionsPanel, StudyPreviousStudyTaskAction.ACTION_ID, StudyIcons.Prev, StudyPreviousStudyTaskAction.SHORTCUT);
|
||||
myNextTaskButton = addButton(taskActionsPanel, StudyNextStudyTaskAction.ACTION_ID, AllIcons.Actions.Forward, StudyNextStudyTaskAction.SHORTCUT);
|
||||
myRefreshButton = addButton(taskActionsPanel, StudyRefreshTaskFileAction.ACTION_ID, AllIcons.Actions.Refresh, StudyRefreshTaskFileAction.SHORTCUT);
|
||||
JButton myShowHintButton = addButton(taskActionsPanel, StudyShowHintAction.ACTION_ID, StudyIcons.ShowHint, StudyShowHintAction.SHORTCUT);
|
||||
if (!taskFile.getTask().getUserTests().isEmpty()) {
|
||||
JButton runButton = addButton(taskActionsPanel, "Run", AllIcons.General.Run);
|
||||
JButton runButton = addButton(taskActionsPanel, StudyRunAction.ACTION_ID, AllIcons.General.Run, null);
|
||||
runButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
@@ -206,7 +217,7 @@ public class StudyEditor implements TextEditor {
|
||||
studyRunAction.run(myProject);
|
||||
}
|
||||
});
|
||||
JButton watchInputButton = addButton(taskActionsPanel, "Watch Test Input", StudyIcons.WatchInput);
|
||||
JButton watchInputButton = addButton(taskActionsPanel, "WatchInputAction", StudyIcons.WatchInput, null);
|
||||
watchInputButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
|
||||
@@ -418,10 +418,7 @@ def run_python_code_linux(pid, python_code, connect_debugger_tracing=False, show
|
||||
if not os.path.exists(target_dll):
|
||||
raise RuntimeError('Could not find dll file to inject: %s' % target_dll)
|
||||
|
||||
gdb_threads_settrace_file = os.path.join(filedir, 'linux', 'gdb_threads_settrace.py')
|
||||
gdb_threads_settrace_file = os.path.normpath(gdb_threads_settrace_file)
|
||||
if not os.path.exists(gdb_threads_settrace_file):
|
||||
raise RuntimeError('Could not find file to settrace: %s' % gdb_threads_settrace_file)
|
||||
gdb_threads_settrace_file = find_helper_script(filedir, 'gdb_threads_settrace.py')
|
||||
|
||||
# Note: we currently don't support debug builds
|
||||
is_debug = 0
|
||||
@@ -476,6 +473,15 @@ def run_python_code_linux(pid, python_code, connect_debugger_tracing=False, show
|
||||
return out, err
|
||||
|
||||
|
||||
def find_helper_script(filedir, script_name):
|
||||
lldb_threads_settrace_file = os.path.join(filedir, 'linux', script_name)
|
||||
lldb_threads_settrace_file = os.path.normpath(lldb_threads_settrace_file)
|
||||
if not os.path.exists(lldb_threads_settrace_file):
|
||||
raise RuntimeError('Could not find file to settrace: %s' % lldb_threads_settrace_file)
|
||||
|
||||
return lldb_threads_settrace_file
|
||||
|
||||
|
||||
def run_python_code_mac(pid, python_code, connect_debugger_tracing=False, show_debug_info=0):
|
||||
assert '\'' not in python_code, 'Having a single quote messes with our command.'
|
||||
filedir = os.path.dirname(__file__)
|
||||
@@ -498,12 +504,10 @@ def run_python_code_mac(pid, python_code, connect_debugger_tracing=False, show_d
|
||||
if not os.path.exists(target_dll):
|
||||
raise RuntimeError('Could not find dll file to inject: %s' % target_dll)
|
||||
|
||||
lldb_threads_settrace_file = os.path.join(filedir, 'linux', 'lldb_threads_settrace.py')
|
||||
lldb_threads_settrace_file = os.path.normpath(lldb_threads_settrace_file)
|
||||
if not os.path.exists(lldb_threads_settrace_file):
|
||||
raise RuntimeError('Could not find file to settrace: %s' % lldb_threads_settrace_file)
|
||||
|
||||
lldb_threads_settrace_file = find_helper_script(filedir, 'lldb_threads_settrace.py')
|
||||
lldb_threads_prepare_file = find_helper_script(filedir, 'lldb_threads_prepare.py')
|
||||
# Note: we currently don't support debug builds
|
||||
|
||||
is_debug = 0
|
||||
# Note that the space in the beginning of each line in the multi-line is important!
|
||||
cmd = [
|
||||
@@ -521,8 +525,9 @@ def run_python_code_mac(pid, python_code, connect_debugger_tracing=False, show_d
|
||||
|
||||
cmd.extend([
|
||||
"-o 'process attach --pid %d'"%pid,
|
||||
"-o 'command script import \'%s\''" % (lldb_threads_prepare_file,),
|
||||
"-o 'expr (void*)dlopen(\"%s\", 2);'" % target_dll,
|
||||
"-o 'expr (int)hello();'",
|
||||
# "-o 'expr (int)hello();'",
|
||||
"-o 'expr (int)DoAttach(%s, \"%s\", %s);'" % (
|
||||
is_debug, python_code, show_debug_info),
|
||||
])
|
||||
@@ -531,7 +536,7 @@ def run_python_code_mac(pid, python_code, connect_debugger_tracing=False, show_d
|
||||
if connect_debugger_tracing:
|
||||
cmd.extend([
|
||||
# "-o 'expr (int) SetSysTraceFunc(0, 0);'",
|
||||
"-o 'command script import %s'" % (lldb_threads_settrace_file,),
|
||||
"-o 'command script import \'%s\''" % (lldb_threads_settrace_file,),
|
||||
])
|
||||
|
||||
cmd.extend([
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# This file is meant to be run inside lldb as a command before
|
||||
# attaching the debugger to mark process threads as suspended
|
||||
# to distinguish them from debugger threads later
|
||||
|
||||
def __lldb_init_module(debugger, internal_dict):
|
||||
import lldb
|
||||
|
||||
try:
|
||||
target = debugger.GetSelectedTarget()
|
||||
if target:
|
||||
process = target.GetProcess()
|
||||
if process:
|
||||
for thread in process:
|
||||
# print('Marking process thread %d'%thread.GetThreadID())
|
||||
internal_dict['_thread_%d' % thread.GetThreadID()] = True
|
||||
# thread.Suspend()
|
||||
except:
|
||||
import traceback;traceback.print_exc()
|
||||
@@ -2,11 +2,11 @@
|
||||
# the attach_linux.dylib dll has already been loaded to settrace for all threads.
|
||||
def __lldb_init_module(debugger, internal_dict):
|
||||
# Command Initialization code goes here
|
||||
print('Startup LLDB in Python!')
|
||||
# print('Startup LLDB in Python!')
|
||||
import lldb
|
||||
|
||||
try:
|
||||
show_debug_info = 1
|
||||
show_debug_info = 0
|
||||
is_debug = 0
|
||||
target = debugger.GetSelectedTarget()
|
||||
if target:
|
||||
@@ -14,15 +14,11 @@ def __lldb_init_module(debugger, internal_dict):
|
||||
if process:
|
||||
for thread in process:
|
||||
# Get the first frame
|
||||
print('Thread %s, suspended %s\n'%(thread, thread.IsStopped()))
|
||||
# print('Thread %s, suspended %s\n'%(thread, thread.IsStopped()))
|
||||
|
||||
process.SetSelectedThread(thread)
|
||||
|
||||
if not thread.IsStopped():
|
||||
error = process.Stop()
|
||||
print(error)
|
||||
|
||||
if thread:
|
||||
if internal_dict.get('_thread_%d' % thread.GetThreadID(), False):
|
||||
frame = thread.GetSelectedFrame()
|
||||
if frame:
|
||||
print('Will settrace in: %s' % (frame,))
|
||||
@@ -31,6 +27,6 @@ def __lldb_init_module(debugger, internal_dict):
|
||||
error = res.GetError()
|
||||
if error:
|
||||
print(error)
|
||||
thread.Resume()
|
||||
thread.Resume()
|
||||
except:
|
||||
import traceback;traceback.print_exc()
|
||||
|
||||
Reference in New Issue
Block a user