提交 ba21f1d3 编写于 作者: S serge-rider

Merge remote-tracking branch 'origin/devel' into devel

......@@ -33,8 +33,11 @@ import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.model.WorkbenchLabelProvider;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.core.DBeaverCore;
import org.jkiss.dbeaver.debug.core.DebugCore;
import org.jkiss.dbeaver.debug.core.breakpoints.DatabaseLineBreakpoint;
import org.jkiss.dbeaver.debug.core.breakpoints.IDatabaseBreakpoint;
import org.jkiss.dbeaver.debug.core.model.DatabaseProcess;
import org.jkiss.dbeaver.debug.core.model.DatabaseStackFrame;
import org.jkiss.dbeaver.debug.core.model.DatabaseThread;
......@@ -42,10 +45,16 @@ import org.jkiss.dbeaver.debug.core.model.DatabaseVariable;
import org.jkiss.dbeaver.debug.core.model.IDatabaseDebugTarget;
import org.jkiss.dbeaver.model.DBPScriptObject;
import org.jkiss.dbeaver.model.navigator.DBNDatabaseNode;
import org.jkiss.dbeaver.model.navigator.DBNModel;
import org.jkiss.dbeaver.model.navigator.DBNNode;
import org.jkiss.dbeaver.model.navigator.DBNRoot;
import org.jkiss.dbeaver.model.runtime.VoidProgressMonitor;
import org.jkiss.dbeaver.ui.editors.entity.EntityEditorInput;
public class DatabaseDebugModelPresentation extends LabelProvider implements IDebugModelPresentationExtension {
private static Log log = Log.getLog(DatabaseDebugModelPresentation.class);
private final Map<String, Object> attributes = new HashMap<>();
private final ILabelProvider labelProvider;
......@@ -134,17 +143,38 @@ public class DatabaseDebugModelPresentation extends LabelProvider implements IDe
@Override
public IEditorInput getEditorInput(Object element) {
if (element instanceof DBNDatabaseNode) {
DBNDatabaseNode dbnNode = (DBNDatabaseNode) element;
EntityEditorInput editorInput = new EntityEditorInput(dbnNode);
editorInput.setAttribute(DBPScriptObject.OPTION_DEBUGGER_SOURCE, Boolean.TRUE);
// FIXME:AF: how to retrieve it? probably org.jkiss.dbeaver.databaseor and EntityEditorsRegistry can help
// String folderId = "postgresql.source.view";
// editorInput.setDefaultFolderId(folderId);
return editorInput;
DBNDatabaseNode databaseNode = (DBNDatabaseNode) element;
return createEditorInput(databaseNode);
}
if (element instanceof IDatabaseBreakpoint) {
IDatabaseBreakpoint breakpoint = (IDatabaseBreakpoint) element;
try {
String nodePath = breakpoint.getNodePath();
DBNModel navigatorModel = DBeaverCore.getInstance().getNavigatorModel();
DBNNode node = navigatorModel.getNodeByPath(new VoidProgressMonitor(), nodePath);
if (node instanceof DBNDatabaseNode) {
DBNDatabaseNode databaseNode = (DBNDatabaseNode) node;
return createEditorInput(databaseNode);
}
} catch (Exception e) {
String message = NLS.bind("Unable to resolve editor input for breakpoint {0}", breakpoint);
log.error(message, e);
}
}
return null;
}
protected IEditorInput createEditorInput(DBNDatabaseNode dbnNode) {
EntityEditorInput editorInput = new EntityEditorInput(dbnNode);
editorInput.setAttribute(DBPScriptObject.OPTION_DEBUGGER_SOURCE, Boolean.TRUE);
// FIXME:AF: how to retrieve it? probably org.jkiss.dbeaver.databaseor and EntityEditorsRegistry can help
// String folderId = "postgresql.source.view";
// editorInput.setDefaultFolderId(folderId);
return editorInput;
}
@Override
public String getEditorId(IEditorInput input, Object element) {
// FIXME:AF: is there a constant anywhere?
......
......@@ -158,7 +158,8 @@
id="numericSequenceGenerator"
label="Sequence"
description="Sequence of numbers with adjustable start, step and order"
class="org.jkiss.dbeaver.ext.mockdata.generator.NumericSequenceGenerator">
class="org.jkiss.dbeaver.ext.mockdata.generator.NumericSequenceGenerator"
tags="id,number,order">
<type kind="NUMERIC"/>
<propertyGroup label="General">
......@@ -184,7 +185,8 @@
id="stringTextGenerator"
label="Text"
description="Random length substrings from the 'Lorem ipsum' text"
class="org.jkiss.dbeaver.ext.mockdata.generator.StringTextGenerator">
class="org.jkiss.dbeaver.ext.mockdata.generator.StringTextGenerator"
tags="text,paragraph,chapter">
<type kind="STRING"/>
<propertyGroup label="General">
......@@ -199,7 +201,8 @@
id="stringUuidGenerator"
label="UUID"
description="UUID random values"
class="org.jkiss.dbeaver.ext.mockdata.generator.StringUuidGenerator">
class="org.jkiss.dbeaver.ext.mockdata.generator.StringUuidGenerator"
tags="uuid">
<type kind="STRING"/>
</generator>
......
......@@ -175,13 +175,13 @@ public class MockDataSettings {
for (Map.Entry<String, AttributeGeneratorProperties> entry : attributeGenerators.entrySet()) {
String attributeName = entry.getKey();
IDialogSettings attributeSection = UIUtils.getSettingsSection(tableSection, attributeName);
String selectedGeneratorId = attributeSection.get(KEY_SELECTED_GENERATOR);
if (selectedGeneratorId != null) {
AttributeGeneratorProperties attrGeneratorProperties = entry.getValue();
attrGeneratorProperties.setSelectedGeneratorId(selectedGeneratorId);
String savedGeneratorId = attributeSection.get(KEY_SELECTED_GENERATOR);
AttributeGeneratorProperties attrGeneratorProperties = entry.getValue();
if (savedGeneratorId != null) {
attrGeneratorProperties.setSelectedGeneratorId(savedGeneratorId);
attrGeneratorProperties.setPresetId(attributeSection.get(KEY_PRESET_ID));
PropertySourceCustom generatorPropertySource = attrGeneratorProperties.getGeneratorPropertySource(selectedGeneratorId);
PropertySourceCustom generatorPropertySource = attrGeneratorProperties.getGeneratorPropertySource(savedGeneratorId);
IDialogSettings generatorSection = UIUtils.getSettingsSection(attributeSection, KEY_GENERATOR_SECTION);
if (generatorPropertySource != null) {
Map<Object, Object> properties = generatorPropertySource.getPropertiesWithDefaults();
......@@ -194,6 +194,44 @@ public class MockDataSettings {
generatorPropertySource.setPropertyValue(voidProgressMonitor, propEntry.getKey(), savedValue);
}
}
} else {
autoAssignGenerator(attrGeneratorProperties); // set the default generator
}
}
}
public void autoAssignGenerator(AttributeGeneratorProperties attrGeneratorProperties) {
DBSAttributeBase attribute = attrGeneratorProperties.getAttribute();
String attributeName = attribute.getName().toLowerCase();
Set<String> attrGeneratorIds = attrGeneratorProperties.getGenerators();
boolean found = false;
for (String generatorId : attrGeneratorIds) {
MockGeneratorDescriptor generatorDescriptor = getGeneratorDescriptor(generatorId);
for (String tag : generatorDescriptor.getTags()) {
// find & set the appropriate generator
if (attributeName.contains(tag)) {
attrGeneratorProperties.setSelectedGeneratorId(generatorId);
found = true;
break;
}
}
if (found) break;
}
if (!found) {
// set the default generator
switch (attribute.getDataKind()) {
case BOOLEAN:
attrGeneratorProperties.setSelectedGeneratorId(MockGeneratorDescriptor.BOOLEAN_RANDOM_GENERATOR_ID);
break;
case DATETIME:
attrGeneratorProperties.setSelectedGeneratorId(MockGeneratorDescriptor.DATETIME_RANDOM_GENERATOR_ID);
break;
case NUMERIC:
attrGeneratorProperties.setSelectedGeneratorId(MockGeneratorDescriptor.NUMERIC_RANDOM_GENERATOR_ID);
break;
case STRING:
attrGeneratorProperties.setSelectedGeneratorId(MockGeneratorDescriptor.STRING_TEXT_GENERATOR_ID);
break;
}
}
}
......
......@@ -29,16 +29,17 @@ import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.browser.IWorkbenchBrowserSupport;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.core.DBeaverUI;
import org.jkiss.dbeaver.ext.mockdata.MockDataSettings.AttributeGeneratorProperties;
import org.jkiss.dbeaver.ext.mockdata.model.MockGeneratorDescriptor;
import org.jkiss.dbeaver.model.DBPEvaluationContext;
import org.jkiss.dbeaver.model.DBUtils;
import org.jkiss.dbeaver.model.DBValueFormatting;
import org.jkiss.dbeaver.model.preferences.DBPPropertyDescriptor;
import org.jkiss.dbeaver.model.runtime.VoidProgressMonitor;
import org.jkiss.dbeaver.model.struct.DBSAttributeBase;
import org.jkiss.dbeaver.runtime.properties.PropertySourceCustom;
import org.jkiss.dbeaver.ui.DBeaverIcons;
import org.jkiss.dbeaver.ui.UIIcon;
import org.jkiss.dbeaver.ui.UIUtils;
import org.jkiss.dbeaver.ui.controls.CustomComboBoxCellEditor;
import org.jkiss.dbeaver.ui.dialogs.ActiveWizardPage;
......@@ -52,6 +53,7 @@ import java.util.List;
public class MockDataWizardPageSettings extends ActiveWizardPage<MockDataExecuteWizard>
{
private static final Log log = Log.getLog(MockDataWizardPageSettings.class);
public static final int DEFAULT_NAME_COLUMN_WIDTH = 110;
private MockDataSettings mockDataSettings;
......@@ -62,7 +64,7 @@ public class MockDataWizardPageSettings extends ActiveWizardPage<MockDataExecute
private PropertyTreeViewer propsEditor;
private PropertySourceCustom propertySource;
private TableViewer columnsTableViewer;
private TableViewer generatorsTableViewer;
private DBSAttributeBase selectedAttribute;
private boolean firstInit = true;
private Combo generatorCombo;
......@@ -132,16 +134,16 @@ public class MockDataWizardPageSettings extends ActiveWizardPage<MockDataExecute
gd.verticalIndent = 5;
generatorsGroup.setLayoutData(gd);
columnsTableViewer = new TableViewer(generatorsGroup, SWT.BORDER | SWT.SINGLE | SWT.FULL_SELECTION);
final Table table = columnsTableViewer.getTable();
generatorsTableViewer = new TableViewer(generatorsGroup, SWT.BORDER | SWT.SINGLE | SWT.FULL_SELECTION);
final Table table = generatorsTableViewer.getTable();
gd = new GridData(GridData.FILL_VERTICAL);
gd.widthHint = 230;
gd.widthHint = 250;
table.setLayoutData(gd);
table.setHeaderVisible(true);
table.setLinesVisible(true);
columnsTableViewer.setContentProvider(new IStructuredContentProvider() {
generatorsTableViewer.setContentProvider(new IStructuredContentProvider() {
@Override
public void dispose() { }
@Override
......@@ -185,15 +187,35 @@ public class MockDataWizardPageSettings extends ActiveWizardPage<MockDataExecute
}
};
TableViewerColumn attributeColumn = new TableViewerColumn(columnsTableViewer, SWT.LEFT);
TableViewerColumn attributeColumn = new TableViewerColumn(generatorsTableViewer, SWT.LEFT);
attributeColumn.setLabelProvider(labelProvider);
attributeColumn.getColumn().setText("Attribute");
TableViewerColumn generatorColumn = new TableViewerColumn(columnsTableViewer, SWT.LEFT);
TableViewerColumn generatorColumn = new TableViewerColumn(generatorsTableViewer, SWT.LEFT);
generatorColumn.setLabelProvider(labelProvider);
generatorColumn.getColumn().setText("Generator");
TableColumn column = generatorColumn.getColumn();
column.setText("Generator");
column.setImage(DBeaverIcons.getImage(UIIcon.OBJ_REFRESH));
column.setToolTipText("Automatically assign the generators");
column.addListener(SWT.Selection, new Listener() {
@Override
public void handleEvent(Event event) {
if (UIUtils.confirmAction(getShell(), MockDataMessages.tools_mockdata_wizard_title, "The generators will be assigned automatically. Proceed?")) {
autoAssignGenerators();
}
}
});
/* TODO for some reason it doesn't work over the header
generatorsTableViewer.getTable().addListener(SWT.MouseMove, new Listener() {
@Override
public void handleEvent(Event event) {
log.debug(">>>>>>>>>>>>>>>>>>> "+event.x+" <<>> "+event.y);
// SET THE HAND CURSOR
}
});
*/
generatorColumn.setEditingSupport(new EditingSupport(columnsTableViewer) {
generatorColumn.setEditingSupport(new EditingSupport(generatorsTableViewer) {
@Override
protected CellEditor getCellEditor(Object element) {
DBSAttributeBase attribute = (DBSAttributeBase) element;
......@@ -201,9 +223,8 @@ public class MockDataWizardPageSettings extends ActiveWizardPage<MockDataExecute
AttributeGeneratorProperties attributeGenerators = mockDataSettings.getAttributeGeneratorProperties(attribute);
Set<String> generators = new LinkedHashSet<>();
if (attributeGenerators.isEmpty()) {
// TODO item.setForeground(columnsTableViewer.getDisplay().getSystemColor(SWT.COLOR_RED));
noGeneratorInfoLabel.setVisible(true);
TextCellEditor textCellEditor = new TextCellEditor(columnsTableViewer.getTable());
TextCellEditor textCellEditor = new TextCellEditor(generatorsTableViewer.getTable());
textCellEditor.getControl().setEnabled(false);
return textCellEditor;
} else {
......@@ -212,8 +233,8 @@ public class MockDataWizardPageSettings extends ActiveWizardPage<MockDataExecute
}
CustomComboBoxCellEditor customComboBoxCellEditor = new CustomComboBoxCellEditor(
columnsTableViewer,
columnsTableViewer.getTable(),
generatorsTableViewer,
generatorsTableViewer.getTable(),
generators.toArray(new String[generators.size()]),
SWT.BORDER | SWT.READ_ONLY);
return customComboBoxCellEditor;
......@@ -305,7 +326,7 @@ public class MockDataWizardPageSettings extends ActiveWizardPage<MockDataExecute
propertySource.resetPropertyValueToDefault(key);
}
propsEditor.loadProperties(propertySource);
columnsTableViewer.refresh(true, true);
generatorsTableViewer.refresh(true, true);
}
});
gd = new GridData();
......@@ -319,7 +340,7 @@ public class MockDataWizardPageSettings extends ActiveWizardPage<MockDataExecute
noGeneratorInfoLabel = UIUtils.createInfoLabel(composite,
"Generators for the red highlighted attributes aren't found. So, no data will be generated for them.");
//noGeneratorInfoLabel.setForeground(columnsTableViewer.getDisplay().getSystemColor(SWT.COLOR_RED));
//noGeneratorInfoLabel.setForeground(generatorsTableViewer.getDisplay().getSystemColor(SWT.COLOR_RED));
gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
gd.horizontalSpan = 2;
gd.verticalIndent = 5;
......@@ -339,7 +360,15 @@ public class MockDataWizardPageSettings extends ActiveWizardPage<MockDataExecute
setControl(composite);
boldFont = UIUtils.makeBoldFont(columnsTableViewer.getControl().getFont());
boldFont = UIUtils.makeBoldFont(generatorsTableViewer.getControl().getFont());
}
private void autoAssignGenerators() {
Map<String, AttributeGeneratorProperties> attributeGenerators = mockDataSettings.getAttributeGenerators();
for (String attrName : attributeGenerators.keySet()) {
mockDataSettings.autoAssignGenerator(attributeGenerators.get(attrName));
}
generatorsTableViewer.refresh(true, true);
}
private void selectGenerator(DBSAttributeBase attribute, String generatorName) {
......@@ -348,30 +377,7 @@ public class MockDataWizardPageSettings extends ActiveWizardPage<MockDataExecute
saveGeneratorProperties();
reloadProperties(attribute, generatorForName.getId());
}
columnsTableViewer.refresh(true, true);
}
private void selectPreset(String presetName) {
AttributeGeneratorProperties attributeGeneratorProperties = mockDataSettings.getAttributeGeneratorProperties(selectedAttribute);
String generatorId = attributeGeneratorProperties.getSelectedGeneratorId();
List<MockGeneratorDescriptor.Preset> presets = mockDataSettings.getGeneratorDescriptor(generatorId).getPresets();
for (MockGeneratorDescriptor.Preset preset : presets) {
// Apply the preset
if (preset.getLabel().equals(presetName)) {
propertySource = attributeGeneratorProperties.getGeneratorPropertySource(generatorId);
VoidProgressMonitor monitor = new VoidProgressMonitor();
for (DBPPropertyDescriptor prop : preset.getProperties()) {
propertySource.setPropertyValue(monitor, prop.getId(), prop.getDefaultValue());
}
propsEditor.loadProperties(propertySource);
propsEditor.setExpandMode(PropertyTreeViewer.ExpandMode.FIRST);
propsEditor.expandAll();
attributeGeneratorProperties.setPresetId(preset.getId());
columnsTableViewer.refresh(true, true);
}
}
generatorsTableViewer.refresh(true, true);
}
@Override
......@@ -387,30 +393,36 @@ public class MockDataWizardPageSettings extends ActiveWizardPage<MockDataExecute
removeOldDataCheck.setSelection(mockDataSettings.isRemoveOldData());
rowsText.setText(String.valueOf(mockDataSettings.getRowsNumber()));
columnsTableViewer.setInput(mockDataSettings.getAttributes());
generatorsTableViewer.setInput(mockDataSettings.getAttributes());
}
entityNameText.setText(DBUtils.getObjectFullName(mockDataSettings.getEntity(), DBPEvaluationContext.DML));
propsEditor.getControl().setFocus();
// select the attributes table item
final Table table = columnsTableViewer.getTable();
final Table table = generatorsTableViewer.getTable();
if (table.getItemCount() > 0) {
int selectedItem = 0;
int selectedItemIndex = 0;
TableItem selectedItem = null;
String selectedAttribute = mockDataSettings.getSelectedAttribute();
if (selectedAttribute != null) {
for (int i = 0; i < table.getItemCount(); i++) {
if (selectedAttribute.equals(table.getItem(i).getText())) {
selectedItem = i; break;
selectedItemIndex = i;
selectedItem = table.getItem(i);
break;
}
}
}
table.select(selectedItem);
table.select(selectedItemIndex);
if (selectedItem != null) {
table.showItem(selectedItem);
}
// and notify the listeners
Event event = new Event();
event.widget = table;
event.display = table.getDisplay();
event.item = table.getItem(selectedItem);
event.item = table.getItem(selectedItemIndex);
event.type = SWT.Selection;
table.notifyListeners(SWT.Selection, event);
} else {
......@@ -488,10 +500,20 @@ public class MockDataWizardPageSettings extends ActiveWizardPage<MockDataExecute
propsEditor.clearProperties();
}
// set the properties table columns width
DBeaverUI.asyncExec(() -> {
((Tree) propsEditor.getControl()).getColumn(0).setWidth(DEFAULT_NAME_COLUMN_WIDTH);
((Tree) propsEditor.getControl()).getColumn(1).setWidth(
propsEditor.getControl().getSize().x - DEFAULT_NAME_COLUMN_WIDTH - 30);
});
// generator combo & description
List<String> generators = new ArrayList<>();
for (String genId : attributeGeneratorProperties.getGenerators()) {
generators.add(mockDataSettings.getGeneratorDescriptor(genId).getLabel());
MockGeneratorDescriptor generatorDescriptor = mockDataSettings.getGeneratorDescriptor(genId);
if (generatorDescriptor != null) {
generators.add(generatorDescriptor.getLabel());
}
}
generatorDescriptionLink.setVisible(false);
if (!generators.isEmpty()) {
......
......@@ -28,6 +28,7 @@ import org.jkiss.dbeaver.registry.datatype.DataTypeAbstractDescriptor;
import org.jkiss.utils.CommonUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
......@@ -37,6 +38,11 @@ public class MockGeneratorDescriptor extends DataTypeAbstractDescriptor<MockValu
public static final String EXTENSION_ID = "org.jkiss.dbeaver.mockGenerator"; //$NON-NLS-1$
public static final String BOOLEAN_RANDOM_GENERATOR_ID = "booleanRandomGenerator"; //NON-NLS-1
public static final String DATETIME_RANDOM_GENERATOR_ID = "dateRandomGenerator"; //NON-NLS-1
public static final String NUMERIC_RANDOM_GENERATOR_ID = "numericRandomGenerator"; //NON-NLS-1
public static final String STRING_TEXT_GENERATOR_ID = "stringTextGenerator"; //NON-NLS-1
public static final String TAG_PRESET = "preset"; //NON-NLS-1
private Preset preset;
......@@ -47,6 +53,7 @@ public class MockGeneratorDescriptor extends DataTypeAbstractDescriptor<MockValu
private final DBPImage icon;
private List<DBPPropertyDescriptor> properties = new ArrayList<>();
private List<Preset> presets = new ArrayList<>();
private List<String> tags = new ArrayList<>();
public MockGeneratorDescriptor(IConfigurationElement config)
{
......@@ -71,7 +78,8 @@ public class MockGeneratorDescriptor extends DataTypeAbstractDescriptor<MockValu
preset.getAttribute("label"),
preset.getAttribute("mnemonics"),
preset.getAttribute("description"),
PropertyDescriptor.extractProperties(preset)
PropertyDescriptor.extractProperties(preset),
extractTags(preset)
));
}
......@@ -83,6 +91,11 @@ public class MockGeneratorDescriptor extends DataTypeAbstractDescriptor<MockValu
"General", "uppercase", "Upper Case", null, false,
PropertyDescriptor.PropertyType.t_boolean.getValueType(), false, null));
}
List<String> tags = extractTags(config);
if (tags != null) {
this.tags = tags;
}
}
public MockGeneratorDescriptor(IConfigurationElement config, Preset preset) {
......@@ -96,9 +109,20 @@ public class MockGeneratorDescriptor extends DataTypeAbstractDescriptor<MockValu
for (DBPPropertyDescriptor prop : preset.getProperties()) {
setDefaultProperty(prop.getId(), prop.getDefaultValue());
}
if (preset.getTags() != null) {
this.tags.addAll(preset.getTags());
}
this.presets.clear();
}
private List<String> extractTags(IConfigurationElement config) {
String tagsAttr = config.getAttribute("tags");
if (!CommonUtils.isEmpty(tagsAttr)) {
return Arrays.asList(tagsAttr.split(",").clone());
}
return null;
}
private void setDefaultProperty(Object id, Object defaultValue) {
for (DBPPropertyDescriptor property : properties) {
if (property.getId().equals(id)) {
......@@ -141,6 +165,10 @@ public class MockGeneratorDescriptor extends DataTypeAbstractDescriptor<MockValu
return properties;
}
public List<String> getTags() {
return tags;
}
public DBPPropertyDescriptor getProperty(Object id) {
for (DBPPropertyDescriptor descriptor : getProperties()) {
if (id.equals(descriptor.getId())) {
......@@ -165,13 +193,15 @@ public class MockGeneratorDescriptor extends DataTypeAbstractDescriptor<MockValu
private final String mnemonics;
private final String description;
private final List<DBPPropertyDescriptor> properties;
private List<String> tags = new ArrayList<>();
public Preset(String id, String label, String mnemonics, String description, List<DBPPropertyDescriptor> properties) {
public Preset(String id, String label, String mnemonics, String description, List<DBPPropertyDescriptor> properties, List<String> tags) {
this.id = id;
this.label = label;
this.mnemonics = mnemonics;
this.description = description;
this.properties = properties;
this.tags = tags;
}
public String getId() {
......@@ -193,5 +223,9 @@ public class MockGeneratorDescriptor extends DataTypeAbstractDescriptor<MockValu
public List<DBPPropertyDescriptor> getProperties() {
return properties;
}
public List<String> getTags() {
return tags;
}
}
}
......@@ -18,6 +18,7 @@ Require-Bundle: org.eclipse.core.runtime,
org.eclipse.ui.views,
org.eclipse.ui.workbench.texteditor,
org.eclipse.mylyn.commons.ui,
org.eclipse.mylyn.commons.workbench,
org.eclipse.mylyn.commons.notifications.core,
org.eclipse.mylyn.commons.notifications.ui,
org.eclipse.mylyn.commons.workbench,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册